gpt4 book ai didi

ms-word - Word 插件 CustomXMLParts 数据建模和/或性能优化

转载 作者:行者123 更新时间:2023-12-04 21:04:34 25 4
gpt4 key购买 nike

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

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

我正在编写一个加载项,我需要在可见文档之外保留一些数据,但在 docx 文件内。

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

我拿走这些发票,在 Word 文档中呈现其中的一些,然后在任务 Pane 中对其余数据进行一些可视化分析 - 用户可以在其中将注释写回(并保存)到自定义 XML 部分(到该发票中)他们正在看)。

现在......这是我有点困惑的地方......我不确定将每张发票作为单独的 CustomXMLPart 存储在文件中(例如每个发票 1 个 XML 文件),还是存储所有发票更好在单个大型 CustomXMLPart 中,或者如果有中间地带(例如,每个 XML 部分 10 张发票)。如前所述,用例是回读所有发票,然后偶尔更新大约 10-20% 的发票中的数据。

现在,我为每个 XML 部分存储 1 张发票,当我加载插件并进行批量读取以将所有内容放入内存时,每张发票平均需要 250-500 毫秒才能并行读取它们(所以, 250-500ms * 100-200 张发票)。按顺序,它需要更长的时间(2-3 倍)。使用 performance.now() 进行测试,使用挂钟计时进行验证。

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

// 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)
}

我用 Promise 手动包装了 Office-JS 回调,但我已经使用 async/await、then/catch 和 office-js 回调测试了这个示例 - 结果都大致相同。
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),这样我就不会只是进行完全删除和重新保存?

最佳答案

Promises 的使用很好,我正在为 non-promise officejs 函数做同样的包装。使用基于 Promise 的 api,您现在可以利用 Promise.all() 进行并行操作。您可以同时开始所有操作并等待完成。这应该更快。

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 作为您的值。也许尝试将所有发票放入一个数组并将其写入相同的键。这是我的辅助函数来做到这一点:
   /** 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.');
}
});
}

关于ms-word - Word 插件 CustomXMLParts 数据建模和/或性能优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49764127/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com