Ellipse added with docx4j but not displayed in document

505 Views Asked by At

I'm adding an ellipse to a docx document via docx4j like this:

String xmlEllipse = getXmlEllipse();
Object ellipse = XmlUtils.unmarshalString(xmlEllipse);
Graphic ellipseGraphic = (Graphic) ((JAXBElement)ellipse).getValue();

Anchor anchor = new Anchor();
anchor.setGraphic(ellipseGraphic);

ObjectFactory factory = new ObjectFactory();
P paragraph = factory.createP();
R run = factory.createR();
paragraph.getContent().add(run);
Drawing drawing = factory.createDrawing();
run.getContent().add(drawing);
drawing.getAnchorOrInline().add(anchor);

WordprocessingMLPackage newDoc = WordprocessingMLPackage.createPackage();
newDoc.getMainDocumentPart().getContent().add(paragraph);

newDoc.save(new File(dirPath + outputFilePath));

The getXmlEllipse method is following:

private static String getXmlEllipse() {
        String xmlEllipse = ""
                + " <a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" xmlns:wps=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\">"
                + "     <a:graphicData uri=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\">"
                + "         <wps:wsp>"
                + "             <wps:cNvSpPr/>"
                + "             <wps:spPr>"
                + "                 <a:xfrm>"
                + "                     <a:off x=\"0\" y=\"0\"/>"
                + "                     <a:ext cx=\"130629\" cy=\"130629\"/>"
                + "                     </a:xfrm>"
                + "                 <a:prstGeom prst=\"ellipse\">"
                + "                     <a:avLst/>"
                + "                 </a:prstGeom>"
                + "             </wps:spPr>"
                + "             <wps:style>"
                + "                 <a:lnRef idx=\"2\">"
                + "                     <a:schemeClr val=\"accent1\">"
                + "                         <a:shade val=\"50000\"/>"
                + "                     </a:schemeClr>"
                + "                 </a:lnRef>"
                + "                 <a:fillRef idx=\"1\">"
                + "                     <a:schemeClr val=\"accent1\"/>"
                + "                 </a:fillRef>"
                + "                 <a:effectRef idx=\"0\">"
                + "                     <a:schemeClr val=\"accent1\"/>"
                + "                 </a:effectRef>"
                + "                 <a:fontRef idx=\"minor\">"
                + "                     <a:schemeClr val=\"lt1\"/>"
                + "                 </a:fontRef>"
                + "             </wps:style>"
                + "             <wps:bodyPr rot=\"0\" spcFirstLastPara=\"0\" vertOverflow=\"overflow\" horzOverflow=\"overflow\" vert=\"horz\" wrap=\"square\" lIns=\"91440\" tIns=\"45720\" rIns=\"91440\" bIns=\"45720\" numCol=\"1\" spcCol=\"0\" rtlCol=\"0\" fromWordArt=\"0\" anchor=\"ctr\" anchorCtr=\"0\" forceAA=\"0\" compatLnSpc=\"1\">"
                + "                 <a:prstTxWarp prst=\"textNoShape\">"
                + "                     <a:avLst/>"
                + "                 </a:prstTxWarp>"
                + "                 <a:noAutofit/>"
                + "             </wps:bodyPr>"
                + "         </wps:wsp>"
                + "     </a:graphicData>"
                + " </a:graphic>";

        return xmlEllipse;
    }

