Excel 自动化

开发日志:120,000 行电子表格实际上会破坏什么

针对包含 121,254 行和 180 万个单元格的电子表格的工作会话,以及在大型跨表分析完成、验证其输出并返回可用的格式化报告之前必须更改的五个独立内容。

大多数电子表格功能都是根据适合屏幕的数据进行测试的。该日志涵盖了使用 121,254 行跨 15 列 — 大约 180 万个单元格 进行销售工作簿的工作会话,以及一个听起来很普通的请求:合并产品、客户、订单和销售表,然后标记下降的产品、补货风险和低价值客户。

这个请求没有什么奇怪的。无论如何,它失败了好几次,其原因几乎与分析本身无关。接下来是实际发生的情况和发生的变化。

平台限制,而不是慢速查询

第一次失败看起来像是持久作业系统中的一个错误。真正的原因是 Google Apps 脚本中的一条规则:编辑器插件不得创建每小时触发一次以上的时间驱动触发器。

后台作业设计假设一分钟触发。在开发过程中,容器绑定的脚本可以自由调度,并且在相同的代码作为安装的附加组件运行时就不再保留该假设。安装触发器的请求并没有降级——它抛出了,它抛出了 之前 作业已创建,因此工作从未开始。

随后进行了两项更改。安装触发器现在是尽力而为:它尝试一分钟的节奏,回落到每小时,最后根本没有触发器,并且它永远不会抛出。第一个处理步骤现在在创建任务的同一执行中运行,而不是在必须再次查找任务的第二次调用中运行。

第二个细节比听起来更重要。 Apps 脚本属性在执行过程中无法可靠地读取您的写入,因此之前写入的任务可能会在下一次调用时以 “找不到任务” 的形式返回。

报告进度与完成不同

工作终于开始了,但它仍然没有完成。该工具运行了一步,然后返回一个状态,表明工作“在后台继续”。

这句话是错误的。由于没有可用的每小时以下触发器,后台不会继续任何操作。助手读取状态,向用户转发百分比,然后停止——将作业无限期地停在 121,253 行中的 34,000 行。

现在,运行时在有限的预算内驱动作业自行完成,并且每个后续状态调用都会推进工作,而不仅仅是读取它。如果预算用完,状态文本会明确表示任务尚未完成,没有其他方法可以推进它。

原则值得直接说明:进度报告不是可交付成果。 用户要求提供表格,而不是百分比。

请求只能由模型可以看到的工具提供服务

为了保持刀具选择的准确性,GetSheetAI 根据请求每轮公开其刀具的子集。该机制是围绕 Excel 工具集构建的,Google Sheets 附加组件注册了仅存在于其中的 22 个工具。这些工具被从每个请求中过滤掉。

效果很具体,很容易被忽视。要求提供条形图时,会显示 44 个工具中的 6 个,其中图表工具属于隐藏工具。要求对范围进行排序,公开了 44 个中的 5 个,但没有排序工具。助手并没有拒绝——它确实看不到完成这项工作的工具。

Sheets 现在有自己的工具到捆绑包映射,镜像每个 Excel 对应项,并且过滤器会通过它没有意见的任何工具,而不是丢弃它。现在,测试直接从源读取注册的工具名称,因此添加一个工具而不对其进行分类会使构建失败,而不是悄悄地使其无法访问。

措辞中出现了同一类间隙。意思是“创建新工作表”的中文请求不匹配任何规则,因为该模式仅识别工作表的两个常见单词之一。工作表创建工具保持隐藏状态,助手报告说创建工作表是不可能的。事实并非如此。

错误消息是产品的一部分

几次失败都归结于一条消息,该消息指出了问题而没有说明解决办法。

写入不存在的工作表返回 “请求的资源不存在。” 读起来就像一个损坏的加载项。现在它说工作表不存在,写入工具不创建工作表,以及哪两个调用创建了工作表。

在很大范围内拒绝行级分类只会返回赤裸裸的拒绝。标记聚合结果适用于任何大小,因此消息现在将该路径命名为:首先进行分组,然后将分类规则应用于分组结果。

覆盖防护仅返回 blocked: true,读取为失败。现在它解释了目标已经保存了数据以及如何继续。

这些都不是装饰性的。在每种情况下,前一条消息都结束了仍可完成的任务。

确定性表达式需要更多算术

从整数日期键(如 20170702)派生年月(如 201707)需要 floor(x / 100) 或模数。两者都不存在。两次尝试都失败了,派生列被放弃。

表达式层现在包括 floorroundabsmod,并且不支持的函数错误列出了完整的集合并给出了确切的表达式,而不是仅仅命名被拒绝的表达式。

现状

在同一工作簿上,持久路径现已完成:处理、分组、写入和格式化所有 121,253 行,并验证每个结果块。在 Excel 上,相同的请求对所有 397 种产品进行了分类——132 种近期没有销售,101 种标记为补货风险,99 种下降,65 种正常——使用本机 SUMIFS 根据源表进行计算,而不是将数据移动到任何地方。

值得了解的操作值:

  • 持久路由阈值:大于100,000 个细胞
  • 源分块:有界读取,在写回时验证每个块;
  • 回归覆盖率:跨共享运行时的826 项测试
  • Google Sheets 插件上的后台执行:最多每小时,因此侧边栏在打开时会驱动长作业。

最后一点是真正的限制,而不是暂时的限制。安装的附加组件无法更频繁地安排工作,因此在侧边栏打开时会进行大型作业。持久检查点意味着关闭它不会丢失已完成的工作,但诚实的描述是工作是驱动的,而不是计划的。

这次会议更广泛的教训不是关于规模。这些故障中的每一个都是系统知道用户看不到的东西的情况:平台规则、隐藏工具、错误中无处命名的受支持路径。尺寸使它们同时可见。