Move multiple rows at once with multiple conditions - google-apps-script

I want to iterate through each row at once with the for loop. When the row has the value "Done" in column P and "Update" in column M, I want to move the row to Done Sheet, if the row just has "Done" in P, I want it to move to Control Sheet.
function done() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var numColumns = s.getLastColumn();
for(var i = 1; i < 50; i++) {
var cP = s.getRange(i, 13).getValue();
var cM = s.getRange(i, 10).getValue();
if (cP == "Done" && cM == "Update") {
var targetSheet = ss.getSheetByName("Done Sheet"); // Logger.log(targetSheet); —> no output
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(i, 1, 1, numColumns).moveTo(target);
s.deleteRow(i);
}
else if (cP == "Done") {
var targetSheet = ss.getSheetByName("Control Sheet");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(i, 1, 1, numColumns).moveTo(target);
s.deleteRow(i);
}
}
}

Please check if this code works for you:
function done() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Main Sheet'); // ss.getActiveSheet(); <= better call by name
var numColumns = s.getLastColumn();
var values = s.getDataRange().getValues(); // values keeps an array from the whole Sheet
var doneSheet = ss.getSheetByName("Done Sheet");
var ctrlSheet = ss.getSheetByName("Control Sheet");
var rows_to_delete = []; // will receive the indexes to delete
var doneSheetInputs = []; // will receive data to be inputed on doneSheet
var ctrlSheetInputs = []; // will receive data to be inputed on ctrlSheet
for(var i = 0; i < values.length; i++) {
var cP = values[i][15]; //s.getRange(i, 13).getValue();
var cM = values[i][12]; //s.getRange(i, 10).getValue();
if (cP == "Done" && cM == "Update") {
doneSheetInputs.push(values[i]);
rows_to_delete.push(i + 1); // +1 because of difference in Array versus Google Sheets index
Logger.log('Moving row ' + (i + 1) + ' to DONE');
}
else if (cP == "Done") {
ctrlSheetInputs.push(values[i]);
rows_to_delete.push(i + 1);
Logger.log('Moving row ' + (i + 1) + ' to CONTROL');
}
}
Logger.log('doneSheetInputs has ' + doneSheetInputs.length + ' entries');
if (doneSheetInputs.length > 0) {
doneSheet.getRange(doneSheet.getLastRow() + 1, 1, doneSheetInputs.length, doneSheetInputs[0].length).setValues(doneSheetInputs);
}
Logger.log('ctrlSheetInputs has ' + ctrlSheetInputs.length + ' entries');
if (ctrlSheetInputs.length > 0) {
ctrlSheet.getRange(ctrlSheet.getLastRow() + 1, 1, ctrlSheetInputs.length, ctrlSheetInputs[0].length).setValues(ctrlSheetInputs);
}
Logger.log('rows_to_delete has ' + rows_to_delete.length + ' entries');
var rev = rows_to_delete.reverse(); // delete from bottom to top
for (var i = 0; i < rev.length; i++) {
s.deleteRow(rev[i]);
}
}
It's not recommended to call getRange().getValues() so many times, specially inside a long for statement as described in Google Apps Script Best Practices. I always try to call getValues before doing any iterations and return the values at the end of the code, in a batch operation.
EDIT: found out that the indexes for P and M columns were wrong - didn't check that out. Here is a working example: https://docs.google.com/spreadsheets/d/1n68KqmI7HongEzJ_MSwmeQUqlAExjvCu2epEjEBZrlg/edit#gid=0 (send me request to access if you need it).

Related

Create an array of values that were looped through

