从Google表格中删除多列,避免昂贵的循环

菲利波:

我试图避免以下代码,因为它太慢了:

 for (var c = 25; c>2; c--){

    if (sheet2.getRange(1,c).getValue() == 0) 

    {sheet2.deleteColumn(c)}

  }

相反,我尝试找到要从数组中删除的列的列表,然后设置数组。(我最近发现,删除循环中的行/列非常昂贵:谷歌脚本循环性能

我发现此“ 删除javascript数组中的数据列”并尝试将其应用于我的代码,但无法正常工作。

这是代码。

  var ary = sheet2.getRange(2,1,outData.length+1,outData[0].length).getValues();
  var indexesToRemove = [];
  for (var c = 25; c>2; c--){

    if (sheet2.getRange(1,c).getValue() == 0)

    {
      indexesToRemove.push(c);

    }
  }

上面的部分效果很好。一旦我找到要删除的索引,该功能将无法从数组中删除列。数组_row不是我要的。我究竟做错了什么?

removeColumns(ary, indexesToRemove);}



function removeColumns(data, indexes) {
    return data.map(function (row) {
        // when we remove columns, the indexing gets off by 1 each time, keep track of how many to adjust
        var indexAdjustment = 0;
        // copy row w/ .slice so we do not modify the original array
        var _row = row.slice();
        indexes.forEach(function (colIndex) {
            // remove column
            _row.splice(colIndex - indexAdjustment, 1);
            // add 1 to adjustment to account for the column we just removed
            indexAdjustment++
        });
        return _row;
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var sheet2 = ss.getSheetByName('Cache');  
      sheet2.clear();
      sheet2.getRange(2,1,_row.length,_row[0].length).setValues(_row);
    });
}  

顺便说一句,我之前也尝试过此方法,但仍无法正常工作:

  var ary = sheet2.getRange(2,1,outData.length+1,outData[0].length).getValues();
  for (var c = 25; c>2; c--){

    if (sheet2.getRange(1,c).getValue() == 0)

    { ary = ary.map(function(item){
        return item.splice(0,c)});

    }
  }
Tanaike :
  • 您要删除0单元格中的值所在的列C1:Y1
  • 您想减少脚本的处理成本。
  • 您想要不使用Sheets API来实现这一目标。

模式1:

在这种模式下,首先,使用TextFinder 0单元格中获得值的单元C1:Y1格,并使用从已检索单元格中删除列deleteColumn()

示例脚本:

const sheet = SpreadsheetApp.getActiveSheet();

sheet.getRange("C1:Y1")
  .createTextFinder(0)
  .matchEntireCell(true)
  .findAll()
  .reverse()
  .forEach(e => sheet.deleteColumn(e.getColumn()));

模式2:

在这种模式下,首先,将所有值从“ C1”检索到所有数据行的最后一列,然后删除数组中的列并清除范围,然后将这些值放入表中。已经提出了直接处理取回值的方法。因此,作为其他模式,我提出了使用转置的方法。

示例脚本:

const sheet = SpreadsheetApp.getActiveSheet();

const range = sheet.getRange(1, 3, sheet.getLastRow(), sheet.getLastColumn() - 2);
const values = range.getValues();
const t = values[0].reduce((ar, r, i) => {
  if (r != 0) ar.push(values.map(c => c[i]));
  return ar;
}, []);
const v = t[0].map((_, i) => t.map(c => c[i]));
range.clearContent();
sheet.getRange(1, 3, v.length, v[0].length).setValues(v);

模式3:

在此模式下,使用第一行值创建Sheets API的batchUpdate方法的请求正文,该请求正文用于请求Sheets API。这样,一个API调用可以删除几列。

在运行脚本之前,请在高级Google服务中启用Sheets API。

示例脚本:

const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const sheet = spreadsheet.getActiveSheet();
const sheetId = sheet.getSheetId();

// Create rerequests for DeleteDimensionRequest.
const requests = sheet.getRange("C1:Y1")
  .createTextFinder(0)
  .matchEntireCell(true)
  .findAll()
  .reverse()
  .map(e => {
    const col = e.getColumn();
    return {deleteDimension: {range: {sheetId: sheetId, dimension: "COLUMNS", startIndex: col - 1, endIndex: col}}}
  });

// Request to the batchUpdate method using the request body.
Sheets.Spreadsheets.batchUpdate({requests: requests}, spreadsheet.getId());
  • 在这种情况下,requests使用模式1的方法创建。每个请求如下。您可以在文档中看到有关此结构的信息。

    {
      "deleteDimension": {
        "range": {
          "sheetId": "###",
          "dimension": "COLUMNS",
          "startIndex": ##,
          "endIndex": ##
        }
      }
    }
    

参考文献:

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章