Word Online中ContentControl显示/隐藏的问题及解决尝试
预期目标
我希望能基于特定逻辑,通过编程方式显示/隐藏文本块(单个或多个段落)。
尝试方案
我试过以下几种解决方法,但每种都存在相应问题,具体如下:
隐藏文本
最简单的方式是开启段落的「隐藏」选项。这种方法原本效果很好,但遗憾的是它在Word Online中不受支持。真的是这样吗?
OOXML方案
另一种方法是将内容控件(Content Control)的内容存储在文档内的XML部件中,之后再恢复。该方案仅部分可行,体验极不稳定:操作速度极慢,且经常静默失败。
隐藏Content Control
隐藏Content Control的操作相当简单,且每次都能快速完成:
/** * 存储文档设置的辅助函数 **/ type DocumentSettingSet = <T>(settingName: string, settingValue: T) => void; const documentSettingSet: DocumentSettingSet = (settingName, settingValue) => Office.context.document.settings.set(settingName, settingValue); /** * 将所有文档设置保存到文档中 **/ export type DocumentSettingsSave = () => Promise<void>; export const documentSettingsSave: DocumentSettingsSave = async () => { await Office.context.document.settings.saveAsync(); }; /** * 在文档中设置XML部件的辅助函数 **/ const xmlPartSet = (xml: string): Promise<Office.CustomXmlPart> => new Promise((resolve, reject) => { Office.context.document.customXmlParts.addAsync(xml, (result) => { if (result.status === Office.AsyncResultStatus.Failed) { reject(result.error); return; } resolve(result.value); }); }); /** * 隐藏Content Control并存储其内容以便后续恢复 **/ Word.run(async (context) => { // 找到要隐藏的Content Control - 假设已知其ID const contentControl = context.document.contentControls.getById('the-control-id'); context.load(contentControl, ['appearance', 'tag', 'title']); await context.sync(); // 获取Content Control内的OOXML并存储到自定义XML部件中 // 将自定义XML部件的ID存储到文档设置中,供后续使用 const xml = contentControl.getRange('Content').getOoxml(); await context.sync(); const xmlPart = await xmlPartSet(xml.value); documentSettingSet<string>(`block-xml-part-id-${contentControl.tag}`, xmlPart.id); await documentSettingsSave(); // 清空Content Control并隐藏其作为控件的外观 contentControl.cannotEdit = false; await context.sync(); contentControl.appearance = Word.ContentControlAppearance.hidden; contentControl.insertText('\u200b', Word.InsertLocation.replace); contentControl.cannotEdit = true; await context.sync(); });
显示Content Control
显示Content Control时问题频发:首先加载耗时极长,加载器消失后仍需等待一分钟以上才能显示,多次出现显示失败,控制台提示需刷新页面才能显示内容。
/** * 获取文档设置值的辅助函数 **/ export type DocumentSettingGet = <T>(settingName: string) => T; export const documentSettingGet: DocumentSettingGet = (settingName) => Office.context.document.settings.get(settingName); /** * 从文档中获取自定义XML部件的辅助函数 **/ export const xmlPartGet = (id: string): Promise<Office.CustomXmlPart | null> => new Promise((resolve, reject) => { Office.context.document.customXmlParts.getByIdAsync(id, (result) => { if (result.status === Office.AsyncResultStatus.Failed) { reject(result.error); return; } resolve(result.value); }); }); /** * 读取自定义XML部件值的辅助函数 **/ export const xmlPartRead = ( xmlPart: Office.CustomXmlPart | Office.CustomXmlNode, ): Promise<string> => new Promise((resolve, reject) => { xmlPart.getXmlAsync((result) => { if (result.status === Office.AsyncResultStatus.Failed) { reject(result.error); return; } resolve(result.value); }); }); /** * 从文档中移除自定义XML部件的辅助函数 **/ export const xmlPartRemove = (xmlPart: Office.CustomXmlPart): Promise<void> => new Promise((resolve, reject) => { xmlPart.deleteAsync((result) => { if (result.status === Office.AsyncResultStatus.Failed) { reject(result.error); return; } resolve(); }); }); /** * 显示之前隐藏的Content Control(如上述操作) **/ Word.run(async (context) => { // 找到要显示的Content Control - 假设已知其ID const contentControl = context.document.contentControls.getById(contentControlId); context.load(contentControl, ['appearance', 'tag', 'title']); await context.sync(); // 获取要插入到Content Control中的OOXML const xmlPartId = documentSettingGet<string>(`block-xml-part-id-${contentControl.tag}`); const xmlPart = await xmlPartGet(xmlPartId); if (xmlPart) { const xml = await xmlPartRead(xmlPart); contentControl.cannotEdit = false; await context.sync(); contentControl.insertOoxml(value, Word.InsertLocation.replace); contentControl.appearance = Word.ContentControlAppearance.boundingBox; await context.sync(); // 使用完毕后移除XML部件 await xmlPartRemove(xmlPart); } });
内容的提问来源于stack exchange,提问作者Hendrik Volschenk
相关产品推荐
相关产品推荐

