Reputation:
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
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
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