Удалить несколько столбцов из Google Sheets, избегая дорогой цикл - PullRequest
2 голосов
/ 15 апреля 2020

Я пытаюсь избежать следующего кода, потому что он слишком медленный:

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

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

    {sheet2.deleteColumn(c)}

  }

Вместо этого я попытался найти список столбцов, которые я хочу удалить из массива, а затем установить массив. (Недавно я выяснил, что удаление строк / столбцов в al oop очень дорого: скрипт Google l oop производительность )

Я нашел это Удаление столбцов данных в 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)});

    }
  }

Ответы [ 3 ]

3 голосов
/ 15 апреля 2020
  • Вы хотите удалить столбцы со значением 0 в ячейках C1:Y1.
  • Вы хотите уменьшить стоимость процесса сценария.
  • Вы хотите добиться этого без использования Sheets API.

Шаблон 1:

В этом шаблоне сначала ячейки со значением 0 имеют значения из ячеек * 1014. * с использованием TextFinder, и столбцы удаляются из извлеченных ячеек с использованием 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:

В этом шаблоне тело запроса для Метод batchUpdate API Sheets создается с использованием значений 1-й строки, а тело запроса используется для запроса к API Sheets. Таким образом, можно удалить несколько столбцов одним вызовом API.

Перед запуском сценария включите Sheets API в службах Advanced Google.

Пример сценария:

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": ##
        }
      }
    }
    

Ссылки:

1 голос
/ 15 апреля 2020
function runOne() {
  var d=0;
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getActiveSheet();
  var hA=sh.getRange(1,1,1,sh.getLastColumn()).getValues()[0];//header array
  var vs=sh.getRange(2,1,sh.getLastRow()-1,sh.getLastColumn()).getValues();//data array
  vs.forEach(function(r,j){
    var d=0;
    hA.forEach(function(h,i){
      if(h==0)r.splice(i-d++,1);//removes elements in columns whose headers are == 0
    });
  });
  Logger.log(vs);
}
0 голосов
/ 15 апреля 2020
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...