Надстройка Word для вставки сложной структуры списка со стилем в contentControl с использованием office.js сделано или нет? - PullRequest
0 голосов
/ 16 марта 2019

Я пытаюсь вставить сложную структуру списка в contentControl в MS Word, используя javascript API.Структура строится в соответствии с объектом, который содержит вложенные массивы: различные элементы, содержащие вложенные элементы, которые содержат различные свойства.Эти массивы элементов могут изменяться в размере, поэтому они должны быть общими.Возможно, API Office.js на самом деле не создан для того, чего я пытаюсь достичь, и я должен использовать либо insertHTML (со структурой, встроенной в HTML), либо OOXML.

Это структура, которую я уже построил

Функция, которая произвела это:

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 (), потому что мне нужны свойства идентификатора списка и если абзац принадлежит списку.Есть ли лучший способ добиться того, чего я пытаюсь достичь с помощью API office.js?

В идеале очередь должна быть синхронизирована один раз, чтобы пользователь не увидел добавление и изменение содержимого очень странным образом.как он сейчас ведет себя.

Спасибо

1 Ответ

0 голосов
/ 16 марта 2019

Существует метод, позволяющий избежать наличия context.sync внутри цикла.Основная идея состоит в том, что у вас есть две петли, с одной context.sync между ними.В первом цикле вы создаете массив объектов.Каждый объект содержит ссылку на один из объектов Office, который вы хотите обработать (например, изменить, удалить и т. Д.). Он выглядит как параграфы в вашем случае.Но у объекта есть другие свойства.Каждый из них содержит какой-то элемент данных, который необходим для обработки объекта.Эти другие элементы могут быть свойствами других объектов Office или другими данными.Кроме того, либо в вашем цикле, либо сразу после него вы load получаете все свойства, которые вам понадобятся для всех объектов Office в объектах в вашем массиве.(Обычно это проще сделать внутри цикла.)

Тогда у вас есть context.sync.

После синхронизации вы перебираете массив объектов, которые вы создали до context.sync,Код внутри этого второго цикла обрабатывает первый элемент в каждом объекте (который является объектом Office, который вы хотите обработать), используя другие свойства созданного вами объекта.

Вот пара примеров этого метода:

Мой ответ на этот вопрос StackOverflow: Документ не синхронизирован после замены текста .

Этот пример кода: https://github.com/OfficeDev/Word-Add-in-Angular2-StyleChecker/blob/master/app/services/word-document/word.document.service.js.

...