如何使用docx4j在docx文件中追加数据

发布于 2024-11-15 10:52:29 字数 3824 浏览 2 评论 0原文

请告诉我如何使用 java 和 docx4j 在 docx 文件中附加数据。

我正在做的是,我正在使用 docx 格式的模板,其中某些字段在运行时由 java 删除,

我的问题是它为每组数据创建一个新文件,我只想将新文件附加到1 个文件。这不是使用 java 流完成的,

String outputfilepath = "e:\\Practice/DOC/output/generatedLatterOUTPUT.docx";
String outputfilepath1 = "e:\\Practice/DOC/output/generatedLatterOUTPUT1.docx";
WordprocessingMLPackage wordMLPackage;

public void templetsubtitution(String name, String age, String gender, Document document)
        throws Exception {

    // input file name
    String inputfilepath = "e:\\Practice/DOC/profile.docx";
    // out put file name

    // id of Xml file
    String itemId1 = "{A5D3A327-5613-4B97-98A9-FF42A2BA0F74}".toLowerCase();
    String itemId2 = "{A5D3A327-5613-4B97-98A9-FF42A2BA0F74}".toLowerCase();
    String itemId3 = "{A5D3A327-5613-4B97-98A9-FF42A2BA0F74}".toLowerCase();
    // Load the Package

    if (inputfilepath.endsWith(".xml")) {

        JAXBContext jc = Context.jcXmlPackage;
        Unmarshaller u = jc.createUnmarshaller();
        u.setEventHandler(new org.docx4j.jaxb.JaxbValidationEventHandler());

        org.docx4j.xmlPackage.Package wmlPackageEl = (org.docx4j.xmlPackage.Package) ((JAXBElement) u
                .unmarshal(new javax.xml.transform.stream.StreamSource(
                        new FileInputStream(inputfilepath)))).getValue();

        org.docx4j.convert.in.FlatOpcXmlImporter xmlPackage = new org.docx4j.convert.in.FlatOpcXmlImporter(
                wmlPackageEl);

        wordMLPackage = (WordprocessingMLPackage) xmlPackage.get();

    } else {
        wordMLPackage = WordprocessingMLPackage
                .load(new File(inputfilepath));
    }

    CustomXmlDataStoragePart customXmlDataStoragePart = wordMLPackage
            .getCustomXmlDataStorageParts().get(itemId1);
    // Get the contents
    CustomXmlDataStorage customXmlDataStorage = customXmlDataStoragePart
            .getData();
    // Change its contents
    ((CustomXmlDataStorageImpl) customXmlDataStorage).setNodeValueAtXPath(
            "/ns0:orderForm[1]/ns0:record[1]/ns0:name[1]", name,
            "xmlns:ns0='EasyForm'");

    customXmlDataStoragePart = wordMLPackage.getCustomXmlDataStorageParts()
            .get(itemId2);
    // Get the contents
    customXmlDataStorage = customXmlDataStoragePart.getData();
    // Change its contents
    ((CustomXmlDataStorageImpl) customXmlDataStorage).setNodeValueAtXPath(
            "/ns0:orderForm[1]/ns0:record[1]/ns0:age[1]", age,
            "xmlns:ns0='EasyForm'");

    customXmlDataStoragePart = wordMLPackage.getCustomXmlDataStorageParts()
            .get(itemId3);
    // Get the contents
    customXmlDataStorage = customXmlDataStoragePart.getData();
    // Change its contents
    ((CustomXmlDataStorageImpl) customXmlDataStorage).setNodeValueAtXPath(
            "/ns0:orderForm[1]/ns0:record[1]/ns0:gender[1]", gender,
            "xmlns:ns0='EasyForm'");

    // Apply the bindings
    BindingHandler.applyBindings(wordMLPackage.getMainDocumentPart());
    File f = new File(outputfilepath);
    wordMLPackage.save(f);
    FileInputStream fis = new FileInputStream(f);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    byte[] buf = new byte[1024];
    try {
        for (int readNum; (readNum = fis.read(buf)) != -1;) {
            bos.write(buf, 0, readNum);
        }
        // System.out.println( buf.length);

    } catch (IOException ex) {
    }
    byte[] bytes = bos.toByteArray();
    FileOutputStream file = new FileOutputStream(outputfilepath1, true);
    DataOutputStream out = new DataOutputStream(file);
    out.write(bytes);
    out.flush();
    out.close();

    System.out.println("..done");
}