I have a spreadsheet where each row in "MASTER" sheet is a task. It has checkboxes to check if it's done.
On another sheet, "Sin despachar", the data is filtered so that only the tasks which are not done show. There I have empty checkboxes to check when an incomplete task is completed.
I wrote a script so that when a button is pressed, it loops through the whole column in "Sin despachar" to see if checkboxes are checked, and for those that are, it changes the value in a master sheet.
I would like to have a confirmation pop up that mentions all the tasks it'll edit, but for that I need to somehow retrieve that list when the script runs, and I don't know how.
So what I need is to create an array or something else that contains the names of the tasks with the checkbox checked.
Does anyone know how to do this?
The task names are in column 4, and the checkboxes are in column 18.
Thanks in advance!!
function marcarEtiquetado() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Sin despachar");
var sheetRange = s.getDataRange();
var sheetValues = sheetRange.getValues();
for (var i=sheetRange.getLastRow()-1; i>1; i--) {
// si valor en columna R (etiquetado) = TRUE
if ( sheetValues[i][17] === true) {
var checkboxRange = s.getRange(i, 18);
var usuariosRange = s.getRange(i, 3)
Logger.log(usuariosRange)
var targetSheet = ss.getSheetByName("*MASTER*");
var targetRow = sheetValues[i][1];
var targetRange = targetSheet.getRange( targetRow, 16);
var targetTS = targetSheet.getRange( targetRow, 17);
checkboxRange.setValue(false)
targetRange.setValue(true);
targetTS.setValue(new Date()).setNumberFormat("dd-mm-yy hh:mm")
} ;
}
s.getRange(3, 18, s.getLastRow()-2).setValue(false)
}
You use alerts to confirm for every checked box individually either and action shall be carried out.
Sample:
function marcarEtiquetado() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Sin despachar");
var sheetRange = s.getDataRange();
var sheetValues = sheetRange.getValues();
var ui = SpreadsheetApp.getUi();
for (var i=sheetRange.getLastRow()-1; i>1; i--) {
// si valor en columna R (etiquetado) = TRUE
if ( sheetValues[i][17] === true) {
var checkboxRange = s.getRange(i, 18);
var usuariosRange = s.getRange(i, 3)
var targetSheet = ss.getSheetByName("*MASTER*");
var targetRow = sheetValues[i][1];
var targetRange = targetSheet.getRange(targetRow, 16);
var targetTS = targetSheet.getRange(targetRow, 17);
var response = ui.alert('Do you want to set the timestamp for row ' + (i+1) + '?', ui.ButtonSet.YES_NO);
// Process the user's response.
if (response == ui.Button.YES) {
checkboxRange.setValue(false)
targetRange.setValue(true);
SpreadsheetApp.getActiveSpreadsheet().toast("Timestamp will be set for row " + (i+1));
targetTS.setValue(new Date()).setNumberFormat("dd-mm-yy hh:mm")
} else {
SpreadsheetApp.getActiveSpreadsheet().toast("Timestamp will not be set for row " + (i+1));
}
} ;
}
s.getRange(3, 18, s.getLastRow()-2).setValue(false)
}
If this is not what you wanted and you prefer to have a single confirmation dialog for all checked boxes, you can implement a help array and string as following:
function marcarEtiquetado2() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Sin despachar");
var sheetRange = s.getDataRange();
var sheetValues = sheetRange.getValues();
var ui = SpreadsheetApp.getUi();
var rowKeeper = [];
var rowArray = ['\n'];
for (var i=sheetRange.getLastRow()-1; i>1; i--) {
// si valor en columna R (etiquetado) = TRUE
if ( sheetValues[i][17] === true) {
rowKeeper.push(i);
rowArray.push(i+1);
}
}
for (k = 0; k < rowArray.length-4; k += 5) {
rowArray[k+4] = rowArray[k+4] + "\n";
}
var rowString = rowArray.join(" ");
Logger.log(rowString);
var response = ui.alert('Do you want to set the timestamp for rows ' + rowString + '?', ui.ButtonSet.YES_NO);
// Process the user's response.
if (response == ui.Button.YES) {
for (var j = 0; j < rowKeeper.length; j++){
var i = rowKeeper[j];
var checkboxRange = s.getRange(i, 18);
var usuariosRange = s.getRange(i, 3)
var targetSheet = ss.getSheetByName("*MASTER*");
var targetRow = sheetValues[i][1];
var targetRange = targetSheet.getRange(targetRow, 16);
var targetTS = targetSheet.getRange(targetRow, 17);
checkboxRange.setValue(false)
targetRange.setValue(true);
targetTS.setValue(new Date()).setNumberFormat("dd-mm-yy hh:mm")
}
} else {
SpreadsheetApp.getActiveSpreadsheet().toast("No action will be carried out");
}
s.getRange(3, 18, s.getLastRow()-2).setValue(false)
}

Google Apps Script Substring

