我遇到类似这样的问题:想象一下,我有一张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
}
答案 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");
}
}
}