问题
I have a document with three ContentControl
objects that looks like this:
Here is the .docx file in its entirety - but essentially the markup of the document body looks like this:
<w:body>
<w:p w:rsidR="0075044D" w:rsidRDefault="0075044D">
<w:r>
<w:t xml:space="preserve">Video provides a powerful way to help you </w:t>
</w:r>
<w:sdt>
<w:sdtPr>
<w:alias w:val="cc1"/>
<w:tag w:val="prove"/>
<w:id w:val="806369342"/>
<w:placeholder>
<w:docPart w:val="1F3FDE3D075A4E8AADE251C4E318E379"/>
</w:placeholder>
<w15:color w:val="FF9900"/>
<w15:appearance w15:val="tags"/>
<w:text/>
</w:sdtPr>
<w:sdtContent>
<w:r>
<w:t>prove</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
<w:r>
<w:t xml:space="preserve"> your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also </w:t>
</w:r>
<w:sdt>
<w:sdtPr>
<w:alias w:val="cc2"/>
<w:tag w:val="number 2"/>
<w:id w:val="1463999480"/>
<w:placeholder>
<w:docPart w:val="1F3FDE3D075A4E8AADE251C4E318E379"/>
</w:placeholder>
<w15:color w:val="FF0000"/>
<w15:appearance w15:val="tags"/>
</w:sdtPr>
<w:sdtContent>
<w:r>
<w:t>type</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
<w:r>
<w:t xml:space="preserve"> a keyword to search online for the video that best fits your document.</w:t>
</w:r>
</w:p>
<w:p w:rsidR="0075044D" w:rsidRDefault="0075044D">
<w:r>
<w:t xml:space="preserve">To make your document look professionally produced, Word provides </w:t>
</w:r>
<w:sdt>
<w:sdtPr>
<w:alias w:val="cc3"/>
<w:tag w:val="xxx"/>
<w:id w:val="1703202634"/>
<w:placeholder>
<w:docPart w:val="1F3FDE3D075A4E8AADE251C4E318E379"/>
</w:placeholder>
<w15:color w:val="FF99CC"/>
<w15:appearance w15:val="tags"/>
<w:text/>
</w:sdtPr>
<w:sdtContent>
<w:r>
<w:t>header</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
<w:r>
<w:t>, footer, cover page, and text box designs that complement each other. For example, you can add a matching cover page, header, and sidebar. Click Insert and then choose the elements you want from the different galleries.</w:t>
</w:r>
</w:p>
<w:p w:rsidR="0075044D" w:rsidRDefault="0075044D"/>
<w:p w:rsidR="00000000" w:rsidRDefault="0075044D"/>
<w:sectPr w:rsidR="00000000">
<w:pgSz w:w="11906" w:h="16838"/>
<w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="708" w:footer="708" w:gutter="0"/>
<w:cols w:space="708"/>
<w:docGrid w:linePitch="360"/>
</w:sectPr>
</w:body>
When I run the code below, only the control in the middle is returned by document.contentControls
and therefore changed by my code. Any ideas why the other two controls are not returned? Did anyone else encounter this issue? Is there a way to fix it?
Word.run(function (context) {
var myContentControls = context.document.contentControls;
myContentControls.load("tag");
return context.sync()
.then(function () {
for (var i = 0; i < myContentControls.items.length; i++)
{
myContentControls.items[i].color = "blue";
myContentControls.items[i].title = "myCC";
myContentControls.items[i].appearance = "tags";
}
return context.sync();
});
}).catch(OfficeHelpers.Utilities.log);
Here is a ScriptLab gist for convenience.
Interestingly, this VBA code returns the correct result (3
):
Sub Main()
MsgBox ActiveDocument.ContentControls.Count
End Sub
I have only tried this on Windows 10 / Office 365 desktop client.
回答1:
As stated in the Word JS APIs' documentation for content controls, only Rich Text content controls are supported / recognized. So code will not "see" plain text content controls.
Whether a content control is plain text or rich text is not visually recognizable (unless it contains formatting or content other than text). There's also nothing in the Word Open XML to differentiate the type of content control, unless it contains formatting or a non-text object.
回答2:
As Cindy Meister already said, the Word OfficeJS API only returns RichText content controls - see Word.ContentControl.
If you dive into the OOXML, you'll find that plain text context controls (the ones that are not returned) main difference from the rich text ones is that they are marked with <w:text/>
. This essentially means that if that tag is removed, then the plain text content control becomes a rich text content control. So here is my workaround to this issue:
var ooxml = context.document.body.getOoxml();
await context.sync();
var newxml = ooxml.value.replace(/<w:text\/>/g, '');
context.document.body.insertOoxml(newxml, Word.InsertLocation.replace);
var myContentControls = context.document.contentControls;
myContentControls.load();
await context.sync();
console.log(myContentControls.items.length); // now returns 3. Yay!!!
return context.sync();
Nota Bene: getOoxml()
and insertOoxml()
are slow methods and this workaround will take a long time to execute, so only use when strictly necessary.
来源:https://stackoverflow.com/questions/60095160/document-contentcontrols-not-returning-all-contentcontrols-in-the-document