【问题标题】:Replacing content in a word template document with java using POI使用POI用java替换word模板文档中的内容
【发布时间】:2019-02-08 11:08:34
【问题描述】:

我需要打开一个 .dotx 文档,修改内容(或类似内容)并放入我自己的数据,然后返回生成的 .docx/document。

以dotx文件为例,在生成的docx文件中,字符串“name”应替换为“John”。

public static void main( String[] args ) throws IOException
{
    String inputFile="D:/Copies 2.dotx";
//  String outputeFile="D:/test.txt";
    String outputeFile="D:/test.docx";
    File inFile=new File(inputFile);
    File ouFile=new File(outputeFile);
    Map<String,String> hm = new HashMap<String,String>();
    hm.put("Namur","Youssef");
    App a = new App();
    a.changeData(inFile,ouFile, hm);    
}
private void changeData(File targetFile,File out, Map<String,String> substitutionData) throws IOException{
    BufferedReader br = null;
    String docxTemplate = "";
    try {
        br = new BufferedReader(new InputStreamReader(new FileInputStream(targetFile)));
        String temp;
        while( (temp = br.readLine()) != null) {
            docxTemplate = docxTemplate + temp;   
        }
        br.close();
    } 
    catch (IOException e) {
        br.close();
        throw e;
    }

    Iterator<Entry<String, String>> substitutionDataIterator = substitutionData.entrySet().iterator();
    while(substitutionDataIterator.hasNext()){
        Map.Entry<String,String> pair = (Map.Entry<String,String>)substitutionDataIterator.next();
        if(docxTemplate.contains(pair.getKey())){
            if(pair.getValue() != null)
                docxTemplate = docxTemplate.replace(pair.getKey(), pair.getValue());
            else
                docxTemplate = docxTemplate.replace(pair.getKey(), "NEDOSTAJE");
        }
    }

    FileOutputStream fos = null;
    try{
        fos = new FileOutputStream(out);
        fos.write(docxTemplate.getBytes());
        fos.close();
    }
    catch (IOException e) {
        fos.close();
        throw e;
    }

}

有人可以给我一些建议吗?

Ps:我使用的是 apach POI 3.16

【问题讨论】:

  • 您认为您在当前代码中使用了哪些apache poi 类?
  • 是的,确实在这段代码中我没有使用 apache POI,它运行和编译正确但是当我尝试打开它时输出文件给我这个错误“我们很抱歉我们无法打开你的test1 因为我们发现内容有问题”,我想知道是否有办法使用 POI 用 java 替换 word 模板文档中的内容。
  • 首先要知道:*.dotx 文件是什么?它只是一个文本文件吗?不,它是 Office Open XML 格式的文件,它是一个 ZIP 存档,包含一个特殊的目录结构,其中存储了不同的其他文件(主要是 XML 文件)。所以你不能像文本文件那样简单地处理它。这就是 apache poi 的用途。
  • 第二件要知道的事:*.dotx*.docx 文件有什么区别?主要是内容类型。因此,在读取 *.dotx 然后保存 *.docx 时,您还需要更改文件中的内容类型设置。见stackoverflow.com/questions/54377200/…
  • @AxelRichter 非常感谢,我认为你是对的我应该先转换它!

标签: java apache-poi docx


【解决方案1】:

因为解析 dotx/docx 文件并不简单 我们让 apache poi 付出了一些努力,比如

XWPFDocument doc = new XWPFDocument(OPCPackage.open("-you docx/dotx file-path-"));

使用它,您可以加载现有文件。 现在解析文件 你得到

XWPFParagraph
XWPFTable

你可以像这样解析两者

for (XWPFParagraph p : doc.getParagraphs()) {
                List<XWPFRun> runs = p.getRuns();
                if (runs != null) {
                    for (XWPFRun r : runs) {
                        String text = r.getText(0);
                        if (text != null && text.contains("$$key$$")) {
                            text = text.replace("<asdas>", "ABCD");// your content
                            r.setText(text, 0);
                        }
                    }
                }
            }

对表格进行解析

for (XWPFTable tbl : doc.getTables()) {
                for (XWPFTableRow row : tbl.getRows()) {
                    for (XWPFTableCell cell : row.getTableCells()) {
                        for (XWPFParagraph p : cell.getParagraphs()) {
                            for (XWPFRun r : p.getRuns()) {
                                String text = r.getText(0);
                                if (text != null && text.contains("$$key$$")) {
                                    text = text.replace("<asdas>", "abcd");
                                    r.setText(text, 0);
                                }
                            }
                        }
                    }
                }
            }

现在将解析后的文件写入你得到的目标

doc.write(new FileOutputStream("-taget-path-"));

这需要 apache POI 的所有依赖项 喜欢

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>

您需要在构建路径中添加更多内容,检查您的异常并添加。

您可以使用此链接并探索更多

http://poi.apache.org/apidocs/dev/org/apache/poi/xwpf/usermodel/XWPFRun.html#setText%28java.lang.String%29

【讨论】:

  • 我刚刚尝试了这段代码,但是当我打开输出文件时出现此错误“我们很抱歉我们无法打开您的 test1,因为我们发现内容有问题”
  • 先检查文件内容,然后检查你写的内容,你应该阅读 docx/dotx 并将其写为 docx
  • @Kishan C S:如果不更改 [Content_Types].xml,您将无法读取 *.dotx 并将其写为 *.docxLibreofficeOpenOffice Writer 将容忍错误的内容类型,但 Microsoft Word 不会。
  • 然后他必须通过打开文件来更新 content.xml。谢谢 Axel Richter
  • 是的,我应该先检查文件内容,谢谢@KishanCS。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-04
  • 1970-01-01
  • 2015-01-31
  • 1970-01-01
相关资源
最近更新 更多