2016-12-30 80 views
1

我收到了一张数据表,每天自动刷新数据。这里是结构:复制和粘贴数据的循环脚本,如何优化

data1 data2 data3 data4 data5 etc... 
a1  a2  a3  a4  a5 etc... 
b1  b2  b3  b4  b5 etc... 
c1  c2  c3  c4  c5 etc... 

我写了一个脚本来保存这些数据在另一张纸每天。这里是我的脚本:

function savedata() { 
    var sheet = SpreadsheetApp.openById('my_id').getSheetByName('Sheet1'); 
    var numRows = sheet.getLastRow()-1; 

for(var i = 0; i < numRows; i++) { 
    var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2") 
    var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1") 

    var data1 = sheet.getRange('Sheet1!A2:G2').getValues(); 

    sheet.appendRow(data1[0]); 
    ss.deleteRow(2) 
    } 
} 

正如你能理解我通过循环我所有的行复制它们并逐个删除它们一个,直到有一无所有。一切都被添加到第二张纸上。

有没有更有效的方法来完成这项工作?

回答

2

确实我们可以优化此代码。

几点要牢记

  • 总是首先尝试使用内置appscript功能,而不是循环的循环消耗比在服务器端,并最终你的脚本内置功能,更多的时间将是缓慢的时候数据变得巨大。

  • 此外,在您的for循环中,您已写入SpreadsheetApp.getActiveSpreadsheet()。每次循环运行时它都会得到电子表格,你不必这样做,在循环之外声明它们,仍然会得到相同的结果。除非你的数据被修改了运行时,否则你不想这样做。

另外,我不认为你data1变量是获取新范围的for循环新反复做,我认为它带来的同一行的值,你会在你的目标上写在多行相同的数据。现在

,你可以编写这样的事情来获得类似的结果在有效的方式:

var sheet1 = SpreadsheetApp.openById("ID1").getSheetByName("Sheet1"); 
var sheet2 = SpreadsheetApp.openById("ID2").getSheetByName("Sheet2"); 

var content = sheet1.getRange(1, 1, sheet1.getLastRow(), sheet1.getLastColumn()).getValues(); //Get all the values starting from 1st row 1st column and till end of rows and columns 

sheet2.getRange(1, 1,sheet1.getLastRow(), sheet1.getLastColumn()).setValues(content); //Get the same length and width to paste the data 

sheet1.clear(); //You can put a condition here to make sure that all the data is copied successfully by checking if no. of rows in sheet1 and sheet2 is same 
  • 此外,还有sheet1.clear()sheet1.deleteRow()之间的差异。如果您使用清除,则只会使电子表格单元格变为空白。如果您使用删除,它将完全删除行,并且如果您只有5行,则在删除后,它会显示警告,您不能删除所有单元格。

  • 还有一件事,如果你没有使用这些作为有20个亿个细胞的电子表格,其中包括所有选项卡中的细胞限制删除完全空白的行和列。

编辑

if(sheet2.getRange(1, 1).getValue().trim() == "") 
{ 
    var startIndex = 0; //I'm assuming your destination sheet is blank in first iteration 
} 
else 
    var startIndex = sheet2.getLastRow(); 

sheet2.getRange(startIndex+1, 1,sheet1.getLastRow(), sheet1.getLastColumn()).setValues(content); 
  • 还有我刚才添加,看到我在if语句中使用.trim()一个更重要的事情。原因是,假设您通过按下目标工作表A1单元格中的空格键输入了4-5个空格,那么它将被视为书写行,并且getLastRow()将返回1而不是任何错误。所以,trim()在这里将删除A1单元格的所有空格并检查它是否仍为空。当您检查空白单元格或值时,它非常有用,因此无法绕过代码。
+0

非常感谢所有的详细解释。但是,这可能是我的错,我应该更清楚,但是在使用脚本时,表2中的数据通过覆盖已存在的内容而被复制。我想累积所有在表格2上每日复制的数据。你明白我的意思吗?谢谢 ! –

+1

@SimonBreton欢迎您!我明白了你的观点,请在我的回答中查看编辑部分。 –

+2

我想补充一些答案,忘记强调:批量操作。代码中的一个非常大的问题是你有一个循环,而你并不需要。只需使用'.getValues()'获取范围内的所有数据,并在目标范围上使用'setValues()'。如果您需要操作正在移动的数据,请在数组内执行操作,而不要在将数据粘贴到电子表格中之后进行操作。 **使用尽可能少的服务调用,这意味着尽可能少的'.getRange()','.getSpreadsheet()''** – Vytautas