public static void main(String[] args) {
  utility u = new utility();
  u.templetsubtitution("aditya",24,mohan);
}

提前致谢

Please tell me how to append data in docx file using java and docx4j.

What I'm doing is, I am using a template in docx format in which some field are dilled by java at run time,

My problem is for every group of data it creates a new file and i just want to append the new file into 1 file. and this is not done using java streams

String outputfilepath = "e:\\Practice/DOC/output/generatedLatterOUTPUT.docx";
String outputfilepath1 = "e:\\Practice/DOC/output/generatedLatterOUTPUT1.docx";
WordprocessingMLPackage wordMLPackage;

public void templetsubtitution(String name, String age, String gender, Document document)
        throws Exception {

    // input file name
    String inputfilepath = "e:\\Practice/DOC/profile.docx";
    // out put file name

    // id of Xml file
    String itemId1 = "{A5D3A327-5613-4B97-98A9-FF42A2BA0F74}".toLowerCase();
    String itemId2 = "{A5D3A327-5613-4B97-98A9-FF42A2BA0F74}".toLowerCase();
    String itemId3 = "{A5D3A327-5613-4B97-98A9-FF42A2BA0F74}".toLowerCase();
    // Load the Package

    if (inputfilepath.endsWith(".xml")) {

        JAXBContext jc = Context.jcXmlPackage;
        Unmarshaller u = jc.createUnmarshaller();
        u.setEventHandler(new org.docx4j.jaxb.JaxbValidationEventHandler());

        org.docx4j.xmlPackage.Package wmlPackageEl = (org.docx4j.xmlPackage.Package) ((JAXBElement) u
                .unmarshal(new javax.xml.transform.stream.StreamSource(
                        new FileInputStream(inputfilepath)))).getValue();

        org.docx4j.convert.in.FlatOpcXmlImporter xmlPackage = new org.docx4j.convert.in.FlatOpcXmlImporter(
                wmlPackageEl);

        wordMLPackage = (WordprocessingMLPackage) xmlPackage.get();

    } else {
        wordMLPackage = WordprocessingMLPackage
                .load(new File(inputfilepath));
    }

    CustomXmlDataStoragePart customXmlDataStoragePart = wordMLPackage
            .getCustomXmlDataStorageParts().get(itemId1);
    // Get the contents
    CustomXmlDataStorage customXmlDataStorage = customXmlDataStoragePart
            .getData();
    // Change its contents
    ((CustomXmlDataStorageImpl) customXmlDataStorage).setNodeValueAtXPath(
            "/ns0:orderForm[1]/ns0:record[1]/ns0:name[1]", name,
            "xmlns:ns0='EasyForm'");

    customXmlDataStoragePart = wordMLPackage.getCustomXmlDataStorageParts()
            .get(itemId2);
    // Get the contents
    customXmlDataStorage = customXmlDataStoragePart.getData();
    // Change its contents
    ((CustomXmlDataStorageImpl) customXmlDataStorage).setNodeValueAtXPath(
            "/ns0:orderForm[1]/ns0:record[1]/ns0:age[1]", age,
            "xmlns:ns0='EasyForm'");

    customXmlDataStoragePart = wordMLPackage.getCustomXmlDataStorageParts()
            .get(itemId3);
    // Get the contents
    customXmlDataStorage = customXmlDataStoragePart.getData();
    // Change its contents
    ((CustomXmlDataStorageImpl) customXmlDataStorage).setNodeValueAtXPath(
            "/ns0:orderForm[1]/ns0:record[1]/ns0:gender[1]", gender,
            "xmlns:ns0='EasyForm'");

    // Apply the bindings
    BindingHandler.applyBindings(wordMLPackage.getMainDocumentPart());
    File f = new File(outputfilepath);
    wordMLPackage.save(f);
    FileInputStream fis = new FileInputStream(f);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    byte[] buf = new byte[1024];
    try {
        for (int readNum; (readNum = fis.read(buf)) != -1;) {
            bos.write(buf, 0, readNum);
        }
        // System.out.println( buf.length);

    } catch (IOException ex) {
    }
    byte[] bytes = bos.toByteArray();
    FileOutputStream file = new FileOutputStream(outputfilepath1, true);
    DataOutputStream out = new DataOutputStream(file);
    out.write(bytes);
    out.flush();
    out.close();

    System.out.println("..done");
}

