Объединение многих электронных таблиц в файл отчета превышает максимальное время выполнения - PullRequest
0 голосов
/ 25 октября 2018

Я использую следующий сценарий для добавления строк файлов из студенческого цикла в электронную таблицу Google, если количество кредитов меньше x.Сценарий работал хорошо, но поскольку данные в электронной таблице добавляются ежедневно, теперь сценарий выдает ошибку «Превышено максимальное время выполнения» (у нас более 2000 файлов).Поскольку я новичок в написании сценариев, я не знаю, как оптимизировать код.

Может ли кто-нибудь помочь мне оптимизировать код или любое решение, чтобы время выполнения занимало менее 5 минут.Каждый раз, когда вы сравниваете электронную почту, ее следует сравнивать со многими электронными письмами.Пожалуйста, помогите!

function updated() {  
  //Final file data (Combined)
  var filecombined = SpreadsheetApp.openById("XXXXXXXXXX");
  var sheet2 = filecombined.getSheets();

  //Folder with all the files 
  var parentFolder = DriveApp.getFolderById("YYYYYYYYYYYY");
  var files = parentFolder.getFiles();

  //Current Date
  var fecha = new Date();

  //Path for each file in the folder
  while (files.hasNext()) {
    var idarchivo = files.next().getId();
    var sps = SpreadsheetApp.openById(idarchivo);

    var sheet = sps.getSheetByName('STUDENT PROFILE');
    var data = sheet.getDataRange().getValues();
    var credits = data[5][1];

    //Flat; bandera:1 (new row), bandera:2 (update row)
    var bandera = 1;

    //Take data from final file (Combined) 
    var data2 = sheet2[0].getDataRange().getValues();

    //If credits are less than X: write
    if (credits < 120) {
      var email = data[2][1];
      var lastrow = filecombined.getLastRow();
      var u = 0;
      //comparison loop by email, if found it, update and exit the loop
      while (u < lastrow) {
        u = u + 1;
        if (email == data2[u - 1][1]) {
          sheet2[0].getRange(u, 3).setValue(credits);
          sheet2[0].getRange(u, 4).setValue(fecha);
          u = lastrow;
          bandera = 2;
        }
      }
      //if that email does not exist, write a new row
      if (bandera == 1) {
        var nombre = data[0][1];
        sheet2[0].getRange(lastrow + 1, 1).setValue(nombre);
        sheet2[0].getRange(lastrow + 1, 2).setValue(email);
        sheet2[0].getRange(lastrow + 1, 3).setValue(credits);
        sheet2[0].getRange(lastrow + 1, 4).setValue(fecha);
      }
    }
  }
  SpreadsheetApp.flush();
}

Ответы [ 2 ]

0 голосов
/ 05 ноября 2018

Как я уже упоминал в моем комментарии , самая большая проблема, с которой вы сталкиваетесь, заключается в том, что вы постоянно ищите в массиве значение, когда вы можете использовать намного более быструю функцию поиска.

// Create an object that maps an email address to the (last) array
// index of that email in the `data2` array.
const knownEmails = data2.reduce(function (acc, row, index) {
  var email = row[1]; // email is the 2nd element of the inner array (Column B on a spreadsheet)
  acc[email] = index;
  return acc;
}, {});

Затем вы можете определить, существует ли электронное письмо в data2, попытавшись получить его значение:

// Get this email's index in `data2`:
var index = knownEmails[email];
if (index === undefined) {
  // This is a new email we didn't know about before
  ...
} else {
  // This is an email we knew about already.
  var u = ++index; // Convert the array index into a worksheet row (assumes `data2` is from a range that started at Row 1)
  ...
}

Чтобы понять, как мы создаем knownEmails из data2Вы можете найти документацию по Array#reduce полезной.

0 голосов
/ 04 ноября 2018

Код спрашивающего занимает более 4-6 минут для выполнения и получает ошибку Exceeded maximum execution time.

