0
votes

I come from a VB background and am having some trouble implementing a scripts solution for Sheets, I imagine the function is fairly basic but am not yet sure how to express it in JS. The goal is to loop through each cell in a range (Sheet 1, Q3:Q1000), get the row number where the cell in that range has the value "TRUE", copy/cut the entirety of each row on Sheet 1 that meets that qualification (or simply store the values and skip the copy/paste step), paste the values to the first unused row on a separate sheet (Sheet2), then delete the original row on Sheet1.

So far, I have managed to put together this crude function which successfully finds the row number of the first cell in the given range containing the specified value, but it returns NaN if there is more than one occurrence of the value in the range. Any indication as to what I am doing wrong will be helpful, thank you.

function onEditTesting(e) {

var ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName("Sheet1");
const range = "Q3:1000";
var whereTrue = "TRUE";
var range = sheet.getRange("Q3:Q1000");
var rangeValues = sheet.getRange(range).getValues();

var i = []; 
for (var y = 0; y < rangeValues.length; y++) {
   if(rangeValues[y] == whereTrue){
      i.push(y);
   }
}

var Row = Number(i)+Number(range.getRow());

}
2

2 Answers

1
votes
function moveData() {
  const ss=SpreadsheetApp.getActive();
  const ssh=ss.getSheetByName('Sheet1');
  const dsh=ss.getSheetByName('Sheet2');
  const vs=ssh.getRange(3,1,ssh.getLastRow()-2,ssh.getLastColumn()).getValues();
  let oA=[];
  let d=0;
  vs.forEach((r,i)=>{
    if(r[16]=='TRUE') {
      oA.push(r);
      ssh.deleteRow(i+3-d++);
    }
  });
  dsh.getRange(dsh.getLastRow()+1,1,oA.length,oA[0].length).setValues(oa);
}
1
votes

Here is another approach using onEdit() Simple Trigger.

Sample Code:

function onEdit(e) {
  var ss = e.source;
  var cell = e.range;
  var sourceSheet = ss.getActiveSheet();
  var destinationSheet = ss.getSheetByName("Sheet2");

  var col = cell.getColumn();
  var row = cell.getRow();
  var lastCol = sourceSheet.getLastColumn();

  Logger.log("row: "+row+" maxCol: "+lastCol+" col: "+col+" val: "+cell.getDisplayValue()+" sheet: "+sourceSheet.getName());
  //Check if modified cell is in column Q (index 17) in Sheet1 has a value of TRUE
  if(sourceSheet.getName() == "Sheet1" && col == 17 && cell.getDisplayValue() == "TRUE"){
    //Append current row to the destination sheet
    var values = sourceSheet.getRange(row,1,1,lastCol).getValues();
    Logger.log(values);
    destinationSheet.appendRow(values.flat());
    
    //Delete current row
    sourceSheet.deleteRow(row);
  }
}

What it does?

  1. Get the sourceSheet and cell modified using e.range event object
  2. Check the cell modified if it is in column Q (index 17) of Sheet1 having a value of "TRUE". I used Range.getDisplayValue() to get the actual string value of the cell because when I test it using Range.getValue() it gave me a boolean object
  3. Get the row values from the first column up to the last column of the current row using Sheet.getLastColumn() and Sheet.getRange(row, column, numRows, numColumns)
  4. Append the current row values of the source sheet to your destination sheet using Sheet.appendRow(rowContents) where rowContents is a 1-d array and since the Range.getValues() returns a 2-d array, I used array.flat() to convert 2-d array to 1-d array
  5. Delete the current row using Sheet.deleteRow(rowPosition)

Output:

Before (Sheet1):

enter image description here

After (Sheet1):

enter image description here

After (Sheet2):

enter image description here