赞
踩
效果如下:
- <!-- excel工具 -->
- <dependency>
- <groupId>org.apache.poi</groupId>
- <artifactId>poi-ooxml</artifactId>
- <version>${poi.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.poi</groupId>
- <artifactId>poi-ooxml-schemas</artifactId>
- <version>${poi-ooxml-schemas.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.poi</groupId>
- <artifactId>poi</artifactId>
- <version>${poi.version}</version>
- </dependency>
- <dependency>
- <groupId>com.deepoove</groupId>
- <artifactId>poi-tl</artifactId>
- <version>${poi-tl.version}</version>
- </dependency>
注意点:poi-tl 1.12.x 要求 POI 版本在 5.2.2+.
说明:
1、为什么要用区块?由于需求是每页30行,每页都要有基本信息表头,所以用区块标签,将表头和表格作为一个区块。区块可循环N次,一个区块就是一页。
2、为什么要分页标记?通过分页标记来插入分页符。
3、为什么底部签名要用整个标签?表格内容动态,会将底部内容挤到下一页,所以通过代码在最后一行插入签名文本。
4、为什么不用excel模板?excel单元格插入图片展示不美观,且不好分页打印。其实也可以用excel操作,参考这篇文章:使用poi操作excel模板记录
- public SysFile materialUseGenWord(MachineMaterialUseResult useResult) {
- try {
- // 从resources下获取模板
- ClassPathResource resource = new ClassPathResource("template/lldmb.docx");
- InputStream inputStream = resource.getInputStream();
- // 添加二维码图片
- BufferedImage qrCodeImage = QrCodeUtil.generate(useResult.getSerialNo(), QrConfig.create().setMargin(1));
- // 计算页数:每页30行,新页都要有表头
- double page = 1;
- if (useResult.getParts().size() > 30) {
- page = Math.ceil((double) useResult.getParts().size() / 30);
- }
- List<Map<String, Object>> foreachList = new ArrayList<>();
- // 区块标签
- Map<String, Object> resMap = new HashMap<>();
- resMap.put("list", foreachList);
- for (int i = 0; i < page; i++) {
- log.info("第{}页表格数据", i + 1);
- List<MachineMaterialUseDetail> parts = new ArrayList<>();
- for (int j = 0; j < 30; j++) {
- if (i * 30 + j < useResult.getParts().size()) {
- parts.add(useResult.getParts().get(i * 30 + j));
- } else {
- break;
- }
- }
- Map<String, Object> materialMap = new HashMap<>();
- // 表格行数据循环标签:置于循环行的上一行
- materialMap.put("tables", parts);
- // 其他标签
- materialMap.put("serialNo", useResult.getSerialNo());
- materialMap.put("useDate", useResult.getUseTime());
- materialMap.put("deptName", "测试部门");
- materialMap.put("warehouse", "DJ0001");
- materialMap.put("projectCode", "XM123121");
- materialMap.put("projectName", "项目0001");
- materialMap.put("startTime", "2024-05-06");
- // 插入分页标记,最后一页不用分页
- if (i != page - 1) {
- materialMap.put("isPageBreak", "分页标记");
- }
- // 底部文字(签名)
- String bottomWord = "\n制单人:" +
- useResult.getSponsor() +
- " 发料人:" +
- useResult.getOperator() +
- " 领料人:领料人";
- materialMap.put("bottomWord", Texts.of(bottomWord).create());
- materialMap.put("qrCode", Pictures.ofBufferedImage(qrCodeImage, PictureType.PNG).size(120, 120).create());
- foreachList.add(materialMap);
- }
-
- //渲染表格:将插件应用到表格标签
- LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
- Configure config = Configure.builder().bind("tables", policy).build();
- XWPFTemplate template = XWPFTemplate.compile(inputStream, config).render(resMap);
- // 替换分页标记为分页符
- List<XWPFParagraph> paragraphs = template.getXWPFDocument().getParagraphs();
- for (XWPFParagraph p : paragraphs) {
- List<XWPFRun> runs = p.getRuns();
- if (runs != null) {
- for (XWPFRun r : runs) {
- String text = r.getText(0);
- if (text != null && text.contains("分页标记")) {
- text = text.replace("分页标记", "");
- r.setText(text, 0);
- r.addBreak(BreakType.PAGE);
- }
- }
- }
- }
-
- // 1将文档写入到输出流
- // FileOutputStream outStream = new FileOutputStream("D:\\opt\\mes\\领料单.docx");
- // template.write(outStream);
- // 2将文档作为响应返回
- // response.setHeader("Content-Disposition", "attachment; filename=exported-word.docx");
- // response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
- // OutputStream outStream = new BufferedOutputStream(response.getOutputStream());
- // template.write(outStream);
-
- // 将word转为输出流
- ByteArrayOutputStream outStream = new ByteArrayOutputStream();
- template.write(outStream);
- template.close();
- // 3将输出流转为 multipartFile 并上传
- MockMultipartFile multipartFile = new MockMultipartFile("file", useResult.getSerialNo() + "领料单" + System.currentTimeMillis() + ".docx", null, outStream.toByteArray());
- outStream.close();
- R<SysFile> upload = fileService.upload(multipartFile, 1);
- return upload.getData();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
将模板放入resource目录下,无法读取,maven打包时,报错MalformedInputException。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。