如何使用Java将.docx的段落复制到另一个.docx并保留样式 [英] How to copy a paragraph of .docx to another .docx with Java and retain the style

查看:366
本文介绍了如何使用Java将.docx的段落复制到另一个.docx并保留样式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将内容从.docx中的特定段落复制到另一个空的.docx中.我遇到的问题是source.docx中的样式,项目符号,编号等未保留在目标.docx中这是我的代码

I am trying to copy the content from a particular paragraph in a .docx to another empty .docx .the problem i have is that the style,bullets,numbering etc from the source.docx is not retained in the destination .docx.Here is my code

谁能告诉我要对上述代码进行哪些更改? 在此先感谢!

can anyone please tell me what are the changes to be added to the above code? Thanks in Advance!!

public class WordFinal {

        public static void main(String[] args) throws IOException, XmlException {

        XWPFDocument doc = new XWPFDocument(new FileInputStream("source.docx"));

        XWPFDocument destDoc =new XWPFDocument(); 

        OutputStream out = new FileOutputStream("Destination.docx"); 

        XWPFParagraph pr =doc.getParagraphs()[1];

        String copy=pr.getText();

        XWPFParagraph paragraphOne = destDoc.createParagraph(); 

        XWPFRun paragraphOneRunOne = paragraphOne.createRun();

        paragraphOneRunOne.setText(copy);

        destDoc.write(out);

         }
             }

推荐答案

我正在使用 http://poi.apache.org/

您可以循环 doc.getParagraphs()复制.docx文件中的所有段落.

You can copy all paragraphs in the .docx file looping doc.getParagraphs().

但是表格"不是段落,因此不会复制表格".

But "Table" is not paragraph, so "Table" is not copied.

要复制表格",您必须获取 IBodyElement 并循环 doc.getBodyElements().

To copy "Table", you have to get IBodyElement and looping doc.getBodyElements().

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.xmlbeans.XmlException;

public class WordFinal {

    public static void main(String[] args) throws IOException, XmlException {

        XWPFDocument doc = new XWPFDocument(new FileInputStream("source.docx"));

        XWPFDocument destDoc = new XWPFDocument();

        OutputStream out = new FileOutputStream("Destination.docx");

        // ** This code will copy just one paragraph. **

        XWPFParagraph pr = doc.getParagraphs().get(0);

        destDoc.createParagraph();

        int pos = destDoc.getParagraphs().size() - 1;

        destDoc.setParagraph(pr, pos);

        destDoc.write(out);

    }
}

所以复制所有段落和表格的代码如下所示.

So the code that copy all paragraphs and tables is like below.

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.apache.poi.xwpf.usermodel.BodyElementType;
import org.apache.poi.xwpf.usermodel.IBodyElement;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.xmlbeans.XmlException;

public class WordFinal {

    public static void main(String[] args) throws IOException, XmlException {

        XWPFDocument doc = new XWPFDocument(new FileInputStream("source.docx"));

        XWPFDocument destDoc = new XWPFDocument();

        OutputStream out = new FileOutputStream("Destination.docx");

        for (IBodyElement bodyElement : doc.getBodyElements()) {

            BodyElementType elementType = bodyElement.getElementType();

            if (elementType.name().equals("PARAGRAPH")) {

                XWPFParagraph pr = (XWPFParagraph) bodyElement;

                destDoc.createParagraph();

                int pos = destDoc.getParagraphs().size() - 1;

                destDoc.setParagraph(pr, pos);

            } else if( elementType.name().equals("TABLE") ) {

                XWPFTable table = (XWPFTable) bodyElement;

                destDoc.createTable();

                int pos = destDoc.getTables().size() - 1;

                destDoc.setTable(pos, table);
            }
        }

        destDoc.write(out);
    }
}

但是即使通过这种方式,您也无法复制图像和样式.

But even through this way, you can't copy image and style.

因此复制的文档看起来与原始文档不同.

So copied document looks different with original document.

似乎org.apache.poi.xwpf.usermodel.XWPFRun.addPicture()方法有错误.

It seems that org.apache.poi.xwpf.usermodel.XWPFRun.addPicture() method has bug.

Microsoft Word无法打开包含XWPFRun.addPicture()添加的图像的Docx文档.

Docx document including image added by XWPFRun.addPicture() is not opened by Microsoft Word.

[ref.] https://issues.apache.org/bugzilla/show_bug.cgi?id = 49765

