Max*_*rov 4 performance triggers google-sheets google-apps-script google-sheets-formula
这个问题最近出现~2022年8月25日。
\n我的onEdit触发器依赖于工作表名称,并且脚本运行时间太长而无法获取它。这是在我的环境中重现错误的最小脚本:
function onEdit(e) {\n var t = new Date();\n console.log(\'we are in onEdit!\');\n var sheetName = e.range.getSheet().getName();\n console.log(sheetName);\n console.log(\'We got sheet name. Time past = \' + (new Date() - t));\n}\nRun Code Online (Sandbox Code Playgroud)\n该函数range.getName()运行速度太慢,并且脚本超时。
我以前从未见过这种行为。其他样本:SpreadsheetApp. 在我的另一个文件中,这一行需要 30 秒:
SpreadsheetApp.openById(id);
这是重现错误所需的最少代码的文件:
\nonEdit 崩溃测试 \xe2\x9e\xa1\xef\xb8\x8f e.range.getSheet().getName()
\n请复印一份。
\n重现onEdit错误
它有一些公式,并且脚本运行速度很快。
\n我的目标是理解为什么公式会导致sheet.getName()方法变慢。
\n\n超过最大执行时间
\n
最大。onEdit 的时间为 30 秒。测试表明它的sheet.getName()工作时间太长了。如果没有该功能,我无法看到编辑后的工作表名称getName(),因为它位于触发器内。
即使是 Lock 和 Cache 也没有解决这个问题:
\n注射
\n /** Injection. Use Cache to Speed Up `getName()` method */ \n var lock = LockService.getScriptLock();\n try {\n lock.waitLock(30000); // wait 30 seconds for others\'\n } catch (e) {\n throw \'Could not get Sheet Name in 30 sec. :(\';\n } \n var sheetNameCacheKey = \'sheetNameforThoseWhoForgotten\';\n var c = CacheService.getUserCache();\n var sheetNameFromCache = c.get(sheetNameCacheKey);\n if (sheetNameFromCache) {\n sets.sheetName = sheetNameFromCache; \n console.log(\'Prolongated Cache Life!\');\n c.put(sheetNameCacheKey, sets.sheetName, 5);\n } else {\n // This function is actually needed, \n // but does not work fast\n // \xe2\x8f\xb3\n sets.sheetName = sets.sheet.getName(); \n // Write Sheet Name to Memory for 5 seconds\n c.put(sheetNameCacheKey, sets.sheetName, 5);\n console.log(\'Added Sheet Name to Cache!\');\n }\n lock.releaseLock();\n /** End of Injection */\nRun Code Online (Sandbox Code Playgroud)\n这段代码使我的触发器更加稳定,但仍然偶尔会失败。
\n\n\n读取工作表名称的时间为:151766
\n
这已经快3分钟了!但这个数字会发生变化,有时可能需要大约 150 毫秒才能运行。
\n我的猜测是这个错误是由 Google Sheets 的最新大更新和新功能引起的:
\n\nIMPORTRANGE我这么认为是因为这个问题与错误有关:
\n\n导入范围内部错误。
\n
我也经历过和你一样的情况。似乎当电子表格中包含公式的大量计算时,就会发生这种情况。在这种情况下,这也体现在脚本的触发和直接执行上。我不确定这种情况是当前规范还是错误。
\n当时我注意到,在这种情况下,Google Apps Script 的方法的处理成本存在差异。例如,当我在示例电子表格中看到您提供的脚本时,我发现了以下脚本。
\nfunction onEdit(e) {\n var t = new Date();\n console.log(\'we are in onEdit!\');\n var sheetName = e.range.getSheet().getName(); // times out \xe2\x8f\xb3!\n console.log(sheetName);\n console.log(\'We got sheet name. Time past = \' + (new Date() - t));\n}\nRun Code Online (Sandbox Code Playgroud)\n当以该脚本为样本时,在这种情况下, 的流程成本e.range.getSheet()远低于e.range.getSheet().getName(). 由此,作为示例,为了检索活动工作表的工作表名称,需要使用低处理成本的方法。在此解决方法中,作为示例情况,使用您提供的电子表格,我想从您的上述脚本中提出一个修改后的脚本。
在此解决方法中,我使用e.range.getSheet().getSheetId()而不是e.range.getSheet().getName(). 并且,使用Sheets API。因为 的处理成本e.range.getSheet().getSheetId()低于e.range.getSheet().getName(),并且,为了从工作表 ID 检索工作表名称,当使用电子表格服务(SpreadsheetApp)时,处理成本会变高。
当此解决方法反映在您的上述脚本中时,它会变成如下所示。
\n请将以下脚本复制并粘贴到您提供的电子表格的脚本编辑器中。并且,请启用 Sheets API。并且,请将 OnEdit 触发器安装到 的函数中installedOnEdit。当您使用此脚本时,请在单元格中输入一个值。这样,脚本就可以工作,您可以在日志中看到活动工作表的工作表名称。
function installedOnEdit(e) {\n var t = new Date();\n console.log(\'we are in onEdit!\');\n var sheetId = e.range.getSheet().getSheetId();\n var ssId = e.source.getId();\n const sheetName = Sheets.Spreadsheets.get(ssId).sheets.find(s => s.properties.sheetId == sheetId).properties.title;\n console.log(sheetName)\n console.log(\'We got sheet name. Time past = \' + (new Date() - t));\n}\nRun Code Online (Sandbox Code Playgroud)\n当将值放入单元格时,您可以在日志中看到工作表名称。在我的测试中,处理时间约为 3 秒。
\n就我而言,作为这样的解决方法,当在包含公式的大量计算的电子表格中使用 OnEdit 触发器和脚本时,我研究低成本方法并使用它们。
\n作为补充信息,当我测试这种情况时,发现单元格值没有被检索,并且该过程不受公式计算的影响。当看到上面的示例脚本时,不会检索单元格值。看来这样可以减少公式计算时的过程成本。
\n另一方面,当使用Sheets API将单元格值放入单元格时,发现该过程不受公式计算的影响。此外,我们还发现,当使用电子表格服务(SpreadsheetApp)输入单元格值时,该过程会受到公式计算的影响。
\n| 归档时间: |
|
| 查看次数: |
594 次 |
| 最近记录: |