代码之家  ›  专栏  ›  技术社区  ›  cs_pupil

Office.js Excel:在使用格式编写行时提高性能

  •  3
  • cs_pupil  · 技术社区  · 6 年前

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

    但是,一旦我添加的文本超过了纯文本(格式、公式、单元格颜色、条件格式、列宽调整等),就需要花费相当长的时间才能完成。

    例如,我用 range.getCell(i, 0).format.fill.color = 'yellow' 它用了31.223秒,即使使用 suspendApiCalculationUntilNextSync() .

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

    2 回复  |  直到 6 年前
        1
  •  3
  •   Michael Zlatkovsky    6 年前

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

    首先, 长期

    1. 首先,我们正在寻找一个API[还没有eta,但是它 积极调查]这应该可以将一个二维格式数组输入一个范围(就像你今天可以使用“.values”那样,而不是单独创建范围,一次只设置一个单元格)。如果你有一个矩形的单元格块,并且想同时在上面设置一系列格式,这会使它更快。
    2. 如果您的单元格分散在网格中,但是它们在概念上是分组的,因此其中一些单元格共享相同的颜色/格式,那么另一个即将到来的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运行 ,这正是你的问题所在。

    所以:正如我所提到的,从新的版本开始(不使用旧的版本),你可以打电话给 .untrack() 在该范围内表示您不需要对其进行长期跟踪。为了方便起见,对“.untrack()”的调用返回对象本身,以便您可以按如下方式链接它:

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

    注意 .untrack()。 在每个中间范围以及“rangexyz”本身上。标记为取消跟踪的任何范围都将在处理 context.sync() . 你仍然可以继续使用这个范围 之前 context.sync()。 ,但在 context.sync()。 将引发错误。基本上,想想 untrack() 将对象标记为在下一个 context.sync()。 .

    您的里程数会有所不同,但在我使用的示例中,性能从13.7秒提高到5.7秒,即在格式化100x100单元格的范围时,性能提高了2.5倍,您可以在这里看到代码差异: https://github.com/OfficeDev/office-js-snippets/pull/184/files#diff-4bec6e2366b688602d12011ad3b0f2ef . 如你所见,很容易洒在 .untrack()。 打电话,情况可能会有很大的改善。

    最好!

    ~迈克尔

        2
  •  1
  •   LuFFy Тип Странный    6 年前

    尝试为尽可能多的单元格创建一个区域,然后调用下面的代码一次:

    range.format.fill.color = 'yellow'
    

    如果无法创建大的连续范围,请尝试在一个范围内批处理尽可能多的以下代码调用 context.sync()

    range.format.fill.color='yellow'