首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Word外接程序CustomXMLParts数据建模和/或性能优化

Word外接程序CustomXMLParts数据建模和/或性能优化
EN

Stack Overflow用户
提问于 2018-04-10 23:13:25
回答 1查看 811关注 0票数 6

环境: Mac 10.12.6,Word 2016 (16.11.1),@microsoft/office-js "^1.1.4“

我想知道在如何使用CustomXMLParts以最大限度地提高读/写性能方面是否有任何指南或最佳实践,或者是否有一种“理想的”方法来对XML部件中的数据进行建模,以达到相同的目的。

我正在编写一个外接程序,根据该外接程序,我需要将一些数据保存在可见文档之外,但在docx文件中。

例如,我正在存储一个发票列表(可能是100-200张发票),每个发票都有典型的结构化数据(名称、id、日期、工作项列表)和一个自由式注释部分,其中可以包含多达5-10 to的文本、说明等。

我接受这些发票,在Word doc中呈现其中的一些,然后在任务窗格中对来自其余部分的数据进行一些可视化分析--用户可以在其中将注释写入(并保存)到自定义XML部件(到他们正在查看的发票中)。

现在..。我有点困惑..。我不确定是否最好将每个发票作为单独的CustomXMLPart存储在文件中(例如,每个发票一个XML文件),或者是否最好将所有发票存储在一个大型CustomXMLPart中,或者是否有一个中间位置(例如,每个XML部分10张发票)。如前所述,用例正在读取所有发票,然后零星地更新10%-20%的发票中的数据。

现在,我在每个XML部件存储一张发票,当我加载我的加载项并进行批量读取以将所有内容输入内存时,每张发票大约需要250到500 my才能并行地读取它们(所以,250-500 my* 100-200发票)。然后,它需要更长的时间(2-3倍)。使用performance.now()进行测试,并使用挂钟定时进行验证。

这似乎是一段很长的时间,所以我不知道我是否做错了什么--或者这仅仅是打开和从这些文件中提取数据所需的时间?

代码语言:javascript
复制
// Sequential example - excluding error handling and type-safety
// Parallel equivalent is essentially a Promise.all with a .map

// Approx 50ms
let result = await this.xmlPartsHelper.getByNamespaceAsync(...);

for (const item of result.value) {
    // Approx 150-200ms
    result = await this.xmlPartsHelper.getByIdAsync(item.id);

    // Approx 150-200ms
    result = await this.xmlPartsHelper.getXmlAsync(result.value);

    // Approx 5ms
    const invoice = this.mapper.reverseMap(result.value);
    invoices.push(invoice)
}

我用承诺手动包装了Office-JS回调,但是我已经用异步/等待、然后/catch和office-js回调测试了这个示例,结果几乎是一样的。

代码语言:javascript
复制
public getByNamespaceAsync(namespace: string): Promise<Office.AsyncResult> {
    return new Promise<Office.AsyncResult>((resolve, reject) => {
        Office.context.document.customXmlParts.getByNamespaceAsync(namespace, (result: Office.AsyncResult) => {
            return resolve(result);
        });
    });
}

public getByIdAsync(id: string): Promise<Office.AsyncResult> {
    return new Promise<Office.AsyncResult>((resolve, reject) => {
        Office.context.document.customXmlParts.getByIdAsync(id, (result: Office.AsyncResult) => {
            return resolve(result);
        });
    });
}

public getXmlAsync(xmlPart: Office.CustomXmlPart): Promise<Office.AsyncResult> {
    return new Promise<Office.AsyncResult>((resolve, reject) => {
        xmlPart.getXmlAsync((result: Office.AsyncResult) => {
            return resolve(result);
        });
    });
}

更新

我不完全理解的谜题之一是CustomXMLNode --也许这会有所帮助。似乎有一些方法可以在CustomXMLPart (https://dev.office.com/reference/add-ins/shared/customxmlnode.customxmlnode)的节点中专门获取/设置数据--所以这可能是一个中间选项,我可以将所有发票放在一个CustomXMLPart中(这样我就可以只为一个CustomXMLPart被文件系统击中),然后我可以有选择地更新这个CustomXMLPart的各个部分(使用CustomXMLNode),这样我就不只是做一个完整的删除和重新保存了吗?

EN

回答 1

Stack Overflow用户

发布于 2018-04-15 20:20:05

很好地利用了承诺,我正在为非承诺的officejs函数做同样的包装。有了基于承诺的api,您现在可以利用Promise.all()执行并行操作。您可以同时启动所有操作并等待完成。这应该更快。

代码语言:javascript
复制
function getAllParts(ids) {
   return Promise.all(ids.map(id => xmlPartsHelper.getByIdAsync(id)));
}

let namespaces = await this.xmlPartsHelper.getByNamespaceAsync(...);
getAllParts(namespaces.value).then((results) => {
   console.log('invioces are', results);
});

在文档中存储数据的另一种方法是Office.context.document.settings。您可以使用它作为密钥/值存储,并将JSON作为您的值。也许试着把你所有的发票放在一个数组中,然后把它写到同一个键上。下面是我的助手函数来完成这个任务:

代码语言:javascript
复制
   /** Set a document property. Properties are specific to the document and the Addin-ID.
    * @param {string} propertyName Name of the property.
    * @param {string} value Value of the property.
    * @returns {Promise} A promise without content.
    */
   function setDocumentProperty(propertyName, value) {
      return new Promise((resolve, reject) => {
         if (Office.context.document.settings) {
            Office.context.document.settings.set(propertyName, value);
            Office.context.document.settings.saveAsync((asyncResult) => {
               if (asyncResult.status === Office.AsyncResultStatus.Failed) {
                  reject(`[ExcelApi] Property '${propertyName}=${value}' could not be saved. Error: ${asyncResult.error.message}`);
               } else {
                  resolve(`[ExcelApi] Property '${propertyName}=${value}' saved.`);
               }
            });
         } else {
            reject('[ExcelApi] document.settings is not ready.');
         }
      });
   }

   /** Get a document property.
    * @param {string} propertyName Name of the property. Properties are specific to the document and the Addin-ID.
    * @returns {Promise<object>} A promise that contains the property value.
    */
   function getDocumentProperty(propertyName) {
      return new Promise((resolve, reject) => {
         if (Office.context.document.settings) {
            const result = Office.context.document.settings.get(propertyName);
            if (result === null) reject(`[ExcelApi] Property '${propertyName}' not found.`);
            resolve(result);
         } else {
            reject('[ExcelApi] document.settings is not ready.');
         }
      });
   }
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49764127

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档