在为Google表格编写Google Apps脚本以删除已删除其所引用目标而成为孤儿的命名范围时,会出现意外的服务器错误"发生了。有人可以告诉我如何避免它吗?
编辑:请注意,除了解决附加的演示脚本之外,我每次调用例程SpreadsheetApp.getNamedRanges()时都会寻求一般解决方案。我将部署一个命令,以从任何Google电子表格中删除孤立范围名称。它将成为dlbTools中NamedRanges例程的一部分,该例程已在{4}的Google加载项商店中提供。
我写了一个演示它的Google电子表格,产生了这样的信息: - "我们很抱歉,发生了服务器错误。请稍等一下再试一次。 (第8行,文件"代码")"。 此电子表格可在https://chrome.google.com/webstore/detail/dlbtools./ochdleihpppeoboanknpbmabbdjfihjj
公开发布发生错误:
使用Google电子表格演示此意外服务器错误的步骤如下:
以下是演示服务器错误的测试脚本: function findOrphans(){
// Helper function logs Named Range names and references.
var logNamedRanges = function (scenario) {
Logger.log('Logging named ranges for scenario: ' + scenario);
Logger.log('In logNamedRanges() before call to getNamedRanges()');
var namedRanges = ss.getNamedRanges();
Logger.log('In logNamedRanges() after call to getNamedRanges()');
var names = namedRanges.map(function (nr){return nr.getName() + ' --> ' + nr.getRange().getA1Notation();});
Logger.log('\n' + names.join('\n'));
}
// Helper function alters Named Ranges to full row references.
// That is, "A1:B1" becomes "1:1".
var changeRangeReferencesToFullRow = function () {
Logger.log('In changeRangeReferencesToFullRow() before call to getNamedRanges()');
var namedRanges = shtTest.getNamedRanges();
Logger.log('In changeRangeReferencesToFullRow() after call to getNamedRanges()');
for (var i = 0; i < namedRanges.length; i++) {
var n = namedRanges[i].getRange().getA1Notation();
var num = n.charAt(1);
var fullRowA1Notation = num + ':' + num;
var fullRowNameRange = shtTest.getRange(fullRowA1Notation);
namedRanges[i].setRange(fullRowNameRange);
}
Logger.log('Successfully changed Named Ranges to full row references');
}
// Helper function creates test sheet by copying sheet Static and
// creates Named Ranges for each of the first two rows.
var setupTestSheet = function () {
if (ss.getSheetByName('Copy of Static') != null) {
// Test sheet already exists, so delete it.
ss.deleteSheet(ss.getSheetByName('Copy of Static'));
Logger.log('Deleted existing copy of test sheet');
}
// Activate sheet Static, duplicate it, and grab reference to it.
shtStatic.activate();
ss.duplicateActiveSheet();
shtTest = ss.getSheetByName('Copy of Static');
// Create or update Named Nanges pointing to the first two rows.
ss.setNamedRange('row1Name', shtTest.getRange('1:1'));
ss.setNamedRange('row2Name', shtTest.getRange('2:2'));
Logger.log('Successfully set up test sheet');
}
// Helper function runs test sequence.
function doTest (whichPass) {
Logger.log('\n\nStarting test using ' + whichPass + '\n\n');
setupTestSheet();
if (whichPass.slice(0,3) == '1:1') {
// next line is only difference between the passes
changeRangeReferencesToFullRow();
}
logNamedRanges('Before row delete')
shtTest.deleteRow(1);
if (whichPass.slice(-5) == 'error') {
// next line stops test before error occurs
Logger.log('Halted test to avoid error');
return;
}
logNamedRanges('After row delete')
Logger.log('Finished test using ' + whichPass );
}
// Create variables that will be available to helper functions.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var shtStatic = ss.getSheetByName('Static');
var shtTest;
// Execute test sequence three times.
doTest('A1:B1 style references');
doTest('1:1 style references with stop before server error');
doTest('1:1 style references without stopping');
}
@ Tanaike建议使用Sheets API有帮助,因为它成功检索SpreadsheetAPP调用失败的命名范围列表。不幸的是,它不包括最感兴趣的人 - 孤儿。
https://docs.google.com/spreadsheets/d/1IKwGb9guw5Ud1q2YJj3Ao1yjjIvMGv35Pcpe_lyq48I/edit?usp=sharing处的演示电子表格现在包含一个名为trySheetsAPI.gs
的附加脚本文件。顶部的注释告诉我们如何识别测试Sheets API的其他代码。虽然我很欣赏这个有用且有趣的建议,但它仍然不允许我编写一个通用的孤儿删除例程。
答案 0 :(得分:3)
这个考虑怎么样?我不知道这是否是最好的。对不起。
发现当更新named范围时,会发生错误。您的脚本流程如下。
运行setupTestSheet()
时,ss.setNamedRange('row1Name', shtTest.getRange('1:1'))
和ss.setNamedRange('row2Name', shtTest.getRange('2:2'))
定义了命名范围,如下所示。使用Sheet API检索以下值。
{
"namedRanges": [
{
"namedRangeId": "#####",
"name": "row1Name",
"range": {
"endColumnIndex": 26,
"startRowIndex": 0,
"endRowIndex": 1,
"sheetId": #####,
"startColumnIndex": 0
}
},
{
"namedRangeId": "#####",
"name": "row2Name",
"range": {
"endColumnIndex": 26,
"startRowIndex": 1,
"endRowIndex": 2,
"sheetId": #####,
"startColumnIndex": 0
}
}
]
}
此时,各个命名范围在电子表格上定义如下。这可以使用您的浏览器在电子表格中看到。
row1Name 'Copy of Static'!A1:Z1
row2Name 'Copy of Static'!A2:Z2
此处,当shtTest.deleteRow(1)
运行时,以上命名范围会发生如下变化。
row1Name #REF
row2Name 'Copy of Static'!A2:Z2
在这种情况下,var namedRanges = shtTest.getNamedRanges()
处没有发生错误。
在setupTestSheet()
,ss.setNamedRange('row1Name', shtTest.getRange('1:1'));
和ss.setNamedRange('row2Name', shtTest.getRange('2:2'));
都可以正常工作。
但是,changeRangeReferencesToFullRow()
并不完全有效。运行changeRangeReferencesToFullRow()
时,命名范围如下。发现列数据丢失了。
{
"namedRanges": [
{
"namedRangeId": "#####",
"name": "row1Name",
"range": {
"startRowIndex": 0,
"endRowIndex": 1,
"sheetId": #####
}
},
{
"namedRangeId": "#####",
"name": "row2Name",
"range": {
"startRowIndex": 1,
"endRowIndex": 2,
"sheetId": #####
}
}
]
}
此时,各个命名范围在电子表格上定义如下。
row1Name 'Copy of Static'!1:1
row2Name 'Copy of Static'!2:2
在这种情况下,var namedRanges = shtTest.getNamedRanges()
处没有发生错误。
此处,当shtTest.deleteRow(1)
运行时,以上命名范围变为如下。
row1Name #REF
row2Name 'Copy of Static'!2:2
在这种情况下,错误发生 var namedRanges = shtTest.getNamedRanges()
。因此,在使用shtTest.deleteRow(1)
时,必须删除或更新row1Name #REF
。
这表示1:1
和2:2
等范围可能不适合SpreadsheetApp
的命名范围。
上述反映的解决方法如下:
deleteRow()
删除该行后,使用ss.setNamedRange('row1Name', shtTest.getRange('1:1'))
和ss.setNamedRange('row2Name', shtTest.getRange('2:2'))
重新定义该行的命名范围。deleteRow()
删除的行的命名范围。仅修改doTest()
以下脚本。function doTest (whichPass) {
Logger.log('\n\nStarting test using ' + whichPass + '\n\n');
setupTestSheet();
var r = shtTest.getNamedRanges(); // <--- Added
if (whichPass.slice(0,3) == '1:1') {
// next line is only difference between the passes
changeRangeReferencesToFullRow();
}
logNamedRanges('Before row delete')
var dummy = [i.remove() for each (i in r) if (i.getName() == "row1Name")]; // <--- Added
shtTest.deleteRow(1);
if (whichPass.slice(-5) == 'error') {
// next line stops test before error occurs
Logger.log('Halted test to avoid error');
return;
}
logNamedRanges('After row delete')
Logger.log('Finished test using ' + whichPass );
}
在我的环境中,上面的脚本运行正常。如果这些不适合您的环境。随时告诉我。
如何使用Sheet API?
要从任何Google电子表格中删除孤立范围名称,您可以使用namedRangeId
。 namedRangeId
是每个命名范围的个人ID。通过使用它,可以删除孤立的范围名称。
为了使用namedRangeId
,它使用Sheet API。因此,请为高级Google服务和Google API控制台启用Sheet API。
Google表格API v4 https://developers.google.com/sheets/api/
高级Google服务https://developers.google.com/apps-script/guides/services/advanced
var ss = SpreadsheetApp.getActiveSpreadsheet();
var r = Sheets.Spreadsheets.get(ss.getId(), {fields: "namedRanges(name,namedRangeId)"});
Sheets.Spreadsheets.batchUpdate(
{"requests": [{
"deleteNamedRange": {
"namedRangeId": [i.namedRangeId for each (i in r.namedRanges) if (i.name == "### name ###")][0]
}}]},
ss.getId()
);
流程如下。
Sheets.Spreadsheets.get()
,检索名称和namedrangeID。在使用Sheet API的情况下,如果范围数据丢失,虽然错误发生getNamedRanges()
,但Sheet API可以检索命名范围。
如果我误解了你的其他问题,我很抱歉。