So I'm getting a docx document that appears to be empty when opened with proper editor. If I extract the zipped content of the docx and inspect the document.xml file I can see the ellipse graphic tag:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:ns8="http://schemas.openxmlformats.org/schemaLibrary/2006/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:ns12="http://schemas.openxmlformats.org/drawingml/2006/chartDrawing" xmlns:dgm="http://schemas.openxmlformats.org/drawingml/2006/diagram" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture" xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing" xmlns:dsp="http://schemas.microsoft.com/office/drawing/2008/diagram" xmlns:ns17="urn:schemas-microsoft-com:office:excel" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:ns21="urn:schemas-microsoft-com:office:powerpoint" xmlns:ns23="http://schemas.microsoft.com/office/2006/coverPageProps" xmlns:odx="http://opendope.org/xpaths" xmlns:odc="http://opendope.org/conditions" xmlns:odq="http://opendope.org/questions" xmlns:oda="http://opendope.org/answers" xmlns:odi="http://opendope.org/components" xmlns:odgm="http://opendope.org/SmartArt/DataHierarchy" xmlns:ns30="http://schemas.openxmlformats.org/officeDocument/2006/bibliography" xmlns:ns31="http://schemas.openxmlformats.org/drawingml/2006/compatibility" xmlns:ns32="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas" mc:Ignorable="w14 w15">
<w:body>
        <w:p w14:paraId="01b73d7" w14:textId="01b73d7">
            <w:pPr>
                <w15:collapsed w:val="false"/>
            </w:pPr>
            <w:r>
                <w:drawing>
                    <wp:anchor relativeHeight="0" behindDoc="false" locked="false" layoutInCell="false" allowOverlap="false">
                        <a:graphic>
                            <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/>
                                    <wps:spPr>
                                        <a:xfrm>
                                            <a:off x="0" y="0"/>
                                            <a:ext cx="130629" cy="130629"/>
                                        </a:xfrm>
                                        <a:prstGeom prst="ellipse">
                                            <a:avLst/>
                                        </a:prstGeom>
                                    </wps:spPr>
                                    <wps:style>
                                        <a:lnRef idx="2">
                                            <a:schemeClr val="accent1">
                                                <a:shade val="50000"/>
                                            </a:schemeClr>
                                        </a:lnRef>
                                        <a:fillRef idx="1">
                                            <a:schemeClr val="accent1"/>
                                        </a:fillRef>
                                        <a:effectRef idx="0">
                                            <a:schemeClr val="accent1"/>
                                        </a:effectRef>
                                        <a:fontRef idx="minor">
                                            <a:schemeClr val="lt1"/>
                                        </a:fontRef>
                                    </wps:style>
                                    <wps:bodyPr anchor="ctr" anchorCtr="0" bIns="45720" compatLnSpc="1" forceAA="0" fromWordArt="0" horzOverflow="overflow" lIns="91440" numCol="1" rIns="91440" rot="0" rtlCol="0" spcCol="0" spcFirstLastPara="0" tIns="45720" vert="horz" vertOverflow="overflow" wrap="square">
                                        <a:prstTxWarp prst="textNoShape">
                                            <a:avLst/>
                                        </a:prstTxWarp>
                                        <a:noAutofit/>
                                    </wps:bodyPr>
                                </wps:wsp>
                            </a:graphicData>
                        </a:graphic>
                    </wp:anchor>
                </w:drawing>
            </w:r>
        </w:p>
        <w:sectPr>
            <w:pgSz w:w="11907" w:h="16839" w:code="9"/>
            <w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440"/>
        </w:sectPr>
    </w:body>
</w:document>

Anyone can tell me what am I missing or doing wrong? Thank you very much.

EDIT:

Following JasonPlutext's advice I added missing children to wp:anchor like this:

CTPoint2D simplePos = new CTPoint2D();
simplePos.setX(0L);
simplePos.setY(0L);
anchor.setSimplePos(simplePos);

CTPosH ctPosH = new CTPosH();
ctPosH.setRelativeFrom(STRelFromH.COLUMN);
ctPosH.setPosOffset(904875);
anchor.setPositionH(ctPosH);

CTPosV ctPosV = new CTPosV();
ctPosV.setRelativeFrom(STRelFromV.PARAGRAPH);
ctPosV.setPosOffset(514350);
anchor.setPositionV(ctPosV);

CTPositiveSize2D ctPositiveSize2D = new CTPositiveSize2D();
ctPositiveSize2D.setCx(2238375);
ctPositiveSize2D.setCy(1057275);
anchor.setExtent(ctPositiveSize2D);


CTEffectExtent ctEffectExtent = new CTEffectExtent();
ctEffectExtent.setL(0);
ctEffectExtent.setT(0);
ctEffectExtent.setR(28575);
ctEffectExtent.setB(28575);
anchor.setEffectExtent(ctEffectExtent);

CTWrapNone ctWrapNone = new CTWrapNone();
anchor.setWrapNone(ctWrapNone);

CTNonVisualDrawingProps ctNonVisualDrawingProps = new CTNonVisualDrawingProps();
ctNonVisualDrawingProps.setId(1);
ctNonVisualDrawingProps.setName("Oval 1");
anchor.setDocPr(ctNonVisualDrawingProps);

CTNonVisualGraphicFrameProperties ctNonVisualGraphicFrameProperties = new CTNonVisualGraphicFrameProperties();
anchor.setCNvGraphicFramePr(ctNonVisualGraphicFrameProperties);

For w:drawing missing attributes seems that the class org.docx4j.wml.Drawing doesn't have proper methods like #setDistT, etc. The class org.docx4j.dml.wordprocessingDrawing.Anchor has those methods so I tried:

anchor.setSimplePosAttr(false);
anchor.setRelativeHeight(251659264);
anchor.setDistB(0L);
anchor.setDistT(0L);
anchor.setDistL(114300L);
anchor.setDistR(114300L);
anchor.setAllowOverlap(true);
anchor.setLayoutInCell(true);

