如何将.docx的段落复制到另一个.docx withJava并保留样式

我试图将内容从.docx中的特定段落复制到另一个空的.docx。我遇到的问题是来自source.docx的样式,项目符号,编号等不会保留在目标.docx.Here是我的代码

任何人都可以告诉我上面的代码中添加了哪些更改? 提前致谢!!

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/上使用“poi-bin-3.10.1-20140818”库

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

但“表”不是段落,因此不会复制“表”。

要复制“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()方法有bug。

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

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

下面的代码包括下一个function。

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 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 = "" + "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + ""; //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); } }