下面的代码包括下一个功能.

Below code is including next functionality.

1)复制段落和表格的内容和样式

1) copy contents and styles of paragraphs and tables

2)复制页面布局

3)从源docx文件复制图像

3) copy images from source docx file

package com.overflow.heeseok;

import java.io.*;
import java.math.BigInteger;
import java.util.List;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STPageOrientation.Enum;

public class WordFinal {

    public static void main(String[] args) throws IOException, XmlException
    {
        XWPFDocument srcDoc = new XWPFDocument(new FileInputStream("Source.docx"));

        CustomXWPFDocument destDoc = new CustomXWPFDocument();

        // Copy document layout.
        copyLayout(srcDoc, destDoc);

        OutputStream out = new FileOutputStream("Destination.docx");

        for (IBodyElement bodyElement : srcDoc.getBodyElements()) {

            BodyElementType elementType = bodyElement.getElementType();

            if (elementType == BodyElementType.PARAGRAPH) {

                XWPFParagraph srcPr = (XWPFParagraph) bodyElement;

                copyStyle(srcDoc, destDoc, srcDoc.getStyles().getStyle(srcPr.getStyleID()));

                boolean hasImage = false;

                XWPFParagraph dstPr = destDoc.createParagraph();

                // Extract image from source docx file and insert into destination docx file.
                for (XWPFRun srcRun : srcPr.getRuns()) {

                    // You need next code when you want to call XWPFParagraph.removeRun().
                    dstPr.createRun();

                    if (srcRun.getEmbeddedPictures().size() > 0)
                        hasImage = true;

                    for (XWPFPicture pic : srcRun.getEmbeddedPictures()) {

                        byte[] img = pic.getPictureData().getData();

                        long cx = pic.getCTPicture().getSpPr().getXfrm().getExt().getCx();
                        long cy = pic.getCTPicture().getSpPr().getXfrm().getExt().getCy();

                        try {
                            // Working addPicture Code below...
                            String blipId = dstPr.getDocument().addPictureData(new ByteArrayInputStream(img),
                                    Document.PICTURE_TYPE_PNG);
                            destDoc.createPictureCxCy(blipId, destDoc.getNextPicNameNumber(Document.PICTURE_TYPE_PNG),
                                    cx, cy);

                        } catch (InvalidFormatException e1) {
                            e1.printStackTrace();
                        }
                    }
                }

                if (hasImage == false)
                {
                    int pos = destDoc.getParagraphs().size() - 1;
                    destDoc.setParagraph(srcPr, pos);
                }

            } else if (elementType == BodyElementType.TABLE) {

                XWPFTable table = (XWPFTable) bodyElement;

                copyStyle(srcDoc, destDoc, srcDoc.getStyles().getStyle(table.getStyleID()));

                destDoc.createTable();

                int pos = destDoc.getTables().size() - 1;

                destDoc.setTable(pos, table);
            }
        }

        destDoc.write(out);
        out.close();
    }

    // Copy Styles of Table and Paragraph.
    private static void copyStyle(XWPFDocument srcDoc, XWPFDocument destDoc, XWPFStyle style)
    {
        if (destDoc == null || style == null)
            return;

        if (destDoc.getStyles() == null) {
            destDoc.createStyles();
        }

        List<XWPFStyle> usedStyleList = srcDoc.getStyles().getUsedStyleList(style);
        for (XWPFStyle xwpfStyle : usedStyleList) {
            destDoc.getStyles().addStyle(xwpfStyle);
        }
    }

