Word 插件使用 office.js 在 contentControl 中插入具有样式的复杂列表结构完成与否?

Word addin inserting complex list structure with styling in a contentControl using office.js done or not?

我正在尝试使用 javascript API 将复杂的列表结构插入到 MS Word 中的 contentControl 中。该结构是根据包含嵌套数组的对象构建的:不同的项目包含包含不同属性的子项目。这些项目数组的大小可以改变,因此它需要是通用的。也许 Office.js API 并不是真正为我想要实现的目标而构建的,我应该使用 insertHTML (在 HTML 中构建结构)或 OOXML .

This is the structure I already build

产生这个的函数:

import ContentControl = Word.ContentControl;
import {formatDate} from '../formatters';
let firstItem = true;
let listId;

export async function resolveItems(contentControl: ContentControl, data: Array<any>, t) {
Word.run(  contentControl, async (context) => {
    contentControl.load('paragraphs');
    await context.sync();
    for (const item of data) {
        if (firstItem) {
            const firstPara = contentControl.paragraphs.getFirst();
            firstPara.insertText('ITEM (' + formatDate(item.date) + ')', 'Replace');
            firstItem = false;
            const contactList = firstPara.startNewList();
            contactList.load('id');
            await context.sync().catch((error) => {
                console.log('Error: ' + error);
                if (error instanceof OfficeExtension.Error) {
                    console.log('Debug info: ' + JSON.stringify(error.debugInfo));
                }
            });
            listId = contactList.id;
        } else {
            const otherItem = contentControl.insertParagraph('ITEM (' + formatDate(item.date) + ')', 'End');
            otherItem.load(['isListItem']);
            await context.sync();
            otherItem.attachToList(listId, 0);
        }
        for (const subItem of item.subItems) {
            let descriptionParaList = new Array();
            let subItemPara = contentControl.insertParagraph(subItem.title + ' (' + formatDate(subItem.date) + ')', 'End');
            subItemPara.load(['isListItem']);
            await context.sync();
            if (subItemPara.isListItem) {
                subItemPara.listItem.level = 1;
            } else {
                subItemPara.attachToList(listId, 1);
            }
            let descriptions = subItem.descriptions;
            for (const description of descriptions) {
                let descriptionPara = contentControl.insertParagraph('', 'End');
                descriptionPara.insertText(t(description.descriptionType) + ': ', 'Start').font.set({
                    italic: true
                });
                descriptionPara.insertText(description.description, 'End').font.set({
                    italic: false
                });
                descriptionPara.load(['isListItem', 'leftIndent']);
                descriptionParaList.push(descriptionPara);
            }
            await context.sync();
            for (const subItemPara of descriptionParaList) {
                if (subItemPara.isListItem) {
                    subItemPara.detachFromList();
                }
                subItemPara.leftIndent = 72;
            }

        }
    }
    return context.sync().catch((error) => {
        console.log('Error: ' + error);
        if (error instanceof OfficeExtension.Error) {
            console.log('Debug info: ' + JSON.stringify(error.debugInfo));
        }
    });
});}

数据结构如下所示:

'LAST_5_Items': [
    {
        'date': '2019-03-14T14:51:29.506+01:00',
        'type': 'ITEM',
        'subItems': [
            {
                'date': '2019-03-14T14:51:29.506+01:00',
                'title': 'SUBITEM 1',
                'descriptions': [
                    {
                        'descriptionType': 'REASON',
                        'description': 'Reason 1',
                        'additionalInformation': ''
                    }
                ]
            },
            {
                'date': '2019-03-14T14:51:29.506+01:00',
                'title': 'SUBITEM 2',
                'descriptions': [
                    {
                        'descriptionType': 'REASON',
                        'description': 'Reason 1',
                        'additionalInformation': ''
                    }
                ]
            }
        ]
    },
    {
        'date': '2019-03-14T14:16:26.220+01:00',
        'type': 'ITEM',
        'subItems': [
            {
                'date': '2019-03-14T14:16:26.220+01:00',
                'title': 'SUBITEM 1',
                'descriptions': [
                    {
                        'descriptionType': 'REASON',
                        'description': 'Reason 1',
                        'additionalInformation': ''
                    }
                ]
            },
            {
                'date': '2019-03-14T14:16:26.220+01:00',
                'title': 'SUBITEM 2',
                'descriptions': [
                    {
                        'descriptionType': 'REASON',
                        'description': 'Reason 1',
                        'additionalInformation': ''
                    },
                    {
                        'descriptionType': 'SUBJECTIVE',
                        'description': 'Subjective 1',
                        'additionalInformation': ''
                    },
                    {
                        'descriptionType': 'SUBJECTIVE',
                        'description': 'Subjective 2',
                        'additionalInformation': ''
                    },
                    {
                        'descriptionType': 'OBJECTIVE',
                        'description': 'Objective 1',
                        'additionalInformation': ''
                    },
                    {
                        'descriptionType': 'OBJECTIVE',
                        'description': 'Objective 2',
                        'additionalInformation': ''
                    },
                    {
                        'descriptionType': 'EVALUATION',
                        'description': 'Evaluation',
                        'additionalInformation': ''
                    },
                    {
                        'descriptionType': 'REASON',
                        'description': 'Reason 1',
                        'additionalInformation': ''
                    }
                ]
            }
        ]
    }
]

我想要实现的是一个模板解析器。该插件将允许用户在文档中放置占位符 (ContentControls)、名字、姓氏等标签,以及最后 5 个联系人(我现在正在描述的联系人),当他解析文件时,它将获取所有需要的数据并开始用这个结构化布局替换 ContentControls。

是的,代码有效,但我非常怀疑代码结构良好,有这么多 context.sync() 调用。它太慢了,无法使用。 我需要这么多 context.sync() 因为我需要列表 ID 的属性以及段落是否属于列表。 有没有更好的方法来实现我正在尝试使用 office.js API?

理想情况下,队列应该同步一次,这样用户就不会看到以一种非常奇怪的方式添加和更改的内容,就像现在的行为一样。

谢谢

有一种技术可以避免在循环中出现 context.sync。基本思想是你有两个循环,它们之间有一个 context.sync。在第一个循环中,您创建了一个对象数组。每个对象都包含对您要处理的 Office 对象之一的引用(例如,更改、删除等)。它看起来像您案例中的段落。但是该对象具有其他属性。它们中的每一个都包含处理对象所需的一些数据项。这些其他项目可能是其他 Office 对象的属性,也可能是其他数据。此外,无论是在循环中还是在循环之后,您 load 都需要数组中对象中所有 Office 对象的所有属性。 (这通常在循环内更容易完成。)

那么你有 context.sync.

同步后,您将遍历在 context.sync 之前创建的对象数组。第二个循环中的代码使用您创建的对象的其他属性处理每个对象(即您要处理的 Office 对象)中的第一项。

以下是此技术的几个示例:

我对这个 Whosebug 问题的回答:

此代码示例: https://github.com/OfficeDev/Word-Add-in-Angular2-StyleChecker/blob/master/app/services/word-document/word.document.service.js.