如何使用新的电子表格更新旧电子表格,只添加新元素并更改减去元素的颜色?

时间:2014-01-06 12:51:41

标签: google-apps-script google-sheets

我遇到类似这样的问题:想象一下,我有一张Google表格(例如,有学生信息),我从学校网站上下载(想象一下学校系统非常糟糕,所以使用一张表更有用我的Google脚本)。但我必须每周更新这张从学校网站下载新表格的表格。为了不丢失我之前的笔记,我想编写一个脚本来实现更新过程,这样:   - 如果最近的工作表有一个不在上一个工作表中的新行(一个新的学生行),则将该行添加到新工作表中;   - 如果旧工作表中有一行不在新工作表中,则会更改该行的颜色并添加一个注释“已转移的学生”或类似的内容。

我得到了这个示例代码,但我想知道是否有更好的方法来执行此操作。这是我的代码:

function updateSheet(){
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var sourceSpreadsheetID = ss.getId();
    var oldSpreadsheet = SpreadsheetApp.openById(sourceSpreadsheetID);
    var oldWorksheet = oldSpreadsheet.getSheetByName("students");
    var oldData = oldWorksheet.getDataRange().getValues();  
    var newSpreadsheetUrl = Browser.inputBox("New sheet", "Put the new sheet link here:", Browser.Buttons.OK_CANCEL);
    Logger.log("newSpreadsheetUrl = " + newSpreadsheetUrl);
    var newSpreadsheetID = newSpreadsheetUrl.split('d/')[1].split('/')[0];
    var newSpreadsheet = SpreadsheetApp.openById(newSpreadsheetID);
    var newWorksheet = newSpreadsheet.getSheetByName("students");
    var newData = newWorksheet.getDataRange().getValues();
  // Iterates through the new sheet rows
    for(i=1; i<newData.length; i++){
    var alreadyInOldSheet = false;
    var remainsInNewSheet = false;
      Logger.log("newData[i][0] = " + newData[i][0]);
    // Iterates through the old sheet rows
        for(j=1; j<oldData.length; j++){
            // compares the firs cell (student name)
            Logger.log("oldData[j][0] = " + oldData[j][0]);
            Logger.log("newData[i][0] == oldData[j][0] = " + (newData[i][0] == oldData[j][0]) );
            if (newData[i][0] == oldData[j][0]) {                
                alreadyInOldSheet = true;
                break; // This student is already in the old sheet, so, jump to the next row
            }            
        // After iterates through all old sheet rows, the student name isn't found, so we add it
        }
          Logger.log("Last condition 'alreadyInOldSheet =' " + alreadyInOldSheet);
          Logger.log("newData =' " + newData);
          if (alreadyInOldSheet == false) {
             oldWorksheet.appendRow(newData[i]);
         }
  }
  absentInNewSheet(oldData, newData, oldWorksheet);
}


