Search code examples
javascriptgoogle-apps-scriptjavascript-objectsgoogle-sheets-query

Google Script: trying to copy row to another sheet cannot convert error


I am working on a function that would

  1. Go row by row through a specified column in a Google sheet (column H indicated as value[7] in the script).
  2. Based on the cell in the value[7] column having specific value ("YES") it would select the entire row.
  3. It would then copy the selected row (in its entirety) into a separate sheet within the same document.

This is what I've got so far:

function moveRowsBasedOnCellValue(){

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet();
  var master = ss.getSheetByName('Main');
  var values = master.getDataRange().getValues(); //selects all values in a sheet

  values.forEach(function(value){
    //if cell in the column H equals YES execute the script
    if (value[7] == "YES"){
      //variable to select all columns in the source sheet that aren't blank
      var colWidth = master.getMaxColumns();
      //variable containing the target sheet
      var destinationYeses = ss.getSheetByName("Yeses");
      //select first empty row in the destination sheet
      var destinationYesesRange = destinationYeses.getRange(destinationYeses.getLastRow()+1,1);
      //copy the relevant row into the sheet
      master.getRange(value,1, 1, colWidth).copyTo(destinationYesesRange);   
    }});
}

The script executes fine until the last row of the script:

master.getRange(value,1, 1, colWidth).copyTo(destinationYesesRange);  

The error states:

Cannot convert [here the Logger error provides a list of all values in a row separated by a comma] to (class).

Any thoughts on what I may be doing wrong?


Solution

  • The reason you are getting that error is, in the following code

     master.getRange(value,1, 1, colWidth).copyTo(destinationYesesRange);
    

    getRange expects all the values passed to it to be an integer. Whereas the value variable is an array. So to fix it you will have to make the following two changes

    First: Documentation

    values.forEach(function(value,index){  // gives the array index to index variable
    

    Second

    //Index for array(values) starts at 0, whereas for the rows number in sheet starts at 1. 
    //so add 1 to convert the index to row number
     master.getRange(index + 1,1, 1, colWidth).copyTo(destinationYesesRange);
    

    So your final code will look like this:

    function moveRowsBasedOnCellValue(){
    
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var sheet = ss.getActiveSheet();
      var master = ss.getSheetByName('Main');
      var values = master.getDataRange().getValues(); //selects all values in a sheet
    
      values.forEach(function(value,index){
        //if cell in the column H equals YES execute the script
        if (value[7] == "YES"){
          //variable to select all columns in the source sheet that aren't blank
          var colWidth = master.getMaxColumns();
          //variable containing the target sheet
          var destinationYeses = ss.getSheetByName("Yeses");
          //select first empty row in the destination sheet
          var destinationYesesRange = destinationYeses.getRange(destinationYeses.getLastRow()+1,1);
          //copy the relevant row into the sheet
    
          master.getRange(index +1 ,1, 1, colWidth).copyTo(destinationYesesRange);   
        }});
    }
    

    Final note: This is a highly inefficient way of transferring data and the execution will terminate if you have a large data to copy and the script takes more than 5-6min to execute. Check this post that addresses this issue