Search code examples
javams-worddocx4j

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?


Solution

  • 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.