In my spreadsheet I have a file path to an image stored in a sub folder. The image is stored like this because I am making an app for my employer using appsheet.com. They want this app developed using AppSheet, which does not allow images to be stored directly into the spreadsheets that are used to build these app.
The data stored in the spreadsheet must also be extracted and applied to a template and I am making a Google Apps Script to do this. I have a functional script which finds the template and extract the users chosen data row, but I cannot extract the image needed.
I have been trying to make a substring of the file path to get the file name, but I have been unable to do this.
In the block of code where I am trying to create the substring, I am getting an error on the line sig = signature.getText();. The error is TypeError: signature.getText is not a function (line 176, file "Code").
This is what the file path looks like Signatures/FT101.Signed (%SIGNED%).103735.png, and the substring I need would look like this FT101.Signed (%SIGNED%).103735.png
I have tried multiple methods that were provided by other questions asked on stack overflow as well as any potential methods available in the Google Apps Script reference.
The following function takes the users input from a prompt and uses it to find the desired row number. It then takes the data from that row and applies it to a template based on the category the data falls under.
var response = {};
var sign = "";
function chooseRowMethod(templateId){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var dataRange = sheet.getDataRange();
var values = dataRange.getValues();
var data = sheet.getRange(2, 2, 11, 18).getValues();//starting with row 2 and column 1 as our upper-left most column, get values from cells from 1 row down, and 15 columns along - hence (2,1,1,15)
var docTitle = sheet.getRange(2, 2, 11, 1).getValues();//this is grabbing the data in field B2
var docTitleTagNumber = sheet.getRange(2, 3, 11, 1).getValues();
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth() + 1;
var yyyy = today.getFullYear();
today = dd + '/' + mm + '/' + yyyy;
for(var i = 0; i < values.length; i++){
for(var j = 0; j < values[i].length; j++){
if(values[i][j] == response){
Logger.log(i);
var row = data[i - 1];
var docId = DriveApp.getFileById(templateId).makeCopy().getId();
var doc = DocumentApp.openById(docId);
var body = doc.getActiveSection();
body.replaceText("%SITEID%", row[0]);
body.replaceText("%TAG%", row[1]);
...
body.replaceText("%SAT%", row[14]);
var signature = sheet.getRange(2, 18, 11, 1).getValues();
var sig;
var sign = {};
for(var i = 0; i < values.length; i++){
for(var j = 0; j < values[i].length; j++){
if(values[i][j] == response){
sig = signature.getText();
sign[i][0] = sig.substring(sig.indexOf("/") + 1);
}
}
}
var sigFolder = DriveApp.getFolderById("1LiJKGjTbpvRZ5RrMTQoyTuAjrozA14FN");
var file = sigFolder.getFilesByName(sign);
var image = file.getId();
body.appendImage(image);
doc.saveAndClose();
var file = DriveApp.getFileById(doc.getId());
var newFolder = DriveApp.getFolderById("16wRGBVdV0OZ5YfKhqEQSFMsux-ekGCCa");
newFolder.addFile(file);
var newDocTitle = docTitle[i - 1][0];
var newDocTagNumber = docTitleTagNumber[i - 1][0];
doc.setName(newDocTitle + " " + newDocTagNumber + " " + today);
}
}
}
}
This is where I have been attempting to get the image.
var signature = sheet.getRange(2, 18, 11, 1).getValues();
var sig;
var sign = {};
for(var i = 0; i < values.length; i++){
for(var j = 0; j < values[i].length; j++){
if(values[i][j] == response){
sig = signature.getText();
sign[i][0] = sig.substring(sig.indexOf("/") + 1);
}
}
}
var sigFolder = DriveApp.getFolderById("1LiJKGjTbpvRZ5RrMTQoyTuAjrozA14FN");
var file = sigFolder.getFilesByName(sign);
var image = file.getId();
body.appendImage(image);
This next function gives the user the prompt and applies the correct template.
function chooseRow(){
var ui = SpreadsheetApp.getUi(); // Same variations.
var result = ui.prompt('Please enter the Tag number of the row you wish to print.', ui.ButtonSet.OK_CANCEL);
var button = result.getSelectedButton();
response = result.getResponseText();
if (button == ui.Button.OK) {
// User clicked "OK".
ui.alert('Your tag number is' + response + '.');
} else if (button == ui.Button.CANCEL) {
// User clicked X in the title bar.
ui.alert('You closed the dialog.');
return 'the end';
}
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var dataRange = sheet.getDataRange();
var values = dataRange.getValues();
var category = sheet.getRange(2, 4, 11, 1).getValues();
var templateId = {};
for(var i = 0; i < values.length; i++){
for(var j = 0; j < values[i].length; j++){
if(values[i][j] == response && category[i - 1][0] == "Instrument"){
templateId = "1cx2-6ju-o7DaRPnbuYxxdvVVFeGQzpTXaXV3wMuRpqo";
chooseRowMethod(templateId);
return "";
} else if(values[i][j] == response && category[i][0] == "Motor" || values[i][j] == response && category[i][0] == "Valve"){
templateId = "1sYx_JcoDHY-pzjEDlxMMa3dtdzOOE8CyyLGQk8WHg7s";
chooseRowMethod(templateId);
return "";
}
}
}
}
The expected result is a substring of the file path that can be used to retrieve an image that can be appended to the body of a document.
Here is a link to the spreadsheet.
I did several changes to your code, including the edit proposed by Cooper. It's retrieving the substring and adding the image to the file successfully. I hope it works for you:
function chooseRow(){
var ui = SpreadsheetApp.getUi(); // Same variations.
var result = ui.prompt('Please enter the Tag number of the row you wish to print.', ui.ButtonSet.OK_CANCEL);
var button = result.getSelectedButton();
response = result.getResponseText();
if (button == ui.Button.OK) {
// User clicked "OK".
ui.alert('Your tag number is' + response + '.');
} else if (button == ui.Button.CANCEL) {
// User clicked X in the title bar.
ui.alert('You closed the dialog.');
return 'the end';
}
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var tags = sheet.getRange(2, 4, 11, 1).getValues();
var category = sheet.getRange(2, 3, 11, 1).getValues();
for(var i = 0; i < tags.length; i++){
if(tags[i][0] == response && category[i][0] == "Instrument"){
var templateId = "my_template_id";
chooseRowMethod(templateId, i);
return ""; // You don't need to return empty string, just return null
} else if(tags[i][0] == response && category[i][0] == "Motor" || tags[i][0] == response && category[i][0] == "Valve"){
var templateId = "my_template_id_bis";
chooseRowMethod(templateId, i);
return ""; // You don't need to return empty string, just return null
}
}
}
The function chooseRowMethod gets the row index chosen by the user in chooseRow so that it doesn't have to be looked for again:
function chooseRowMethod(templateId, rowNumber){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var data = sheet.getRange(2, 2, 11, 18).getValues();
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth() + 1;
var yyyy = today.getFullYear();
today = dd + '/' + mm + '/' + yyyy;
var row = data[rowNumber];
var docTitle = row[1];
var docTitleTagNumber = row[2];
var docId = DriveApp.getFileById(templateId).makeCopy().getId();
var doc = DocumentApp.openById(docId);
var body = doc.getActiveSection();
body.replaceText("%SITEID%", row[0]);
body.replaceText("%TAG%", row[1]);
// ...
body.replaceText("%SAT%", row[14]);
var signature = row[17];
var sign = signature.substring(signature.indexOf("/") + 1);
var sigFolder = DriveApp.getFolderById("my_sigfolder_id");
var files=sigFolder.getFilesByName(sign);
var n = 0;
while(files.hasNext()) {
var file=files.next();
n++;
} if(n>1) {
SpreadsheetApp.getUi().alert('There is more than one file with this name: ' + sign);
}
body.appendImage(file);
doc.saveAndClose();
var file = DriveApp.getFileById(doc.getId());
var newFolder = DriveApp.getFolderById("my_newfolder_id");
newFolder.addFile(file);
doc.setName(docTitle + " " + docTitleTagNumber + " " + today);
}

