替换.docx(Apache POI,Docx4j或其他)中的文本模板

我想使用正则表达式(java RegEx)在MS Word.docx )文档中进行替换:

Example: …, с одной стороны, и %SOME_TEXT% именуемое в дальнейшем «Заказчик», в лице %SOME_TEXT% действующего на основании %SOME_TEXT% с другой стороны, заключили настоящий Договор о нижеследующем: … 

我试图让文本模板(比如%SOME_TEXT% )使用Apache POI – XWPF并替换文本,但不能保证替换,因为POI分离了runs =>我得到这样的东西( System.out.println(run.getText(0)) ):

 … , с одной стороны, и % SOME_TEXT % именуемое в дальнейшем «Заказчик», в лице % SOME _ TEXT % 

代码示例:

 FileInputStream fis = new FileInputStream(new File("document.docx")); XWPFDocument document = new XWPFDocument(fis); List paragraphs = document.getParagraphs(); paragraphs.forEach(para -> { para.getRuns().forEach(run -> { String text = run.getText(0); if (text != null) { System.out.println(text); // text replacement process // run.setText(newText,0); } }); }); 

我发现了许多类似的问题(比如“ 替换Apache POI XWPF中的文本 ”),但没有找到我的问题的答案(回答这里“ Apache POI XWPFRun对象中的分隔文本行 ”提供了不方便的解决方案)。

我试图使用docx4j和这个例子=>“ docx4j find and replace ”,但docx4j的工作方式类似。

对于docx4j,请参阅stackoverflow.com/questions/17093781 / … – JasonPlutext

我尝试使用docx4j => documentPart.variableReplace(mappings); ,但不保证更换( plutext / docx4j )。

你使用VariablePrepare了吗? stackoverflow.com/a/17143488/1031689 – JasonPlutext

是的,没有结果:

 WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new File("test.docx")); HashMap mappings = new HashMap(); VariablePrepare.prepare(wordMLPackage);//see notes mappings.put("SOME_TEXT", "XXXX"); wordMLPackage.getMainDocumentPart().variableReplace(mappings); wordMLPackage.save(new File("out.docx")); 

输入\输出文本:

 Input: …, с одной стороны, и ${SOME_TEXT} именуемое в дальнейшем «Заказчик» ... Output: …, с одной стороны, и SOME_TEXT именуемое в дальнейшем «Заказчик» ... 

要在VariablePrepare之后查看运行,请打开VariablePrepare的INFO级别日志记录,或者只打开System.out.println(wordMLPackage.getMainDocumentPart().getXML())

我理解模板被分成不同的运行 ,但主题的主要问题,如何不将模板分离到不同的运行 。 我使用System.out.println(wordMLPackage.getMainDocumentPart().getXML())并看到:

  , с одной стороны, и   $ {       SOME        _         TEXT        }  

,该模板位于不同的xml标签中,我不明白为什么…

请帮我找到方便的方法来替换文字…..

如您所见,“使用正则表达式(Java RegEx)在MS Word(.docx)文档中进行替换”的方法并不是很好,因为您永远无法确定要替换的文本将在一个文本运行中一起使用。 更好的方法是在Word中使用字段(合并字段或表单字段)或内容控件。

我对这些要求的最爱仍然是Word很好的旧表单字段。

第一个优点是,即使没有文档保护,也不可能将表单字段内容的部分格式化为不同,因此将表单字段内容分成不同的运行(但请参见注释1)。 第二个优点是,由于灰色背景,表单字段在文档内容中很好地可见。 另一个优点是应用文档保护的可能性,即使在Word的GUI中也只能填写表单字段。 这对于保留这些合同文件免于不必要的变更非常有用。

(注1):至少Word阻止格式化表单字段内容的不同部分,从而将表单字段内容撕成不同的运行。 其他文字处理软件(例如Writer )可能不尊重此限制。

所以我会像这样使用Word模板:

在此处输入图像描述

灰色字段是Word文本Textfields ,名为Text1Text2Text3Textfields块看起来像:

                   

然后是以下代码:

 import java.io.FileOutputStream; import java.io.FileInputStream; import org.apache.poi.xwpf.usermodel.*; import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.SimpleValue; import javax.xml.namespace.QName; public class WordReplaceTextInFormFields { private static void replaceFormFieldText(XWPFDocument document, String ffname, String text) { boolean foundformfield = false; for (XWPFParagraph paragraph : document.getParagraphs()) { for (XWPFRun run : paragraph.getRuns()) { XmlCursor cursor = run.getCTR().newCursor(); cursor.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//w:fldChar/@w:fldCharType"); while(cursor.hasNextSelection()) { cursor.toNextSelection(); XmlObject obj = cursor.getObject(); if ("begin".equals(((SimpleValue)obj).getStringValue())) { cursor.toParent(); obj = cursor.getObject(); obj = obj.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//w:ffData/w:name/@w:val")[0]; if (ffname.equals(((SimpleValue)obj).getStringValue())) { foundformfield = true; } else { foundformfield = false; } } else if ("end".equals(((SimpleValue)obj).getStringValue())) { if (foundformfield) return; foundformfield = false; } } if (foundformfield && run.getCTR().getTList().size() > 0) { run.getCTR().getTList().get(0).setStringValue(text); //System.out.println(run.getCTR()); } } } } public static void main(String[] args) throws Exception { XWPFDocument document = new XWPFDocument(new FileInputStream("WordTemplate.docx")); replaceFormFieldText(document, "Text1", "Моя Компания"); replaceFormFieldText(document, "Text2", "Аксель Джоачимович Рихтер"); replaceFormFieldText(document, "Text3", "Доверенность"); document.write(new FileOutputStream("WordReplaceTextInFormFields.docx")); document.close(); } } 

这段代码需要FAQ-N10025中提到的所有模式ooxml-schemas-1.3.jar的完整jar。

生产:

在此处输入图像描述