首页 > 解决方案 > 替换文本框 docx4j 中的占位符

问题描述

我正在使用 docx4j。我有一个word文档,我在其中画了一个文本框。在那个文本框中,我有“dummyPlaceHolderInTextBox”这个词。我想用“testString”替换这个占位符,如下面我调用的方法所示。尽管我在 getAllElementFromObject 方法中将类更改为 CTTextbox.class,但这不起作用。我怎样才能做到这一点?

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

代替

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);
                }
            }
        }

获取所有元素

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;
}

标签: javadocx4j

解决方案


我猜你的文本框看起来像:

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

在此示例中,请注意它使用 2 种替代格式表示:

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

那是一个 org.docx4j.wml.CTTxbxContent

您的代码假定每个父对象都实现 ContentAccessor。我怀疑情况是否如此。

因此,如果您想做这样的事情,请尝试使用 TraversalUtil 更强大的 get children 的 org.docx4j.finders.ClassFinder。见https://github.com/plutext/docx4j/blob/master/docx4j-samples-docx4j/src/main/java/org/docx4j/samples/TraverseFind.java

在这里,我的包含“testString”的运行没有拆分,但在您的情况下这可能是一个问题(例如拼写/语法检查或编辑会话)。

作为一般性评论,这似乎是一种非常费力的 docgen 方式。有些人使用变量替换:https ://github.com/plutext/docx4j/blob/master/docx4j-samples-docx4j/src/main/java/org/docx4j/samples/VariableReplace.java但正如它所说的那样,对于复杂文档 我建议将内容控件绑定到 XML 部件(通过 XPath)


推荐阅读