How to merge two word documents which are saved with .docx to a third file?
I've developed the next class:
import java.io.InputStream;import java.io.OutputStream;import java.util.ArrayList;import java.util.List;import org.apache.poi.openxml4j.opc.OPCPackage;import org.apache.poi.xwpf.usermodel.XWPFDocument;import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;public class WordMerge { private final OutputStream result; private final List<InputStream> inputs; private XWPFDocument first; public WordMerge(OutputStream result) { this.result = result; inputs = new ArrayList<>(); } public void add(InputStream stream) throws Exception{ inputs.add(stream); OPCPackage srcPackage = OPCPackage.open(stream); XWPFDocument src1Document = new XWPFDocument(srcPackage); if(inputs.size() == 1){ first = src1Document; } else { CTBody srcBody = src1Document.getDocument().getBody(); first.getDocument().addNewBody().set(srcBody); } } public void doMerge() throws Exception{ first.write(result); } public void close() throws Exception{ result.flush(); result.close(); for (InputStream input : inputs) { input.close(); } } }
And its use:
public static void main(String[] args) throws Exception { FileOutputStream faos = new FileOutputStream("/home/victor/result.docx"); WordMerge wm = new WordMerge(faos); wm.add( new FileInputStream("/home/victor/001.docx") ); wm.add( new FileInputStream("/home/victor/002.docx") ); wm.doMerge(); wm.close();}
I have a suggestion!First the main method; the parameters are: test1=firstDocxFileName, test2=secondDocxFileName, dest=destinationFileName; document is a global variable;
public void mergeDocx(String test1, String test2, String dest){ try { XWPFDocument doc1 = new XWPFDocument(new FileInputStream(new File(test1))); XWPFDocument doc2 = new XWPFDocument(new FileInputStream(new File(test2))); document = new XWPFDocument(); passaElementi(doc1); passaElementi(doc2); passaStili(doc1,doc2); OutputStream out = new FileOutputStream(new File(dest)); document.write(out); out.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }}
The private method 'passaElementi'copies and paste the body elements from doc1 to document object;I don't know what is XWPFSDT object...; (pay attention: i don't copy all the document but only the body!! .. for headers, sections, footers it proceed similarly) (the integer variables i and j are global and 0 at the beginning obviously)
private void passaElementi(XWPFDocument doc1){ for(IBodyElement e : doc1.getBodyElements()){ if(e instanceof XWPFParagraph){ XWPFParagraph p = (XWPFParagraph) e; if(p.getCTP().getPPr()!=null && p.getCTP().getPPr().getSectPr()!=null){ continue; }else{ document.createParagraph(); document.setParagraph(p, i); i++; } }else if(e instanceof XWPFTable){ XWPFTable t = (XWPFTable)e; document.createTable(); document.setTable(j, t); j++; }else if(e instanceof XWPFSDT){ // boh! } }}
The private method 'passaStili' copies and paste styles from doc1 and doc2 to document object;
private void passaStili(XWPFDocument doc1, XWPFDocument doc2){ try { CTStyles c1 = doc1.getStyle(); CTStyles c2 = doc2.getStyle(); int size1 = c1.getStyleList().size(); int size2 = c2.getStyleList().size(); for(int i = 0; i<size2; i++ ){ c1.addNewStyle(); c1.setStyleArray(size1+i, c2.getStyleList().get(i)); } document.createStyles().setStyles(c1); } catch (XmlException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }}
I don't handle exceptions to be fast! Leave a like if you liked it!Best regards!
B.M.
You should use XWPFDocument
instead of HWPFDocument
.
The documentation states:
The partner to HWPF for the new Word 2007 .docx format is XWPF. Whilst HWPF and XWPF provide similar features, there is not a common interface across the two of them at this time.
Change your code to:
XWPFDocument doc = new XWPFDocument(new FileInputStream("..."));XWPFDocument doc2 = new XWPFDocument(new FileInputStream("...")); XWPFDocument doc3 = new XWPFDocument(new FileInputStream("..."));