Проблема с 2D-массивом - Google Apps Script - PullRequest
0 голосов
/ 04 июня 2018

Я пытаюсь пройтись по большому диапазону ячеек, проверяя значение в столбце A, если это возвращает true, тогда я хочу сохранить соседние 3 ячейки (столбцы BD) в массиве и в конечном итоге вставить массив на отдельный лист,Текущий код находит все правильные значения, но записывает их все в одну строку вместо нескольких строк и 3 столбцов, как в исходном источнике данных.

var dataset = [],
    month,
    i,
    j,
    x = 0,
    targetmonth = ss.getSheetByName("BOH").getRange("B2").getValue(),
    location = ss.getSheetByName(output).getRange("D3").getValue();

for ( i = 7; i < 3000; i++){
  month = ss.getSheetByName(location).getRange(i,1).getValue();
  if (month == targetmonth){
    for (j = 2; j<5; j++){
      dataset [x] = [ss.getSheetByName(location).getRange(i,j).getValues()];
      x = x + 1;
    } 
  }
}

//I've changed the range size in line below to 360x3 which is what it should be 
//but this line currently only runs when set to 1x360

ss.getSheetByName(output).getRange(8,3,360,3).setValues([dataset]);

1 Ответ

0 голосов
/ 05 июня 2018

Следуя рекомендациям, вы должны свести к минимуму повторные обращения в службу электронных таблиц с помощью getValues().Ваш текущий сценарий циклически обращается к значениям A7: A2999 один за другим, когда он может сделать это за одно чтение:

// const x -> no reassignment / redeclaring x allowed. (You can still manipulate the object).
const startRow = 7, endRow = 2999,
    numRows = endRow - startRow + 1;
const months = ss.getSheetByName(location)
  .getRange(startRow, 1, numRows, 1).getValues();

Затем вы получаете условный доступ к столбцам B: D того же диапазона.Вы обнаружите, что все еще быстрее просто прочитать все это в память с самого начала и получить доступ к нужным строкам и столбцам только при необходимости:

const startCol = 2, endCol = 4,
    numCols = endCol - startCol + 1;
const targetValues = ss.getSheetByName(location)
  .getRange(startRow, startCol, numRows, numCols).getValues();

Вам также следует использовать более значимые имена индексов итерации, чем i и j, и вам не нужно объявлять все в начале вашей функции (читайте о JavaScript и «подъеме»), когда смысл использования более значим.

ОстальныеВаша функция выглядит следующим образом:

const output = [],
    targetMonth = /** set this */,
    destinationName = /** set this */;
for (var monthIndex = 0; monthIndex < months.length; ++monthIndex) {
  // Add the array of target column values to the output (by reference)
  if (months[monthIndex][0] === targetMonth) {
    output.push(targetValues[monthIndex]);
  }
}
// Write the output array.
ss.getSheetByName(destinationName).getRange(8, 3, output.length, output[0].length).setValues(output);

Мы только что перешли от ~ numRows x numColumns Spreadsheet к доступу к ~ 4!Учитывая, что отдельные вызовы для доступа к сотовой сети занимают около 0,1 секунды, это будет загрузка лодки быстрее .Да, если вы читаете много ячеек, это может занять некоторое время (получение / установка значений из ячеек 400 КБ составляет ~ 30 секунд), но это не займет столько времени, сколько доступ 1: 1.

Ссылки:

PS: если вы измените значения в targetValues перед сериализацией данных, те, на которые есть ссылки в output, также обновятся, потому что это один и тот же объект.(Прочтите «по значению» / глубокая копия и «по ссылке» / мелкая копия, чтобы понять, почему. Для этого сценария, как написано, различие не имеет значения, поскольку они не изменены.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...