function absentInNewSheet(oldData, newData, workSheet) {
   for(i=1; i<newData.length; i++){
    var alreadyInOldSheet = false;
    Logger.log("newData[i][0] = " + newData[i][0]);
    // Iterates through the old sheet rows
        for(j=1; j<oldData.length; j++){
            // compares the firs cell (student name)
            Logger.log("oldData[j][0] = " + oldData[j][0]);
            Logger.log("newData[i][0] == oldData[j][0] = " + (newData[i][0] == oldData[j][0]) );
            if (newData[i][0] == oldData[j][0]) {                
                alreadyInOldSheet = true;
                break; // This student is already in the old sheet, so, jump to the next row
            }
        // After iterates through all old sheet rows, the student name isn't found, so we add it
        }

2 个答案:

答案 0 :(得分:1)

示例代码

function updateSheet()
{
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  var masterSheet = ss.getSheetByName("Master");
  var masterRange = masterSheet.getDataRange();
  var masterData = masterRange.getValues();
  masterData.shift();
  var masterBackgrounds = masterRange.getBackgrounds();
  var masterNotes = masterRange.getNotes();
  var masterLength = masterNotes.length;

  var updateData = ss.getSheetByName("Update").getDataRange().getValues();
  updateData.shift();

  for (var i = 0; i < (masterLength - 1); i++)
  {
    masterData[i].unshift(i + 1);
  }
  masterData.sort(function(a,b) {return (a[1] > b[1]) ? 1 : ((a[1] < b[1]) ? -1 : 0 );});
  updateData.sort(function(a,b) {return (a[0] > b[0]) ? 1 : ((a[0] < b[0]) ? -1 : 0 );});

  var addedData = [];
  while (masterData.length || updateData.length)
  {
    if (!masterData.length || (updateData.length && masterData[0][1] > updateData[0][0]))
    {
      addedData.push(updateData.splice(0, 1)[0]);
    }
    else if (!updateData.length || (masterData.length && masterData[0][1] < updateData[0][0]))
    {
      for (var k = 0; k < masterBackgrounds[0].length; k++)
      {
        masterBackgrounds[masterData[0][0]][k] = "#dcdcdc";
      }
      masterNotes[masterData[0][0]][0] = "This student was transfered from this school";
      masterData.shift();
    }
    else
    {
      masterData.shift();
      updateData.shift();
    }
  }

  var extraRows = masterLength + addedData.length - masterSheet.getMaxRows();
  if (extraRows > 0) masterSheet.insertRowsAfter(masterLength, extraRows);

  if (addedData.length > 0) masterSheet.getRange(masterLength + 1, 1, addedData.length, addedData[0].length).setValues(addedData);
  masterRange.setBackgrounds(masterBackgrounds).setNotes(masterNotes);  
}

Test spreadsheet(请随意尝试 - 希望您可以根据具体的电子表格进行调整)

感谢您重新发帖;我碰巧得到了一个类似的问题的帮助,当我在GPF上的Google Apps脚本论坛结束时我发布了这个问题(我根本找不到那个帖子,但感谢+ ScampMichael帮助我;我已经对脚本进行了微调有点自。)

一般来说,算法是对主数据和更新数组进行排序,并同时处理每个数组,比较每个数组的第一个元素然后执行某些操作,包括shift() - 当你使用每个数组时该元素完成它。在对主数组进行排序之前,在您的情况下,您还需要附加一个索引列,以便知道应用注释/背景的单元格 - 使用此方法,您可以在每个批处理集中执行这些操作,这也应该可以提高性能。

无论如何,我并不是说没有更高效的算法,但是当我在我的情况下有数千行时,花了大约8秒钟,而“多循环”方法通常会超时。我希望它有所帮助。

答案 1 :(得分:0)

这是我执行此任务的实际代码。也许它不是更有效的解决方案(任何建议?)但它正在解决这个问题。

function updateSheet(){
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var sourceSpreadsheetID = ss.getId();
    var oldSpreadsheet = SpreadsheetApp.openById(sourceSpreadsheetID);
    var oldWorksheet = oldSpreadsheet.getSheetByName("students");
    var oldData = oldWorksheet.getDataRange().getValues();  
    var newSpreadsheetUrl = Browser.inputBox("New sheet", "Put the new sheet link here:", Browser.Buttons.OK_CANCEL);
  //  Logger.log("newSpreadsheetUrl = " + newSpreadsheetUrl);
    var newSpreadsheetID = newSpreadsheetUrl.split('d/')[1].split('/')[0];
    var newSpreadsheet = SpreadsheetApp.openById(newSpreadsheetID);
    var newWorksheet = newSpreadsheet.getSheetByName("students");
    var newData = newWorksheet.getDataRange().getValues();
  // Iterates through the new sheet rows
    for(i=1; i<newData.length; i++){
    var alreadyInOldSheet = false;
    var remainsInNewSheet = false;
//      Logger.log("newData[i][0] = " + newData[i][0]);
    // Iterates through the old sheet rows
        for(j=1; j<oldData.length; j++){
            // compares the firs cell (student name)
        //    Logger.log("oldData[j][0] = " + oldData[j][0]);
         //   Logger.log("newData[i][0] == oldData[j][0] = " + (newData[i][0] == oldData[j][0]) );
            if (newData[i][0] == oldData[j][0]) {                
                alreadyInOldSheet = true;
                break; // This student is already in the old sheet, so, jump to the next row
            }            
        // After iterates through all old sheet rows, the student name isn't found, so we add it
        }
      //    Logger.log("Last condition 'alreadyInOldSheet =' " + alreadyInOldSheet);
      //    Logger.log("newData =' " + newData);
          if (alreadyInOldSheet == false) {
             oldWorksheet.appendRow(newData[i]);
         }
  }
  absentInNewSheet(oldWorksheet.getDataRange().getValues(), newData, oldWorksheet);
}


function absentInNewSheet(oldData, newData, workSheet) {
   for(i=1; i<oldData.length; i++){
    var remainsInNewSheet = false;
    Logger.log("oldData[i][0] = " + oldData[i][0]);
    // Iterates through the old sheet rows
     Logger.log("oldData.length = " + oldData.length);
        for(j=1; j<newData.length; j++){
            // compares the firs cell (student name)
            Logger.log("newData[j][0] = " + newData[j][0]);
            Logger.log("first condition oldData[i][0] == newData[j][0] = " + (oldData[i][0] == newData[j][0]) );
            if (oldData[i][0] == newData[j][0]) {                
                remainsInNewSheet = true;
                Logger.log("break");
                break; // This student is already in the old sheet, so, jump to the next row
            }
        // After iterates through all old sheet rows, the student name isn't found, so we add it
        }
          Logger.log("Last condition 'remainsInNewSheet =' " + remainsInNewSheet);
          Logger.log(" ");
          //Logger.log("newData =' " + newData);     
          if (remainsInNewSheet == false) {
             var lastColumn = workSheet.getLastColumn();
             var firstColumn = workSheet.getLastColumn(); 
             var currentRow = workSheet.getRange(i+1, 1, 1, lastColumn);
             currentRow.setBackgroundRGB(220, 220, 220).setNote("This student was transfered from this school");             
         }
    }
}