Script exceeds maximum execution time

I am using a script to first copy a list of all terminated products from "data" tab of the sheet to the "terminated tab"
The data tab looks like below
The code checks if there is an end date written
if it is - the row is copied and pasted in the "terminated" tab
Once all rows (around 2000) are completed
the code the deletes all rows from the "data" tab that have an end date on it
But the code is not very efficient and data is huge - I get a "maximum execution time exceeded" error
function movingTerms() {
var app = SpreadsheetApp ;
var sheet1 = app.getActiveSpreadsheet().getSheetByName("data") ;
var sheet3 = app.getActiveSpreadsheet().getSheetByName("Terminations");
var range1 = sheet1.getRange(2, 1, sheet1.getLastRow() - 1,9);
var range3 = sheet3.getRange(2, 1, sheet3.getLastRow(), 9);
var values1 = range1.getValues();
var values3 = range3.getValues();
var rowcount = sheet1.getLastRow();
var row_deleted = 0;
for (var i = 0; i < (sheet1.getLastRow() - 1); i++)
{
if (values1[i][4] !== "")
{
var rowtodelete = sheet1.getRange(i + 2, 1, 1, 10);
var rowtoadd = sheet3.getRange(sheet3.getLastRow() + 1, 1);
rowtodelete.copyTo(rowtoadd);
}
}
for (var k = 0; k < values1.length; k++)
{
var row = k + 1 - row_deleted;
if (values1[k][4] !== "")
{
var getridof = row +1;
sheet1.deleteRow(getridof);
row_deleted++;
}
}
}
I generally like to see the spreadsheet to do this correctly but this is the way that I would do it.
function movingTerms() {
var ss=SpreadsheetApp.getActive();
var sheet1=ss.getSheetByName("data") ;
var sheet3=ss.getSheetByName("Terminations");
var range1=sheet1.getRange(2, 1, sheet1.getLastRow()-1,9);
var range3=sheet3.getRange(2, 1, sheet3.getLastRow(),9);//You don't really need this
var values1=range1.getValues();
var values3=range3.getValues();//You don't really need this
var rowcount=sheet1.getLastRow();
var rowsdeleted = 0;
for (var i=0;i<values1.length;i++) {
if (values1[i][4]!="") {//column5
var rowtodelete = sheet1.getRange(i-rowsdeleted+2, 1, 1, 10);
var rowtoadd = sheet3.getRange(sheet3.getLastRow()+1,1);//You could also append to sheet 3 if you wish
rowtodelete.copyTo(rowtoadd);
sheet1.deleteRow(i-rowsdeleted+2);
rowsdeleted++;
}
}
}

