我可以在 .3 秒内写入 25000 行 x 3 列纯文本,这太棒了。
但是,一旦我添加的不仅仅是纯文本(格式、公式、单元格着色、条件格式、columnWidth 调整等(,它就会花费更长的时间才能完成。
例如,我用 range.getCell(i, 0).format.fill.color = 'yellow'
编写了相同的 25000 行(x 1 列(,即使使用 suspendApiCalculationUntilNextSync()
也花了 31.223 秒。
在将带有格式的行写入 Excel 时,如何获得更好的写入性能?
一、长期
- 首先,我们正在考虑制作一个API[还没有ETA,但正在积极研究],它应该可以将2D格式数组输入到Range中(就像你今天可以使用".values"一样,而不必单独创建范围并且一次只设置一个单元格(。 当您有一个矩形单元格块并希望同时在其上设置一堆格式时,这应该会更快。
- 如果您的单元格分散在网格中,但它们在概念上被分组,以便其中一些共享相同的颜色/格式,另一个即将推出的 API 将允许您创建多区域范围也将允许您加快处理速度。 如果内存来自 VBA/VSTO,则最佳选择是创建一个由 ~30 个单独范围组成的多区域范围对象(例如,"A1、B7:B9、C11、A4、..."(,并一次性设置它们的格式。 这也应该有所帮助。
现在,对于短期解决方法:如果您引用 CDN 并且使用的是较新的 Office 版本(可能只是"当前频道"就足够了(,您应该能够通过释放不需要的范围看到显着的改进。
先介绍一下背景。 当你执行Excel.run(...)
时,你在回调中使用的任何范围都会在run
期间被跟踪,以便在添加/删除新行/列时可以调整它们。 此过程会占用内存,虽然在大多数情况下无法察觉,但如果您创建 1000 个范围,它会大大减慢 Excel 的速度。 使用格式设置时,如果您单独将不同的单元格格式化为不同的颜色,并且您的起始范围足够大,则很可能会进入 1000 年代。 此外,这包括您创建的任何范围,甚至是中间范围(例如,如果您var rangeXYZ = originalRange.getCell(0,0).getResizedRange(1,1).getIntersection(somethingElse)
,您不仅会创建rangeXYZ
范围,而且还会创建两个无名的中间范围,一个用于originalRange.getCell(0,0)
,另一个用于调整大小的范围。 这些范围仍将在整个Excel.run
期间持续存在,即使您再也不会访问它们! 当然,好消息是,最后,我们确实会在Excel.run
完成后垃圾收集所有这些不需要的范围,但是您的代码在Excel.run
内仍然运行缓慢,这正是您的问题所在。
所以:正如我所提到的,从较新的版本开始(在旧版本上没有操作(,你可以在 Range 上调用 .untrack()
来表明你不需要长期跟踪它。 为方便起见,对 ".untrack((" 的调用返回对象本身,以便您可以按如下方式链接它:
var rangeXYZ = originalRange
.getCell(0,0).untrack()
.getResizedRange(1,1).untrack()
.getIntersection(somethingElse).untrack();
rangeXYZ.format.fill.color = "yellow"
请注意每个中间范围以及"范围XYZ"本身的.untrack()
。 任何标记为取消跟踪的范围都将在处理context.sync()
过程中的适当时机进行处置。 您仍然可以在 context.sync()
之前继续使用 Range,但在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()
调用中撒上非常容易,并且改进可能是显着的。
最好!
~迈克尔
尝试为尽可能多的单元格创建一个范围,然后调用以下代码一次:
range.format.fill.color = 'yellow'
如果无法创建较大的连续范围,请尝试在一个context.sync()
内对尽可能多的以下代码调用进行批处理
range.format.fill.color='yellow'