2013-06-20 3 views
1

У меня есть две таблицы. Я хочу сопоставить колонку C spreadsheet1 со столбцом A spreadsheet2. Обе эти таблицы имеют записи более 8000. Из-за большого количества записей мой скрипт постоянно дает ошибку exceeded maximum execution time. Вот сценарийпревысило максимальное время выполнения в google-apps-script

function compare() { 

var ss=SpreadsheetApp.getActiveSpreadsheet(); 
    var sheetList1=ss.getSheetByName("spreadsheet1"); 
    var sheetList2=ss.getSheetByName("spreadsheet2"); 

    var sheet1Data=sheetList1.getRange(2,3,sheetList1.getLastRow(),1).getValues(); 

    var sheet2Data=sheetList2.getRange(1,1,sheetList2.getLastRow(),1).getValues(); 

    for (i in sheet2Data){ 
    var row = 2; 
     for (j in sheet1Data){ 
     if (sheet1Data[j][0]==sheet2Data[i][0]){ 
      sheetList1.getRange("A"+row).setValue('Inactive');   
     } 
     row++; 
     } 


    } 

} 

любые предложения для оптимизации этого скрипта. Или как справиться с этой ошибкой? Заранее спасибо :)

EDIT

Спасибо за прекрасный ответ. Есть одна проблема. Если я нажимаю данные в массиве newSheet1Data перед оператором if, тогда он записывает Inactive дважды. т.е., если есть две строки он пишет inactive в четыре rows.Like

newSheet1Data.push(sheet1Data[j]); 
     if (sheet1Data[j][2]==sheet2Data[i][0]){ 
      newSheet1Data[j][0]='Inactive'; 
     } 

Если я нажимаю данные в if высказывания и не матча происходит, то он не находит строки и дать эту ошибку TypeError: Cannot set property "0.0" of undefined to "Inactive". Вроде бы

if (sheet1Data[j][0]==sheet2Data[i][0]){ 
      newSheet1Data.push(sheet1Data[j]); 
      newSheet1Data[j][0]='Inactive';   
     } 

ответ

2

Вы должны избегать любых вызовов API таблиц в цикле, особенно когда у вас так много данных.

Идея состоит в том, чтобы играть только с массивами и записывать результат назад после его завершения. Приведенный ниже код (на основе вашего кода, если данные в листе col C1 совпадают с данными в таблице 2 col A, а затем введите строку в листе 1 col A). Я надеюсь, что я не ошибся, но у меня не было возможности протестировать мой код ... это может понадобиться отладку ;-)

function compare() { 
    var ss=SpreadsheetApp.getActiveSpreadsheet(); 
    var sheetList1=ss.getSheetByName("Sheet1"); 
    var sheetList2=ss.getSheetByName("Sheet2"); 
    var sheet1Data=sheetList1.getDataRange().getValues();// get the whole sheet in an array 
    var sheet2Data=sheetList2.getRange(1,1,sheetList2.getLastRow(),1).getValues(); 
    var newSheet1Data = [] ; // create a new array to collect data 
    for (i=0;i<sheet1Data.length;++i){ 
     for (j=0;j<sheet2Data.length;++j){ 
     if(i!=j){continue}; 
     newSheet1Data.push(sheet1Data[i]); // add the full row to target array 
     if (sheet1Data[i][2]==sheet2Data[j][0]){ 
      newSheet1Data[i][0]='Inactive';//if condition is true change column A 
      break 
     } 
     } 
    } 
    newSheet1Data.shift();// remove first row (probably headers ?) 
    sheetList1.getRange(2,1,newSheet1Data.length,newSheet1Data[0].length).setValues(newSheet1Data); // write back to sheet1 in one batch 
} 

EDIT: после того, как Seing ваш документ Я понимаю, что ты хотят более точно ... здесь новый код (проверено на вашем SS)

function compare() { 
    var ss=SpreadsheetApp.getActiveSpreadsheet(); 
    var sheetList1=ss.getSheetByName("Sheet1"); 
    var sheetList2=ss.getSheetByName("Sheet2"); 
    var sheet1Data=sheetList1.getDataRange().getValues();// get the whole sheet in an array 
    var sheet2Data=sheetList2.getRange(1,1,sheetList2.getLastRow(),1).getValues(); 
    var newSheet1Data = [] ; // create a new array to collect data 
    for (i=0;i<sheet1Data.length;++i){ 
    newSheet1Data.push(sheet1Data[i]); // add the full row to target array 
     for (j=0;j<sheet2Data.length;++j){ 
     if (sheet1Data[i][2]==sheet2Data[j][0]){ 
      newSheet1Data[i][0]='Inactive';//if condition is true change column A 
      break;// don't continue after condition was true, this will speed up the process 
     } 
     } 
    } 
    newSheet1Data.shift();// remove first row (probably headers ?) 
    sheetList1.getRange(2,1,newSheet1Data.length,newSheet1Data[0].length).setValues(newSheet1Data); // write back to sheet1 in one batch 
} 
+1

жаль, что я сделал опечатку в коде, последняя строка кода спосо: конечно, должны использовать SheetName использовать .getRange() , Я обновил свой ответ. –

+1

Я, наконец, протестировал его, эта версия работает так, как ожидалось, петли не подходят для этой логики. –

+1

Я обновил вопрос, пожалуйста, посмотрите. – Noor

Смежные вопросы