Следующий ответ основан исключительно на коде, предоставленном спрашивающим.У нас нет никакой информации о «комбинированной» электронной таблице, ее размере и триггерах.Мы также находимся в неведении относительно различных электронных таблиц студентов, их размера и т. Д., За исключением того, что мы знаем, что существует 2000 таких файлов.Мы не знаем, как часто эта процедура выполняется, и сколько учеников имеют баллы <120. Заявления </p>

getvalues и setvalues очень дороги;как правило, 0,2 секунды каждый.Код задаваемых вопросов включает в себя множество таких утверждений - некоторые из них неизбежны, а другие нет.

Рассматривая оптимизацию этого кода, я внес два основных изменения.
1 - я переместил строку 27 var data2 = sheet2[0].getDataRange().getValues();
Эта строка должна быть выполнена только один раз, и я переместил ее в верхнюю часть кода сразу после различных команд "filecombined".В нынешнем виде эта строка выполнялась один раз для каждой таблицы ученика;это, возможно, способствовало нескольким минутам времени выполнения.

2) Я преобразовал некоторые команды setvalue в массив, а затем обновил «объединенную в файл» электронную таблицу из массива только один раз, в концеобработка.В зависимости от количества учеников с низким кредитом и тех, кто еще не занесен в «комбинированный файл», это может существенно сэкономить.Код затрагивал строки с 47 по 50.

line47:         sheet2[0].getRange(lastrow+1, 1).setValue(nombre);
line48:         sheet2[0].getRange(lastrow+1, 2).setValue(email);
line49:         sheet2[0].getRange(lastrow+1, 3).setValue(credits);
line50:         sheet2[0].getRange(lastrow+1, 4).setValue(fecha);

В строках 38 и 39 также выполняются команды setvalue (если учащийся уже находится в электронной таблице с комбинированием файлов), но я решил оставитьэто как есть.Как отмечалось выше, мы не знаем, сколько таких студентов может быть, и стоимость этих setvalue команд может быть незначительной или нет.До тех пор, пока это не станет ясно, и с учетом экономии времени я решил оставить их как есть.


function updated() {  

  //Final file data (Combined)
  var filecombined = SpreadsheetApp.openById("XXXXXXXXXX");
  var sheet2 = filecombined.getSheets();

    //Take data from final file (Combined) 
    var data2 = sheet2[0].getDataRange().getValues();

    // create some arrays
    var Newdataarray = [];
    var Masterarray = [];

  //Folder with all the files 
  var parentFolder = DriveApp.getFolderById("YYYYYYYYYYYY");
  var files = parentFolder.getFiles();

  //Current Date
  var fecha = new Date();

  //Path for each file in the folder
  while (files.hasNext()) {
  var idarchivo = files.next().getId();
  var sps = SpreadsheetApp.openById(idarchivo);

  var sheet = sps.getSheetByName('STUDENT PROFILE');
  var data = sheet.getDataRange().getValues();
  var credits = data[5][1];

  //Flat; bandera:1 (new row), bandera:2 (update row)
  var bandera = 1;

    //If credits are less than X: write
    if (credits < 120){
        var email = data[2][1];
        var lastrow = filecombined.getLastRow();
        var u = 0;
        //comparison loop by email, if found it, update and exit the loop
        while (u < lastrow) {
         u = u + 1;
         if (email == data2[u-1][1]){
           sheet2[0].getRange(u, 3).setValue(credits);
           sheet2[0].getRange(u, 4).setValue(fecha);
           u = lastrow;
           bandera = 2;
         }
        }
        //if that email does not exist, write a new row
        if(bandera == 1){
         var nombre = data[0][1];
          Newdataarray = [];
          Newdataarray.push(nombre);
          Newdataarray.push(email);
          Newdataarray.push(credits);
          Newdataarray.push(fecha);
          Masterarray.push(Newdataarray);
        }
    }
  }
  // update the target sheet with the contents of the array
  // these are all adding new rows
  lastrow = filecombined.getLastRow();
  sheet2[0].getRange(lastrow+1, 1, Masterarray.length, 4);
  sheet2[0].setValues(Masterarray); 

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