-1

I am using docx4j. I have word document where i drew a text box. In that text box, i have the word "dummyPlaceHolderInTextBox". I would like to replace this placeholder word with "testString" as shown in the method i called below. This is not working although i changed the class to CTTextbox.class in the getAllElementFromObject method. How can i do this?

 replacePlaceholder(wp, "testString", "dummyPlaceHolderInTextBox")

Replace

private static void replacePlaceholder(WordprocessingMLPackage template, String name, String placeholder) {
            List<Object> texts = getAllElementFromObject(template.getMainDocumentPart(), CTTextbox.class);
            for (Object text : texts) {
                Text textElement = (Text) text;
    
                if (textElement != null && textElement.getValue() != null
                        && placeholder != null && textElement.getValue().equals(placeholder)) {
                    textElement.setValue(name);
                }
            }
        }

Get all elements

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;
}
Ninja Dude
  • 1,332
  • 4
  • 27
  • 54

1 Answers1

0

I guess your text box looks something like:

    <w:p w:rsidR="00000000" w:rsidRDefault="00880BC0">
        <w:r>
            <w:rPr>
                <w:noProof/>
            </w:rPr>
            <mc:AlternateContent>
                <mc:Choice Requires="wps">
                    <w:drawing>
                        <wp:anchor xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" allowOverlap="true" behindDoc="false" distB="45720" distL="114300" distR="114300" distT="45720" layoutInCell="true" locked="false" relativeHeight="251659264" simplePos="false" wp14:anchorId="19C599C7" wp14:editId="4CA921F6">
                            <wp:simplePos x="0" y="0"/>
                            <wp:positionH relativeFrom="column">
                                <wp:align>center</wp:align>
                            </wp:positionH>
                            <wp:positionV relativeFrom="paragraph">
                                <wp:posOffset>182880</wp:posOffset>
                            </wp:positionV>
                            <wp:extent cx="2360930" cy="1404620"/>
                            <wp:effectExtent b="11430" l="0" r="22860" t="0"/>
                            <wp:wrapSquare wrapText="bothSides"/>
                            <wp:docPr id="217" name="Text Box 2"/>
                            <wp:cNvGraphicFramePr>
                                <a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"/>
                            </wp:cNvGraphicFramePr>
                            <a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
                                <a:graphicData uri="http://schemas.microsoft.com/office/word/2010/wordprocessingShape">
                                    <wps:wsp xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape">
                                        <wps:cNvSpPr txBox="true">
                                            <a:spLocks noChangeArrowheads="true"/>
                                        </wps:cNvSpPr>
                                        <wps:spPr bwMode="auto">
                                            <a:xfrm>
                                                <a:off x="0" y="0"/>
                                                <a:ext cx="2360930" cy="1404620"/>
                                            </a:xfrm>
                                            <a:prstGeom prst="rect">
                                                <a:avLst/>
                                            </a:prstGeom>
                                            <a:solidFill>
                                                <a:srgbClr val="FFFFFF"/>
                                            </a:solidFill>
                                            <a:ln w="9525">
                                                <a:solidFill>
                                                    <a:srgbClr val="000000"/>
                                                </a:solidFill>
                                                <a:miter lim="800000"/>
                                                <a:headEnd/>
                                                <a:tailEnd/>
                                            </a:ln>
                                        </wps:spPr>
                                        <wps:txbx>
                                            <w:txbxContent>
                                                <w:p w:rsidP="00880BC0" w:rsidR="00880BC0" w:rsidRDefault="00880BC0">
                                                    <w:r>
                                                        <w:t>Some testString</w:t>
                                                    </w:r>
                                                </w:p>
                                            </w:txbxContent>
                                        </wps:txbx>
                                        <wps:bodyPr anchor="t" anchorCtr="false" bIns="45720" lIns="91440" rIns="91440" rot="0" tIns="45720" vert="horz" wrap="square">
                                            <a:spAutoFit/>
                                        </wps:bodyPr>
                                    </wps:wsp>
                                </a:graphicData>
                            </a:graphic>
                            <wp14:sizeRelH relativeFrom="margin">
                                <wp14:pctWidth>40000</wp14:pctWidth>
                            </wp14:sizeRelH>
                            <wp14:sizeRelV relativeFrom="margin">
                                <wp14:pctHeight>20000</wp14:pctHeight>
                            </wp14:sizeRelV>
                        </wp:anchor>
                    </w:drawing>
                </mc:Choice>
                <mc:Fallback>
                    <w:pict>
                        <v:shapetype xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml" coordsize="21600,21600" id="_x0000_t202" path="m,l,21600r21600,l21600,xe" o:spt="202.0">
                            <v:stroke joinstyle="miter"/>
                            <v:path gradientshapeok="t" o:connecttype="rect"/>
                        </v:shapetype>
                        <v:shape xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml" id="Text Box 2" style="position:absolute;margin-left:0;margin-top:14.4pt;width:185.9pt;height:110.6pt;z-index:251659264;visibility:visible;mso-wrap-style:square;mso-width-percent:400;mso-height-percent:200;mso-wrap-distance-left:9pt;mso-wrap-distance-top:3.6pt;mso-wrap-distance-right:9pt;mso-wrap-distance-bottom:3.6pt;mso-position-horizontal:center;mso-position-horizontal-relative:text;mso-position-vertical:absolute;mso-position-vertical-relative:text;mso-width-percent:400;mso-height-percent:200;mso-width-relative:margin;mso-height-relative:margin;v-text-anchor:top" type="#_x0000_t202" o:gfxdata="UEsDBBQAB..AAAAhwUAAAAA" o:spid="_x0000_s1026">
                            <v:textbox style="mso-fit-shape-to-text:t">
                                <w:txbxContent>
                                    <w:p w:rsidP="00880BC0" w:rsidR="00880BC0" w:rsidRDefault="00880BC0">
                                        <w:r>
                                            <w:t>Some testString</w:t>
                                        </w:r>
                                    </w:p>
                                </w:txbxContent>
                            </v:textbox>
                            <w10:wrap xmlns:w10="urn:schemas-microsoft-com:office:word" type="square"/>
                        </v:shape>
                    </w:pict>
                </mc:Fallback>
            </mc:AlternateContent>
        </w:r>
    </w:p>

In this example, notice that it is represented using 2 alternative formats:

  • v:textbox/w:txbxContent
  • wps:txbx/w:txbxContent

That's a org.docx4j.wml.CTTxbxContent

Your code assumes each parent object implements ContentAccessor. I doubt this is the case.

So if you want to do something like this, try org.docx4j.finders.ClassFinder which uses TraversalUtil's more robust get children. See https://github.com/plutext/docx4j/blob/master/docx4j-samples-docx4j/src/main/java/org/docx4j/samples/TraverseFind.java

Here my run containing "testString" wasn't split, but that could be a problem in your case (eg spelling/grammar checking, or editing sessions).

As a general comment, this seems a pretty laborious way to do docgen. Some people use variable replacement: https://github.com/plutext/docx4j/blob/master/docx4j-samples-docx4j/src/main/java/org/docx4j/samples/VariableReplace.java but as it says there, for complex documents I recommend binding content controls to an XML Part (via XPath)

JasonPlutext
  • 15,352
  • 4
  • 44
  • 84