【问题标题】:Service Invoked Too Many Times (Google Apps Script)服务调用次数过多(Google Apps 脚本)
【发布时间】:2012-12-15 00:57:43
【问题描述】:

我想使用 Google Apps 脚本为电子表格制作自定义函数。我做了一个非常简单的函数:

function foo(){
    return "bar";
};

问题是我需要在几百个单元格中使用此功能。当我将函数 =foo() 粘贴到所有这些单元格中时,该函数在一些单元格中工作,但在大多数情况下我收到此错误:“服务调用次数过多:电子表格。在调用之间尝试 Utilities.sleep(1000) 。”

[Screenshot here]

我想我不明白为什么这个简单的函数被认为是对电子表格服务的调用。我什至没有请求任何数据(函数本身除外)。那是问题吗?如果是这样,是否有解决方法?自定义函数可以使 Google 电子表格功能无限强大,但这个问题阻碍了在多个单元格中使用自定义函数的可能性。有什么建议吗?

(附注——当所有单元格同时调用它们的函数时,按照错误消息的建议使用 Utilities.sleep() 函数根本没有帮助;它只会减慢单个单元格重复调用函数的速率。)

【问题讨论】:

    标签: google-apps-script google-sheets custom-function


    【解决方案1】:

    根据Apps脚本功能指南中的Optimization section

    每次在电子表格中使用自定义函数时,Google 表格都会单独调用 Apps 脚本服务器。如果您的电子表格包含数十个(或数百个,或数千个!)自定义函数调用,则此过程可能会非常缓慢。

    因此,如果您计划对大量数据多次使用自定义函数,请考虑修改该函数,使其接受二维数组形式的范围作为输入,然后返回二维可以溢出到相应单元格的数组。

    为此,请传入一个表示您要返回的数组大小的输入。当你开始执行你的函数时,检查输入参数是否是一个带有input.map 的数组。如果是,您可以在每个项目上调用该函数并返回整个集合。

    所以在你的情况下是这样的:

    function foo(){
        return "bar";
    };
    

    你可以像这样更新函数:

    function foo(input){
      if (input.map) {         // Test whether input is an array.
        return input.map(foo); // Recurse over array if so.
      } else {
        // do actual function work here
        return "bar";
      }
    };
    

    然后这样称呼它:

    【讨论】:

    • 如果foo函数接受多个参数但只有第一个参数可能是一个数组,是否也有类似的方法来递归数组?
    • 这很好,但是如果我将单个值(不是单元格)传递给它,我会收到错误消息。它在if (input.map) 出错。在此之前我们如何检查传递的值是一个单元格还是一个单元格数组而不是一个简单的字符串?
    • @NikhilVJ, input.map 如果值为数组,则应返回truthy;如果不是,该函数应评估为 false 并开始处理单个输入值/字符串
    • @KyleMit 我的错!我用单引号而不是双引号传递字符串。这对单个值和数组都很有效。谢谢!
    【解决方案2】:

    通过调用电子表格中的函数,您调用了电子表格服务,要求它往返于服务器以运行函数的结果。结果,您在很短的时间内发出了几百个请求。

    一种解决方法可能是一次添加几个单元格的函数。当然,当您随后再次打开工作表时,您可能会遇到同样的问题。

    根据您的函数要完成的任务,可能值得使用内置的电子表格函数。那里有很多权力。编写一个作用于一系列值而不是单个单元格的函数可能是另一个更好的选择。它可以通过自定义菜单项或使用脚本管理器触发。

    请记住,在使用电子表格时,批处理操作是您最好的朋友。

    【讨论】:

    • 我想我应该在我的问题中透露更多关于我的最终目标的信息。简而言之,我编写了一个执行“3D”求和(跨表求和)的函数。虽然我知道您可以使用内置函数执行此操作,但问题是我每周添加工作表,这意味着我必须返回并更新这些函数以包含新工作表。我想要的只是一个函数,它可以迭代地从所有工作表中获取值并返回它们的总和,而我不必每周更新函数。
    • 我还有一个问题:为什么像我的问题中这样的简单功能需要服务器?为什么不能在客户端计算像这样简单的事情,然后将其推送到单元格中(或者至少像电子表格上的 HUD 一样显示)?我知道这个过程会导致各种权限和安全问题,但是 Google Apps 脚本不是已经能够在摆弄用户数据之前请求权限了吗?
    • 请提供有关此“3D”总和性质的更多详细信息,或提供一些示例代码以获得更多帮助。您在 Google Apps 脚本中编写的代码本质上是服务器端代码。它不是电子表格的一部分。我打赌它就像一项服务。每个脚本都被授予自己的小数据库,它具有 CPU 配额、超时限制等。除了使用“="bar" 作为电子表格功能之外,还有很多事情要做。无论如何,我相信有一种方法可以完成你的在不达到这些限制的情况下求和。
    • “3D”总和涉及将多张纸上的值相加。例如,我想从 Sheet1、Sheet2 和 Sheet3 添加 A1 单元格。在传统表示法中,公式为 =SUM(Sheet1!A1; Sheet2!A1; Sheet3!A1)。但就像我说的,我每周添加工作表,这意味着要一直更新此功能。您是否认为有一种方法可以迭代地执行此操作(即,从所有工作表中获取所有 A1 单元格)而不编写自定义函数?
    • 您可以添加一个脚本,在总和范围内调用.getFormulas(),并在所有公式的最后一个括号前添加"; Sheet14!A1",并使用.setFormulas(formulas) 设置它们。您甚至可以让脚本创建工作表并将其添加到公式中。它可以成为您每周进行的任何自动化的一部分,或者这将是开始自动化的好机会。
    猜你喜欢
    • 2017-06-23
    • 2019-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多