How to check particular value in google spreadsheet

I picked this code online and I am trying to check if the value in the column B is 'Done' then the value will be be copied otherwise not. Here is the code I am using:
copy sheet function below will copy the datat from source sheet to destination sheet but what I want that it will only pick the row if the col B value contains Done
function copySheet() {
var sourceSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Source");
var destSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Destination");
var columns_to_be_copied =['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U'];
var columns_to_be_pasted =['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U'];
for (column in columns_to_be_copied) {
var copy_range_string = columns_to_be_copied[column] + ':' + columns_to_be_copied[column];
var paste_range_string = columns_to_be_pasted[column] + ':' + columns_to_be_pasted[column];
var source = sourceSheet.getRange(copy_range_string);
var destination = destSheet.getRange(paste_range_string);
if(findInColumn('A','Done') !== -1) {
copyTo(source,destination );
}
}
}
function copyTo(source,destination) {
var sourceSheet = source.getSheet();
var destSheet = destination.getSheet();
var sourceData = source.getValues();
var dest = destSheet.getRange(
destination.getRow(), // Top row of destination
destination.getColumn(), // left col of destination
sourceData.length, // # rows in source
sourceData[0].length); // # cols in source (elements in first row)
dest.setValues(sourceData);
SpreadsheetApp.flush();
}
function findInColumn(column, data) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sprint");
var column = sheet.getRange(column + ":" + column); // like A:A
var values = column.getValues();
var row = 0;
while (values[row] && values[row][0] !== data) {
row++;
}
if (values[row][0] === data)
return row+1;
else
return -1;
}
As I am a fan of simple and easy to read (even after long time) solutions I would suggest the following script:
function main() {
var sourceSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Source');
var destinationSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Destination');
copyFromTo(sourceSheet, destinationSheet);
}
function copyFromTo(sourceSheet, destinationSheet) {
const ColumnB = 1; //Array indexing starts from 0
const FilterValue = 'Done';
var sourceValues = sourceSheet.getSheetValues(1, 1, 100, 28); //startRow, startColumn, numRows, numColumns
var filteredValues = sourceValues.filter(function(row) {
return row[ColumnB] === FilterValue;
});
destinationSheet.getRange(1, 1, filteredValues.length, filteredValues[0].length).setValues(filteredValues);
}
It's about the same function. I just modified it to facilitate my debugging process. It copies the columns from source to destination if Sprint has "Done" in that column.
function copySheet() {
var srcsh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Source");
var dessh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Destination");
var from = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U'];
var to = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U'];
for(var i=0;i<from.length;i++) {
var fromrg = from[i] + ':' + from[i];
var torg = to[i] + ':' + to[i];
var src = srcsh.getRange(fromrg);
var des = dessh.getRange(torg);
if(findInColumn(from[i],'Done')!== -1){
src.copyTo(des);
}
}
}
function findInColumn(col, data) {
var col=col || 'A';//This is here for initial testing so I could run the function without parameters.
var data=data || 'Done';
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sprint");
var rg = sh.getRange(col + "1:" + col + sh.getMaxRows());//MaxRows is kind of big but I was not sure what else you'd like to do and I dont know what your Sprint sheet looks like.
var vA = rg.getValues();
var rv=-1;
for(var i=0;i<vA.length;i++){
if(vA[i][0]==data){
rv=i+1;
break;
}
}
return rv;
}
I see that you changed the question a bit. This function looks in your sprint sheet as you show in your answer and copies from source to destination only those columns that have the word "Done" on any row of that column. But it checks every column in your "columns_to_be_copied" which I called "from". Originally, that's what your function was trying to do. So I just wanted to be clear what this function is doing. If it's not what you want then leave a comment and I'll delete it.

