Page 1 of 1

Unable to prorgrammatically create Word document with repeat

PostPosted: Wed May 10, 2017 2:46 am
by manish.imaginea
Hello everyone,

My requirement is that I should be able to programmatically create an opendope repeat tag using Docx4j. My aim is to recreate the invoice.docx file ( at https://github.com/plutext/docx4j/blob/ ... voice.docx ) programmatically from scratch using nothing but the docx4j Java API.

I think I have followed the right approach but obviously something is missing. Upon opening the file in word I get an "Unspecified error at line 0 column 0 in document.xml" . Please see screenshot of error.
I renamed the output file to .zip, extracted it's contents and I found the following markup:

Here's the XML inside the w:body tag in document.xml:

Code: Select all
  <w:body>
        <w:p w:rsidR="00062A3D" w:rsidRDefault="00AD1B05">
            <w:r>
                <w:t>Hello</w:t>
            </w:r>
            <w:bookmarkStart w:name="_GoBack" w:id="0"/>
            <w:bookmarkEnd w:id="0"/>
        </w:p>
        <w:sdt>
            <w:sdtPr>
                <w:tag w:val="od:repeat=x2"/>
                <w:id w:val="1622600050"/>
            </w:sdtPr>
            <w:sdtContent>
                <w:tr>
                    <w:sdt>
                        <w:sdtPr>
                            <w:id w:val="1253242576"/>
                            <w:tag w:val="Description=Description&amp;amp;od:xpath=x3"/>
                            <w:dataBinding w:xpath="/invoice[1]/items/item[1]/name" w:storeItemID="{B4E06C7A-B0A6-491B-B14A-7E2E8C294A87}"/>
                        </w:sdtPr>
                        <w:sdtContent>
                            <w:tc>
                     <w:tcPr>
                        <w:tcW w:w="6771" w:type="dxa"/>
                     </w:tcPr>
                     <w:p>
                        <w:r>
                           <w:t>apples</w:t>
                        </w:r>
                     </w:p>
                            </w:tc>
                        </w:sdtContent>
                    </w:sdt>
                </w:tr>
            </w:sdtContent>
        </w:sdt>
        <w:sectPr w:rsidR="00062A3D">
            <w:pgSz w:w="12240" w:h="15840"/>
            <w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="720" w:footer="720" w:gutter="0"/>
            <w:cols w:space="720"/>
            <w:docGrid w:linePitch="360"/>
        </w:sectPr>
    </w:body>


The above generated XML looks alright to me. Why is word complaining about this and why is the databinding not working?
I also checked and the custom XML part I injected is also visible inside the document and the ItemID's and references have been set correctly.
I've attached my code and the generated output to this message.

Any help/pointers will be very welcome!
Thanks in advance!
Manish Chakravarty

Re: Unable to prorgrammatically create Word document with re

PostPosted: Wed May 10, 2017 7:38 am
by jason
At a glance, its complaining because you have a table row (w:tr) which is not inside a table (w:tbl). When you add your w:tbl, remember that that doesn't go inside w:p, it should be a sibling. Content control content has to respect these rules.

Re: Unable to prorgrammatically create Word document with re

PostPosted: Thu May 11, 2017 6:05 pm
by manish.imaginea
Thank you for the reply, Jason.
After fixing the order of the elements, the corruption problem has gone and Word is able to open the document.
Upon opening the document, I can see the content control as well.
However, OpenDope is not showing the data being repeated. Please see this screenshot:
Repeat-binding-docx4j.png
Programmatically generated document with repeats
Repeat-binding-docx4j.png (35.41 KiB) Viewed 2884 times


The w:body inside document.xml looks like this:

Code: Select all
<w:body>
        <w:p w:rsidR="00062A3D" w:rsidRDefault="00AD1B05">
            <w:r>
                <w:t>Hello</w:t>
            </w:r>
            <w:bookmarkStart w:name="_GoBack" w:id="0"/>
            <w:bookmarkEnd w:id="0"/>
        </w:p>

        <w:tbl>
            <w:sdt>
                <w:sdtPr>
                    <w:tag w:val="od:repeat=x2"/>
                    <w:id w:val="1786079969"/>
                </w:sdtPr>
                <w:sdtContent>
                    <w:tr>
                        <w:sdt>
                            <w:sdtPr>
                                <w:id w:val="142408898"/>
                                <w:tag w:val="Description=Description&amp;amp;od:xpath=x3"/>
                                <w:dataBinding w:xpath="/invoice[1]/items/item[1]/name"
                                               w:storeItemID="{F29E6C0D-C406-4A7D-94C3-D409D96D2468}"/>
                            </w:sdtPr>
                            <w:sdtContent>
                                <w:tc>
                                    <w:tcPr>
                                        <w:tcW w:w="6771" w:type="dxa"/>
                                    </w:tcPr>
                                    <w:p>
                                        <w:r>
                                            <w:t>apples</w:t>
                                        </w:r>
                                    </w:p>
                                </w:tc>
                            </w:sdtContent>
                        </w:sdt>
                    </w:tr>
                </w:sdtContent>
            </w:sdt>
        </w:tbl>
        <w:sectPr w:rsidR="00062A3D">
            <w:pgSz w:w="12240" w:h="15840"/>
            <w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="720" w:footer="720"
                     w:gutter="0"/>
            <w:cols w:space="720"/>
            <w:docGrid w:linePitch="360"/>
        </w:sectPr>
    </w:body>


This looks pretty OK to me. I've also attached the code, the output document and the screenshot.
Thank you again for answering my questions and thanks in advance!

Regards,
Manish Chakravarty

Re: Unable to prorgrammatically create Word document with re

PostPosted: Mon May 15, 2017 9:09 pm
by manish.imaginea
Hi Jason,

I am still trying to insert repeats programmatically - starting from a blank document but it does not work.
Instead of using tables, I used a simple text to test repeat bindings and the results are the same - ie - contents to do not repeat.

I've used the following code:

Code: Select all
public class SimpleRepeatDemo {
    private static final String INPUT_FILE_PATH = System.getProperty("user.dir") + "/input_docs/empty.docx";
    private static final String INPUT_XML_FILE_PATH = System.getProperty("user.dir") + "/input_docs/invoice-data.xml";

    private static final String DEFAULT_NAMESPACE = "http://default.com";
    private static final String OD_REPEAT_X2 = "od:repeat=x2";
    public static final String INVOICE_ITEM_NAME_XPATH = "/invoice[1]/items/item[1]/name";
    private static final String OUTPUT_FILE_PATH = System.getProperty("user.dir") + "/simple-repeat-demo.docx";
    public static final int ZERO = 0;
    public static final String AUTO = "auto";
    public static final String TABLE_GRID = "TableGrid";
    public static final String TABLE_LOOK_VALUE = "04A0";
    public static final String DXA = "dxa";
    public static final BigInteger TABLE_WIDTH = BigInteger.valueOf(6771);
    private static Logger log = LoggerFactory.getLogger(RepeatBindDemo.class);
    private final WordprocessingMLPackage outputWordPackage;
    private CustomXmlDataStoragePart customXmlDataStoragePart;
    private String storeItemID;


    public static void main(String[] args) throws Exception {
        SimpleRepeatDemo simpleRepeatDemo = new SimpleRepeatDemo();
        simpleRepeatDemo.injectRepeats();
    }

    public SimpleRepeatDemo() throws Docx4JException {
        outputWordPackage = (WordprocessingMLPackage) WordprocessingMLPackage.load(new File(INPUT_FILE_PATH)).clone();
    }

    public void injectRepeats() throws Exception {
        customXmlDataStoragePart = Helper.injectCustomXmlDataStoragePart(outputWordPackage.getMainDocumentPart(),
                new File(INPUT_XML_FILE_PATH));
        storeItemID = Helper.addPropertiesPartForSimpleBind(customXmlDataStoragePart, DEFAULT_NAMESPACE);

        // Create basic content control
        SdtRun sdt = Helper.createSdtRun();

        //sdtpr
        SdtPr sdtPr = Helper.createSdtPr();
        sdt.setSdtPr(sdtPr);

        //sdtContent
        CTSdtContentRun sdtContent = Helper.createCTSdtContentRun();
        sdt.setSdtContent(sdtContent);

        // Create paragraph with text
        P p = Helper.createP();
        sdtContent.getContent().add(p);
        Text text = Helper.createText();
        text.setValue("item_name");
        R r = Helper.createR();
        p.getContent().add(r);
        r.getContent().add(text);


        // Bind the data to the XML
        CTDataBinding dataBinding = Helper.createDataBinding();
        dataBinding.setXpath(INVOICE_ITEM_NAME_XPATH);
        dataBinding.setStoreItemID(storeItemID);
        sdtPr.setDataBinding(dataBinding);

        // create the repeat tag for repeat binding
        Tag repeatTag = Helper.createTag();
        repeatTag.setVal("od:repeat=x2");
        sdtPr.setTag(repeatTag);
        Id tagId  = Helper.createId();
        tagId.setVal(new Id().getVal());

        outputWordPackage.getMainDocumentPart().getContent().add(sdt);
        SaveToZipFile saver = new SaveToZipFile(outputWordPackage);
        saver.save(OUTPUT_FILE_PATH);

    }
}


The document.xml seems to have the correct markup - with databinding and repeats:
Code: Select all
<w:body>
        <w:p w:rsidR="00062A3D" w:rsidRDefault="00AD1B05">
            <w:r>
                <w:t>Hello</w:t>
            </w:r>
            <w:bookmarkStart w:name="_GoBack" w:id="0"/>
            <w:bookmarkEnd w:id="0"/>
        </w:p>
        <w:sdt>
            <w:sdtPr>
                <w:dataBinding w:xpath="/invoice[1]/items/item[1]/name" w:storeItemID="{ED67B9AA-2D88-49B4-821E-61AF75E7AE97}"/>
                <w:tag w:val="od:repeat=x2"/>
            </w:sdtPr>
            <w:sdtContent>
                <w:p>
                    <w:r>
                        <w:t>item_name</w:t>
                    </w:r>
                </w:p>
            </w:sdtContent>
        </w:sdt>
        <w:sectPr w:rsidR="00062A3D">
            <w:pgSz w:w="12240" w:h="15840"/>
            <w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="720" w:footer="720" w:gutter="0"/>
            <w:cols w:space="720"/>
            <w:docGrid w:linePitch="360"/>
        </w:sectPr>
    </w:body>


Why are the contents not being repeated by MS Word? This is very puzzling. Can someone please provide some pointers on this?
I'm including the code and the output document to this post.

Re: Unable to prorgrammatically create Word document with re

PostPosted: Tue May 16, 2017 11:10 pm
by jason
I ran your code. The output docx does not contain an OpenDoPE XPathsPart. Without that, docx4j can't process it (and it is docx4j which processes these, not Word).

As you may know, Word (2013 and later) supports a different format for repeats. See https://www.docx4java.org/blog/2015/01/ ... rime-time/

Re: Unable to prorgrammatically create Word document with re

PostPosted: Tue May 23, 2017 8:20 pm
by manish.imaginea
Hi Jason,

Thank you for your reply. I have made changes to the code, it is inserting the XPathsPart and other stuff correctly. I can still only see that the first element has been bound, but the repeats are not displayed.

Can you please provide some guidance? Basically I need to create a document (programmatically) from scratch with repeated data inside it via content controls.

Re: Unable to prorgrammatically create Word document with re

PostPosted: Tue May 23, 2017 9:23 pm
by jason
Looking at your docx, you have:

Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
    <odx:xpath id="x2" questionID="x2">
        <odx:dataBinding xpath="/invoice[1]/items/item[1]/name" storeItemID="{1E11D567-6598-40C1-A048-4C77A4EC97BA}"
                        prefixMappings="xmlns:oda='http://opendope.org/answers'"/>
    </odx:xpath>
 
Parsed in 0.001 seconds, using GeSHi 1.0.8.4


I guess it should be xpath="/invoice[1]/items/item[1]"

That repeats the items. Then inside the repeat, you need an additional content control for any data you want to insert, eg /invoice[1]/items/item[1]/name

I haven't tried to run this iteration of your code. There may be other issues.

Re: Unable to prorgrammatically create Word document with re

PostPosted: Wed May 24, 2017 5:56 pm
by manish.imaginea
Hi Jason,

Unfortunately, after changing the XPath as suggested by you, MS Word complains of a corrupted document.
Can you please supply us with an example that creates a repeat content control in an empty document? It will greatly help us and other users of docx4j who are facing similar issues.

Regards,
Manish

Re: Unable to prorgrammatically create Word document with re

PostPosted: Wed May 24, 2017 8:11 pm
by jason
You are nearly there!

Using the Docx4j Helper AddIn, sample code for the Main Document Part:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
import java.math.BigInteger;
import javax.xml.bind.JAXBElement;
import org.docx4j.wml.Body;
import org.docx4j.wml.CTColumns;
import org.docx4j.wml.CTDataBinding;
import org.docx4j.wml.CTPlaceholder;
import org.docx4j.wml.CTPlaceholder.DocPart;
import org.docx4j.wml.CTSdtCell;
import org.docx4j.wml.CTSdtContentCell;
import org.docx4j.wml.CTSdtContentRow;
import org.docx4j.wml.CTSdtRow;
import org.docx4j.wml.CTSdtText;
import org.docx4j.wml.CTTblLook;
import org.docx4j.wml.CTTblPrBase;
import org.docx4j.wml.CTTblPrBase.TblStyle;
import org.docx4j.wml.Document;
import org.docx4j.wml.Id;
import org.docx4j.wml.P;
import org.docx4j.wml.R;
import org.docx4j.wml.SdtPr;
import org.docx4j.wml.SdtPr.Alias;
import org.docx4j.wml.Tag;
import org.docx4j.wml.Tbl;
import org.docx4j.wml.TblGrid;
import org.docx4j.wml.TblGridCol;
import org.docx4j.wml.TblPr;
import org.docx4j.wml.TblWidth;
import org.docx4j.wml.Tc;
import org.docx4j.wml.TcPr;
import org.docx4j.wml.Text;
import org.docx4j.wml.Tr;


public class Foo {
public Document createIt() {

org.docx4j.wml.ObjectFactory wmlObjectFactory = new org.docx4j.wml.ObjectFactory();

Document document = wmlObjectFactory.createDocument();
    // Create object for body
    Body body = wmlObjectFactory.createBody();
    document.setBody(body);
        // Create object for p
        P p = wmlObjectFactory.createP();
        body.getContent().add( p);
        // Create object for tbl (wrapped in JAXBElement)
        Tbl tbl = wmlObjectFactory.createTbl();
        JAXBElement<org.docx4j.wml.Tbl> tblWrapped = wmlObjectFactory.createBodyTbl(tbl);
        body.getContent().add( tblWrapped);
            // Create object for tr
            Tr tr = wmlObjectFactory.createTr();
            tbl.getContent().add( tr);
                // Create object for tc (wrapped in JAXBElement)
                Tc tc = wmlObjectFactory.createTc();
                JAXBElement<org.docx4j.wml.Tc> tcWrapped = wmlObjectFactory.createTrTc(tc);
                tr.getContent().add( tcWrapped);
                    // Create object for p
                    P p2 = wmlObjectFactory.createP();
                    tc.getContent().add( p2);
                        // Create object for r
                        R r = wmlObjectFactory.createR();
                        p2.getContent().add( r);
                            // Create object for t (wrapped in JAXBElement)
                            Text text = wmlObjectFactory.createText();
                            JAXBElement<org.docx4j.wml.Text> textWrapped = wmlObjectFactory.createRT(text);
                            r.getContent().add( textWrapped);
                                text.setValue( "Item");
                    // Create object for tcPr
                    TcPr tcpr = wmlObjectFactory.createTcPr();
                    tc.setTcPr(tcpr);
                        // Create object for tcW
                        TblWidth tblwidth = wmlObjectFactory.createTblWidth();
                        tcpr.setTcW(tblwidth);
                            tblwidth.setW( BigInteger.valueOf( 6771) );
                            tblwidth.setType( "dxa");
                // Create object for tc (wrapped in JAXBElement)
                Tc tc2 = wmlObjectFactory.createTc();
                JAXBElement<org.docx4j.wml.Tc> tcWrapped2 = wmlObjectFactory.createTrTc(tc2);
                tr.getContent().add( tcWrapped2);
                    // Create object for p
                    P p3 = wmlObjectFactory.createP();
                    tc2.getContent().add( p3);
                        // Create object for r
                        R r2 = wmlObjectFactory.createR();
                        p3.getContent().add( r2);
                            // Create object for t (wrapped in JAXBElement)
                            Text text2 = wmlObjectFactory.createText();
                            JAXBElement<org.docx4j.wml.Text> textWrapped2 = wmlObjectFactory.createRT(text2);
                            r2.getContent().add( textWrapped2);
                                text2.setValue( "Price");
                    // Create object for tcPr
                    TcPr tcpr2 = wmlObjectFactory.createTcPr();
                    tc2.setTcPr(tcpr2);
                        // Create object for tcW
                        TblWidth tblwidth2 = wmlObjectFactory.createTblWidth();
                        tcpr2.setTcW(tblwidth2);
                            tblwidth2.setW( BigInteger.valueOf( 2268) );
                            tblwidth2.setType( "dxa");
            // Create object for sdt (wrapped in JAXBElement)
            CTSdtRow sdtrow = wmlObjectFactory.createCTSdtRow();
            JAXBElement<org.docx4j.wml.CTSdtRow> sdtrowWrapped = wmlObjectFactory.createTblSdt(sdtrow);
            tbl.getContent().add( sdtrowWrapped);
                // Create object for sdtPr
                SdtPr sdtpr = wmlObjectFactory.createSdtPr();
                sdtrow.setSdtPr(sdtpr);
                    // Create object for alias (wrapped in JAXBElement)
                    SdtPr.Alias sdtpralias = wmlObjectFactory.createSdtPrAlias();
                    JAXBElement<org.docx4j.wml.SdtPr.Alias> sdtpraliasWrapped = wmlObjectFactory.createSdtPrAlias(sdtpralias);
                    sdtpr.getRPrOrAliasOrLock().add( sdtpraliasWrapped);
                        sdtpralias.setVal( "Repeat");
                    // Create object for tag
                    Tag tag = wmlObjectFactory.createTag();
                    sdtpr.getRPrOrAliasOrLock().add( tag);
                        tag.setVal( "od:repeat=x2");
                    // Create object for id
                    Id id = wmlObjectFactory.createId();
                    sdtpr.getRPrOrAliasOrLock().add( id);
                        id.setVal( BigInteger.valueOf( 1418037945) );
                    // Create object for tag
                    Tag tag2 = wmlObjectFactory.createTag();
                    sdtpr.setTag(tag2);
                        tag2.setVal( "od:repeat=x2");
                    // Create object for id
                    Id id2 = wmlObjectFactory.createId();
                    sdtpr.setId(id2);
                        id2.setVal( BigInteger.valueOf( 1418037945) );
                // Create object for sdtContent
                CTSdtContentRow sdtcontentrow = wmlObjectFactory.createCTSdtContentRow();
                sdtrow.setSdtContent(sdtcontentrow);
                    // Create object for tr
                    Tr tr2 = wmlObjectFactory.createTr();
                    sdtcontentrow.getContent().add( tr2);
                        // Create object for sdt (wrapped in JAXBElement)
                        CTSdtCell sdtcell = wmlObjectFactory.createCTSdtCell();
                        JAXBElement<org.docx4j.wml.CTSdtCell> sdtcellWrapped = wmlObjectFactory.createTrSdt(sdtcell);
                        tr2.getContent().add( sdtcellWrapped);
                            // Create object for sdtPr
                            SdtPr sdtpr2 = wmlObjectFactory.createSdtPr();
                            sdtcell.setSdtPr(sdtpr2);
                                // Create object for dataBinding
                                CTDataBinding databinding = wmlObjectFactory.createCTDataBinding();
                                sdtpr2.setDataBinding(databinding);
                                    databinding.setStoreItemID( "{8B049945-9DFE-4726-9DE9-CF5691E53858}");  // you'll need to alter this
                                    databinding.setXpath( "/invoice[1]/items/item[1]/name");
                                // Create object for alias (wrapped in JAXBElement)
                                SdtPr.Alias sdtpralias2 = wmlObjectFactory.createSdtPrAlias();
                                JAXBElement<org.docx4j.wml.SdtPr.Alias> sdtpraliasWrapped2 = wmlObjectFactory.createSdtPrAlias(sdtpralias2);
                                sdtpr2.getRPrOrAliasOrLock().add( sdtpraliasWrapped2);
                                    sdtpralias2.setVal( "Description");
                                // Create object for tag
                                Tag tag3 = wmlObjectFactory.createTag();
                                sdtpr2.getRPrOrAliasOrLock().add( tag3);
                                    tag3.setVal( "Description=Description&od:xpath=x3");
                                // Create object for id
                                Id id3 = wmlObjectFactory.createId();
                                sdtpr2.getRPrOrAliasOrLock().add( id3);
                                    id3.setVal( BigInteger.valueOf( 1418037946) );
                                // Create object for dataBinding (wrapped in JAXBElement)
                                CTDataBinding databinding2 = wmlObjectFactory.createCTDataBinding();
                                JAXBElement<org.docx4j.wml.CTDataBinding> databindingWrapped = wmlObjectFactory.createSdtPrDataBinding(databinding2);
                                sdtpr2.getRPrOrAliasOrLock().add( databindingWrapped);
                                    databinding2.setStoreItemID( "{8B049945-9DFE-4726-9DE9-CF5691E53858}");  // you'll need to alter this
                                    databinding2.setXpath( "/invoice[1]/items/item[1]/name");
                                // Create object for text (wrapped in JAXBElement)
                                CTSdtText sdttext = wmlObjectFactory.createCTSdtText();
                                JAXBElement<org.docx4j.wml.CTSdtText> sdttextWrapped = wmlObjectFactory.createSdtPrText(sdttext);
                                sdtpr2.getRPrOrAliasOrLock().add( sdttextWrapped);
                                // Create object for tag
                                Tag tag4 = wmlObjectFactory.createTag();
                                sdtpr2.setTag(tag4);
                                    tag4.setVal( "Description=Description&od:xpath=x3");  // you'll need to alter this
                                // Create object for id
                                Id id4 = wmlObjectFactory.createId();
                                sdtpr2.setId(id4);
                                    id4.setVal( BigInteger.valueOf( 1418037946) );
                            // Create object for sdtContent
                            CTSdtContentCell sdtcontentcell = wmlObjectFactory.createCTSdtContentCell();
                            sdtcell.setSdtContent(sdtcontentcell);
                                // Create object for tc (wrapped in JAXBElement)
                                Tc tc3 = wmlObjectFactory.createTc();
                                JAXBElement<org.docx4j.wml.Tc> tcWrapped3 = wmlObjectFactory.createCTSdtContentCellTc(tc3);
                                sdtcontentcell.getContent().add( tcWrapped3);
                                    // Create object for p
                                    P p4 = wmlObjectFactory.createP();
                                    tc3.getContent().add( p4);
                                        // Create object for r
                                        R r3 = wmlObjectFactory.createR();
                                        p4.getContent().add( r3);
                                            // Create object for t (wrapped in JAXBElement)
                                            Text text3 = wmlObjectFactory.createText();
                                            JAXBElement<org.docx4j.wml.Text> textWrapped3 = wmlObjectFactory.createRT(text3);
                                            r3.getContent().add( textWrapped3);
                                                text3.setValue( "apples");
                                    // Create object for tcPr
                                    TcPr tcpr3 = wmlObjectFactory.createTcPr();
                                    tc3.setTcPr(tcpr3);
                                        // Create object for tcW
                                        TblWidth tblwidth3 = wmlObjectFactory.createTblWidth();
                                        tcpr3.setTcW(tblwidth3);
                                            tblwidth3.setW( BigInteger.valueOf( 6771) );
                                            tblwidth3.setType( "dxa");
                        // Create object for sdt (wrapped in JAXBElement)
                        CTSdtCell sdtcell2 = wmlObjectFactory.createCTSdtCell();
                        JAXBElement<org.docx4j.wml.CTSdtCell> sdtcellWrapped2 = wmlObjectFactory.createTrSdt(sdtcell2);
                        tr2.getContent().add( sdtcellWrapped2);
                            // Create object for sdtPr
                            SdtPr sdtpr3 = wmlObjectFactory.createSdtPr();
                            sdtcell2.setSdtPr(sdtpr3);
                                // Create object for dataBinding
                                CTDataBinding databinding3 = wmlObjectFactory.createCTDataBinding();
                                sdtpr3.setDataBinding(databinding3);
                                    databinding3.setStoreItemID( "{8B049945-9DFE-4726-9DE9-CF5691E53858}");
                                    databinding3.setXpath( "/invoice[1]/items/item[1]/price");
                                // Create object for alias (wrapped in JAXBElement)
                                SdtPr.Alias sdtpralias3 = wmlObjectFactory.createSdtPrAlias();
                                JAXBElement<org.docx4j.wml.SdtPr.Alias> sdtpraliasWrapped3 = wmlObjectFactory.createSdtPrAlias(sdtpralias3);
                                sdtpr3.getRPrOrAliasOrLock().add( sdtpraliasWrapped3);
                                    sdtpralias3.setVal( "Price");
                                // Create object for tag
                                Tag tag5 = wmlObjectFactory.createTag();
                                sdtpr3.getRPrOrAliasOrLock().add( tag5);
                                    tag5.setVal( "price=price&od:xpath=x4");
                                // Create object for id
                                Id id5 = wmlObjectFactory.createId();
                                sdtpr3.getRPrOrAliasOrLock().add( id5);
                                    id5.setVal( BigInteger.valueOf( 1418037951) );
                                // Create object for placeholder (wrapped in JAXBElement)
                                CTPlaceholder placeholder3 = wmlObjectFactory.createCTPlaceholder();
                                JAXBElement<org.docx4j.wml.CTPlaceholder> placeholderWrapped3 = wmlObjectFactory.createSdtPrPlaceholder(placeholder3);
                                sdtpr3.getRPrOrAliasOrLock().add( placeholderWrapped3);
                                    // Create object for docPart
                                    CTPlaceholder.DocPart placeholderdocpart3 = wmlObjectFactory.createCTPlaceholderDocPart();
                                    placeholder3.setDocPart(placeholderdocpart3);
                                        placeholderdocpart3.setVal( "E918F341A2F54C0A9743EE2731AB58B8");
                                // Create object for dataBinding (wrapped in JAXBElement)
                                CTDataBinding databinding4 = wmlObjectFactory.createCTDataBinding();
                                JAXBElement<org.docx4j.wml.CTDataBinding> databindingWrapped2 = wmlObjectFactory.createSdtPrDataBinding(databinding4);
                                sdtpr3.getRPrOrAliasOrLock().add( databindingWrapped2);
                                    databinding4.setStoreItemID( "{8B049945-9DFE-4726-9DE9-CF5691E53858}");
                                    databinding4.setXpath( "/invoice[1]/items/item[1]/price");
                                // Create object for text (wrapped in JAXBElement)
                                CTSdtText sdttext2 = wmlObjectFactory.createCTSdtText();
                                JAXBElement<org.docx4j.wml.CTSdtText> sdttextWrapped2 = wmlObjectFactory.createSdtPrText(sdttext2);
                                sdtpr3.getRPrOrAliasOrLock().add( sdttextWrapped2);
                                // Create object for tag
                                Tag tag6 = wmlObjectFactory.createTag();
                                sdtpr3.setTag(tag6);
                                    tag6.setVal( "price=price&od:xpath=x4");
                                // Create object for id
                                Id id6 = wmlObjectFactory.createId();
                                sdtpr3.setId(id6);
                                    id6.setVal( BigInteger.valueOf( 1418037951) );
                            // Create object for sdtContent
                            CTSdtContentCell sdtcontentcell2 = wmlObjectFactory.createCTSdtContentCell();
                            sdtcell2.setSdtContent(sdtcontentcell2);
                                // Create object for tc (wrapped in JAXBElement)
                                Tc tc4 = wmlObjectFactory.createTc();
                                JAXBElement<org.docx4j.wml.Tc> tcWrapped4 = wmlObjectFactory.createCTSdtContentCellTc(tc4);
                                sdtcontentcell2.getContent().add( tcWrapped4);
                                    // Create object for p
                                    P p5 = wmlObjectFactory.createP();
                                    tc4.getContent().add( p5);
                                        // Create object for r
                                        R r4 = wmlObjectFactory.createR();
                                        p5.getContent().add( r4);
                                            // Create object for t (wrapped in JAXBElement)
                                            Text text4 = wmlObjectFactory.createText();
                                            JAXBElement<org.docx4j.wml.Text> textWrapped4 = wmlObjectFactory.createRT(text4);
                                            r4.getContent().add( textWrapped4);
                                                text4.setValue( "$20");
                                    // Create object for tcPr
                                    TcPr tcpr4 = wmlObjectFactory.createTcPr();
                                    tc4.setTcPr(tcpr4);
                                        // Create object for tcW
                                        TblWidth tblwidth4 = wmlObjectFactory.createTblWidth();
                                        tcpr4.setTcW(tblwidth4);
                                            tblwidth4.setW( BigInteger.valueOf( 2268) );
                                            tblwidth4.setType( "dxa");
            // Create object for tblPr
            TblPr tblpr = wmlObjectFactory.createTblPr();
            tbl.setTblPr(tblpr);
                // Create object for tblStyle
                CTTblPrBase.TblStyle tblprbasetblstyle = wmlObjectFactory.createCTTblPrBaseTblStyle();
                tblpr.setTblStyle(tblprbasetblstyle);
                    tblprbasetblstyle.setVal( "TableGrid");
                // Create object for tblW
                TblWidth tblwidth5 = wmlObjectFactory.createTblWidth();
                tblpr.setTblW(tblwidth5);
                    tblwidth5.setW( BigInteger.valueOf( 0) );
                    tblwidth5.setType( "auto");
                // Create object for tblLook
                CTTblLook tbllook = wmlObjectFactory.createCTTblLook();
                tblpr.setTblLook(tbllook);
                    tbllook.setVal( "04A0");
                    tbllook.setFirstColumn(org.docx4j.sharedtypes.STOnOff.ONE);
                    tbllook.setFirstRow(org.docx4j.sharedtypes.STOnOff.ONE);
                    tbllook.setLastColumn(org.docx4j.sharedtypes.STOnOff.ZERO);
                    tbllook.setLastRow(org.docx4j.sharedtypes.STOnOff.ZERO);
                    tbllook.setNoHBand(org.docx4j.sharedtypes.STOnOff.ZERO);
                    tbllook.setNoVBand(org.docx4j.sharedtypes.STOnOff.ONE);
            // Create object for tblGrid
            TblGrid tblgrid = wmlObjectFactory.createTblGrid();
            tbl.setTblGrid(tblgrid);
                // Create object for gridCol
                TblGridCol tblgridcol = wmlObjectFactory.createTblGridCol();
                tblgrid.getGridCol().add( tblgridcol);
                    tblgridcol.setW( BigInteger.valueOf( 6771) );
                // Create object for gridCol
                TblGridCol tblgridcol2 = wmlObjectFactory.createTblGridCol();
                tblgrid.getGridCol().add( tblgridcol2);
                    tblgridcol2.setW( BigInteger.valueOf( 2268) );
        // Create object for p
        P p6 = wmlObjectFactory.createP();
        body.getContent().add( p6);

return document;
}
}
 
Parsed in 0.058 seconds, using GeSHi 1.0.8.4


In the example, we have XPaths Part:

Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
<ns15:xpaths  xmlns:ns15="http://opendope.org/xpaths" >
        <ns15:xpath id="x1">
          <ns15:dataBinding storeItemID="{8B049945-9DFE-4726-9DE9-CF5691E53858}" xpath="/invoice[1]/customer[1]/name[1]"/>
        </ns15:xpath>
        <ns15:xpath id="x2">
          <ns15:dataBinding storeItemID="{8b049945-9dfe-4726-9de9-cf5691e53858}" xpath="/invoice[1]/items/item"/>
        </ns15:xpath>
        <ns15:xpath id="x3">
          <ns15:dataBinding storeItemID="{8B049945-9DFE-4726-9DE9-CF5691E53858}" xpath="/invoice[1]/items/item[1]/name"/>
        </ns15:xpath>
        <ns15:xpath id="x4">
          <ns15:dataBinding storeItemID="{8B049945-9DFE-4726-9DE9-CF5691E53858}" xpath="/invoice[1]/items/item[1]/price"/>
        </ns15:xpath>

      </ns15:xpaths>
 
Parsed in 0.001 seconds, using GeSHi 1.0.8.4

Re: Unable to prorgrammatically create Word document with re

PostPosted: Fri May 26, 2017 4:55 pm
by manish.imaginea
Hi Jason,

Thank you for your reply.
I was able to create the document, but unfortunately it has the same output - ie it only shows a repeat of 1!
I have taken your code and added XpathsPart and SchemaRefs.
Please see the screenshot of the output below:
Screenshot_2.png
Repeat of only 1
Screenshot_2.png (5.91 KiB) Viewed 2837 times


What I want is something like this:
Screenshot_3.png
What is required
Screenshot_3.png (3.24 KiB) Viewed 2837 times


Please note that is example is derived from the "ContentControlBindingExtensions" example in the github repo.

However, I am still not able to get it to work.
Doubts:
    - At what point in the lifecycle should Docx4j.bind should be called?
    - I can see in https://github.com/plutext/docx4j/blob/ ... dings.java that BindingHandler is used to apply the binding. Is this the recommended way?
    - In https://github.com/plutext/docx4j/blob/ ... s.java#L90 Docx4j.bind is used. It requires an xmlStream as an argument. If the XML has already been injected before, how do I work around this?
    - You have used sdtpr.getRPrOrAliasOrLock().add( sdtpraliasWrapped) - what does this method do? I have not used this before. Looks like it's just for setting aliases to tags and do not have impact on the binding? ( just trying to understand the process)
    - I need to understand the repeat-bind process better. If the XML is injected and relevant XpathsParts are added, why do I need to inject the XML again when running Docx4j.bind() ?
    - In your XPathsPart you have the ns:15 prefix. How did you generate this programmatically? In my case the tags I generate have the odx: prefix. This is the generated XPathsPart ( item1.xml):

    MY VERSION:
    Code: Select all
        <odx:xpath id="x2">
            <odx:dataBinding xpath="/invoice[1]/items/item[1]/price" storeItemID="{8B049945-9DFE-4726-9DE9-CF5691E53858}"/>
        </odx:xpath>
        <odx:xpath id="x1">
            <odx:dataBinding xpath="/invoice[1]/items/item[1]/name" storeItemID="{8B049945-9DFE-4726-9DE9-CF5691E53858}"/>
        </odx:xpath>

    YOUR VERSION:
    Code: Select all
    <ns15:xpaths  xmlns:ns15="http://opendope.org/xpaths" >
            <ns15:xpath id="x1">
              <ns15:dataBinding storeItemID="{8B049945-9DFE-4726-9DE9-CF5691E53858}" xpath="/invoice[1]/customer[1]/name[1]"/>
            </ns15:xpath>
            <ns15:xpath id="x2">
              <ns15:dataBinding storeItemID="{8b049945-9dfe-4726-9de9-cf5691e53858}" xpath="/invoice[1]/items/item"/>
            </ns15:xpath>
            <ns15:xpath id="x3">
              <ns15:dataBinding storeItemID="{8B049945-9DFE-4726-9DE9-CF5691E53858}" xpath="/invoice[1]/items/item[1]/name"/>
            </ns15:xpath>
            <ns15:xpath id="x4">
              <ns15:dataBinding storeItemID="{8B049945-9DFE-4726-9DE9-CF5691E53858}" xpath="/invoice[1]/items/item[1]/price"/>
            </ns15:xpath>
          </ns15:xpaths>

    Why does this have a different prefix? How to generate these programmatically?


Here's my code Jason ( based on your code and XPathsPart, PropertiesPart etc added)

Code: Select all
package com.unirisx.poc;

import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.util.UUID;
import javax.xml.bind.JAXBElement;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.docx4j.customXmlProperties.DatastoreItem;
import org.docx4j.customXmlProperties.SchemaRefs;
import org.docx4j.model.datastorage.CustomXmlDataStorage;
import org.docx4j.model.datastorage.CustomXmlDataStorageImpl;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.exceptions.InvalidFormatException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.CustomXmlDataStoragePart;
import org.docx4j.openpackaging.parts.CustomXmlDataStoragePropertiesPart;
import org.docx4j.openpackaging.parts.Part;
import org.docx4j.openpackaging.parts.PartName;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.openpackaging.parts.opendope.XPathsPart;
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
import org.docx4j.wml.*;
import org.opendope.xpaths.Xpaths;
import org.xml.sax.SAXException;

public class Repeats {
    private static final String ITEM1_XML = "/customXml/item1.xml";
    private static final String OUTPUT_FILE_PATH = System.getProperty("user.dir") + "/repeats-out.docx";
    private static final String DATA_XML_FILE = System.getProperty("user.dir") + "/input_docs/invoice-data.xml";
    private static final String DXA_TEXT = "dxa";
    private static final String OD_REPEAT_X2 = "od:repeat=x2";
    private static final String STORE_ITEM_ID = "{8B049945-9DFE-4726-9DE9-CF5691E53858}";
    private static final String INVOICE_ITEMS_NAME_XPATH = "/invoice[1]/items/item[1]/name";
    private static final String INVOICE_ITEMS_PRICE_XPATH = "/invoice[1]/items/item[1]/price";
    private static final String ITEM_TEXT = "Item";
    private static final String PRICE_TEXT = "Price";
    private static final String REPEAT_TEXT = "Repeat";
    private static final int RANDOM_ID_2 = 1418037945;
    private static final int TABLE_WIDTH_6771 = 6771;
    private static final int TABLE_WIDTH_2268 = 2268;
    private static final String DESCRIPTION_TEXT = "Description";
    private static final int RANDOM_ID_1 = 1418037946;
    private static final String DESCRIPTION_OD_XPATH_X3 = "Description=Description&od:xpath=x3";
    private static final String APPLES_TEXT = "apples";
    private static final String PRICE_OD_XPATH_X4 = "price=price&od:xpath=x4";
    private static final int RANDOM_ID_3 = 1418037951;
    private static final String TWENTY_DOLLARS = "$20";
    private static final String TABLE_GRID = "TableGrid";
    private static final String AUTO_TEXT = "auto";
    private static final String TABLE_LOOK_VALUE = "04A0";
    private static final int ZERO = 0;
    private static final String PLACEHOLDER_VALUE = "E918F341A2F54C0A9743EE2731AB58B8";
    private static CustomXmlDataStoragePart customXMLDataStoragePart;

    private Document document;
    private WordprocessingMLPackage wordprocessingMLPackage;
    private XPathsPart xPathsPart;

    public static void main(String[] args) throws Exception {
        Repeats repeats = new Repeats();
        repeats.createDocumentWithRepeats();
        CustomXmlDataStoragePart customXmlDataStoragePart = repeats.injectCustomXmlDataStoragePart(repeats.getMainDocumentPart(), new File(DATA_XML_FILE));
        repeats.addPropertiesPart(customXmlDataStoragePart, STORE_ITEM_ID);
        repeats.addXpathsPart();
        repeats.save();

    }

    public Repeats() throws Docx4JException {
        document = getWmlObjectFactory().createDocument();
        wordprocessingMLPackage = (WordprocessingMLPackage) WordprocessingMLPackage.load(new File(System.getProperty("user.dir") + "/input_docs/empty.docx")).clone();
    }

    private ObjectFactory getWmlObjectFactory() {
        return new ObjectFactory();
    }
   
    private MainDocumentPart getMainDocumentPart(){
        return wordprocessingMLPackage.getMainDocumentPart();
    }

    private void save() throws Docx4JException {
        String outputFilePath = OUTPUT_FILE_PATH;
        wordprocessingMLPackage.save(new File(outputFilePath));

    }


    private void addXpathsPart() throws InvalidFormatException {
        xPathsPart = new XPathsPart(new PartName(ITEM1_XML));
        getMainDocumentPart().addTargetPart(xPathsPart,"http://opendope.org/xpaths");
        xPathsPart.setJaxbElement(new Xpaths());

        // for Price
        Xpaths.Xpath xp2 = createXpath();
        Xpaths.Xpath.DataBinding db2 = createDataBinding();
        xp2.setId("x2");
        db2.setXpath(INVOICE_ITEMS_PRICE_XPATH);
        db2.setStoreItemID(STORE_ITEM_ID);
        xp2.setDataBinding(db2);
        xPathsPart.getJaxbElement().getXpath().add(xp2);

        // for item Name
        Xpaths.Xpath xp1 = createXpath();
        Xpaths.Xpath.DataBinding db1 = createDataBinding();
        xp1.setId("x1");
        db1.setXpath(INVOICE_ITEMS_NAME_XPATH);
        db1.setStoreItemID(STORE_ITEM_ID);
        xp1.setDataBinding(db1);
        xPathsPart.getJaxbElement().getXpath().add(xp1);
    }

    private  CustomXmlDataStoragePart injectCustomXmlDataStoragePart(Part parent) throws Exception {

        org.docx4j.openpackaging.parts.CustomXmlDataStoragePart customXmlDataStoragePart =
                new org.docx4j.openpackaging.parts.CustomXmlDataStoragePart();
        // Defaults to /customXml/item1.xml

        CustomXmlDataStorage data = new CustomXmlDataStorageImpl();
        data.setDocument(createCustomXmlDocument(new File(DATA_XML_FILE)));

        customXmlDataStoragePart.setData(data);
        parent.addTargetPart(customXmlDataStoragePart, RelationshipsPart.AddPartBehaviour.RENAME_IF_NAME_EXISTS);

        return customXmlDataStoragePart;
    }


    private void addPropertiesPart(CustomXmlDataStoragePart customXmlDataStoragePart, String itemID) throws InvalidFormatException {
        CustomXmlDataStoragePropertiesPart part = new CustomXmlDataStoragePropertiesPart();

        org.docx4j.customXmlProperties.ObjectFactory of = new org.docx4j.customXmlProperties.ObjectFactory();

        DatastoreItem dsi = of.createDatastoreItem();
        String newItemId = "{" + itemID + "}";
        dsi.setItemID(newItemId);

        part.setJaxbElement(dsi );

        customXmlDataStoragePart.addTargetPart(part);
    }

    private Xpaths.Xpath.DataBinding createDataBinding() {
        return new org.opendope.xpaths.ObjectFactory().createXpathsXpathDataBinding();
    }

    private Xpaths.Xpath createXpath() {
        return new org.opendope.xpaths.ObjectFactory().createXpathsXpath();
    }


    public void createDocumentWithRepeats() {

        ObjectFactory wmlObjectFactory = new ObjectFactory();
        // Create object for body
        Body body = wmlObjectFactory.createBody();
        document.setBody(body);

        // Create object for p
        P p = wmlObjectFactory.createP();
        body.getContent().add( p);
        // Create object for tbl (wrapped in JAXBElement)
        Tbl tbl = wmlObjectFactory.createTbl();
        JAXBElement<org.docx4j.wml.Tbl> tblWrapped = wmlObjectFactory.createBodyTbl(tbl);
        body.getContent().add( tblWrapped);
        // Create object for tr
        Tr tr = wmlObjectFactory.createTr();
        tbl.getContent().add( tr);
        // Create object for tc (wrapped in JAXBElement)
        Tc tc = wmlObjectFactory.createTc();
        JAXBElement<org.docx4j.wml.Tc> tcWrapped = wmlObjectFactory.createTrTc(tc);
        tr.getContent().add( tcWrapped);
        // Create object for p
        P p2 = wmlObjectFactory.createP();
        tc.getContent().add( p2);
        // Create object for r
        R r = wmlObjectFactory.createR();
        p2.getContent().add( r);
        // Create object for t (wrapped in JAXBElement)
        Text text = wmlObjectFactory.createText();
        JAXBElement<org.docx4j.wml.Text> textWrapped = wmlObjectFactory.createRT(text);
        r.getContent().add( textWrapped);
        text.setValue(ITEM_TEXT);
        // Create object for tcPr
        TcPr tcpr = wmlObjectFactory.createTcPr();
        tc.setTcPr(tcpr);
        // Create object for tcW
        TblWidth tblwidth = wmlObjectFactory.createTblWidth();
        tcpr.setTcW(tblwidth);
        tblwidth.setW( BigInteger.valueOf(TABLE_WIDTH_6771) );
        tblwidth.setType(DXA_TEXT);
        // Create object for tc (wrapped in JAXBElement)
        Tc tc2 = wmlObjectFactory.createTc();
        JAXBElement<org.docx4j.wml.Tc> tcWrapped2 = wmlObjectFactory.createTrTc(tc2);
        tr.getContent().add( tcWrapped2);
        // Create object for p
        P p3 = wmlObjectFactory.createP();
        tc2.getContent().add( p3);
        // Create object for r
        R r2 = wmlObjectFactory.createR();
        p3.getContent().add( r2);
        // Create object for t (wrapped in JAXBElement)
        Text text2 = wmlObjectFactory.createText();
        JAXBElement<org.docx4j.wml.Text> textWrapped2 = wmlObjectFactory.createRT(text2);
        r2.getContent().add( textWrapped2);
        text2.setValue(PRICE_TEXT);
        // Create object for tcPr
        TcPr tcpr2 = wmlObjectFactory.createTcPr();
        tc2.setTcPr(tcpr2);
        // Create object for tcW
        TblWidth tblwidth2 = wmlObjectFactory.createTblWidth();
        tcpr2.setTcW(tblwidth2);
        tblwidth2.setW( BigInteger.valueOf(TABLE_WIDTH_2268) );
        tblwidth2.setType(DXA_TEXT);
        // Create object for sdt (wrapped in JAXBElement)
        CTSdtRow sdtrow = wmlObjectFactory.createCTSdtRow();
        JAXBElement<org.docx4j.wml.CTSdtRow> sdtrowWrapped = wmlObjectFactory.createTblSdt(sdtrow);
        tbl.getContent().add( sdtrowWrapped);
        // Create object for sdtPr
        SdtPr sdtpr = wmlObjectFactory.createSdtPr();
        sdtrow.setSdtPr(sdtpr);
        // Create object for alias (wrapped in JAXBElement)
        SdtPr.Alias sdtpralias = wmlObjectFactory.createSdtPrAlias();
        JAXBElement<org.docx4j.wml.SdtPr.Alias> sdtpraliasWrapped = wmlObjectFactory.createSdtPrAlias(sdtpralias);
        sdtpr.getRPrOrAliasOrLock().add( sdtpraliasWrapped);
        sdtpralias.setVal(REPEAT_TEXT);
        // Create object for tag
        Tag tag = wmlObjectFactory.createTag();
        sdtpr.getRPrOrAliasOrLock().add( tag);
        tag.setVal(OD_REPEAT_X2);
        // Create object for id
        Id id = wmlObjectFactory.createId();
        sdtpr.getRPrOrAliasOrLock().add( id);
        id.setVal( BigInteger.valueOf(RANDOM_ID_2) );
        // Create object for tag
        Tag tag2 = wmlObjectFactory.createTag();
        sdtpr.setTag(tag2);
        tag2.setVal(OD_REPEAT_X2);
        // Create object for id
        Id id2 = wmlObjectFactory.createId();
        sdtpr.setId(id2);
        id2.setVal( BigInteger.valueOf(RANDOM_ID_2) );
        // Create object for sdtContent
        CTSdtContentRow sdtcontentrow = wmlObjectFactory.createCTSdtContentRow();
        sdtrow.setSdtContent(sdtcontentrow);
        // Create object for tr
        Tr tr2 = wmlObjectFactory.createTr();
        sdtcontentrow.getContent().add( tr2);
        // Create object for sdt (wrapped in JAXBElement)
        CTSdtCell sdtcell = wmlObjectFactory.createCTSdtCell();
        JAXBElement<org.docx4j.wml.CTSdtCell> sdtcellWrapped = wmlObjectFactory.createTrSdt(sdtcell);
        tr2.getContent().add( sdtcellWrapped);
        // Create object for sdtPr
        SdtPr sdtpr2 = wmlObjectFactory.createSdtPr();
        sdtcell.setSdtPr(sdtpr2);
        // Create object for dataBinding
        CTDataBinding databinding = wmlObjectFactory.createCTDataBinding();
        sdtpr2.setDataBinding(databinding);
        databinding.setStoreItemID(STORE_ITEM_ID);  // you'll need to alter this
        databinding.setXpath(INVOICE_ITEMS_NAME_XPATH);
        // Create object for alias (wrapped in JAXBElement)
        SdtPr.Alias sdtpralias2 = wmlObjectFactory.createSdtPrAlias();
        JAXBElement<org.docx4j.wml.SdtPr.Alias> sdtpraliasWrapped2 = wmlObjectFactory.createSdtPrAlias(sdtpralias2);
        sdtpr2.getRPrOrAliasOrLock().add( sdtpraliasWrapped2);
        sdtpralias2.setVal(DESCRIPTION_TEXT);
        // Create object for tag
        Tag tag3 = wmlObjectFactory.createTag();
        sdtpr2.getRPrOrAliasOrLock().add( tag3);
        tag3.setVal(DESCRIPTION_OD_XPATH_X3);
        // Create object for id
        Id id3 = wmlObjectFactory.createId();
        sdtpr2.getRPrOrAliasOrLock().add( id3);
        id3.setVal( BigInteger.valueOf(RANDOM_ID_1) );
        // Create object for dataBinding (wrapped in JAXBElement)
        CTDataBinding databinding2 = wmlObjectFactory.createCTDataBinding();
        JAXBElement<org.docx4j.wml.CTDataBinding> databindingWrapped = wmlObjectFactory.createSdtPrDataBinding(databinding2);
        sdtpr2.getRPrOrAliasOrLock().add( databindingWrapped);
        databinding2.setStoreItemID(STORE_ITEM_ID);  // you'll need to alter this
        databinding2.setXpath(INVOICE_ITEMS_NAME_XPATH);
        // Create object for text (wrapped in JAXBElement)
        CTSdtText sdttext = wmlObjectFactory.createCTSdtText();
        JAXBElement<org.docx4j.wml.CTSdtText> sdttextWrapped = wmlObjectFactory.createSdtPrText(sdttext);
        sdtpr2.getRPrOrAliasOrLock().add( sdttextWrapped);
        // Create object for tag
        Tag tag4 = wmlObjectFactory.createTag();
        sdtpr2.setTag(tag4);
        tag4.setVal(DESCRIPTION_OD_XPATH_X3);  // you'll need to alter this
        // Create object for id
        Id id4 = wmlObjectFactory.createId();
        sdtpr2.setId(id4);
        id4.setVal( BigInteger.valueOf(RANDOM_ID_1) );
        // Create object for sdtContent
        CTSdtContentCell sdtcontentcell = wmlObjectFactory.createCTSdtContentCell();
        sdtcell.setSdtContent(sdtcontentcell);
        // Create object for tc (wrapped in JAXBElement)
        Tc tc3 = wmlObjectFactory.createTc();
        JAXBElement<org.docx4j.wml.Tc> tcWrapped3 = wmlObjectFactory.createCTSdtContentCellTc(tc3);
        sdtcontentcell.getContent().add( tcWrapped3);
        // Create object for p
        P p4 = wmlObjectFactory.createP();
        tc3.getContent().add( p4);
        // Create object for r
        R r3 = wmlObjectFactory.createR();
        p4.getContent().add( r3);
        // Create object for t (wrapped in JAXBElement)
        Text text3 = wmlObjectFactory.createText();
        JAXBElement<org.docx4j.wml.Text> textWrapped3 = wmlObjectFactory.createRT(text3);
        r3.getContent().add( textWrapped3);
        text3.setValue(APPLES_TEXT);
        // Create object for tcPr
        TcPr tcpr3 = wmlObjectFactory.createTcPr();
        tc3.setTcPr(tcpr3);
        // Create object for tcW
        TblWidth tblwidth3 = wmlObjectFactory.createTblWidth();
        tcpr3.setTcW(tblwidth3);
        tblwidth3.setW( BigInteger.valueOf( TABLE_WIDTH_6771) );
        tblwidth3.setType(DXA_TEXT);
        // Create object for sdt (wrapped in JAXBElement)
        CTSdtCell sdtcell2 = wmlObjectFactory.createCTSdtCell();
        JAXBElement<org.docx4j.wml.CTSdtCell> sdtcellWrapped2 = wmlObjectFactory.createTrSdt(sdtcell2);
        tr2.getContent().add( sdtcellWrapped2);
        // Create object for sdtPr
        SdtPr sdtpr3 = wmlObjectFactory.createSdtPr();
        sdtcell2.setSdtPr(sdtpr3);
        // Create object for dataBinding
        CTDataBinding databinding3 = wmlObjectFactory.createCTDataBinding();
        sdtpr3.setDataBinding(databinding3);
        databinding3.setStoreItemID(STORE_ITEM_ID);
        databinding3.setXpath(INVOICE_ITEMS_PRICE_XPATH);
        // Create object for alias (wrapped in JAXBElement)
        SdtPr.Alias sdtpralias3 = wmlObjectFactory.createSdtPrAlias();
        JAXBElement<org.docx4j.wml.SdtPr.Alias> sdtpraliasWrapped3 = wmlObjectFactory.createSdtPrAlias(sdtpralias3);
        sdtpr3.getRPrOrAliasOrLock().add( sdtpraliasWrapped3);
        sdtpralias3.setVal(PRICE_TEXT);
        // Create object for tag
        Tag tag5 = wmlObjectFactory.createTag();
        sdtpr3.getRPrOrAliasOrLock().add( tag5);
        tag5.setVal(PRICE_OD_XPATH_X4);
        // Create object for id
        Id id5 = wmlObjectFactory.createId();
        sdtpr3.getRPrOrAliasOrLock().add( id5);
        id5.setVal( BigInteger.valueOf(RANDOM_ID_3) );
        // Create object for placeholder (wrapped in JAXBElement)
        CTPlaceholder placeholder3 = wmlObjectFactory.createCTPlaceholder();
        JAXBElement<org.docx4j.wml.CTPlaceholder> placeholderWrapped3 = wmlObjectFactory.createSdtPrPlaceholder(placeholder3);
        sdtpr3.getRPrOrAliasOrLock().add( placeholderWrapped3);
        // Create object for docPart
        CTPlaceholder.DocPart placeholderdocpart3 = wmlObjectFactory.createCTPlaceholderDocPart();
        placeholder3.setDocPart(placeholderdocpart3);
        placeholderdocpart3.setVal(PLACEHOLDER_VALUE);
        // Create object for dataBinding (wrapped in JAXBElement)
        CTDataBinding databinding4 = wmlObjectFactory.createCTDataBinding();
        JAXBElement<org.docx4j.wml.CTDataBinding> databindingWrapped2 = wmlObjectFactory.createSdtPrDataBinding(databinding4);
        sdtpr3.getRPrOrAliasOrLock().add( databindingWrapped2);
        databinding4.setStoreItemID(STORE_ITEM_ID);
        databinding4.setXpath(INVOICE_ITEMS_PRICE_XPATH);
        // Create object for text (wrapped in JAXBElement)
        CTSdtText sdttext2 = wmlObjectFactory.createCTSdtText();
        JAXBElement<org.docx4j.wml.CTSdtText> sdttextWrapped2 = wmlObjectFactory.createSdtPrText(sdttext2);
        sdtpr3.getRPrOrAliasOrLock().add( sdttextWrapped2);
        // Create object for tag
        Tag tag6 = wmlObjectFactory.createTag();
        sdtpr3.setTag(tag6);
        tag6.setVal(PRICE_OD_XPATH_X4);
        // Create object for id
        Id id6 = wmlObjectFactory.createId();
        sdtpr3.setId(id6);
        id6.setVal( BigInteger.valueOf(RANDOM_ID_3) );
        // Create object for sdtContent
        CTSdtContentCell sdtcontentcell2 = wmlObjectFactory.createCTSdtContentCell();
        sdtcell2.setSdtContent(sdtcontentcell2);
        // Create object for tc (wrapped in JAXBElement)
        Tc tc4 = wmlObjectFactory.createTc();
        JAXBElement<org.docx4j.wml.Tc> tcWrapped4 = wmlObjectFactory.createCTSdtContentCellTc(tc4);
        sdtcontentcell2.getContent().add( tcWrapped4);
        // Create object for p
        P p5 = wmlObjectFactory.createP();
        tc4.getContent().add( p5);
        // Create object for r
        R r4 = wmlObjectFactory.createR();
        p5.getContent().add( r4);
        // Create object for t (wrapped in JAXBElement)
        Text text4 = wmlObjectFactory.createText();
        JAXBElement<org.docx4j.wml.Text> textWrapped4 = wmlObjectFactory.createRT(text4);
        r4.getContent().add( textWrapped4);
        text4.setValue(TWENTY_DOLLARS);
        // Create object for tcPr
        TcPr tcpr4 = wmlObjectFactory.createTcPr();
        tc4.setTcPr(tcpr4);
        // Create object for tcW
        TblWidth tblwidth4 = wmlObjectFactory.createTblWidth();
        tcpr4.setTcW(tblwidth4);
        tblwidth4.setW( BigInteger.valueOf(TABLE_WIDTH_2268) );
        tblwidth4.setType(DXA_TEXT);
        // Create object for tblPr
        TblPr tblpr = wmlObjectFactory.createTblPr();
        tbl.setTblPr(tblpr);
        // Create object for tblStyle
        CTTblPrBase.TblStyle tblprbasetblstyle = wmlObjectFactory.createCTTblPrBaseTblStyle();
        tblpr.setTblStyle(tblprbasetblstyle);
        tblprbasetblstyle.setVal(TABLE_GRID);
        // Create object for tblW
        TblWidth tblwidth5 = wmlObjectFactory.createTblWidth();
        tblpr.setTblW(tblwidth5);
        tblwidth5.setW( BigInteger.valueOf(ZERO) );
        tblwidth5.setType(AUTO_TEXT);
        // Create object for tblLook
        CTTblLook tbllook = wmlObjectFactory.createCTTblLook();
        tblpr.setTblLook(tbllook);
        tbllook.setVal(TABLE_LOOK_VALUE);
        tbllook.setFirstColumn(org.docx4j.sharedtypes.STOnOff.ONE);
        tbllook.setFirstRow(org.docx4j.sharedtypes.STOnOff.ONE);
        tbllook.setLastColumn(org.docx4j.sharedtypes.STOnOff.ZERO);
        tbllook.setLastRow(org.docx4j.sharedtypes.STOnOff.ZERO);
        tbllook.setNoHBand(org.docx4j.sharedtypes.STOnOff.ZERO);
        tbllook.setNoVBand(org.docx4j.sharedtypes.STOnOff.ONE);
        // Create object for tblGrid
        TblGrid tblgrid = wmlObjectFactory.createTblGrid();
        tbl.setTblGrid(tblgrid);
        // Create object for gridCol
        TblGridCol tblgridcol = wmlObjectFactory.createTblGridCol();
        tblgrid.getGridCol().add( tblgridcol);
        tblgridcol.setW( BigInteger.valueOf( TABLE_WIDTH_6771) );
        // Create object for gridCol
        TblGridCol tblgridcol2 = wmlObjectFactory.createTblGridCol();
        tblgrid.getGridCol().add( tblgridcol2);
        tblgridcol2.setW( BigInteger.valueOf(TABLE_WIDTH_2268) );
        // Create object for p
        P p6 = wmlObjectFactory.createP();
        body.getContent().add( p6);

        // finally add the new content to empty document
        getMainDocumentPart().getContent().add(body);
    }

    private CustomXmlDataStoragePart injectCustomXmlDataStoragePart(Part parent, File inputXmlFile) throws Exception {
        org.docx4j.openpackaging.parts.CustomXmlDataStoragePart customXmlDataStoragePart =
                new org.docx4j.openpackaging.parts.CustomXmlDataStoragePart();
        // Defaults to /customXml/item1.xml
        CustomXmlDataStorage data = new CustomXmlDataStorageImpl();
        data.setDocument(createCustomXmlDocument(inputXmlFile));

        customXmlDataStoragePart.setData(data);
        parent.addTargetPart(customXmlDataStoragePart, RelationshipsPart.AddPartBehaviour.RENAME_IF_NAME_EXISTS);

        return customXmlDataStoragePart;
    }

    private org.w3c.dom.Document createCustomXmlDocument(File xmlFile) throws ParserConfigurationException, IOException, SAXException {
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        documentBuilderFactory.setNamespaceAware(true);
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        org.w3c.dom.Document document = documentBuilder.parse(xmlFile);

        return document;

    }
}



I know I have requested this multiple times - but can you please provide a working example where we start with a blank document and end up with a bunch of repeats? I've been trying for more than a month now to get it to work. ( Simple bind works) If you can provide a small working example, I will clean it up, document it, add it to the samples, so that others can also use the same and benefit. As of now, for me atleast, it has become very confusing as to how to proceed with multiple repeats. Can you please provide me with a simple example that just does a few repeats please?

Regards,
Manish Chakravarty
Architect
Imaginea Inc.

Re: Unable to prorgrammatically create Word document with re

PostPosted: Fri May 26, 2017 7:19 pm
by jason
Please attach the docx your code created.

Re: Unable to prorgrammatically create Word document with re

PostPosted: Fri May 26, 2017 8:20 pm
by manish.imaginea
Hi Jason,

Please find the code and the output document attached.
The code for creating the document is the code that you had helped me with previously.

Re: Unable to prorgrammatically create Word document with re

PostPosted: Fri May 26, 2017 11:49 pm
by jason
Try

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
    public class Repeats {
       
        private static final String ITEM1_XML = "/customXml/item1.xml";
        private static final String OUTPUT_FILE_PATH = System.getProperty("user.dir") + "/repeats-out.docx";
        private static final String DATA_XML_FILE = System.getProperty("user.dir") + "/input_docs/invoice-data.xml";
        private static final String DXA_TEXT = "dxa";
        private static final String OD_REPEAT_X2 = "od:repeat=x2";
       
        private static final String STORE_ITEM_ID_OF_DATA_PART = "{8B049945-9DFE-4726-9DE9-CF5691E53858}";
        //private static final String STORE_ITEM_ID_OF_XPATHS_PART = "{5E015971-2421-4FFC-AD0A-CF7BDB8701E6}";

        private static final String INVOICE_ITEMS_NAME_XPATH = "/invoice[1]/items/item[1]/name";
        private static final String INVOICE_ITEMS_PRICE_XPATH = "/invoice[1]/items/item[1]/price";
        private static final String ITEM_TEXT = "Item";
        private static final String PRICE_TEXT = "Price";
        private static final String REPEAT_TEXT = "Repeat";
        private static final int RANDOM_ID_2 = 1418037945;
        private static final int TABLE_WIDTH_6771 = 6771;
        private static final int TABLE_WIDTH_2268 = 2268;
        private static final String DESCRIPTION_TEXT = "Description";
        private static final int RANDOM_ID_1 = 1418037946;
        private static final String DESCRIPTION_OD_XPATH_X3 = "Description=Description&od:xpath=x3";
        private static final String APPLES_TEXT = "apples";
        private static final String PRICE_OD_XPATH_X4 = "price=price&od:xpath=x4";
        private static final int RANDOM_ID_3 = 1418037951;
        private static final String TWENTY_DOLLARS = "$20";
        private static final String TABLE_GRID = "TableGrid";
        private static final String AUTO_TEXT = "auto";
        private static final String TABLE_LOOK_VALUE = "04A0";
        private static final int ZERO = 0;
        private static final String PLACEHOLDER_VALUE = "E918F341A2F54C0A9743EE2731AB58B8";
        private static CustomXmlDataStoragePart customXMLDataStoragePart;

        private Document document;
        private WordprocessingMLPackage wordprocessingMLPackage;
        private XPathsPart xPathsPart;

        public static void main(String[] args) throws Exception {
            Repeats repeats = new Repeats();
            repeats.createDocumentWithRepeats();
           
            // Add the data part
            CustomXmlDataStoragePart customXmlDataStoragePart = repeats.injectCustomXmlDataStoragePart(repeats.getMainDocumentPart(), new File(DATA_XML_FILE));
            repeats.addPropertiesPart(customXmlDataStoragePart, STORE_ITEM_ID_OF_DATA_PART);
           
            // Add the XPaths Part
            repeats.addXpathsPart();
           
            repeats.save();

        }

        public Repeats() throws Docx4JException {
            document = getWmlObjectFactory().createDocument();
            wordprocessingMLPackage = (WordprocessingMLPackage) WordprocessingMLPackage.load(new File(System.getProperty("user.dir") + "/input_docs/empty.docx")).clone();
        }

        private ObjectFactory getWmlObjectFactory() {
            return new ObjectFactory();
        }
       
        private MainDocumentPart getMainDocumentPart(){
            return wordprocessingMLPackage.getMainDocumentPart();
        }

        private void save() throws Docx4JException {
            String outputFilePath = OUTPUT_FILE_PATH;
            wordprocessingMLPackage.save(new File(outputFilePath));

        }


        private void addXpathsPart() throws InvalidFormatException {
            xPathsPart = new XPathsPart(new PartName(ITEM1_XML));
            getMainDocumentPart().addTargetPart(xPathsPart, AddPartBehaviour.RENAME_IF_NAME_EXISTS);
            xPathsPart.setJaxbElement(new Xpaths());

            // for Repeat
            Xpaths.Xpath xp = createXpath();
            Xpaths.Xpath.DataBinding db = createDataBinding();
            xp.setId("x2");
            db.setXpath("/invoice[1]/items/item[1]");
            db.setStoreItemID(STORE_ITEM_ID_OF_DATA_PART);
            xp.setDataBinding(db);
            xPathsPart.getJaxbElement().getXpath().add(xp);
           
            // for Price
            Xpaths.Xpath xp2 = createXpath();
            Xpaths.Xpath.DataBinding db2 = createDataBinding();
            xp2.setId("x4");
            db2.setXpath(INVOICE_ITEMS_PRICE_XPATH);
            db2.setStoreItemID(STORE_ITEM_ID_OF_DATA_PART);
            xp2.setDataBinding(db2);
            xPathsPart.getJaxbElement().getXpath().add(xp2);

            // for item Name
            Xpaths.Xpath xp1 = createXpath();
            Xpaths.Xpath.DataBinding db1 = createDataBinding();
            xp1.setId("x3");
            db1.setXpath(INVOICE_ITEMS_NAME_XPATH);
            db1.setStoreItemID(STORE_ITEM_ID_OF_DATA_PART);
            xp1.setDataBinding(db1);
            xPathsPart.getJaxbElement().getXpath().add(xp1);
           
            //addPropertiesPart(xPathsPart, STORE_ITEM_ID_OF_XPATHS_PART);
           
        }

        private  CustomXmlDataStoragePart injectCustomXmlDataStoragePart(Part parent) throws Exception {

            org.docx4j.openpackaging.parts.CustomXmlDataStoragePart customXmlDataStoragePart =
                    new org.docx4j.openpackaging.parts.CustomXmlDataStoragePart();
            // Defaults to /customXml/item1.xml

            CustomXmlDataStorage data = new CustomXmlDataStorageImpl();
            data.setDocument(createCustomXmlDocument(new File(DATA_XML_FILE)));

            customXmlDataStoragePart.setData(data);
            parent.addTargetPart(customXmlDataStoragePart, RelationshipsPart.AddPartBehaviour.RENAME_IF_NAME_EXISTS);
           
            return customXmlDataStoragePart;
        }


        private void addPropertiesPart(Part customXmlDataStoragePart, String itemID) throws InvalidFormatException {
            CustomXmlDataStoragePropertiesPart part = new CustomXmlDataStoragePropertiesPart();

            org.docx4j.customXmlProperties.ObjectFactory of = new org.docx4j.customXmlProperties.ObjectFactory();

            DatastoreItem dsi = of.createDatastoreItem();
            String newItemId = itemID;
            dsi.setItemID(newItemId);

            part.setJaxbElement(dsi );

            customXmlDataStoragePart.addTargetPart(part);
        }

        private Xpaths.Xpath.DataBinding createDataBinding() {
            return new org.opendope.xpaths.ObjectFactory().createXpathsXpathDataBinding();
        }

        private Xpaths.Xpath createXpath() {
            return new org.opendope.xpaths.ObjectFactory().createXpathsXpath();
        }


        public void createDocumentWithRepeats() {

            ObjectFactory wmlObjectFactory = new ObjectFactory();
               
                Body body = getMainDocumentPart().getJaxbElement().getBody();

            // Create object for p
            P p = wmlObjectFactory.createP();
            body.getContent().add( p);
            // Create object for tbl (wrapped in JAXBElement)
            Tbl tbl = wmlObjectFactory.createTbl();
            JAXBElement<org.docx4j.wml.Tbl> tblWrapped = wmlObjectFactory.createBodyTbl(tbl);
            body.getContent().add( tblWrapped);
            // Create object for tr
            Tr tr = wmlObjectFactory.createTr();
            tbl.getContent().add( tr);
            // Create object for tc (wrapped in JAXBElement)
            Tc tc = wmlObjectFactory.createTc();
            JAXBElement<org.docx4j.wml.Tc> tcWrapped = wmlObjectFactory.createTrTc(tc);
            tr.getContent().add( tcWrapped);
            // Create object for p
            P p2 = wmlObjectFactory.createP();
            tc.getContent().add( p2);
            // Create object for r
            R r = wmlObjectFactory.createR();
            p2.getContent().add( r);
            // Create object for t (wrapped in JAXBElement)
            Text text = wmlObjectFactory.createText();
            JAXBElement<org.docx4j.wml.Text> textWrapped = wmlObjectFactory.createRT(text);
            r.getContent().add( textWrapped);
            text.setValue(ITEM_TEXT);
            // Create object for tcPr
            TcPr tcpr = wmlObjectFactory.createTcPr();
            tc.setTcPr(tcpr);
            // Create object for tcW
            TblWidth tblwidth = wmlObjectFactory.createTblWidth();
            tcpr.setTcW(tblwidth);
            tblwidth.setW( BigInteger.valueOf(TABLE_WIDTH_6771) );
            tblwidth.setType(DXA_TEXT);
            // Create object for tc (wrapped in JAXBElement)
            Tc tc2 = wmlObjectFactory.createTc();
            JAXBElement<org.docx4j.wml.Tc> tcWrapped2 = wmlObjectFactory.createTrTc(tc2);
            tr.getContent().add( tcWrapped2);
            // Create object for p
            P p3 = wmlObjectFactory.createP();
            tc2.getContent().add( p3);
            // Create object for r
            R r2 = wmlObjectFactory.createR();
            p3.getContent().add( r2);
            // Create object for t (wrapped in JAXBElement)
            Text text2 = wmlObjectFactory.createText();
            JAXBElement<org.docx4j.wml.Text> textWrapped2 = wmlObjectFactory.createRT(text2);
            r2.getContent().add( textWrapped2);
            text2.setValue(PRICE_TEXT);
            // Create object for tcPr
            TcPr tcpr2 = wmlObjectFactory.createTcPr();
            tc2.setTcPr(tcpr2);
            // Create object for tcW
            TblWidth tblwidth2 = wmlObjectFactory.createTblWidth();
            tcpr2.setTcW(tblwidth2);
            tblwidth2.setW( BigInteger.valueOf(TABLE_WIDTH_2268) );
            tblwidth2.setType(DXA_TEXT);
           
            // The repeat
           
            // Create object for sdt (wrapped in JAXBElement)
            CTSdtRow sdtrow = wmlObjectFactory.createCTSdtRow();
            JAXBElement<org.docx4j.wml.CTSdtRow> sdtrowWrapped = wmlObjectFactory.createTblSdt(sdtrow);
            tbl.getContent().add( sdtrowWrapped);
            // Create object for sdtPr
            SdtPr sdtpr = wmlObjectFactory.createSdtPr();
            sdtrow.setSdtPr(sdtpr);
            // Create object for alias (wrapped in JAXBElement)
            SdtPr.Alias sdtpralias = wmlObjectFactory.createSdtPrAlias();
            JAXBElement<org.docx4j.wml.SdtPr.Alias> sdtpraliasWrapped = wmlObjectFactory.createSdtPrAlias(sdtpralias);
            sdtpr.getRPrOrAliasOrLock().add( sdtpraliasWrapped);
            sdtpralias.setVal(REPEAT_TEXT);
            // Create object for tag
            Tag tag = wmlObjectFactory.createTag();
            sdtpr.getRPrOrAliasOrLock().add( tag);
            tag.setVal(OD_REPEAT_X2);
            // Create object for id
            Id id = wmlObjectFactory.createId();
            sdtpr.getRPrOrAliasOrLock().add( id);
            id.setVal( BigInteger.valueOf(RANDOM_ID_2) );
            // Create object for tag
            Tag tag2 = wmlObjectFactory.createTag();
            sdtpr.setTag(tag2);
            tag2.setVal(OD_REPEAT_X2);
            // Create object for id
            Id id2 = wmlObjectFactory.createId();
            sdtpr.setId(id2);
            id2.setVal( BigInteger.valueOf(RANDOM_ID_2) );
           
            // The repeat's contents
           
            // Create object for sdtContent
            CTSdtContentRow sdtcontentrow = wmlObjectFactory.createCTSdtContentRow();
            sdtrow.setSdtContent(sdtcontentrow);
            // Create object for tr
            Tr tr2 = wmlObjectFactory.createTr();
            sdtcontentrow.getContent().add( tr2);
           
           
            // Create object for sdt (wrapped in JAXBElement)
            CTSdtCell sdtcell = wmlObjectFactory.createCTSdtCell();
            JAXBElement<org.docx4j.wml.CTSdtCell> sdtcellWrapped = wmlObjectFactory.createTrSdt(sdtcell);
            tr2.getContent().add( sdtcellWrapped);
            // Create object for sdtPr
            SdtPr sdtpr2 = wmlObjectFactory.createSdtPr();
            sdtcell.setSdtPr(sdtpr2);
           
            // Create object for dataBinding
            CTDataBinding databinding = wmlObjectFactory.createCTDataBinding();
            sdtpr2.setDataBinding(databinding);
            databinding.setStoreItemID(STORE_ITEM_ID_OF_DATA_PART);  // you'll need to alter this
            databinding.setXpath(INVOICE_ITEMS_NAME_XPATH);
            // Create object for alias (wrapped in JAXBElement)
            SdtPr.Alias sdtpralias2 = wmlObjectFactory.createSdtPrAlias();
            JAXBElement<org.docx4j.wml.SdtPr.Alias> sdtpraliasWrapped2 = wmlObjectFactory.createSdtPrAlias(sdtpralias2);
            sdtpr2.getRPrOrAliasOrLock().add( sdtpraliasWrapped2);
            sdtpralias2.setVal(DESCRIPTION_TEXT);
            // Create object for tag
            Tag tag3 = wmlObjectFactory.createTag();
            sdtpr2.getRPrOrAliasOrLock().add( tag3);
            tag3.setVal(DESCRIPTION_OD_XPATH_X3);
            // Create object for id
            Id id3 = wmlObjectFactory.createId();
            sdtpr2.getRPrOrAliasOrLock().add( id3);
            id3.setVal( BigInteger.valueOf(RANDOM_ID_1) );
           
            // Create object for text (wrapped in JAXBElement)
            CTSdtText sdttext = wmlObjectFactory.createCTSdtText();
            JAXBElement<org.docx4j.wml.CTSdtText> sdttextWrapped = wmlObjectFactory.createSdtPrText(sdttext);
            sdtpr2.getRPrOrAliasOrLock().add( sdttextWrapped);
            // Create object for tag
            Tag tag4 = wmlObjectFactory.createTag();
            sdtpr2.setTag(tag4);
            tag4.setVal(DESCRIPTION_OD_XPATH_X3);  // you'll need to alter this
            // Create object for id
            Id id4 = wmlObjectFactory.createId();
            sdtpr2.setId(id4);
            id4.setVal( BigInteger.valueOf(RANDOM_ID_1) );
            // Create object for sdtContent
            CTSdtContentCell sdtcontentcell = wmlObjectFactory.createCTSdtContentCell();
            sdtcell.setSdtContent(sdtcontentcell);
            // Create object for tc (wrapped in JAXBElement)
            Tc tc3 = wmlObjectFactory.createTc();
            JAXBElement<org.docx4j.wml.Tc> tcWrapped3 = wmlObjectFactory.createCTSdtContentCellTc(tc3);
            sdtcontentcell.getContent().add( tcWrapped3);
            // Create object for p
            P p4 = wmlObjectFactory.createP();
            tc3.getContent().add( p4);
            // Create object for r
            R r3 = wmlObjectFactory.createR();
            p4.getContent().add( r3);
            // Create object for t (wrapped in JAXBElement)
            Text text3 = wmlObjectFactory.createText();
            JAXBElement<org.docx4j.wml.Text> textWrapped3 = wmlObjectFactory.createRT(text3);
            r3.getContent().add( textWrapped3);
            text3.setValue(APPLES_TEXT);
            // Create object for tcPr
            TcPr tcpr3 = wmlObjectFactory.createTcPr();
            tc3.setTcPr(tcpr3);
            // Create object for tcW
            TblWidth tblwidth3 = wmlObjectFactory.createTblWidth();
            tcpr3.setTcW(tblwidth3);
            tblwidth3.setW( BigInteger.valueOf( TABLE_WIDTH_6771) );
            tblwidth3.setType(DXA_TEXT);
           
           
           
           
           
            // Create object for sdt (wrapped in JAXBElement)
            CTSdtCell sdtcell2 = wmlObjectFactory.createCTSdtCell();
            JAXBElement<org.docx4j.wml.CTSdtCell> sdtcellWrapped2 = wmlObjectFactory.createTrSdt(sdtcell2);
            tr2.getContent().add( sdtcellWrapped2);
            // Create object for sdtPr
            SdtPr sdtpr3 = wmlObjectFactory.createSdtPr();
            sdtcell2.setSdtPr(sdtpr3);
            // Create object for dataBinding
            CTDataBinding databinding3 = wmlObjectFactory.createCTDataBinding();
            sdtpr3.setDataBinding(databinding3);
            databinding3.setStoreItemID(STORE_ITEM_ID_OF_DATA_PART);
            databinding3.setXpath(INVOICE_ITEMS_PRICE_XPATH);
            // Create object for alias (wrapped in JAXBElement)
            SdtPr.Alias sdtpralias3 = wmlObjectFactory.createSdtPrAlias();
            JAXBElement<org.docx4j.wml.SdtPr.Alias> sdtpraliasWrapped3 = wmlObjectFactory.createSdtPrAlias(sdtpralias3);
            sdtpr3.getRPrOrAliasOrLock().add( sdtpraliasWrapped3);
            sdtpralias3.setVal(PRICE_TEXT);
            // Create object for tag
            Tag tag5 = wmlObjectFactory.createTag();
            sdtpr3.getRPrOrAliasOrLock().add( tag5);
            tag5.setVal(PRICE_OD_XPATH_X4);
            // Create object for id
            Id id5 = wmlObjectFactory.createId();
            sdtpr3.getRPrOrAliasOrLock().add( id5);
            id5.setVal( BigInteger.valueOf(RANDOM_ID_3) );
            // Create object for placeholder (wrapped in JAXBElement)
            CTPlaceholder placeholder3 = wmlObjectFactory.createCTPlaceholder();
            JAXBElement<org.docx4j.wml.CTPlaceholder> placeholderWrapped3 = wmlObjectFactory.createSdtPrPlaceholder(placeholder3);
            sdtpr3.getRPrOrAliasOrLock().add( placeholderWrapped3);
            // Create object for docPart
            CTPlaceholder.DocPart placeholderdocpart3 = wmlObjectFactory.createCTPlaceholderDocPart();
            placeholder3.setDocPart(placeholderdocpart3);
            placeholderdocpart3.setVal(PLACEHOLDER_VALUE);

            // Create object for text (wrapped in JAXBElement)
            CTSdtText sdttext2 = wmlObjectFactory.createCTSdtText();
            JAXBElement<org.docx4j.wml.CTSdtText> sdttextWrapped2 = wmlObjectFactory.createSdtPrText(sdttext2);
            sdtpr3.getRPrOrAliasOrLock().add( sdttextWrapped2);
            // Create object for tag
            Tag tag6 = wmlObjectFactory.createTag();
            sdtpr3.setTag(tag6);
            tag6.setVal(PRICE_OD_XPATH_X4);
            // Create object for id
            Id id6 = wmlObjectFactory.createId();
            sdtpr3.setId(id6);
            id6.setVal( BigInteger.valueOf(RANDOM_ID_3) );
            // Create object for sdtContent
            CTSdtContentCell sdtcontentcell2 = wmlObjectFactory.createCTSdtContentCell();
            sdtcell2.setSdtContent(sdtcontentcell2);
            // Create object for tc (wrapped in JAXBElement)
            Tc tc4 = wmlObjectFactory.createTc();
            JAXBElement<org.docx4j.wml.Tc> tcWrapped4 = wmlObjectFactory.createCTSdtContentCellTc(tc4);
            sdtcontentcell2.getContent().add( tcWrapped4);
            // Create object for p
            P p5 = wmlObjectFactory.createP();
            tc4.getContent().add( p5);
            // Create object for r
            R r4 = wmlObjectFactory.createR();
            p5.getContent().add( r4);
            // Create object for t (wrapped in JAXBElement)
            Text text4 = wmlObjectFactory.createText();
            JAXBElement<org.docx4j.wml.Text> textWrapped4 = wmlObjectFactory.createRT(text4);
            r4.getContent().add( textWrapped4);
            text4.setValue(TWENTY_DOLLARS);
            // Create object for tcPr
            TcPr tcpr4 = wmlObjectFactory.createTcPr();
            tc4.setTcPr(tcpr4);
            // Create object for tcW
            TblWidth tblwidth4 = wmlObjectFactory.createTblWidth();
            tcpr4.setTcW(tblwidth4);
            tblwidth4.setW( BigInteger.valueOf(TABLE_WIDTH_2268) );
            tblwidth4.setType(DXA_TEXT);
            // Create object for tblPr
            TblPr tblpr = wmlObjectFactory.createTblPr();
            tbl.setTblPr(tblpr);
            // Create object for tblStyle
            CTTblPrBase.TblStyle tblprbasetblstyle = wmlObjectFactory.createCTTblPrBaseTblStyle();
            tblpr.setTblStyle(tblprbasetblstyle);
            tblprbasetblstyle.setVal(TABLE_GRID);
            // Create object for tblW
            TblWidth tblwidth5 = wmlObjectFactory.createTblWidth();
            tblpr.setTblW(tblwidth5);
            tblwidth5.setW( BigInteger.valueOf(ZERO) );
            tblwidth5.setType(AUTO_TEXT);
            // Create object for tblLook
            CTTblLook tbllook = wmlObjectFactory.createCTTblLook();
            tblpr.setTblLook(tbllook);
            tbllook.setVal(TABLE_LOOK_VALUE);
            tbllook.setFirstColumn(org.docx4j.sharedtypes.STOnOff.ONE);
            tbllook.setFirstRow(org.docx4j.sharedtypes.STOnOff.ONE);
            tbllook.setLastColumn(org.docx4j.sharedtypes.STOnOff.ZERO);
            tbllook.setLastRow(org.docx4j.sharedtypes.STOnOff.ZERO);
            tbllook.setNoHBand(org.docx4j.sharedtypes.STOnOff.ZERO);
            tbllook.setNoVBand(org.docx4j.sharedtypes.STOnOff.ONE);
            // Create object for tblGrid
            TblGrid tblgrid = wmlObjectFactory.createTblGrid();
            tbl.setTblGrid(tblgrid);
            // Create object for gridCol
            TblGridCol tblgridcol = wmlObjectFactory.createTblGridCol();
            tblgrid.getGridCol().add( tblgridcol);
            tblgridcol.setW( BigInteger.valueOf( TABLE_WIDTH_6771) );
            // Create object for gridCol
            TblGridCol tblgridcol2 = wmlObjectFactory.createTblGridCol();
            tblgrid.getGridCol().add( tblgridcol2);
            tblgridcol2.setW( BigInteger.valueOf(TABLE_WIDTH_2268) );
            // Create object for p
            P p6 = wmlObjectFactory.createP();
            body.getContent().add( p6);

        }

        private CustomXmlDataStoragePart injectCustomXmlDataStoragePart(Part parent, File inputXmlFile) throws Exception {
            org.docx4j.openpackaging.parts.CustomXmlDataStoragePart customXmlDataStoragePart =
                    new org.docx4j.openpackaging.parts.CustomXmlDataStoragePart();
            // Defaults to /customXml/item1.xml
            CustomXmlDataStorage data = new CustomXmlDataStorageImpl();
            data.setDocument(createCustomXmlDocument(inputXmlFile));

            customXmlDataStoragePart.setData(data);
            parent.addTargetPart(customXmlDataStoragePart, RelationshipsPart.AddPartBehaviour.RENAME_IF_NAME_EXISTS);

            return customXmlDataStoragePart;
        }

        private org.w3c.dom.Document createCustomXmlDocument(File xmlFile) throws ParserConfigurationException, IOException, SAXException {
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            documentBuilderFactory.setNamespaceAware(true);
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            org.w3c.dom.Document document = documentBuilder.parse(xmlFile);

            return document;

        }
    }
 
Parsed in 0.060 seconds, using GeSHi 1.0.8.4


Your/this code authors/creates a "template" document, containing sample data.

To create an instance document, you need to merge it with data. To do this, use https://github.com/plutext/docx4j/blob/ ... sions.java

Re: Unable to prorgrammatically create Word document with re

PostPosted: Mon Jun 05, 2017 3:47 pm
by manish.imaginea
Thank you very much Jason! This worked very well.
I've gone ahead and modified the code a bit, it now does both things - ie - it injects the content controls and then injects XML and performs the repeat binding - I've thus merged your code and the one in ContentControlBindingExtensions.
Code: Select all
import org.docx4j.customXmlProperties.DatastoreItem;
import org.docx4j.customXmlProperties.SchemaRefs;
import org.docx4j.jaxb.Context;
import org.docx4j.model.datastorage.CustomXmlDataStorage;
import org.docx4j.model.datastorage.CustomXmlDataStorageImpl;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.exceptions.InvalidFormatException;
import org.docx4j.openpackaging.io.SaveToZipFile;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.CustomXmlDataStoragePart;
import org.docx4j.openpackaging.parts.CustomXmlDataStoragePropertiesPart;
import org.docx4j.openpackaging.parts.Part;
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
import org.docx4j.wml.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.util.UUID;

public class RepeatBindDemo {
    private static final String INPUT_FILE_PATH = System.getProperty("user.dir") + "/input_docs/empty.docx";
    private static final String INPUT_XML_FILE_PATH = System.getProperty("user.dir") + "/input_docs/invoice-data.xml";
    private static final String DEFAULT_NAMESPACE = "http://default.com";
    private static final String OD_REPEAT_X2 = "od:repeat=x3";
    public static final String INVOICE_ITEM_NAME_XPATH = "/invoice[1]/items/item[1]";
    private static final String OUTPUT_FILE_PATH = System.getProperty("user.dir") + "/invoice-output.docx";
    private static Logger log = LoggerFactory.getLogger(RepeatBindDemo.class);
    private final WordprocessingMLPackage inputWordPackage;
    private final WordprocessingMLPackage outputWordPackage;
    private CustomXmlDataStoragePart customXmlDataStoragePart;
    private String storeItemID;


    public RepeatBindDemo() throws Docx4JException {
        inputWordPackage = WordprocessingMLPackage.load(new File(INPUT_FILE_PATH));
        outputWordPackage = (WordprocessingMLPackage) inputWordPackage.clone();
    }

    public static void main(String[] args) throws Exception {
        RepeatBindDemo repeatBindDemo = new RepeatBindDemo();
        repeatBindDemo.injectRepeatsInDocxFile();
    }

    public void injectRepeatsInDocxFile() throws Exception {
//        We need to inject the following XML
//      <w:sdt>
//        <w:sdtPr>
//          <w:alias w:val="Repeat"/>
//          <w:tag w:val="od:repeat=x2"/>
//          <w:id w:val="1418037945"/>
//          <w:placeholder>
//            <w:docPart w:val="DefaultPlaceholder_22675703"/>
//          </w:placeholder>
//        </w:sdtPr>
//        <w:sdtContent>
//          <w:tr>
//            <w:sdt>
//              <w:sdtPr>
//                <w:alias w:val="Description"/>
//                <w:tag w:val="Description=Description&amp;od:xpath=x3"/>
//                <w:id w:val="1418037946"/>
//                <w:placeholder>
//                  <w:docPart w:val="DefaultPlaceholder_22675703"/>
//                </w:placeholder>
//                <w:dataBinding w:xpath="/invoice[1]/items/item[1]/name" w:storeItemID="{8B049945-9DFE-4726-9DE9-CF5691E53858}"/>
//                <w:text/>
//              </w:sdtPr>
//              <w:sdtContent>
//                <w:tc>
//                  <w:tcPr>
//                    <w:tcW w:w="6771" w:type="dxa"/>
//                  </w:tcPr>
//                  <w:p>
//                    <w:r>
//                      <w:t>apples
//                </w:t>
//                    </w:r>
//                  </w:p>
//                </w:tc>
//              </w:sdtContent>
//            </w:sdt>

        // inject custom XML (in a properties part) and store the ITEM_ID to be used later
        customXmlDataStoragePart = injectCustomXmlDataStoragePart(outputWordPackage.getMainDocumentPart(),
                new java.io.File(INPUT_XML_FILE_PATH));
        storeItemID = addPropertiesPartForSimpleBind(customXmlDataStoragePart, DEFAULT_NAMESPACE);

        // create top level sdt and sdtpr block
        Tbl topLevelTable = createTbl();
        SdtRun topLevelSdtRun = createSdtRun();
        topLevelTable.getContent().add(topLevelSdtRun);
        SdtPr topLevelSdtPr = createSdtPr();
        topLevelSdtRun.setSdtPr(topLevelSdtPr);
        SdtPr.Alias alias = createSdtPrAlias();
        alias.setVal("Repeat");
        Tag repeatTag = createTag();
        repeatTag.setVal("od:repeat=x3"); //FIXME: this is hardcoded, needs to be parameterized.
        topLevelSdtPr.setTag(repeatTag);
        topLevelSdtPr.setId();

        //create nested sdtContent block inside the sdtrun above
        CTSdtContentRun topLevelSdtContent = createCTSdtContentRun();
        topLevelSdtRun.setSdtContent(topLevelSdtContent);

        // create the structure
        // Top level tr
        Tr topLevelTr = getWmlObjectFactory().createTr();
        topLevelSdtContent.getContent().add(topLevelTr);
        SdtRun internalSdtRun = createSdtRun();
        topLevelTr.getContent().add(internalSdtRun);
        SdtPr internalSdtPr = createSdtPr();
        internalSdtRun.setSdtPr(internalSdtPr);
        SdtPr.Alias internalSdtPrAlias = createSdtPrAlias();
        alias.setVal("Description");
        Tag internalTag = createTag();
        internalTag.setVal("Description=Description&od:xpath=x3"); //FIXME : od:xpath=x3 needs to be paramterized.
        internalSdtPr.setId();
        internalSdtPr.setTag(internalTag);

        // create the initial data binding
        CTDataBinding dataBinding = createDataBinding();
        dataBinding.setXpath(INVOICE_ITEM_NAME_XPATH);
        dataBinding.setStoreItemID(storeItemID);
        internalSdtPr.setDataBinding(dataBinding);

        // Create the internal content, this gets bound.
        CTSdtContentRun internalSdtContent = createCTSdtContentRun();
        Tc tc = createTC();
        internalSdtContent.getContent().add(tc);
        TcPr tcPr = createTcPr();

        TblWidth tableWidth = createTcW();
        tableWidth.setW(BigInteger.valueOf(6771));
        tableWidth.setType("dxa"); // FIXME What is "dxa" and why is it required?
        tcPr.setTcW(tableWidth);
        tc.setTcPr(tcPr);

        P paragraph = createP();
        R row = createR();

        Text text = createText();
        text.setValue("FOOBAR");
        row.getContent().add(text);
        paragraph.getContent().add(row);
        tc.getContent().add(paragraph);

        internalSdtRun.setSdtContent(internalSdtContent);

        //finally
        outputWordPackage.getMainDocumentPart().getContent().add(topLevelTable);
        SaveToZipFile saver = new SaveToZipFile(outputWordPackage);
        saver.save(OUTPUT_FILE_PATH);
    }

    private Tbl createTbl(){
        return getWmlObjectFactory().createTbl();
    }
    private Text createText() {
        return getWmlObjectFactory().createText();
    }
    private R createR(){
        return getWmlObjectFactory().createR();
    }

    private P createP() {
        return getWmlObjectFactory().createP();
    }

    private TblWidth createTcW() {
        return getWmlObjectFactory().createTblWidth();
    }

    private TcPr createTcPr() {
        return getWmlObjectFactory().createTcPr();
    }

    private Tc createTC(){
        return getWmlObjectFactory().createTc();
    }
    private CTDataBinding createDataBinding(){
        return getWmlObjectFactory().createCTDataBinding();
    }
    private Id createId(){
        return getWmlObjectFactory().createId();
    }

    private CTSdtContentRun createCTSdtContentRun() {
        return getWmlObjectFactory().createCTSdtContentRun();
    }

    private Tag createTag() {
        return getWmlObjectFactory().createTag();
    }

    private SdtPr.Alias createSdtPrAlias() {
        return getWmlObjectFactory().createSdtPrAlias();
    }

    private SdtPr createSdtPr() {
        return getWmlObjectFactory().createSdtPr();
    }

    private SdtRun createSdtRun() {
        return getWmlObjectFactory().createSdtRun();
    }

    private ObjectFactory getWmlObjectFactory() {
        return Context.getWmlObjectFactory();
    }

    private String addPropertiesPartForSimpleBind(CustomXmlDataStoragePart customXmlDataStoragePart, String namespace) throws InvalidFormatException {
        CustomXmlDataStoragePropertiesPart customDataStoragePart = new CustomXmlDataStoragePropertiesPart();

        org.docx4j.customXmlProperties.ObjectFactory of = new org.docx4j.customXmlProperties.ObjectFactory();

        DatastoreItem dsi = of.createDatastoreItem();
        String newItemId = "{" + UUID.randomUUID().toString().toUpperCase() + "}";
        dsi.setItemID(newItemId);

        SchemaRefs srefs = of.createSchemaRefs();
        dsi.setSchemaRefs(srefs);

        SchemaRefs.SchemaRef sref = of.createSchemaRefsSchemaRef();
        sref.setUri(namespace);

        srefs.getSchemaRef().add(sref);

        customDataStoragePart.setJaxbElement(dsi);
        customXmlDataStoragePart.addTargetPart(customDataStoragePart, RelationshipsPart.AddPartBehaviour.RENAME_IF_NAME_EXISTS);
        return newItemId;
    }

    public static CustomXmlDataStoragePart injectCustomXmlDataStoragePart(Part parent, File inputXmlFile) throws Exception {
        org.docx4j.openpackaging.parts.CustomXmlDataStoragePart customXmlDataStoragePart =
                new org.docx4j.openpackaging.parts.CustomXmlDataStoragePart();
        // Defaults to /customXml/item1.xml
        CustomXmlDataStorage data = new CustomXmlDataStorageImpl();
        data.setDocument(createCustomXmlDocument(inputXmlFile));

        customXmlDataStoragePart.setData(data);
        parent.addTargetPart(customXmlDataStoragePart, RelationshipsPart.AddPartBehaviour.RENAME_IF_NAME_EXISTS);

        return customXmlDataStoragePart;
    }

    public static Document createCustomXmlDocument(File xmlFile) throws ParserConfigurationException, IOException, SAXException {
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        documentBuilderFactory.setNamespaceAware(true);
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        Document domDocument = documentBuilder.parse(xmlFile);
        return domDocument;
    }
}




I tried to create a new example and send a pull request but I"m unable to run the example's main method from my IDE. As promised I'd like to contribute this example back to the code base.