public static void main(String[] args) {
  utility u = new utility();
  u.templetsubtitution("aditya",24,mohan);
}

thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

美人骨 2024-11-22 10:52:29

如果我理解正确的话,你本质上是在谈论合并文档。您可以使用两种非常简单的方法,它们的有效性实际上取决于数据的结构和后续使用:

  1. PhilippeAuriach 在他的回答中描述了一种方法,该方法需要
    MaindocumentPart 实例中的所有组件附加到
    其他。就最终的 docx 文件而言,这意味着内容
    出现在 document.xml 中——它不会考虑标头
    和页脚(例如),但这可能适合您。

  2. 您可以通过插入将多个文档插入到单个 docx 文件中
    作为 AltChunk 元素(请参阅 docx4j 文档)。这将
    将一个 Word 文件中的所有内容(包括标题和所有内容)转移到另一个 Word 文件中。
    这样做的缺点是你的最终文件不是一个合适的文件
    流动的 Word 文件,直到您打开它并将其保存在 MS Word 本身中
    (导入的组件在 docx 中保留为独立文件
    捆)。如果您想生成,这会给您带来问题
    “合并”文件,然后对它们执行一些操作,例如渲染 PDF --
    合并的内容将被忽略。

更完整(且复杂)的方法是执行“深度合并”。这会更新并维护文档中保存的所有引用。导入的内容成为文档主要“流”的一部分(即,它不存储为单独的引用),因此最终结果是一个正确合并的文件,可以呈现为 PDF 或其他格式。

这样做的缺点是您需要很好地了解 docx 结构和 API,并且您将编写大量代码(我建议购买 Plutext 的 MergeDocx 代替)。

If I understand you correctly, you're essentially talking about merging documents. There are two very simple approaches that you can use, and their effectiveness really depends on the structure and onward use of your data:

  1. PhilippeAuriach describes one approach in his answer, which entails
    appending all components within a MaindocumentPart instance to
    another. In terms of the final docx file, this means the content
    that appears in document.xml -- it won't take into account headers
    and footers ( for example), but that may be fine for you.

  2. You can insert multiple documents into a single docx file by inserting them
    as AltChunk elements (see the docx4j documentation). This will
    bring everything from one Word file into another, headers and all.
    The downside of this is that your final document won't be a proper
    flowing Word file until you open it and save it in MS Word itself
    (the imported components remain as standalone files within the docx
    bundle). This will cause you issues if you want to generated
    'merged' files and then do something with them like render PDFs --
    the merged content will simply be ignored.

The more complete (and complex) approach is to perform a "deep merge". This updates and maintains all references held within a document. Imported content becomes part of the main "flow" of the document (i.e. it is not stored as separate references), so the end result is a properly-merged file which can be rendered to PDF or whatever.

The downside to this is you need a good knowledge of docx structure and the API, and you will be writing a fair amount of code (I would recommend buying a license to Plutext's MergeDocx instead).

沉默的熊 2024-11-22 10:52:29

我必须处理类似的事情,这就是我所做的(可能不是最有效的,但有效):

  • 创建一个 FinalDoc 加载模板,并
  • 为每个数据行清空它(这样你就有了这个文档中的样式),创建一个加载模板的新文档,然后用您的值替换您的字段
  • 使用下面的函数将填充数据的文档附加到finalDoc:

    public static void append(WordprocessingMLPackage docDest, WordprocessingMLPackage docSource) {
    列表<对象>对象 = docSource.getMainDocumentPart().getContent();
        for(对象 o : 对象){
            docDest.getMainDocumentPart().getContent().add(o);
        }
    }
    

希望这会有所帮助。

I had to deal with similar things, and here is what I did (probably not the most efficient, but working) :

  • create a finalDoc loading the template, and emptying it (so you have the styles in this doc)
  • for each data row, create a new doc loading the template, then replace your fields with your values
  • use the function below to append the doc filled with the datas to the finalDoc :

    public static void append(WordprocessingMLPackage docDest, WordprocessingMLPackage docSource) {
    List<Object> objects = docSource.getMainDocumentPart().getContent();
        for(Object o : objects){
            docDest.getMainDocumentPart().getContent().add(o);
        }
    }
    

Hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文