Google script find specific text in a row range then skip current iteration of a loop

I am attempting to find the keywords "Listing Agent" in each row between columns E through N. If it appears, increment to next row++ then skip the current loop and try the next row. But it just copies the row anyways.
Here is the whole function.
function copydata() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source_sheet = ss.getSheetByName("Data Entry");
var target_sheet = ss.getSheetByName("Data");
var last_row = target_sheet.getLastRow();
var v
var row = 6
var target_range = target_sheet.getRange("B"+(last_row+1)+":W"+(last_row+1));
for (var i = 0; i< 27; i++){
v = source_sheet.getRange("E" + row + ":N" + row).getValues();
if (v[i] == "Listing Agent"){
row++
continue;
}
var triggerCell = source_sheet.getRange("AB" + row).getValue();
if (triggerCell == 0){
var source_range = source_sheet.getRange("B" + row + ":W" + row);
target_sheet.insertRowAfter(last_row);
source_range.copyTo(target_range, {contentsOnly:true});
}
row++
}
ss.setActiveSheet(source_sheet);
source_sheet.getRange('C2').clearContent();
ss.setActiveSelection("C2");
Browser.msgBox("Your data has been moved.");
//SpreadsheetApp.getActiveSpreadsheet().toast("Data has been moved.", "Data Copied");
}
I am sure it has to do with this part.
for (var i = 0; i< 27; i++){
v = source_sheet.getRange("E" + row + ":N" + row).getValues();
if (v[i] == "Listing Agent"){
row++
continue;
}
I have tried several different ways, none of them are working like I intend.
Values retrieved by getValues() is an 2 dimensional array. And in order to know whether a value is included in an array, you can use indexOf(). The modified script is as follows.
From :
if (v[i] == "Listing Agent"){
row++
continue;
}
To :
if (~v[0].indexOf("Listing Agent")){
row++
continue;
}
The detail information of getValues() is here.
Note :
When I saw the modified script, I thought that the time to run the script might be a bit long. So I modified the "for loop". At first, all data is retrieved, and using retrieved data, the data is processed. But I don't know whether this works fine. So if this didn't work, I'm sorry.
function copydata() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source_sheet = ss.getSheetByName("Data Entry");
var target_sheet = ss.getSheetByName("Data");
var last_row = target_sheet.getLastRow();
var ar = [];
var data = source_sheet.getRange("B6:AB32").getValues(); // Here, all data is retrieved. The rows are obtained from "var row = 6" and "for (var i = 0; i< 27; i++){".
data.forEach(function(e){
if (!~e.indexOf("Listing Agent")) {
var temp = [];
if (e[e.length - 1] == 0) {
temp = e.slice(0, 22); // Here, data of "B" + row + ":W" + row is retrieved.
ar.push(temp);
}
}
});
target_sheet.getRange(last_row + 1, 1, ar.length, ar[0].length).setValues(ar);
ss.setActiveSheet(source_sheet);
source_sheet.getRange('C2').clearContent();
ss.setActiveSelection("C2");
Browser.msgBox("Your data has been moved.");
}
If my understanding was wrong, I'm sorry.