8

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

谁能告诉我要添加到上述代码中的更改是什么?提前致谢!!

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);

         }
             }
4

1 回答 1

10

我正在使用来自http://poi.apache.org/的“poi-bin-3.10.1-20140818”库

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

Table不是段落,所以Table不是复制的。

要复制Table,您必须获取IBodyElement和循环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);

    }
}

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

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);
    }
}

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

所以复制的文件看起来与原始文件不同。

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

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

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

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

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

  2. 复制页面布局

  3. 从源 docx 文件复制图像

    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类源。

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);
    }
}
于 2014-08-19T04:46:02.177 回答