The result is a document that can't be opened in MS Word and is displayed as blank document in Libre Office. This is the document.xml produced inside the docx document:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:ns8="http://schemas.openxmlformats.org/schemaLibrary/2006/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:ns12="http://schemas.openxmlformats.org/drawingml/2006/chartDrawing" xmlns:dgm="http://schemas.openxmlformats.org/drawingml/2006/diagram" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture" xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing" xmlns:dsp="http://schemas.microsoft.com/office/drawing/2008/diagram" xmlns:ns17="urn:schemas-microsoft-com:office:excel" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:ns21="urn:schemas-microsoft-com:office:powerpoint" xmlns:ns23="http://schemas.microsoft.com/office/2006/coverPageProps" xmlns:odx="http://opendope.org/xpaths" xmlns:odc="http://opendope.org/conditions" xmlns:odq="http://opendope.org/questions" xmlns:oda="http://opendope.org/answers" xmlns:odi="http://opendope.org/components" xmlns:odgm="http://opendope.org/SmartArt/DataHierarchy" xmlns:ns30="http://schemas.openxmlformats.org/officeDocument/2006/bibliography" xmlns:ns31="http://schemas.openxmlformats.org/drawingml/2006/compatibility" xmlns:ns32="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas" mc:Ignorable="w14 w15">
    <w:body>
        <w:p w14:paraId="18541d2" w14:textId="18541d2">
            <w:pPr>
                <w15:collapsed w:val="false"/>
            </w:pPr>
            <w:r>
                <w:drawing>
                    <wp:anchor distT="0" distB="0" distL="114300" distR="114300" relativeHeight="251659264" behindDoc="false" locked="false" layoutInCell="true" allowOverlap="true">
                        <wp:simplePos x="0" y="0"/>
                        <wp:positionH relativeFrom="column">
                            <wp:posOffset>904875</wp:posOffset>
                        </wp:positionH>
                        <wp:positionV relativeFrom="paragraph">
                            <wp:posOffset>514350</wp:posOffset>
                        </wp:positionV>
                        <wp:extent cx="2238375" cy="1057275"/>
                        <wp:effectExtent l="0" t="0" r="28575" b="28575"/>
                        <wp:wrapNone/>
                        <wp:docPr id="1" name="Oval 1"/>
                        <wp:cNvGraphicFramePr/>
                        <a:graphic>
                            <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/>
                                    <wps:spPr>
                                        <a:xfrm>
                                            <a:off x="0" y="0"/>
                                            <a:ext cx="130629" cy="130629"/>
                                        </a:xfrm>
                                        <a:prstGeom prst="ellipse">
                                            <a:avLst/>
                                        </a:prstGeom>
                                    </wps:spPr>
                                    <wps:style>
                                        <a:lnRef idx="2">
                                            <a:schemeClr val="accent1">
                                                <a:shade val="50000"/>
                                            </a:schemeClr>
                                        </a:lnRef>
                                        <a:fillRef idx="1">
                                            <a:schemeClr val="accent1"/>
                                        </a:fillRef>
                                        <a:effectRef idx="0">
                                            <a:schemeClr val="accent1"/>
                                        </a:effectRef>
                                        <a:fontRef idx="minor">
                                            <a:schemeClr val="lt1"/>
                                        </a:fontRef>
                                    </wps:style>
                                    <wps:bodyPr anchor="ctr" anchorCtr="0" bIns="45720" compatLnSpc="1" forceAA="0" fromWordArt="0" horzOverflow="overflow" lIns="91440" numCol="1" rIns="91440" rot="0" rtlCol="0" spcCol="0" spcFirstLastPara="0" tIns="45720" vert="horz" vertOverflow="overflow" wrap="square">
                                        <a:prstTxWarp prst="textNoShape">
                                            <a:avLst/>
                                        </a:prstTxWarp>
                                        <a:noAutofit/>
                                    </wps:bodyPr>
                                </wps:wsp>
                            </a:graphicData>
                        </a:graphic>
                    </wp:anchor>
                </w:drawing>
            </w:r>
        </w:p>
        <w:sectPr>
            <w:pgSz w:w="11907" w:h="16839" w:code="9"/>
            <w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440"/>
        </w:sectPr>
    </w:body>
</w:document>

Am I missing anything else?

Edit: finally I got a working code (Libre Office fails showing the ellipse but MS Word shows it properly). Here is the code:

String xmlAnchor = getXmlAnchor();
Object anchorXml = XmlUtils.unmarshalString(xmlAnchor);
Anchor anchor = (Anchor) ((JAXBElement)anchorXml).getValue();

WordprocessingMLPackage newDoc = WordprocessingMLPackage.createPackage();

ObjectFactory factory = new ObjectFactory();
P paragraph = factory.createP();

R run = factory.createR();
paragraph.getContent().add(run);
Drawing drawing = factory.createDrawing();
run.getContent().add(drawing);
drawing.getAnchorOrInline().add(anchor);

newDoc.getMainDocumentPart().getContent().add(paragraph);
newDoc.save(new File(dirPath + outputFilePath));

