user1358852
user1358852

Reputation:

Sample code for docx4j, java and MS Word templates

I'm starting to work with some content controls (using the Developer Tools menu) in a MS Word .dotx template. What I would like to do is add some text programatically using Java and the docx4j library. Does anyone know where I can find code examples of this?

Below I have added the XML representation of the content control that I would like to work with. In this case I would like to replace the text "Klicken Sie hier, um Text einzugeben." wih my own text.

-<w:sdt>
-<w:sdtPr>
-<w:rPr>
<w:rStyle w:val="CAPITALS"/>
</w:rPr>
<w:alias w:val="Zeugnisart"/>
<w:tag w:val="Zeugnisart"/>
<w:id w:val="-1662376684"/>
-<w:placeholder>
<w:docPart w:val="DefaultPlaceholder_1082065158"/>
</w:placeholder>
<w:showingPlcHdr/>
<w:text/>
</w:sdtPr>
-<w:sdtEndPr>
-<w:rPr>
<w:rStyle w:val="Absatz-Standardschriftart"/>
<w:rFonts w:hAnsiTheme="minorHAnsi" w:asciiTheme="minorHAnsi"/>
<w:b w:val="0"/>
<w:bCs w:val="0"/>
<w:smallCaps w:val="0"/>
<w:spacing w:val="0"/>
<w:sz w:val="22"/>
</w:rPr>
</w:sdtEndPr>
<w:sdtContent>
<w:p w:rsidP="00D144D4" w:rsidRDefault="006D40B2" w:rsidR="00D144D4">
-<w:r w:rsidRPr="00372E7E">
-<w:rPr>
<w:rStyle w:val="Platzhaltertext"/>
</w:rPr>
<w:t>Klicken Sie hier, um Text einzugeben.</w:t>
</w:r>
</w:p>
</w:sdtContent>
</w:sdt>

I have attempted following code but without success:

private void replacePlaceholder(WordprocessingMLPackage template, String name, String placeholder ) throws Exception{       

    MainDocumentPart documentPart = template.getMainDocumentPart();
    HashMap<String, String> mappings = new HashMap<String, String>();
    mappings.put("Zeugnisart", "a new value");
    documentPart.variableReplace(mappings);
}

private void writeDocxToStream(WordprocessingMLPackage template, String target) throws IOException, Docx4JException {
    File f = new File(target);
    template.save(f);
}

Any tip on where I am going wrong?

Upvotes: 0

Views: 6781

Answers (2)

user1358852
user1358852

Reputation:

I have managed to solve this issue using the following code:

private static List<Object> getAllElementFromObject(Object obj, Class<?> toSearch) {

    List<Object> result = new ArrayList<Object>();
    if (obj instanceof JAXBElement) obj = ((JAXBElement<?>) obj).getValue();

    if (obj.getClass().equals(toSearch))
        result.add(obj); 
    else if (obj instanceof ContentAccessor) {
        List<?> children = ((ContentAccessor) obj).getContent();
        for (Object child : children) {
            result.addAll(getAllElementFromObject(child, toSearch));
        }
    }
    return result; 
}


private void replaceTextValue(WordprocessingMLPackage template, String name, String placeholder ) throws Exception{     

    List<Object> texts = getAllElementFromObject(template.getMainDocumentPart(), SdtBlock.class);

    for (Object text : texts) {         

        SdtBlock textElement = (SdtBlock) text;
        List<Object> cList = textElement.getSdtContent().getContent();

        SdtPr pr = textElement.getSdtPr();
        List<Object> al = pr.getRPrOrAliasOrLock();

        for (Object alias : al) {   // go through all SdtPr objects

            if ( alias.getClass().toString().contains("org.docx4j.wml.Tag")) {

                String CTagVal = ((org.docx4j.wml.Tag) alias).getVal(); 

                if (CTagVal.equalsIgnoreCase(placeholder))  {   

                ClassFinder finder = new ClassFinder(Text.class);
                new TraversalUtil(cList, finder);

                for (Object o : finder.results) {
                    Object o2 = XmlUtils.unwrap(o);
                    if (o2 instanceof org.docx4j.wml.Text) {
                    org.docx4j.wml.Text txt = (org.docx4j.wml.Text)o2;
                    txt.setValue(name);
                    } else {
                    System.out.println( XmlUtils.marshaltoString(o, true, true));
                    }
                    }

                }

        }           

    }
}
}

I call the replaceTextValue method to change the text inside the "Klicken Sie hier, um Text einzugeben." text inside the tags. There may be a more efficient way to do this but this is what I have found to work.

Upvotes: 1

JasonPlutext
JasonPlutext

Reputation: 15863

From your clarification, it seems like you just want VariableReplace.

If you wanted instead to bind its content to an XML part (via XPath), see ContentControlsMergeXML. Of course you'd need to set up the databinding first (via a w:dataBinding element in the SdtPr).

Upvotes: 1

Related Questions