如何使用Java编辑MS Word文档?

我有几个Word模板,我的要求是使用Java基于用户输入替换文档中的一些单词/占位符。 我尝试了很多库,包括2-3个版本的docx4j但没有什么工作,他们都没有做任何事情!

我知道之前已经问过这个问题,但我尝试了所有我知道的选项。 那么,使用什么java库我可以“真正”替换/编辑这些模板? 我倾向于使用“易于使用/几行代码”类型库。

我正在使用Java 8,我的MS Word模板在MS Word 2007中。

更新

此代码是使用SO成员Joop Eggen提供的代码示例编写的

 public Main() throws URISyntaxException, IOException, ParserConfigurationException, SAXException { URI docxUri = new URI("C:/Users/Yohan/Desktop/yohan.docx"); Map zipProperties = new HashMap(); zipProperties.put("encoding", "UTF-8"); FileSystem zipFS = FileSystems.newFileSystem(docxUri, zipProperties); Path documentXmlPath = zipFS.getPath("/word/document.xml"); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(Files.newInputStream(documentXmlPath)); byte[] content = Files.readAllBytes(documentXmlPath); String xml = new String(content, StandardCharsets.UTF_8); //xml = xml.replace("#DATE#", "2014-09-24"); xml = xml.replace("#NAME#", StringEscapeUtils.escapeXml("Sniper")); content = xml.getBytes(StandardCharsets.UTF_8); Files.write(documentXmlPath, content); } 

但是,这会返回以下错误

 java.nio.file.ProviderNotFoundException: Provider "C" Not found at: java.nio.file.FileSystems.newFileSystem(FileSystems.java:341) at java.nio.file.FileSystems.newFileSystem(FileSystems.java:341) at java.nio.fileFileSystems.newFileSystem(FileSystems.java:276) 

可以使用docx(带有XML和其他文件的zip)java zip文件系统和XML或文本处理。

 URI docxUri = ,,, // "jar:file:/C:/... .docx" Map zipProperties = new HashMap<>(); zipProperties.put("encoding", "UTF-8"); try (FileSystem zipFS = FileSystems.newFileSystem(docxUri, zipProperties)) { Path documentXmlPath = zipFS.getPath("/word/document.xml"); 

使用XML时:

  DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(Files.newInputStream(documentXmlPath)); //Element root = doc.getDocumentElement(); 

然后,您可以使用XPath查找位置,然后再次写入XML。

它甚至可能是您不需要XML但可以替换占位符:

  byte[] content = Files.readAllBytes(documentXmlPath); String xml = new String(content, StandardCharsets.UTF_8); xml = xml.replace("#DATE#", "2014-09-24"); xml = xml.replace("#NAME#", StringEscapeUtils.escapeXml("Sniper"))); ... content = xml.getBytes(StandardCharsets.UTF_8); Files.delete(documentXmlPath); Files.write(documentXmlPath, content); 

要进行快速开发,请将.docx的副本重命名为具有.zip文件扩展名的名称,并检查文件。

File.write应该已经应用了StandardOpenOption.TRUNCATE_EXISTING,但是我添加了Files.delete因为发生了一些错误。 看评论。

试试Apache POI 。 POI可以与docdocx ,但docx更具记录性,因此更好地支持它。

UPD :您可以使用使用POI的XDocReport 。 此外,我建议使用xlsx作为模板,因为它更合适, 更有文档记录

我花了几天时间讨论这个问题,直到我发现产生差异的是FileSystem实例上的try-with-resources ,出现在Joop Eggen的代码片段中,但没有问题片段:
try (FileSystem zipFS = FileSystems.newFileSystem(docxUri, zipProperties))
如果没有这样的try-with-resources块, FileSystem资源将不会被关闭(如Java教程中所述 ),并且word文档未被修改。

稍微退一步,有大约4种不同的方法来编辑单词/占位符:

  • MERGEFIELD或DOCPROPERTY字段(如果您在docx4j中遇到此问题,那么您可能没有正确设置输入docx)
  • 内容控制数据绑定
  • 文档表面上的变量替换(在DOM / SAX级别,或使用库)
  • 做XHTML的东西,然后导入它

在选择之前,您应该决定是否还需要能够处理:

  • 重复数据(例如添加表格行)
  • 条件内容(例如,将出现或不存在的整个段落)
  • 添加图像

如果您需要这些,那么MERGEFIELD或DOCPROPERTY字段可能已经输出(尽管您也可以使用IF字段,如果您可以找到支持它们的库)。 并且添加图像使得DOM / SAX操作在其他一个答案中被提倡,更容易混乱和容易出错。

其他需要考虑的事项是:

  • 你的作者:他们有多技术? 这对创作UI意味着什么?
  • 您提到的用于变量替换的“用户输入”是给定的,还是获得它正在解决的问题的一部分?