SpringBoot-Poi-Word

x33g5p2x  于2021-09-22 转载在 Spring  
字(9.1k)|赞(0)|评价(0)|浏览(462)

SpringBoot-Poi-Word

不多解释看代码就明白了

  1. 先准备一个word模板 doc 和docx都行
  2. 给模板空值添加占位符
  3. 使用poi给占位置赋值

Maven

  1. <dependency>
  2. <groupId>org.apache.poi</groupId>
  3. <artifactId>poi-ooxml-schemas</artifactId>
  4. <version>4.0.1</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.apache.poi</groupId>
  8. <artifactId>poi-scratchpad</artifactId>
  9. <version>4.0.1</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.apache.poi</groupId>
  13. <artifactId>poi-ooxml</artifactId>
  14. <version>4.0.1</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.apache.poi</groupId>
  18. <artifactId>poi-examples</artifactId>
  19. <version>4.0.1</version>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.apache.poi</groupId>
  23. <artifactId>poi-excelant</artifactId>
  24. <version>4.0.1</version>
  25. </dependency>
  26. <dependency>
  27. <groupId>org.apache.poi</groupId>
  28. <artifactId>poi</artifactId>
  29. <version>4.0.1</version>
  30. </dependency>
  31. <dependency>
  32. <groupId>org.apache.xmlbeans</groupId>
  33. <artifactId>xmlbeans</artifactId>
  34. <version>3.0.2</version>
  35. </dependency>
  36. <dependency>
  37. <groupId>org.apache.poi</groupId>
  38. <artifactId>ooxml-schemas</artifactId>
  39. <version>1.1</version>
  40. <type>pom</type>
  41. </dependency>
  42. <dependency>
  43. <groupId>commons-beanutils</groupId>
  44. <artifactId>commons-beanutils</artifactId>
  45. <version>1.9.3</version>
  46. </dependency>

准备word模板

因为是演示所以准备两份 为了演示 doc 和docx都支持

文件内容如下:

${} 就是占位符 { } 内的是变量用于使用poi时候替换成实际值

将模板放入resources下面

