2012-04-18 218 views
2

我想将.docx中的特定段落的内容复制到另一个空的.docx中。我遇到的问题是样式,子目录,编号等从源码.docx不会保留在目标.docx.Here是我的代码如何将一段.docx复制到另一个.docx withJava并保留样式

任何人都可以请告诉我什么是要添加到上述代码的更改? 在此先感谢!

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

     } 
      } 
+2

你应该用库标记你的问题来解析你正在使用的docx,这样它会吸引更多的人知道它是如何工作的。 – 2012-04-18 11:29:42

+0

您需要从样式部分复制相关样式,并从编号部分编号。对于POI和docx4j,你如何做到这一点会有所不同。 – JasonPlutext 2012-04-22 16:17:47

+0

可以请你解释我应该如何从样式部分复制样式以及示例代码? – Dharmin 2012-04-23 04:42:21

回答

4

我使用的是从http://poi.apache.org/

“POI彬3.10.1-20140818” 库您可以复制在.docx文件循环doc.getParagraphs()所有段落。

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

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

[给定] 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); 
    } 
}