Java word模板以及填充数据
使用的技术:
poi tl : http://deepoove.com/poi-tl/#_why_poi_tl (数据填充)
poi : http://deepoove.com/poi-tl/apache-poi-guide.html (数据读取)
选择此技术的原因
- 属于动态数据,数据也不相同、比如:出口订单的模板打印、报关单的合同打印
- 自定义模板,可以让用户自定义模板,用来显示打印的数据
- 最开始使用的是 : vue-plugin-hiprint (后面因模板较复杂,重新调研数据)
https://ccsimple.gitee.io/vue-plugin-hiprint/ - 选择了word模板打印了之后,开始调研技术,选了poi-tl,查看了资料以及自己做demo后觉着这个技术还可以
遇到的问题:
- 最开始的时候可以实现基础数据打印了,图片也可以,问题是图片大小不能调整
解决办法:
扩展标签:如 原始的标签为{{@aa}} 将这个标签更改为 {{@aa_150_250}}
获取到{{@}} 格式的数据 如果没有_150_250类似的数据,不管 如果存在,则在后台对象封装是 增加一个属性 aa_150_250(通过jsonObject) 动态增加属性 - 实现了图片自定义大小,模板还是会有问题,位置不能固定,导致模板还不是想要的数据
解决方案:使用pot-tl中的引用标签信息
![]()
设置图片中的可选文字(Microsoft Office 图片右键即可设置 wps找了半天没有找到)
找到之后 后台对应的数据调整一下即可 - 表格中使用除表格之外的数据
比如 订单中存在币别 订单产品中没有币别 模板打印的时候 需要在产品中打印出币别 目前是不支持的
解决方案是: 在订单的产品中 冗余币别信息 用于模板打印 - 循环获取集合数据(非表格),正常循环
{{?array}} 名字{{name}} {{/array}}
Java poi 获取图片的可选文字代码:
private void readImageInfo(String filepath) throws IOException, InvalidFormatException {
XWPFDocument doc = new XWPFDocument(new FileInputStream(filepath));
for (XWPFParagraph paragraph : doc.getParagraphs()) {
for (XWPFRun run : paragraph.getRuns()) {
for (XWPFPicture embeddedPicture : run.getEmbeddedPictures()) {
System.out.println(embeddedPicture.getDescription());
}
}
}
List<XWPFPictureData> allPictures = doc.getAllPictures();
}
附上部分关键性代码:
@Autowired
private SysRuleBillService sysRuleBillService;
@Autowired
private WmsDeclarationContractService wmsDeclarationContractService;
@Autowired
private SysOrganizationService sysOrganizationService;
@Autowired
private SysUserService sysUserService;
@Autowired
private SecurityUserInfoService securityUserInfoService;
private static Long orgId = 1760164245476425728L;
private static Long id = 1760233880706789377L;
private static Long tenantId = 1760164244302020608L;
@Test
public void test() throws Exception {
setLoginUser();
PrintModel printData = wmsDeclarationContractService.getPrintData(id);
JSONObject bus = new JSONObject();
bus.put("contract", printData);
// 获取列表数据
List<String> listProperties = Lists.newArrayList();
getListProperties(bus, StringUtils.EMPTY, listProperties);
// 流获取
// java.net.URL url = new java.net.URL("http://192.168.0.210:9000/huake-erp/1760164244302020608/1760164245476425728/PUBLIC_DOCUMENTS/1765359074774605825_safekeeping_contract.docx");
// URLConnection con = url.openConnection();
// InputStream inputStream = con.getInputStream();
// InputStreamCache streamCache = new InputStreamCache(inputStream);
// 获取图片大小
// String sourceContext = readByExtractor(streamCache.getInputStream());
// 文件获取
String filepath = this.getClass().getClassLoader().getResource("wordtemplates/safekeeping_contract.docx").getPath();
String sourceContext = readByFileExtractor(filepath);
List<ImageInfo> imageInfoList = getImages(sourceContext);
// List<ImageInfo> imageInfoList = Lists.newArrayList();
if (CollUtil.isNotEmpty(imageInfoList)) {
getImagesProperties(bus, "", imageInfoList);
}
Map map = JSONObject.parseObject(JSONObject.toJSONString(bus), Map.class);
PrintModel model = new PrintModel();
model.setPrintOrgId(orgId);
Object printData1 = sysOrganizationService.getPrintData(model);
JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(printData1));
if (CollUtil.isNotEmpty(imageInfoList)) {
getImagesProperties(jsonObject, "commonCompany", imageInfoList);
}
List<ImageInfo> pictureInfoList = getPictureImageInfo(filepath);
if (CollUtil.isNotEmpty(pictureInfoList)) {
getPictureImageProperties(jsonObject, "commonCompany", pictureInfoList);
}
JSONObject object = new JSONObject();
object.put("commonCompany", jsonObject);
map.putAll(object);
log.info("传递的参数:{}", JSON.toJSONString(map));
ConfigureBuilder builder = Configure.builder();
if (CollUtil.isNotEmpty(listProperties)) {
LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
for (String property : listProperties) {
builder.bind(property, policy);
}
}
Configure configure = builder.build();
// 流
// XWPFTemplate template = XWPFTemplate.compile(streamCache.getInputStream(), configure).render(map);
//// 输出到流
// String file="D:\\safekeeping_contract.doc";
// template.writeAndClose(new FileOutputStream(file));
// if (streamCache != null) {
// streamCache.destroyCache();
// }
// 文件
XWPFTemplate template = XWPFTemplate.compile(filepath, configure).render(map);
// 输出到流
String file="D:\\safekeeping_contract.doc";
template.writeAndClose(new FileOutputStream(file));
clearLoginUser();
}
private List<ImageInfo> getPictureImageInfo(String filepath) {
List<ImageInfo> result = Lists.newArrayList();
Pattern P = Pattern.compile("\\{\\{[^}]*}}");
try {
XWPFDocument doc = new XWPFDocument(new FileInputStream(filepath));
for (XWPFParagraph paragraph : doc.getParagraphs()) {
for (XWPFRun run : paragraph.getRuns()) {
for (XWPFPicture embeddedPicture : run.getEmbeddedPictures()) {
Matcher matcher = P.matcher(embeddedPicture.getDescription());
while (matcher.find()) {
String source = matcher.group();
ImageInfo imageInfo = new ImageInfo();
imageInfo.setSource(source);
imageInfo.setImageField(getPictureImageField(imageInfo.getSource()));
imageInfo.setFiled(getField(imageInfo.getSource()));
result.add(imageInfo);
}
}
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return result;
}
public List<ImageInfo> getImages(String content) {
List<ImageInfo> result = Lists.newArrayList();
Pattern P = Pattern.compile("\\{\\{@[^}]*}}");
Matcher matcher = P.matcher(content);
while (matcher.find()) {
ImageInfo imageInfo = new ImageInfo();
imageInfo.setSource(matcher.group());
imageInfo.setImageField(getImageField(imageInfo.getSource()));
imageInfo.setFiled(getField(imageInfo.getSource()));
result.add(imageInfo);
}
return result;
}
private String getField(String source) {
Pattern p = Pattern.compile("\\{\\{[@]?(.*)}}");
Matcher matcher = p.matcher(source);
if (matcher.find()) {
return matcher.group(1);
}
return null;
}
private String getImageField(String source) {
Pattern p = Pattern.compile("\\{\\{@([^_]*)(_)?.*}}");
Matcher matcher = p.matcher(source);
if (matcher.find()) {
return matcher.group(1);
}
return null;
}
private String getPictureImageField(String source) {
Pattern p = Pattern.compile("\\{\\{([^_]*)(_)?.*}}");
Matcher matcher = p.matcher(source);
if (matcher.find()) {
return matcher.group(1);
}
return null;
}
private void getListProperties(Object bus, String prefix, List<String> listProperties) {
String jsonString = JSONObject.toJSONString(bus);
if (JSON.isValidArray(jsonString)) {
JSONArray array = JSONArray.parseArray(jsonString);
listProperties.add(prefix);
getListProperties(array.get(0), prefix, listProperties);
}
if (JSON.isValidObject(jsonString)) {
JSONObject parse = JSONObject.parse(jsonString);
for (Map.Entry<String, Object> entry : parse.entrySet()) {
String newPrefix = getPrefix(prefix, entry.getKey());
getListProperties(entry.getValue(), newPrefix, listProperties);
}
}
}
/**
* 设置新的前缀
*
* @param prefix 前缀
* @param key 新的key
* @return 新的前缀
*/
private String getPrefix(String prefix, String key) {
if (StringUtils.isBlank(prefix)) {
return key;
}
return String.join(".", prefix, key);
}
private void getImagesProperties(JSONObject vo, String prefix,
List<ImageInfo> imageInfos) throws IOException {
String jsonString = JSONObject.toJSONString(vo);
if (JSON.isValidArray(jsonString)) {
JSONArray array = JSONArray.parseArray(jsonString);
getImagesProperties((JSONObject) array.get(0), prefix, imageInfos);
}
if (JSON.isValidObject(jsonString)) {
JSONObject parse = JSONObject.parse(jsonString);
for (Map.Entry<String, Object> entry : parse.entrySet()) {
String newPrefix = getPrefix(prefix, entry.getKey());
for (ImageInfo imageInfo : imageInfos) {
if (!StringUtils.equals(imageInfo.getImageField(), newPrefix)) {
continue;
}
imageInfo.setImagePath((String) entry.getValue());
if (!StringUtils.equals(imageInfo.getFiled(), imageInfo.getImageField())) {
String newFiled = imageInfo.getFiled().substring(imageInfo.getFiled().lastIndexOf(".") + 1);
String[] split = newFiled.split("_");
if (split.length != 3) {
continue;
}
vo.put(newFiled, Pictures.ofUrl(imageInfo.getImagePath(), PictureType.PNG)
.size(Integer.parseInt(split[1]), Integer.parseInt(split[2]))
.create());
}
}
if (entry.getValue() instanceof JSONObject) {
getImagesProperties((JSONObject) entry.getValue(), newPrefix, imageInfos);
}
}
}
}
private void getPictureImageProperties(JSONObject vo, String prefix, List<ImageInfo> imageInfos) {
String jsonString = JSONObject.toJSONString(vo);
if (JSON.isValidArray(jsonString)) {
JSONArray array = JSONArray.parseArray(jsonString);
getPictureImageProperties((JSONObject) array.get(0), prefix, imageInfos);
}
if (JSON.isValidObject(jsonString)) {
JSONObject parse = JSONObject.parse(jsonString);
for (Map.Entry<String, Object> entry : parse.entrySet()) {
String newPrefix = getPrefix(prefix, entry.getKey());
for (ImageInfo imageInfo : imageInfos) {
if (!StringUtils.equals(imageInfo.getImageField(), newPrefix)) {
continue;
}
imageInfo.setImagePath((String) entry.getValue());
if (!StringUtils.equals(imageInfo.getFiled(), imageInfo.getImageField())) {
String newFiled = imageInfo.getFiled().substring(imageInfo.getFiled().lastIndexOf(".") + 1);
String[] split = newFiled.split("_");
if (split.length != 3) {
continue;
}
vo.put(newFiled, Pictures.ofUrl(imageInfo.getImagePath(), PictureType.PNG)
.size(Integer.parseInt(split[1]), Integer.parseInt(split[2]))
.create());
} else {
vo.put(entry.getKey(), Pictures.ofUrl(imageInfo.getImagePath()).create());
}
}
if (entry.getValue() instanceof JSONObject) {
getPictureImageProperties((JSONObject) entry.getValue(), newPrefix, imageInfos);
}
}
}
}
/**
* 通过XWPFWordExtractor访问XWPFDocument的内容
* @throws Exception
*/
public String readByExtractor(InputStream is) throws Exception {
XWPFDocument doc = new XWPFDocument(is);
XWPFWordExtractor extractor = new XWPFWordExtractor(doc);
String text = extractor.getText();
// List<String> result = Lists.newArrayList();
// result.add(text);
/**
* 打印文档信息
*/
// POIXMLProperties.CoreProperties coreProps = extractor.getCoreProperties();
// printCoreProperties(coreProps);
// close(is);
return text;
}
private String readByFileExtractor(String filepath) throws IOException {
XWPFDocument doc = new XWPFDocument(new FileInputStream(filepath));
XWPFWordExtractor extractor = new XWPFWordExtractor(doc);
String text = extractor.getText();
// List<String> result = Lists.newArrayList();
// result.add(text);
/**
* 打印文档信息
*/
// POIXMLProperties.CoreProperties coreProps = extractor.getCoreProperties();
// printCoreProperties(coreProps);
// close(is);
return text;
}
// /**
// * 通过XWPFWordExtractor访问XWPFDocument的内容
// * @throws Exception
// */
// public String readByExtractor(String path) throws Exception {
// InputStream is = new FileInputStream(path);
// XWPFDocument doc = new XWPFDocument(is);
// XWPFWordExtractor extractor = new XWPFWordExtractor(doc);
// String text = extractor.getText();
//// List<String> result = Lists.newArrayList();
//// result.add(text);
// /**
// * 打印文档信息
// */
//// POIXMLProperties.CoreProperties coreProps = extractor.getCoreProperties();
//// printCoreProperties(coreProps);
// close(is);
// return text;
// }
/**
* 关闭输入流
* @param is
*/
private void close(InputStream is) {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void clearLoginUser() {
HuakeSecurityContextHolder.clearContext();
}
private void setLoginUser() {
List<Long> userIds = sysUserService.getBaseMapper().selectIngoreLoginUserList();
List<SecurityUserInfo> securityUserInfos = securityUserInfoService.getSecurityUserByUserIds(Sets.newHashSet(userIds));
if (CollUtil.isEmpty(securityUserInfos)) {
return;
}
SecurityUserInfo securityUserInfo = securityUserInfos.get(NumberConstants.ZERO);
securityUserInfo.setDefaultOrgId(orgId);
securityUserInfo.setTenantId(tenantId);
HuakeSecurityContextHolder.setContext(securityUserInfo);
Thread.currentThread().setName("MAIL_VIR_POOL_CRMJOB");
}


浙公网安备 33010602011771号