word-poi工具类

  1. package com.word.utils;
  2. import org.apache.poi.hwpf.HWPFDocument;
  3. import org.apache.poi.hwpf.usermodel.Range;
  4. import org.apache.poi.xwpf.usermodel.*;
  5. import java.io.*;
  6. import java.util.*;
  7. import java.util.regex.Matcher;
  8. import java.util.regex.Pattern;
  9. public class WordTemplateParse {
  10. public enum WordType {
  11. doc, docx
  12. }
  13. /** * * @param data 替换的数据 * @param tempFileStream 模板文件 * @param targetFileStream 输出的文件 * @param type 文件;类型 * @return */
  14. public static Boolean generate(Map<String, String> data, String tempFileStream, String targetFileStream, WordType type) throws FileNotFoundException {
  15. try {
  16. InputStream in=new FileInputStream(tempFileStream);
  17. OutputStream outputStream= new FileOutputStream(targetFileStream);
  18. if (WordType.docx.equals(type) ) {
  19. return generate_docx(data, in, outputStream);
  20. } else if (WordType.doc.equals(type)){
  21. return generate_doc(data, in, outputStream);
  22. }
  23. } catch (FileNotFoundException e) {
  24. e.printStackTrace();
  25. }
  26. return false;
  27. }
  28. private static Boolean generate_docx(Map<String, String> data, InputStream tempFileStream, OutputStream targetFileStream) {
  29. try {
  30. // 加载磁盘的 temp.docx 文件
  31. XWPFDocument document = new XWPFDocument(tempFileStream);
  32. // 解析文档中的【段落】的插值 ${..}
  33. List<XWPFParagraph> paragraphs = document.getParagraphs();
  34. for (XWPFParagraph paragraph : paragraphs) {
  35. String text = paragraph.getText();
  36. // 如果该单元格为空就遍历下一个
  37. if (text == null || "".equals(text)) {
  38. continue;
  39. }
  40. // 得到解析 ${...} 后的内容
  41. String newText = replaceByMap(text, null, data);
  42. // 判断值是否改变,如果没有改变就不做处理
  43. if (!text.equals(newText)) {
  44. int runSize = paragraph.getRuns().size();
  45. // 清空该段落所有值
  46. for (int i = 0; i < runSize; i++) {
  47. paragraph.removeRun(i);
  48. }
  49. XWPFRun run = paragraph.createRun();
  50. run.setText(newText);
  51. }
  52. }
  53. // 解析文档中【表格】的插值 ${..}
  54. // 获取文档中的表格
  55. List<XWPFTable> tables = document.getTables();
  56. for (XWPFTable table : tables) {
  57. // 得到所有行的集合并遍历
  58. List<XWPFTableRow> rows = table.getRows();
  59. for (XWPFTableRow row : rows) {
  60. // 得到所有列的集合并遍历
  61. List<XWPFTableCell> cells = row.getTableCells();
  62. for (XWPFTableCell cell : cells) {
  63. // 获取整个单元格的值
  64. String text = cell.getText();
  65. // 如果该单元格为空就遍历下一个
  66. if (text == null || "".equals(text)) {
  67. continue;
  68. }
  69. // 得到解析 ${...} 后的内容
  70. String newText = replaceByMap(text, null, data);
  71. // 判断值是否改变,如果没有改变就不做处理
  72. if (!text.equals(newText)) {
  73. // 清空单元格内容
  74. int paragraphsNums = cell.getParagraphs().size();
  75. for (int i = 0; i < paragraphsNums; i++) {
  76. cell.removeParagraph(i);
  77. }
  78. cell.setText(newText);
  79. }
  80. }
  81. }
  82. }
  83. // 将文档写入目标文件中
  84. document.write(targetFileStream);
  85. // 关闭流
  86. tempFileStream.close();
  87. targetFileStream.close();
  88. document.close();
  89. return true;
  90. } catch (Exception e) {
  91. e.printStackTrace();
  92. return false;
  93. }
  94. }
  95. private static Boolean generate_doc(Map<String, String> data, InputStream tempFileStream, OutputStream targetFileStream) {
  96. try {
  97. // 加载磁盘的 temp.docx 文件
  98. HWPFDocument document = new HWPFDocument(tempFileStream);
  99. Range range = document.getRange();
  100. //把range范围内的${reportDate}替换为当前的日期
  101. for (Map.Entry<String, String> stringStringEntry : data.entrySet()) {
  102. range.replaceText("${" + stringStringEntry.getKey() + "}", stringStringEntry.getValue());
  103. }
  104. //把doc输出到输出流中
  105. document.write(targetFileStream);
  106. targetFileStream.close();
  107. tempFileStream.close();
  108. document.close();
  109. return true;
  110. } catch (IOException e) {
  111. e.printStackTrace();
  112. }
  113. return false;
  114. }
  115. // 如果根据正则表达式规则匹配成功则替换,否则返回原值
  116. private static String replaceByMap(String content, String regex, Map<String, String> map) {
  117. // 匹配插值 ${...}
  118. if (regex == null) {
  119. regex = "\\$\\{[\\w\\W]+\\}";
  120. }
  121. // 初始化正则
  122. Pattern p = Pattern.compile(regex);
  123. Matcher matcher = p.matcher(content);
  124. // 找到匹配的内容的 key
  125. if (matcher.find()) {
  126. // 提前key值
  127. String matchContent = matcher.group(0);
  128. int start = matchContent.indexOf("{");
  129. int end = matchContent.indexOf("}");
  130. // 获取key
  131. String key = matchContent.substring(start + 1, end);
  132. // 从map中取出key的值
  133. String value = map.get(key);
  134. if (value == null) {
  135. return content;
  136. }
  137. // 得到替换后的值
  138. String newContent = matcher.replaceAll(value);
  139. return newContent;
  140. }
  141. // 没有匹配到,返回原值
  142. return content;
  143. }
  144. }