    // Copy Page Layout.
    //
    // if next error message shows up, download "ooxml-schemas-1.1.jar" file and
    // add it to classpath.
    //
    // [Error]
    // The type org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageMar
    // cannot be resolved.
    // It is indirectly referenced from required .class files
    //
    // This error happens because there is no CTPageMar class in
    // poi-ooxml-schemas-3.10.1-20140818.jar.
    //
    // [ref.] http://poi.apache.org/faq.html#faq-N10025
    // [ref.] http://poi.apache.org/overview.html#components
    //
    // < ooxml-schemas 1.1 download >
    // http://repo.maven.apache.org/maven2/org/apache/poi/ooxml-schemas/1.1/
    //
    private static void copyLayout(XWPFDocument srcDoc, XWPFDocument destDoc)
    {
        CTPageMar pgMar = srcDoc.getDocument().getBody().getSectPr().getPgMar();

        BigInteger bottom = pgMar.getBottom();
        BigInteger footer = pgMar.getFooter();
        BigInteger gutter = pgMar.getGutter();
        BigInteger header = pgMar.getHeader();
        BigInteger left = pgMar.getLeft();
        BigInteger right = pgMar.getRight();
        BigInteger top = pgMar.getTop();

        CTPageMar addNewPgMar = destDoc.getDocument().getBody().addNewSectPr().addNewPgMar();

        addNewPgMar.setBottom(bottom);
        addNewPgMar.setFooter(footer);
        addNewPgMar.setGutter(gutter);
        addNewPgMar.setHeader(header);
        addNewPgMar.setLeft(left);
        addNewPgMar.setRight(right);
        addNewPgMar.setTop(top);

        CTPageSz pgSzSrc = srcDoc.getDocument().getBody().getSectPr().getPgSz();

        BigInteger code = pgSzSrc.getCode();
        BigInteger h = pgSzSrc.getH();
        Enum orient = pgSzSrc.getOrient();
        BigInteger w = pgSzSrc.getW();

        CTPageSz addNewPgSz = destDoc.getDocument().getBody().addNewSectPr().addNewPgSz();

        addNewPgSz.setCode(code);
        addNewPgSz.setH(h);
        addNewPgSz.setOrient(orient);
        addNewPgSz.setW(w);
    }
}

和CustomXWPFDocument类源.

And CustomXWPFDocument class source.

package com.overflow.heeseok;

import java.io.IOException;

import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.xmlbeans.*;
import org.openxmlformats.schemas.drawingml.x2006.main.*;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;

/**
 * [ref] https://issues.apache.org/bugzilla/show_bug.cgi?id=49765
 * [ref] http://pastebin.com/index/CbQ3iw8t, http://pastebin.com/2YAneYgt
 */
public class CustomXWPFDocument extends XWPFDocument
{
    public CustomXWPFDocument() throws IOException
    {
        super();
    }

    public void createPictureCxCy(String blipId,int id, long cx, long cy)
    {
        CTInline inline = createParagraph().createRun().getCTR().addNewDrawing().addNewInline();

        String picXml = "" +
                "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">" +
                "   <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
                "      <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
                "         <pic:nvPicPr>" +
                "            <pic:cNvPr id=\"" + id + "\" name=\"Generated\"/>" +
                "            <pic:cNvPicPr/>" +
                "         </pic:nvPicPr>" +
                "         <pic:blipFill>" +
                "            <a:blip r:embed=\"" + blipId + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>" +
                "            <a:stretch>" +
                "               <a:fillRect/>" +
                "            </a:stretch>" +
                "         </pic:blipFill>" +
                "         <pic:spPr>" +
                "            <a:xfrm>" +
                "               <a:off x=\"0\" y=\"0\"/>" +
                "               <a:ext cx=\"" + cx + "\" cy=\"" + cy + "\"/>" +
                "            </a:xfrm>" +
                "            <a:prstGeom prst=\"rect\">" +
                "               <a:avLst/>" +
                "            </a:prstGeom>" +
                "         </pic:spPr>" +
                "      </pic:pic>" +
                "   </a:graphicData>" +
                "</a:graphic>";

        //CTGraphicalObjectData graphicData = inline.addNewGraphic().addNewGraphicData();
        XmlToken xmlToken = null;
        try
        {
            xmlToken = XmlToken.Factory.parse(picXml);
        }
        catch(XmlException xe)
        {
            xe.printStackTrace();
        }
        inline.set(xmlToken);
        //graphicData.set(xmlToken);

        inline.setDistT(0);
        inline.setDistB(0);
        inline.setDistL(0);
        inline.setDistR(0);

        CTPositiveSize2D extent = inline.addNewExtent();
        extent.setCx(cx);
        extent.setCy(cy);

        CTNonVisualDrawingProps docPr = inline.addNewDocPr();
        docPr.setId(id);
        docPr.setName("Picture " + id);
        docPr.setDescr("Generated");
    }

    public void createPicture(String blipId,int id, int width, int height)
    {
        final int EMU = 9525;
        width *= EMU;
        height *= EMU;
        //String blipId = getAllPictures().get(id).getPackageRelationship().getId();

        createPictureCxCy(blipId, id, width, height);
    }
}

这篇关于如何使用Java将.docx的段落复制到另一个.docx并保留样式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