Оптимизация методов getRange / Copy

Я ищу способ ускорить свой скрипт, ниже приведен фрагмент (на самом деле он намного длиннее, но по сути то же самое: getrange -> копировать на другой лист.

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

Единственное, что я скрипт-нуб и не могу проработать эту часть, любая помощь будет принята с благодарностью.

function testEV1() {
  var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Test');            
  var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Datastore');            
  var lastRow = sheet2.getLastRow()+1;
 
  if (sheet1.getRange('B3') != " ")
    var confirm = Browser.msgBox('Confirmation required','Are you sure you want to submit this evaluation?', Browser.Buttons.OK_CANCEL);
  if (confirm == 'ok') { 
    var wait = Browser.msgBox('Submission In Progress', 'Submission will take approximately 15 seconds, please wait for notification.', Browser.Buttons.OK);
    /*** Evaluation Details ***/ 
    sheet1.getRange('B2').copyTo(sheet2.getRange(lastRow, 1), {contentsOnly: true});                /*** Agent ***/
    sheet1.getRange('B3').copyTo(sheet2.getRange(lastRow, 2), {contentsOnly: true});               /*** Date of Review ***/
    sheet1.getRange('B4').copyTo(sheet2.getRange(lastRow, 3), {contentsOnly: true});               /*** Date of Call or Chat ***/
    sheet1.getRange('D3').copyTo(sheet2.getRange(lastRow, 4), {contentsOnly: true});               /*** Reviewer ***/
    sheet1.getRange('D4').copyTo(sheet2.getRange(lastRow, 5), {contentsOnly:true});               /*** Method of Enquiry ***/
    sheet1.getRange('B5').copyTo(sheet2.getRange(lastRow, 6), {contentsOnly: true});               /*** Type(Issue vs Query) ***/
    sheet1.getRange('B7').copyTo(sheet2.getRange(lastRow, 7), {contentsOnly: true});               /*** Chat & Call Link ***/
    sheet1.getRange('D5').copyTo(sheet2.getRange(lastRow, 8), {contentsOnly: true});               /*** Category ***/
    sheet1.getRange('B6').copyTo(sheet2.getRange(lastRow, 9), {contentsOnly: true});               /*** FOFC ***/
    sheet1.getRange('D6').copyTo(sheet2.getRange(lastRow, 10), {contentsOnly: true});               /*** If FOFC NO ***/
    
    var complete = Browser.msgBox('Submission Completed', 'Evaluation has been submitted, you may now clear the form or exit the application.', Browser.Buttons.OK);
  }
};  


person bdev    schedule 06.06.2017    source источник


Ответы (1)


Попробуйте получить сразу 2 исходных значения и поместить эти значения в один массив, чтобы затем вставить их в лист. например

function testEV1() {
   var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Test');            
   var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Datastore');            
   var lastRow = sheet2.getLastRow()+1;

   if (sheet1.getRange('B3') != " "){
     var confirm = Browser.msgBox('Confirmation required','Are you sure you want to submit this evaluation?', Browser.Buttons.OK_CANCEL);
   }
   if(confirm=='ok') { 
       var wait = Browser.msgBox('Submission In Progress','Submission will take approximately 15 seconds, please wait for notification.', Browser.Buttons.OK);

       /*** Evaluation Details ***/ 
       // Get all of the values in one query & then order them at the output stage. This gives more data than we actually consume, but it saves in expensive calls to getRange() & getValues()
       var vals = sheet1.getRange('B2:D7').getValues(); // gets a 2D array of the values in the range.
       var dest_range = sheet2.getRange(lastRow, 1, 1, 10); // the destination range: start at last_row:col_1 & make a range 1 row deep, 10 cols wide.
       dest_range.setValues([
                             [vals[0][0], vals[0][1], vals[0][2], vals[2][1], vals[2][2], vals[0][3], vals[0][5], vals[2][3], vals[0][4], vals[2][4]]
                            ]); // this is your 1 x 10 array of values

       Browser.msgBox('Submission Completed','Evaluation has been submitted, you may now clear the form or exit the application.', Browser.Buttons.OK);
  }
};  

Это должно дать вам отправную точку для гораздо лучшей реализации.

person Dean Ransevycz    schedule 06.06.2017
comment
Это также скопирует и вставит содержимое столбца C. - person Parag Jadhav; 06.06.2017
comment
Нет, не будет, потому что он использует только значения из столбцов B и D (vals[0] & vals[2]) в вызове, который устанавливает значения в целевом листе. Он не использует никаких значений из столбца C. - person Dean Ransevycz; 06.06.2017
comment
Тогда зачем получать ненужные значения из столбца C, должен быть другой способ сделать это :) - person Parag Jadhav; 06.06.2017
comment
Правда, вы могли бы получить 2 диапазона, по одному для каждого столбца, но это добавило бы еще один вызов getRange().getValues(). Я решил сделать один вызов для получения всех значений в диапазоне, охватывающем оба набора заполненных ячеек, а не один вызов для B2: B7 и один вызов для D3: D6. Да, в результирующем наборе есть неиспользуемые данные, но на один вызов getRange() & getValues() меньше - person Dean Ransevycz; 06.06.2017
comment
Правильно, но эта операция не увеличит размер массива, учитывая, что может быть (например) более 200000 строк - person Parag Jadhav; 06.06.2017
comment
В этом случае да, возможно, вы захотите провести такую ​​оптимизацию. Как я уже сказал, мой код является отправной точкой, иллюстрирующей концепцию получения значений напрямую и работы с ними, а не частичных вызовов getValues(), getRange() или copyTo(). Если бы OP упомянул что-то вроде шкалы, которую вы предлагаете, я бы подошел к проблеме по-другому, но я придерживаюсь основной концепции получения данных в массовом порядке и их вставки в массовом порядке < / b> - person Dean Ransevycz; 06.06.2017