java方法替换word文档中需要替换的部分操作步骤
1.提供一个word文档,java方法替换需要替换的内容
测试文档:
测试文档HWPFDocument.doc;测试文档XWPFDocument.docx
文档内容:
替换后的文档内容:
1.1概述
处理 .doc 文件,使用POI依赖的HWPFDocument类和相关的类Range和Paragraph来处理;
处理 .docx 文件,使用POI依赖的XWPFParagraph类和XWPFRun的结构化方法来逐段处理文档。
1.2操作步骤
1.2.1引入依赖
本项目使用的aliyun的镜像库,处理word文档引入的是POI依赖,这是一套可以兼容处理doc和docx文件的依赖版本。
<!-- Apache POI dependencies --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.xmlbeans</groupId> <artifactId>xmlbeans</artifactId> <version>3.1.0</version> </dependency> <!-- Apache POI dependencies for OOXML (.docx) --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>4.1.2</version> </dependency> <!-- Apache POI dependencies for OLE2 (.doc) --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-scratchpad</artifactId> <version>4.1.2</version> </dependency>
我这里是引入poi-scratchpad
之后不兼容,报错:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.NoSuchFieldError: Factory] with root cause
就是因为引入poi-scratchpad
之后,导致Apache POI 相关的库版本不一致导致,供参考。
1.2.2创建具体业务方法
这里没有创建service层,直接在controller层实现方法
@RestController @RequestMapping("/word") public class DocumentWordController { @PostMapping("/uploadAndReplaceWord") public String uploadAndReplace(@RequestParam("file") MultipartFile file, @RequestParam Map<String, String> replacements) { // MultipartFile 接口的方法之一,返回上传文件的内容类型(MIME 类型) String contentType = file.getContentType(); // 保存修改后的文档 String outputPath = "C:\\*****\\*****\\*****\\result"; try { if (contentType != null && contentType.equals("application/msword")) { // 处理 .doc 文件 HWPFDocument document = new HWPFDocument(file.getInputStream()); replacePlaceholdersInDoc(document, replacements); outputPath += ".doc"; try (FileOutputStream out = new FileOutputStream(outputPath)) { document.write(out); } } else if (contentType != null && contentType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document")) { // 处理 .docx 文件 XWPFDocument document = new XWPFDocument(file.getInputStream()); replacePlaceholdersInDocx(document, replacements); outputPath += ".docx"; try (FileOutputStream out = new FileOutputStream(outputPath)) { document.write(out); } } else { return "文件类型不支持:" + contentType; } return "文档处理完成,保存至:" + outputPath; } catch (IOException e) { e.printStackTrace(); return "文档处理失败"; } } // 处理 .doc 文件 // HWPFDocument类没有与XWPFParagraph和XWPFRun类似的结构化方法来逐段处理文档 // 所以需要使用HWPFDocument和相关的类Range和Paragraph来处理 private void replacePlaceholdersInDoc(HWPFDocument document, Map<String, String> replacements) { // Range对象表示Word文档中的一段文本范围 // document.getRange()方法返回整个文档的范围,包括所有段落、表格、标题等内容 Range range = document.getRange(); // 遍历替换映射中的每个键值对,并将文本块中的占位符替换为指定的值,entry.getKey() 是占位符(如${name}) for (Map.Entry<String, String> entry : replacements.entrySet()) { // 替换范围内的文本:在整个文本内找到所有匹配entry.getKey()的文本,并用entry.getValue()替换它们 range.replaceText(entry.getKey(), entry.getValue()); } } // 处理 .docx 文件 private void replacePlaceholdersInDocx(XWPFDocument document, Map<String, String> replacements) { // 对文档所有的段落做遍历 for (XWPFParagraph paragraph : document.getParagraphs()) { // 获取段落中的文本块 // 每个段落 (XWPFParagraph) 由一个或多个文本块 (XWPFRun) 组成,文本块是段落中的最小文本单位,可以包含格式化信息(如字体、颜色)。 List<XWPFRun> runs = paragraph.getRuns(); // 若包含文本块,对其做处理 if (runs != null) { for (XWPFRun run : runs) { // 获取文本块中的文本内容,参数0表示获取文本块中的第一段文本(注:通常只有一段文本) String text = run.getText(0); if (text != null) { // 创建StringBuilder处理字符串替换操作,提高性能,减少 String 对象的创建和销毁 StringBuilder textBuilder = new StringBuilder(text); // 遍历替换映射中的每个键值对,并将文本块中的占位符替换为指定的值,entry.getKey() 是占位符(如${name}) // 使用 StringBuilder 的 indexOf 方法找到占位符的位置,并使用 replace 方法进行替换 // 循环确保所有出现的占位符都被替换 for (Map.Entry<String, String> entry : replacements.entrySet()) { int index = textBuilder.indexOf(entry.getKey()); while (index != -1) { // replace 方法的参数分别是开始索引、结束索引和替换内容 textBuilder.replace(index, index + entry.getKey().length(), entry.getValue()); // 将其移动到刚替换的文本的末尾 index += entry.getValue().length(); // 从当前索引 index 开始继续查找下一个占位符,若找到下一个占位符,更新 index 为新位置 // 若找不到,index 将为 -1,循环结束 index = textBuilder.indexOf(entry.getKey(), index); } } // 将替换后的文本重新设置到文本块中 run.setText(textBuilder.toString(), 0); } } } } } }
1.3测试
使用postMan测试接口
1.4扩展
可以将文档上传到数据库中,每次生成的时候先获取文档,再对文档做处理;
这里是将文档生成到指定位置,若是要在浏览器中生成-下载到具体位置,可利用
HttpServletResponse
类,将其写入HttpServletResponse
的输出流,然后设置适当的响应头,使浏览器将响应内容作为文件下载@GetMapping("/download") public void downloadDocument(HttpServletResponse response) { // 创建一个新的 XWPFDocument 对象 XWPFDocument document = new XWPFDocument(); //具体业务处理方法 ...... try { // .doc格式文档,设置响应内容类型为 Word 文档 response.setContentType("application/msword"); // .doc格式文档,设置响应头,指示浏览器将响应内容作为文件下载 response.setHeader("Content-Disposition", "attachment; filename=sample.doc"); // .docx格式文档,设置响应内容类型为 Word 文档 response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); // .docx格式文档,设置响应头,指示浏览器将响应内容作为文件下载 response.setHeader("Content-Disposition", "attachment; filename=sample.docx"); // 将文档写入响应的输出流 document.write(response.getOutputStream()); // 刷新和关闭输出流 response.getOutputStream().flush(); response.getOutputStream().close(); } catch (IOException e) { e.printStackTrace(); } }
总结
到此这篇关于java方法替换word文档中需要替换的部分的文章就介绍到这了,更多相关java替换word文档部分内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
解决spring.thymeleaf.cache=false不起作用的问题
这篇文章主要介绍了解决spring.thymeleaf.cache=false不起作用的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2022-06-06
最新评论