Сложное преобразование, превышающее время выполнения в скрипте Google Apps - PullRequest
0 голосов
/ 29 марта 2020

Я получаю данные в одном столбце и должен перенести их в отдельные записи. Некоторые записи будут иметь длину 12 символов, другие 10 и остаток 9. Кроме того, последние 2 значения в записях длиной 10 и 9 символов должны быть смещены на 1 и 2 поля вправо соответственно. Первое значение в данной записи всегда является датой. Я создал следующий код, который работает хорошо, за исключением того, что он истекает примерно через 6 минут и 77 записей. Мне нужно иметь возможность обрабатывать в 15 раз больше, если не больше.

Я встроил вычисление объектов даты в секцию else каждого оператора if и вложил последующие операторы if, чтобы уменьшить ненужные вычисления. , Это дало мне от 48 записей до 77.

Очень благодарен за любые умные идеи ?


function transposeNew(){
  let ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  let lr = ss.getRange("A13").getDataRegion().getLastRow();
  let sr = 13

  // get the data column
  let data = ss.getRange(sr,1,lr-sr,1).getValues();

  // set up the rows loop
  let pasteRow = 2;
  let arrayField = 0;
  while (arrayField < data.length){
    //use the new Date() constructor to create a date object with the date value passed
    let isDate12 = new Date(data[arrayField+12]).getFullYear(); //processed; size input;record should include 12 rows & 13th should be a date to begin the next row
    if (isDate12 === 2020) {
      let record = data.slice(arrayField, arrayField+12);
      let recordTr = transposeSub(record);
      ss.getRange(pasteRow, 5, 1, 12).setValues(recordTr);
      arrayField = arrayField + 12;
    }
    else {
      let isDate10 = new Date(data[arrayField+10]).getFullYear(); //unprocessed;size input
      if (isDate10 === 2020) {
        let record = data.slice(arrayField, arrayField+10);
        let record1 = record.slice(0,8);
        let record1Tr = transposeSub(record1);
        let record2 = record.slice(8,10);
        let record2Tr = transposeSub(record2);
        ss.getRange(pasteRow, 5, 1, 8).setValues(record1Tr);
        ss.getRange(pasteRow, 14, 1, 2).setValues(record2Tr);
        arrayField = arrayField + 10;
      }
      else {
        let isDate9 = new Date(data[arrayField+9]).getFullYear(); //unprocessed;no size 
          input
        if (isDate9 === 2020) {
          let record = data.slice(arrayField, arrayField+10);
          let record1 = record.slice(0,7);
          let record1Tr = transposeSub(record1);
          let record2 = record.slice(7,9);
          let record2Tr = transposeSub(record2);
          ss.getRange(pasteRow, 5, 1, 7).setValues(record1Tr);
          ss.getRange(pasteRow, 14, 1, 2).setValues(record2Tr);
          arrayField = arrayField + 9;
        }
      }
    }
    pasteRow ++;
  }
}

function transposeSub(a)
{
  return Object.keys(a[0]).map(function (c) { return a.map(function (r) { return r[c]; }); });
}

Ответы [ 2 ]

0 голосов
/ 30 марта 2020

Так что получается, что проблема была в критериях l oop; ладья ie ошибка. Произошла аномалия данных, так что одна запись не соответствовала критериям ни в одном из утверждений if, поэтому l oop продолжался бесконечно. Я обнаружил это, вставив значения для pasteRow и arrayField рядом с каждой записью на листе, чтобы я мог видеть, где она ломалась. Интересно, что записи остановились, но значения pasteRow и arrayField продолжались в течение 20 000 с до выхода из приложения.

Я отмечаю, что отзывы, предоставленные @Bruno Polo и @Cooper, верны. Вскоре после публикации я переделал ее в pu sh записей в новый массив и вставил массив после завершения. Это не удалось по той же причине, указанной выше. Я думаю, что go вернусь к этой версии теперь, когда я понимаю проблему.

Спасибо, что посмотрели на это со мной. Это необыкновенное сообщество экспертов, от которого я многому научился! 100

0 голосов
/ 29 марта 2020

Я вижу, вы создаете al oop, и внутри этого оператора while вы несколько раз вызываете функции SpreadsheetApp. Это создает соединение с электронной таблицей, читает / изменяет ее данные и закрывает соединение много раз, поэтому вашему коду требуется слишком много времени для запуска. Пожалуйста, проверьте GAS Best Practices секцию пакетных операций .

. Вам следует рассмотреть возможность изгнания любого get/setValue() внутри while, вместо этого вызовите getValues(), чтобы сохранить все значения в массиве javascript до while и затем используйте setValues() после while для записи всех выходов одновременно. Описанная концепция рассматривается в этом ответе.

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