Google Sheet Script server error on getNamedRanges()

落爺英雄遲暮 提交于 2019-12-05 19:43:37

How about this consideration? I don't know whether this is the best. I'm sorry.

Modification points :

It was found that when the namedrange was updated, the error occurs. The flow of your script is as follows.

When setupTestSheet() was run, the namedranges are defined by ss.setNamedRange('row1Name', shtTest.getRange('1:1')) and ss.setNamedRange('row2Name', shtTest.getRange('2:2')) as follows. Following value was retrieved using 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
      }
    }
  ]
}

At this time, respective namedranges are defined on Spreadsheet as follows. This can be seen at Spreadsheet using your browser.

row1Name 'Copy of Static'!A1:Z1
row2Name 'Copy of Static'!A2:Z2

Here, when shtTest.deleteRow(1) is run, above namedranges change as follows.

row1Name #REF
row2Name 'Copy of Static'!A2:Z2

Under this situation, no error occurs at var namedRanges = shtTest.getNamedRanges().

At setupTestSheet(), both ss.setNamedRange('row1Name', shtTest.getRange('1:1')); and ss.setNamedRange('row2Name', shtTest.getRange('2:2')); work fine.

But, changeRangeReferencesToFullRow() doesn't work completely. When changeRangeReferencesToFullRow() runs, namedranges are as follows. It is found that the column data is lost.

{
  "namedRanges": [
    {
      "namedRangeId": "#####",
      "name": "row1Name",
      "range": {
        "startRowIndex": 0,
        "endRowIndex": 1,
        "sheetId": #####
      }
    },
    {
      "namedRangeId": "#####",
      "name": "row2Name",
      "range": {
        "startRowIndex": 1,
        "endRowIndex": 2,
        "sheetId": #####
      }
    }
  ]
}

At this time, respective namedranges are defined on Spreadsheet as follows.

row1Name 'Copy of Static'!1:1
row2Name 'Copy of Static'!2:2

Under this situation, no error occurs at var namedRanges = shtTest.getNamedRanges().

Here, when shtTest.deleteRow(1) is run, above namedranges become as follows.

row1Name #REF
row2Name 'Copy of Static'!2:2

Under this situation, the error occurs at var namedRanges = shtTest.getNamedRanges(). So when shtTest.deleteRow(1) is used, row1Name #REF has to be removed or updated.

These indicates that the range like 1:1 and 2:2 might not be suitable for the namedrange of SpreadsheetApp.

Workaround :

The workaround reflected above consideration is as follows.

  1. After the row was removed by deleteRow(), redefine the namedrange of the row using ss.setNamedRange('row1Name', shtTest.getRange('1:1')) and ss.setNamedRange('row2Name', shtTest.getRange('2:2')).
  2. Remove the namedrange of the row removed by deleteRow() using following modified script. Modify only doTest() as following script.

Script :

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 );
}

In my environment, above scripts works fine. If these don't work at your environment. Feel free to tell me.

For additional question

How about use of Sheet API?

In order to remove orphaned range names from any Google Spreadsheet, you can use namedRangeId. namedRangeId is the individual ID for each namedrange. By using this, the orphaned range names can be removed.

In order to use namedRangeId,it uses Sheet API. So please enable Sheet API for Advanced Google Services and Google API Console.

Google Sheets API v4 https://developers.google.com/sheets/api/

Advanced Google Services https://developers.google.com/apps-script/guides/services/advanced

Sample script :

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()
);

The flow is as follows.

  1. Using Sheets.Spreadsheets.get(), retrieve name and namedrangeID.
  2. The namedrangeID matched to the name is removed.

In the case of use of Sheet API, if the range data is lost, although getNamedRanges() occurs the error, Sheet API can retrieve the namedrange.

If I misunderstand your additional question, I'm sorry.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!