获取resources的路径工具类

  1. package com.word.utils;
  2. import org.springframework.util.ResourceUtils;
  3. import java.io.File;
  4. import java.io.FileNotFoundException;
  5. /** * @Description: 项目静态资源文件工具类 * 仅可用于包含在web项目中的资源文件路径,资源文件必须放置于 web 模块下 * @Author: junqiang.lu * @Date: 2019/1/4 */
  6. public class ResourceFileUtil {
  7. /** * 获取资源绝对路径 (就只使用这个 ) * * @param relativePath 资源文件相对路径(相对于 resources路径,路径 + 文件名) * eg: "templates/pdf_export_demo.ftl" * @return * @throws FileNotFoundException */
  8. public static String getAbsolutePath(String relativePath) throws FileNotFoundException {
  9. return getFile(relativePath).getAbsolutePath();
  10. }
  11. /** * 获取资源文件 * * @param relativePath 资源文件相对路径(相对于 resources路径,路径 + 文件名) * eg: "templates/pdf_export_demo.ftl" * @return * @throws FileNotFoundException */
  12. public static File getFile(String relativePath) throws FileNotFoundException {
  13. if (relativePath == null || relativePath.length() == 0) {
  14. return null;
  15. }
  16. if (relativePath.startsWith("/")) {
  17. relativePath = relativePath.substring(1);
  18. }
  19. File file = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX
  20. + relativePath);
  21. return file;
  22. }
  23. /** * 获取资源父级目录 * * @param relativePath 资源文件相对路径(相对于 resources路径,路径 + 文件名) * eg: "templates/pdf_export_demo.ftl" * @return * @throws FileNotFoundException */
  24. public static String getParent(String relativePath) throws FileNotFoundException {
  25. return getFile(relativePath).getParent();
  26. }
  27. /** * 获取资源文件名 * * @param relativePath 资源文件相对路径(相对于 resources路径,路径 + 文件名) * eg: "templates/pdf_export_demo.ftl" * @return * @throws FileNotFoundException */
  28. public static String getFileName(String relativePath) throws FileNotFoundException {
  29. return getFile(relativePath).getName();
  30. }
  31. }

测试

  1. package com.word.utils;
  2. import org.junit.Test;
  3. import java.io.*;
  4. import java.util.HashMap;
  5. import java.util.Map;
  6. import java.util.TreeMap;
  7. public class WordTemplateParseText {
  8. @Test
  9. public void test01() throws FileNotFoundException {
  10. // 数据
  11. TreeMap<String, String> data = new TreeMap<String, String>();
  12. data.put("yue1", "33");
  13. data.put("yue2", "22");
  14. data.put("yue3", "55");
  15. data.put("yue4", "12");
  16. data.put("yue5", "2");
  17. data.put("yue6", "151");
  18. data.put("yue7", "33");
  19. data.put("yue8", "34");
  20. data.put("yue9", "123");
  21. data.put("yue10", "15");
  22. data.put("yue11", "2");
  23. data.put("yue12", "10");
  24. // 加载模型【模型】
  25. String absolutePath = ResourceFileUtil.getAbsolutePath("temp.docx"); //模板位置
  26. // 输出位置【输出】 生成新的word位置和模板在一个目录下
  27. String newabsolutePath = ResourceFileUtil.getParent("temp.docx")+ File.separator+"new_temp.docx";
  28. System.out.println(newabsolutePath);
  29. Boolean generate = WordTemplateParse.generate(data, absolutePath, newabsolutePath, WordTemplateParse.WordType.docx);
  30. System.out.println(generate);
  31. }
  32. @Test
  33. public void test011() throws IOException {
  34. // 数据
  35. TreeMap<String, String> data = new TreeMap<String, String>();
  36. data.put("yue1", "33");
  37. data.put("yue2", "22");
  38. data.put("yue3", "55");
  39. data.put("yue4", "12");
  40. data.put("yue5", "2");
  41. data.put("yue6", "151");
  42. data.put("yue7", "33");
  43. data.put("yue8", "34");
  44. data.put("yue9", "123");
  45. data.put("yue10", "15");
  46. data.put("yue11", "2");
  47. data.put("yue12", "10");
  48. // 加载模型【模型】
  49. String absolutePath = ResourceFileUtil.getAbsolutePath("temp1.doc"); //模板位置
  50. // 输出位置【输出】 生成新的word位置和模板在一个目录下
  51. String newabsolutePath = ResourceFileUtil.getParent("temp1.doc")+ File.separator+"new_temp1.doc";
  52. System.out.println(newabsolutePath);
  53. Boolean generate = WordTemplateParse.generate(data, absolutePath, newabsolutePath, WordTemplateParse.WordType.doc);
  54. System.out.println(generate);
  55. }
  56. }

运行上面代码后会在target下面生成对应的word

相关文章