Office.js Excel: 提高写入带格式的行时的性能

Office.js Excel: Improve performance when writing rows with formatting

我可以在 0.3 秒内写出 25000 行 x 3 列的纯文本,这太棒了。

但是,一旦我添加的不仅仅是纯文本(格式、公式、单元格着色、条件格式、列宽调整等),完成所需的时间就会大大延长。

例如,我用 range.getCell(i, 0).format.fill.color = 'yellow' 写了相同的 25000 行(x 1 列),即使使用 suspendApiCalculationUntilNextSync().

也花了 31.223 秒

在将格式化为 Excel 的行写入时,如何才能获得更好的写入性能?

尝试为尽可能多的单元格创建范围,然后调用以下代码一次:

range.format.fill.color = 'yellow'

如果您无法创建一个大的连续范围,请尝试在一个 context.sync()

内尽可能多地批处理以下代码调用
range.format.fill.color='yellow'

回答这个问题有两个角度。

首先,长期

  1. 首先,我们正在考虑制作一个API[还没有预计到达时间,但正在积极调查]应该可以提供一个二维数组将格式转换为一个范围(就像您今天可以使用“.values”做的那样,而不必单独创建范围并且一次只设置一个单元格)。当您有一个矩形单元格块并想同时在其上设置一堆格式时,这应该会使它更快。
  2. 如果您的单元格分散在网格中,但它们在概念上被分组,使得它们中的一些共享相同的 colors/formatting,另一个即将推出的 API 将允许您创建多区域范围还可以让您加快处理速度。如果内存从 VBA/VSTO 开始服务,最佳选择是创建一个由约 30 个独立范围组成的多区域范围对象(例如,"A1, B7:B9, C11, A4, ..."),并一次性设置它们的格式。这也应该有所帮助。

现在,短期解决方法:如果您正在引用 CDN 并且使用较新版本的 Office(可能 "current channel" 就足够了),您应该能够通过 处理不需要的范围 .

来看到显着的改进

先介绍一下背景。当您执行 Excel.run(...) 时,您在该回调中使用的任何范围都会在 run 的持续时间内得到跟踪,以便在新的 rows/columns 为 added/deleted 时可以调整它们].此过程会占用内存,虽然在大多数情况下无法察觉,但如果您创建 1000 多个范围,它会显着降低 Excel 的速度。使用格式化,如果您将不同的单元格单独格式化为不同的颜色,并且如果您的起始范围足够大,您很可能会进入 1000s。此外,这包括您创建的 任何 范围,甚至是中间范围(例如,如果您这样做 var rangeXYZ = originalRange.getCell(0,0).getResizedRange(1,1).getIntersection(somethingElse),您不仅会创建 rangeXYZ 范围,而且您还将创建两个无名中间范围,一个用于 originalRange.getCell(0,0),另一个用于调整大小的范围。这些范围在 Excel.run 的整个持续时间内仍然存在,即使您永远不会再次访问它们! 当然,好消息是 在最后 ,当 Excel.run 完成时,我们确实会垃圾收集所有这些不需要的范围,但你的代码仍然是 运行 在 Excel.run 内变慢,这正是您的问题所在。

因此:正如我所提到的,从较新的版本开始(对较旧的版本停止操作),您可以在范围上调用 .untrack() 以表明您不需要更长时间地跟踪它-学期。为方便起见,对“.untrack()”的调用 returns 对象本身,以便您可以按如下方式链接它:

var rangeXYZ = originalRange
    .getCell(0,0).untrack()
    .getResizedRange(1,1).untrack()
    .getIntersection(somethingElse).untrack();
rangeXYZ.format.fill.color = "yellow"

注意每个中间范围的 .untrack(),以及 "rangeXYZ" 本身。任何标记为取消跟踪的范围都将在 context.sync() 的处理过程中适时处理。您仍然可以继续使用范围 before context.sync(),但尝试在 context.sync() 之后使用它会引发错误。本质上,将 untrack() 视为在下一个 context.sync().

上标记要进行早期垃圾回收的对象

你的里程会有所不同,但在我使用的示例中,当格式化 100x100 单元格的范围时,性能从 13.7 秒提高到 5.7 秒,即 2.5 倍的性能提升你可以在此处查看代码差异:https://github.com/OfficeDev/office-js-snippets/pull/184/files#diff-4bec6e2366b688602d12011ad3b0f2ef。正如您所看到的,在 .untrack() 调用中加入非常容易,并且改进非常显着。

最好!

~迈克尔