Search code examples
ms-wordopenxmldocx

How to create a document and fill it with textboxes based on x and y coords or pixels?


Im trying to create a template to print some information on a blank document based in coordinates or pixels or cm, wtv is possible.

why? I have some accounting forms which is to bad fill it manual. Im wondering if it is possible to create a function with some parameters related to the text box positions in document.

eg. txtName goes to (3,15) position in a document. It may be necessary define the size of document

If it is possible, what language you recommend?


Solution

  • Yes, it is possible.

    If you use Microsoft Word to insert a text box into a blank document, then save it, and inspect the resulting docx, you'll see Word inserts the text box in 2 formats:

            <mc:AlternateContent>
          <mc:Choice Requires="wps">
            <w:drawing>
              <wp:anchor distT="0" distB="0" distL="114300" distR="114300" simplePos="0" relativeHeight="251659264" behindDoc="0" locked="0" layoutInCell="1" allowOverlap="1" wp14:anchorId="44014479" wp14:editId="7FACADD8">
                <wp:simplePos x="0" y="0"/>
                <wp:positionH relativeFrom="column">
                  <wp:align>center</wp:align>
                </wp:positionH>
                <wp:positionV relativeFrom="paragraph">
                  <wp:posOffset>0</wp:posOffset>
                </wp:positionV>
                <wp:extent cx="2374265" cy="1403985"/>
                <wp:effectExtent l="0" t="0" r="22860" b="23495"/>
                <wp:wrapTopAndBottom/>
                <wp:docPr id="307" 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>
                      <wps:cNvSpPr txBox="1">
                        <a:spLocks noChangeArrowheads="1"/>
                      </wps:cNvSpPr>
                      <wps:spPr bwMode="auto">
                        <a:xfrm>
                          <a:off x="0" y="0"/>
                          <a:ext cx="2374265" cy="1403985"/>
                        </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:rsidR="006C2E97" w:rsidRDefault="006C2E97">
                            <w:proofErr w:type="gramStart"/>
                            <w:r>
                              <w:t>YOUR CONTENT GOES HERE</w:t>
                            </w:r>
                          </w:p>
                        </w:txbxContent>
                      </wps:txbx>
                      <wps:bodyPr rot="0" vert="horz" wrap="square" lIns="91440" tIns="45720" rIns="91440" bIns="45720" anchor="t" anchorCtr="0">
                        <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 id="_x0000_t202" coordsize="21600,21600" o:spt="202" path="m,l,21600r21600,l21600,xe">
                <v:stroke joinstyle="miter"/>
                <v:path gradientshapeok="t" o:connecttype="rect"/>
              </v:shapetype>
              <v:shape id="Text Box 2" o:spid="_x0000_s1026" type="#_x0000_t202" style="position:absolute;margin-left:0;margin-top:0;width:186.95pt;height:110.55pt;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:0;mso-wrap-distance-right:9pt;mso-wrap-distance-bottom:0;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" >
                <v:textbox style="mso-fit-shape-to-text:t">
                  <w:txbxContent>
                    <w:p w:rsidR="006C2E97" w:rsidRDefault="006C2E97">
                      <w:r>
                        <w:t>YOUR CONTENT GOES HERE</w:t>
                      </w:r>
                    </w:p>
                  </w:txbxContent>
                </v:textbox>
                <w10:wrap type="topAndBottom"/>
              </v:shape>
            </w:pict>
          </mc:Fallback>
        </mc:AlternateContent>
      </w:r>
    

    You can use either the w:drawing or the w:pict syntax. I quite like w:pict with its @style

    As a first step you'll want to play in Word with how the boxes are positioned - I guess you want them positioned against the page, not a paragraph.

    Then its just a matter of replicating the XML in your choice of language.

    You could:

    • unzip, manipulate, then rezip
      • doing the manipulation with XML aware tool
      • or doing the manipulation without that
    • or use a lib, such as:
      • for .NET, Microsoft's Open XML SDK
      • for Java, POI, docx4j
      • for C, libopc etc...