Callum
Callum

Reputation: 21

How to insert a floating element in Word using office-js?

We have a use-case in our plugin where we need to insert a textbox-like element into a Word document. It's important that this element can be dragged around freely by the user without moving other elements on the document. We have tried to add a textbox, but it doesn't seem like this is possible with the package at the moment.

For the meantime, we have added a table, and inserted the information we need inside this table. However, when the user moves the table, it moves all the other elements around the page. They also aren't able to place the table near the bottom of the page for example, as this sends it to the next page.

We also explored using an image, but again, the package only allows inserting inline images, so dragging the image around moves other elements on the document.

Has anyone been able to insert any kind of "floating" element with the office-js package, that can be dragged around freely without disturbing other elements? We'd also need to query the document at a later stage, to get a list of all these elements we insert and their content - this is currently possible with tables.

We've tried inserting a table, as the package doesn't cater for inserting textboxes, but the table can't be dragged freely without affecting other elements on the document.

Upvotes: 0

Views: 172

Answers (1)

Callum
Callum

Reputation: 21

I found the answer after a little bit of fiddling. Thankfully, OfficeJS lets you insert OOXML. So, what I did was manually inserted a textbox into the document using Word's controls. Then, dumped the document's OOXML:

Word.run(async (context: Word.RequestContext) => {
      const xml = context.document.body.getOoxml();
      await context.sync();
      console.log(xml.value);
    });

I parsed through and extracted the OOXML for the textbox. I had to fiddle with this a little bit more, and with the help of ChatGPT arrived at this OOXML:

<?xml version="1.0" encoding="UTF-8"?>
<pkg:package xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage">
   <pkg:part pkg:name="/_rels/.rels" pkg:contentType="application/vnd.openxmlformats-package.relationships+xml" pkg:padding="512">
      <pkg:xmlData>
         <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
            <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml" />
         </Relationships>
      </pkg:xmlData>
   </pkg:part>
   <pkg:part pkg:name="/word/document.xml" pkg:contentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml">
      <pkg:xmlData>
         <w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
            <w:body>
               <w:p>
                  <w:r>
                     <w:pict>
                        <v:rect xmlns:v="urn:schemas-microsoft-com:vml" style="position:absolute;width:300pt;height:100pt;v-text-anchor:top" fillcolor="#e6e6e6" textbox-id="textbox1">
                           <v:textbox id="test">
                              <w:txbxContent>
                                 <w:p>
                                    <w:r>
                                       <w:t>Your Text Goes Here</w:t>
                                    </w:r>
                                 </w:p>
                              </w:txbxContent>
                           </v:textbox>
                        </v:rect>
                     </w:pict>
                  </w:r>
               </w:p>
            </w:body>
         </w:document>
      </pkg:xmlData>
   </pkg:part>
</pkg:package>

Now, all I had to do to insert this into my document was:

const xml = //xml above
const range = context.document.getSelection();
await context.sync();
range.insertOoxml(xml, 'Start');
await context.sync();

And viola, a textbox inserted from OfficeJS.

This was a painful process and I really hope that OfficeJS starts supporting textboxes from the API in future. On the flipside, it seems that anything which can be inserted into Word manually (using Word controls) can be done with OfficeJS, by exporting OOXML and manipulating it a bit. Hope this helps someone in future.

Upvotes: 2

Related Questions