0

I am currently trying to perform a "copyTo" or "setValues" action. I need to copy one grid (Sheet1!J16:Q36) to another grid (Sheet2!J16:Q36) But not every cell shall be copied. Only those values that are not identical to the Sheet1 values shall be copied.

I have tried the below code with success, but sadly the script takes ages. I understand that a batch operation with getValues in an array will be quicker, but I lack the capability to do that script.

I also used a third grid which compared the values of sheet1 and 2 and returned 1 or 0. Only if the value 1 was shown, the cell was considered by the for loop. I take it that this is inefficient.

Thank you for your help. I appreciate it a lot.

 var ratenprogramm = SpreadsheetApp.getActiveSpreadsheet(); 
 var ratenprogrammmain = ratenprogramm.getSheetByName("Ratenprogramm");
 var vorlageratenprogramm = 
 ratenprogramm.getSheetByName("VorlageRatenprogramm");

for(i=1;i<=21;i++)
{
  for(j=1;j<=8;j++)
  {
    if(vorlageratenprogramm.getRange(37+i,9+j).getValue() == 1)
    {
      vorlageratenprogramm.getRange(15+i,9+j).copyTo(ratenprogrammmain.getRange(15+i,9+j),{contentsOnly: true}); 
    }

  }
}
2
  • Please include your whole script, we can't tell what vorlageratenprogramm or ratenprogrammmain are defined as. Commented Oct 23, 2019 at 7:41
  • Hi Ross, sorry, I forgot. Those are just the sheet names.I put them in the text above. Commented Oct 23, 2019 at 7:45

1 Answer 1

1
  • As you have noticed, calling any external services, including methods like getValue() make your script slow, see Apps Script Best Practices.

  • Your code can be optimized by replacing the multiple getValue() requests by a single getValues().

  • Within the nested loops you can specify a multiple amount of ranges and values that can be written with the Advanced Sheets Service, with the Sheets API method spreadsheets.values.batchUpdate into the corresponding ranges of the destination sheet, see also here.

Sample

function myFunction() {

 var ratenprogramm = SpreadsheetApp.getActiveSpreadsheet(); 
 var ratenprogrammmain = ratenprogramm.getSheetByName("Ratenprogramm");
 var vorlageratenprogramm = ratenprogramm.getSheetByName("VorlageRatenprogramm");
 var data=[];
 var range=vorlageratenprogramm.getRange(15,9,21,8);
 var values=range.getValues();
 for(i=0;i<4;i++)
  {
    for(j=0;j<1;j++)
    {
      if(values[i+1][j] == 1)
       {
        var cell=range.getCell(i+1,j+1).getA1Notation();
        data.push([{ range:'Ratenprogramm!'+ cell, values: [[values[i+1][j]]]}]);
      }
    }
  }
  var resource = {
    valueInputOption: "USER_ENTERED",
    data: data
  };
  Sheets.Spreadsheets.Values.batchUpdate(resource, spreadsheetId);
}

Keep in mind that if you have many different ranges, it might be easier and faster to overwrite the sheet with the complete range, rather than using nesting looping. E.g. vorlageratenprogramm.getRange(15,9,21,8).copyTo(ratenprogrammmain.getRange(15,9,21,8),{contentsOnly: true});.

Sign up to request clarification or add additional context in comments.

7 Comments

Note: you will need to manually enable the Sheets API for this script to work.
Thank you very much Ziganotschka and Ross for your help. I have two questions on your code: - what line would I need to add to get the "data" input in a grid of my choice? (say "ratenprogramm.getRange(16,9,21,8)). - Your second example with the copyTo: This would work perfect. But I also have some empty cells within the grid that shall not be copied. Is there a way to simply ignore empty cells and copy the rest? Thank you so much. :)
The way to ignore empty cells is not simple, it would probably be simpler to posteriorly delete the cells that should remain empty, after copying the whole range. Otherwise, you need to select all ranges to be copied as you have done with if...getValue... (slow) or (a bit faster) as in my sample with batchUpdate. To obtain data in the range (16,9,21,8), replace var range=vorlageratenprogramm.getRange(15,9,21,8); by var range=vorlageratenprogramm.getRange(16,9,21,8);
I am still struggling to get this to work sadly. I can not figure out how to make the batchUpdate work. I can not figure out where the filled array (var data) shall go within the code. Could you kindly inform where I shall place the setValues(data) part exactly? Currently I am also getting an error which states something like (property of "0.0" of undefined can not be read). Thank you again for your valuable time.
If you use batchUpdate, there is no setValues(). Sheets.Spreadsheets.Values.batchUpdate(resource, spreadsheetId); sets the values specified in data into the range specified in data. The only thing: If you want to set the values a different sheet, range should be defined as: range:'Ratenprogramm!'+ cell`, I updated my answer with the complete code.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.