The getXmlAnchor method is following:

private static String getXmlAnchor() {
    String xmlAnchor = ""
            + "<wp:anchor xmlns:wp14=\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\" xmlns:wps=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" distT=\"0\" distB=\"0\" distL=\"114300\" distR=\"114300\" simplePos=\"0\" relativeHeight=\"251659264\" behindDoc=\"0\" locked=\"0\" layoutInCell=\"1\" allowOverlap=\"1\">"
            + "     <wp:simplePos x=\"0\" y=\"0\"/>"
            + "     <wp:positionH relativeFrom=\"column\">"
            + "         <wp:posOffset>606161</wp:posOffset>"
            + "     </wp:positionH>"
            + "     <wp:positionV relativeFrom=\"paragraph\">"
            + "         <wp:posOffset>287737</wp:posOffset>"
            + "     </wp:positionV>"
            + "     <wp:extent cx=\"130629\" cy=\"130629\"/>"
            + "     <wp:effectExtent l=\"0\" t=\"0\" r=\"22225\" b=\"22225\"/>"
            + "     <wp:wrapNone/>"
            + "     <wp:docPr id=\"1\" name=\"1 Elipse\"/>"
            + "     <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>"
            + "                 <wps:cNvSpPr/>"
            + "                 <wps:spPr>"
            + "                     <a:xfrm>"
            + "                         <a:off x=\"0\" y=\"0\"/>"
            + "                         <a:ext cx=\"130629\" cy=\"130629\"/>"
            + "                     </a:xfrm>"
            + "                     <a:prstGeom prst=\"ellipse\">"
            + "                         <a:avLst/>"
            + "                     </a:prstGeom>"
            + "                 </wps:spPr>"
            + "                 <wps:style>"
            + "                     <a:lnRef idx=\"2\">"
            + "                         <a:schemeClr val=\"accent1\">"
            + "                             <a:shade val=\"50000\"/>"
            + "                         </a:schemeClr>"
            + "                     </a:lnRef>"
            + "                     <a:fillRef idx=\"1\">"
            + "                         <a:schemeClr val=\"accent1\"/>"
            + "                     </a:fillRef>"
            + "                     <a:effectRef idx=\"0\">"
            + "                         <a:schemeClr val=\"accent1\"/>"
            + "                     </a:effectRef>"
            + "                     <a:fontRef idx=\"minor\">"
            + "                         <a:schemeClr val=\"lt1\"/>"
            + "                     </a:fontRef>"
            + "                 </wps:style>"
            + "                 <wps:bodyPr rot=\"0\" spcFirstLastPara=\"0\" vertOverflow=\"overflow\" horzOverflow=\"overflow\" vert=\"horz\" wrap=\"square\" lIns=\"91440\" tIns=\"45720\" rIns=\"91440\" bIns=\"45720\" numCol=\"1\" spcCol=\"0\" rtlCol=\"0\" fromWordArt=\"0\" anchor=\"ctr\" anchorCtr=\"0\" forceAA=\"0\" compatLnSpc=\"1\">"
            + "                     <a:prstTxWarp prst=\"textNoShape\">"
            + "                         <a:avLst/>"
            + "                     </a:prstTxWarp>"
            + "                     <a:noAutofit/>"
            + "                 </wps:bodyPr>"
            + "             </wps:wsp>"
            + "         </a:graphicData>"
            + "     </a:graphic>"
            + "     <wp14:sizeRelH relativeFrom=\"margin\">"
            + "         <wp14:pctWidth>0</wp14:pctWidth>"
            + "     </wp14:sizeRelH>"
            + "     <wp14:sizeRelV relativeFrom=\"margin\">"
            + "         <wp14:pctHeight>0</wp14:pctHeight>"
            + "     </wp14:sizeRelV>"
            + "</wp:anchor>";

    return xmlAnchor;
}
1

There are 1 best solutions below

7
On BEST ANSWER

Your problem is that - for Word 2010 anyway - you are missing some required attributes on w:drawing.

You need some or all of the following:

distT="0" distB="0" distL="114300" distR="114300" simplePos="0"

Also, you need some or all of the following extra children for wp:anchor:

            <wp:simplePos x="0" y="0"/>
        <wp:positionH relativeFrom="column">
          <wp:posOffset>904875</wp:posOffset>
        </wp:positionH>
        <wp:positionV relativeFrom="paragraph">
          <wp:posOffset>514350</wp:posOffset>
        </wp:positionV>
        <wp:extent cx="2238375" cy="1057275"/>
        <wp:effectExtent l="0" t="0" r="28575" b="28575"/>
        <wp:wrapNone/>
        <wp:docPr id="1" name="Oval 1"/>
        <wp:cNvGraphicFramePr/>

I haven't bothered to work out what subset is required for Word 2010 to be happy; if you do that, please come back here with your findings!