【问题标题】:Service Error: Spreadsheets on Google Scripts服务错误:Google Scripts 上的电子表格
【发布时间】:2014-04-19 02:29:53
【问题描述】:

范围

我开始编写一个脚本,该脚本将对 API 进行链式调用(带有 JSON 响应)并将结果写入电子表格。

会发生什么:

一旦我调试了脚本代码,它运行得很好,没有大问题,但是一旦我从电子表格按钮本身(从我创建的菜单中)运行它,它就会运行脚本的一些步骤,然后弹出一个: Service Error: Spreadsheet 没有其他错误详情。

怪事

我开始将流程的当前步骤“记录”到电子表格单元格中,以便在从调试器中运行脚本时监控其进度。

问题是,一旦我移动了一些“随机”的部分,例如:

sheet.getRange("F2").setValue(currentPage);

代码倾向于在不同的点中断。

代码示例:

您可以在此处找到重现该问题的代码:http://pastebin.com/HjmSwEYZ

你所要做的就是:

1 - 在 Google Drive 上创建一个新的电子表格

2 - 点击工具 -> 脚本编辑器

3 - 创建一个新脚本,粘贴代码并保存

4 - 重新加载电子表格 (F5),以便自定义菜单现在将显示“激战 2 追踪器”

5 - 点击按钮并点击“列出所有”

所需的输出:

这段代码应该(如果不是因为这个错误)做的是:

1 - 在这个 url 上执行一个请求:http://www.gw2spidy.com/api/v0.9/json/items/all/1(这将返回激战 2 的第一页)

2 - 遍历每个页面,解析 json 并将返回值写入电子表格

免责声明:

对工作表中的所有“日志”消息感到抱歉。这是跟踪我的进度的绝望尝试,我知道我不应该这样做。

提前致谢

更新 1:

在创建另一个电子表格并将 pastebin 代码粘贴到它自己的脚本项目中后,我可以在交互时运行它,但仅此而已。因此,这一次,它引发了一个不同的错误:We're sorry, a server error occurred. Please wait a bit and try again.

【问题讨论】:

标签: javascript json google-apps-script


【解决方案1】:

当您访问不正确的范围时,您可能会收到类似的服务错误,并且在后续访问之前可能不会引发错误。例如,如果你得到一个 Range 引用不存在的列(如 H,如果你只有 A-E),或不存在的行(如第 10001 行,当你只有 10000 行时)。这在 Apps 脚本问题跟踪器中注明:https://issuetracker.google.com/issues/68062620

关于您的问题的根源,您的脚本高度未优化,并且在使用电子表格服务方面不遵循 Apps 脚本"Best Practices"。也就是说,您应该使用批处理操作,例如Range#setValues 操作来写入整个块,或者至少使用appendRow 来追加每一行(而不是sheet.getRange(rowIndex, someColumn).setValue(oneValue))。如果需要,这些方法将添加相关行来保存数据。

代码修改示例:

var itemFields = [ "name",
                   "rarity",
                   "price_last_changed",
                   "max_offer_unit_price",
                   "min_sale_unit_price",
                   "offer_availability",
                   "sale_availability" ];
function addResultPage_(sheet, results) {
  const imgs = [],
  const data = results.map(function (result, index) {
    if (result.img)
      imgs.push({row: index, url: result.img});
    return itemFields.map(function (field) { return result[field] || ""; });
  });
  if (!data.length) return;

  const startRow = sheet.getLastRow() + 1;
  sheet.getRange(startRow, 2, data.length, data[0].length).setValues(data);
  if (imgs.length)
    imgs.forEach(function (imgInfo) {
      sheet.insertImage(imgInfo.url, 1, startRow + imgInfo.row);
    });
}
function listAllItems() {
  const sheet = SpreadsheetApp.getActiveSheet(),
        totalPages = updateStartStatus("List All Items");

  for (var page = 1; page <= totalPages; ++page) {
    var pageResults = getItemsByPage(page);
    if (pageResults.results)
      addResultPage_(sheet, pageResults.results);
    else
      console.warn({message: "No results for page '" + page + "'", resp: pageResults});
  }
}

【讨论】:

  • 不错的提示!感谢您回来回答这个问题:)
【解决方案2】:

我喜欢 ellockie 所说的 - 我(不知不觉地)遇到了同样的问题。我试图 range.sort(8),但为了收集范围,我使用了:

