如何使用 Apache POI 查找/替换 .docx 文件中的占位符?

Col*_*ole 4 java docx apache-poi

我有一个文件“template.docx”,我希望有占位符(即[序列号]),可以用字符串或表格替换。我正在使用 Apache POI,但我不能使用 docx4j。

有没有办法让程序迭代所有出现的“[序列号]”并将它们替换为字符串?其中许多标签将位于一个大表中,那么 Apache POI 是否有一些与在 Word 中按 ctrl+f 并使用全部替换相同的命令?

任何建议将不胜感激,谢谢

ɢʜʘ*_*ɔʘɴ 6

XWPFDocument (docx)有不同类型的子元素,如XWPFParagraphs、XWPFTablesXWPFNumbering等。

一旦你XWPFDocument通过以下方式创建对象:

document = new XWPFDocument(inputStream);
Run Code Online (Sandbox Code Playgroud)

您可以迭代所有段落:

document.getParagraphsIterator();
Run Code Online (Sandbox Code Playgroud)

当您迭代段落时,对于每个段落,您将获得多个XWPFRuns,它们是具有相同样式的多个文本块,有时相同样式的文本块将被拆分为多个XWPFRuns,在这种情况下,您应该研究这个问题以避免拆分您的运行,这样做将有助于识别您的占位符,而无需在同一段落中合并多个运行。此时,您应该期望您的 placeHolder 不会在多次运行中拆分,如果是这种情况,那么您可以继续迭代每个段落的“XWPFRun”,并查找与您的 placeHolder 匹配的文本,如下所示会有所帮助:

XWPFParagraph para = (XWPFParagraph) xwpfParagraphElement;
for (XWPFRun run : para.getRuns()) {
    if (run.getText(0) != null) {
        String text = run.getText(0);
        Matcher expressionMatcher = expression.matcher(text);
        if (expressionMatcher.find() && expressionMatcher.groupCount() > 0) {
            System.out.println("Expression Found...");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

匹配器在哪里expressionMatcher基于特定占位符的正则表达式。尝试使用正则表达式来匹配占位符之前和之后的可选内容,例如\([]*)(PlaceHolderGroup)([]*)^,相信我,它效果最好。

一旦您找到了您感兴趣的正确XWPFRun提取文本并创建了一个应该足够简单的替换文本,那么您应该在此特定运行中用以前的文本替换新文本:

run.setText(text, 0);
Run Code Online (Sandbox Code Playgroud)

如果您要将整个内容替换XWPFRun为全新的内容XWPFRun,或者在拥有此运行的段落之后插入一个新的段落/表格,您可能会遇到一些问题,例如 A。ConcurrentModificationException这意味着您无法修改此列表(XWPFRuns)您正在迭代并 B. 找到要插入的新位置Element。要解决这些问题,您应该有一个可以保存 paras 的List<XWPFParagraph>of XWPFParagarph,然后在其后插入新元素。一旦你有了替换列表,你就可以对其进行迭代,对于每个替换段落,你只需获取一个光标并在该光标处插入新元素:

for (XWPFParagraph para: paras) {
    XmlCursor cursor = (XmlCursor) para.getCTP().newCursor();
    XWPFTable newTable = para.getBody().insertNewTbl(cursor);
    //Generate your XWPF table based on what's inside para with your own logic
}
Run Code Online (Sandbox Code Playgroud)

要创建一个XWPFTable,请阅读此内容

希望这对某人有帮助。

  • 快速说明 - 如果您有文件,请使用它!不要将其转换为流来提供给 POI,这会导致更高的内存使用量。有关详细信息,请参阅[这部分文档](http://poi.apache.org/spreadsheet/quick-guide.html#FileInputStream) (3认同)