sheet.getRange(2,1,sheet.getMaxRows(), sheet.getMaxColumns());

但我应该使用的是:

sheet.getRange(2, 1, sheet.getMaxRows()-1, sheet.getMaxColumns());

截至 2015 年 5 月 1 日的错误消息仍然非常神秘,除了“服务错误:电子表格”之外没有提供更多详细信息。

【讨论】:

  • 对于您的情况,请考虑 getDataRange 并应用冻结行(冻结行不会被排序)
【解决方案3】:

Marchello,我今天遇到了同样的问题,并且刚刚找到了解决问题的答案:https://code.google.com/p/google-apps-script-issues/issues/detail?id=3815(参见 #4)。这个想法是在工作表的底部添加行,让脚本再次开始工作。在我的情况下它确实有效。

【讨论】:

  • 谢谢,但这只能作为一种解决方法。我最终发现真正的问题是由调用 InsertImage 方法引起的,但问题最终在 flush 调用时“爆炸”,不知道为什么。
  • 它适用于我的情况。需要“监控”可用的 [编号,白化] 行进行操作。但是错误太棒了,我们已经进入服务器端 javascript...
【解决方案4】:

在我的例子中,我有带有“动态”范围的公式,即=sum(b2:b),我记得在新的谷歌电子表格中曾提到它作为问题的原因。

更正为sum(b2:b22)(确保范围不超过工作表的最后一行)解决了问题。

【讨论】:

    【解决方案5】:

    在我的情况下,我收到此错误是因为我要求另一个电子表格对其数据进行排序,其范围为 25 列,而电子表格上只有 19 列。

    根据我的智慧,我认为在编写脚本以对 25 列进行排序而不是使用 getLastColumn 之后,我会通过删除不需要的列来整理电子表格 - 不要问我为什么。

    【讨论】:

      【解决方案6】:

      我和 ellockie 提到的问题原因相同:公式中的动态范围。在我的例子中,我使用=INDEX(B7:B,1) 来获取列标题之后的第一个单元格,即单元格 B7。我正在使用它,因为我使用 sript 插入一个新单元格,将所有实际数据向下移动,所以无论我移动单元格,我都需要获取其他单元格中的第一行值。我将其更改为 =INDIRECT(CONCATENATE(CHARACTER(COLUMN()+64);ROW()+4)) 以动态引用它

      • CHARACTER(COLUMN()+64) 给专栏信。替换=INDEX(B7:B,1) 表示B
      • ROW()+4 给我我想要的行号,下面 4 行我放了这个公式。替换 =INDEX(B7:B,1) 表示 7

      【讨论】:

        【解决方案7】:

        我也有同样的情况。但找出了根本原因,即试图复制单个单元格......你能相信吗?

        脚本的一部分试图清除一行,而那个该死的单元格就在那里。 我试图复制一行,整个电子表格崩溃了。通过一个一个复制单元格重新启动并继续,并发现一个空单元格会导致崩溃。删除了整个柱子和其他所有空柱子……然后穿过了天堂之门!

        现在,可以复制整行并且脚本工作正常!!!!!!

        【讨论】:

          【解决方案8】:

          我遇到了类似的问题,突然我开始在执行脚本时遇到错误。

          异常:服务电子表格在访问具有 id 的文档时失败

          问题在于链接到已移动范围的公式。

          因此,通过包含标题或一个额外的单元格来修改使用问题范围的公式(如果您从编辑器运行脚本,它会显示它堆叠在哪个步骤上)完全解决了我的问题。

          在我的示例中,我使用脚本在第 5 行上方添加了新单元格,而在其他工作表上,我使用 SUMIFS 公式对第 5 行的数据求和。

          我找到的解决方案:

          1. 在公式中包含一个额外的单元格,以便在其中添加新单元格时保持不变

          在我的示例中,我将 SUMIFS 公式改为从第 4 行(标题)开始求和。我总是这样做,在我之前的工作表中,脚本运行良好。

          在开发过程中,我没有注意到我如何将这些公式更改为从第 4 行求和,并且由于 Google 表格中出现的这个问题,脚本停止工作。

          1. 如果第一种方法不适合您,您可以使用 INDIRECT 函数代替实际范围。 通过这种方式,我可以从第 5 行汇总,并且脚本运行良好。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-07-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多