move data from sheet to sheet google sheets - google-apps-script

My sheet is getting data from form responses. I have multiple tabs for the different request types. Currently when the form is submitted, it comes to the main tab and I manually change the column "status" Column 7 to "Pending Assignment" and using the below script to it sends to the corresponding tab. Is there a way to automate this? Or as the request are coming in move to tabs based on what is in column 4 (request type)?
function myEdit(e){
var ss = e.source;
var s = ss.getActiveSheet();
var r = e.range;
var actionCol = 7;
var nameCol = 4;
var rowIndex = r.getRowIndex();
var colIndex = r.getColumnIndex();
var colNumber = s.getLastColumn();
if ((e.value == "Pending Assignment" && colIndex == actionCol)) {
var targetSheet = s.getRange(rowIndex, nameCol).getValue();
if (ss.getSheetByName(targetSheet)) {
var targetSheet = ss.getSheetByName(targetSheet);
var targetRange = targetSheet.getRange(targetSheet.getLastRow()+1, 1, 1, colNumber);
var sourceRange = s.getRange(rowIndex, 1, 1, colNumber);
sourceRange.copyTo(targetRange);
s.deleteRow(rowIndex);
}
}
}

instead of onEdit, you can use onFormResponse trigger.
function onFormResponse() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formsheet = ss.getSheetByName("Form Responses 1");
var lastrow = formsheet.getLastRow();
var actionCol = 7;
var nameCol = 4;
var colNumber = formsheet.getLastColumn();
formsheet.getRange(lastrow, actionCol).setValue("Pending Assignment");
var targetSheet = s.getRange(lastrow, nameCol).getValue();
if (ss.getSheetByName(targetSheet)) {
var targetSheet = ss.getSheetByName(targetSheet);
var targetRange = targetSheet.getRange(targetSheet.getLastRow()+1, 1, 1, colNumber);
var sourceRange = formsheet.getRange(lastrow, 1, 1, colNumber);
sourceRange.copyTo(targetRange);
formsheet.deleteRow(lastrow);
}
}

Related

Issue with onEdit after sending email in google sheets

here is my code in google script:
function Send(){
Browser.msgBox("Send");
}
function myFunction() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2;
var lr = sheet.getLastRow();
var dataRange = sheet.getRange(startRow, 1, lr-1, 6);
var data = dataRange.getValues();
for (var i = 0; i < data.length; i++) {
var row = data[i];
var name = row[0];
var emailAddress = row[1];
var date = row[2];
var city = row[3];
var status = row[6];
if (emailAddress.match('#') === null){
continue;
};
var subject = row[4];
var message = "Hey " + name + ", welcome in the team " + row[5];
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(i+2,7).setValue("Sent");
}
}
Until here everything works fine. I would like then that when "Sent" appears in the 7th column, that the whole row where "Sent" is in, is moved to another tab.
function onEdit(e) {
var ss = e.source;
var s = ss.getActiveSheet();
var r = e.range;
var actionCol = 7;
var nameCol = 7;
var rowIndex = r.getRowIndex();
var colIndex = r.getColumnIndex();
var colNumber = s.getLastColumn()-1;
if (e.value == "Sent" && colIndex == actionCol) {
var targetSheet = s.getRange(rowIndex, nameCol).getValue();
if (ss.getSheetByName("Welcome")) {
var targetSheet = ss.getSheetByName("Done");
var targetRange = targetSheet.getRange(targetSheet.getLastRow()+1, 1, 1, colNumber);
var sourceRange = s.getRange(rowIndex, 1, 1, colNumber);
sourceRange.copyTo(targetRange);
s.deleteRow(rowIndex);
}
}
}
**If I manually write "Sent" in the 7th column, the row is moved to the other sheet. But when I run the first function and that "Sent" appears in that column, the onEdit function doesn't work.
So basically both functions work but not together at the same time.
Does someone know a fix for this?**
Issues:
You are trying to trigger an onEdit function via a script but that's not how triggers work. The official documentation states the following:
The onEdit(e) trigger runs automatically when a user changes the value
of any cell in a spreadsheet.
Namely, onEdit triggers are activated only by user actions, not by scripts nor formulas.
You don't need a separate function to check if the value is Sent and then delete the row with another function. After the email is sent you can move the data and delete the row, all within the same function.
Last but not least, when deleting rows iteratively we change the structure of the sheet and therefore the data input does not match the updated structure. To alleviate this issue, we can store the indexes of the rows we want to delete in an array, and then using that array delete the rows backwards.
Solution:
Assuming your codes work separately, this should also work:
function myFunction() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName("Welcome");
var targetSheet = ss.getSheetByName("Done");
var startRow = 2;
var lr = sheet.getLastRow();
var dataRange = sheet.getRange(startRow, 1, lr-1, 6);
var data = dataRange.getValues();
var colNumber = sheet.getLastColumn()-1;
var delRows = [];
for (var i = 0; i < data.length; i++) {
var row = data[i];
var name = row[0];
var emailAddress = row[1];
var date = row[2];
var city = row[3];
var status = row[6];
if (emailAddress.match('#') === null){
continue;
};
var subject = row[4];
var message = "Hey " + name + ", welcome in the team " + row[5];
MailApp.sendEmail(emailAddress, subject, message);
var targetRange = targetSheet.getRange(targetSheet.getLastRow()+1, 1, 1, colNumber);
var sourceRange = sheet.getRange(i+startRow, 1, 1, colNumber);
sourceRange.copyTo(targetRange);
delRows.push(i+startRow);
}
// delete rows in reverse order
delRows.reverse().forEach(ri=>{sheet.deleteRow(ri)});
}
you don't need the onEdit function anymore so you can delete it.

Check if in cell Today's date then continue

I found a script on the Internet and am trying to alter it a little to fit my needs. But stumbled upon a problem. The script takes a list of bookmarks from the drop down menu and if you write OK in the next cell, then it transfers the line to the selected bookmark. I want to confirm today's date.
Copy of the sheet. Also here some diffeent.
var actionCol = 7;
var nameCol = 6;
https://docs.google.com/spreadsheets/d/1P9avWP8i5Z4KA4zt3EoUZNbgMKeXwnOYKsgCG2_vSLE/edit?usp=sharing
/**
* Moves row of data to another spreadsheet based on criteria in column 6 to sheet with same name as the value in column 4.
*/
function onEdit(e) {
// see Sheet event objects docs
// https://developers.google.com/apps-script/guides/triggers/events#google_sheets_events
var ss = e.source;
var s = e.range.getSheet();
var r = e.range;
// to let you modify where the action and move columns are in the form responses sheet
var actionCol = 10;
var nameCol = 9;
// Get the row and column of the active cell.
var rowIndex = r.getRowIndex();
var colIndex = r.getColumnIndex();
// Get the number of columns in the active sheet.
// -1 to drop our action/status column
var colNumber = s.getLastColumn()-1;
// if our action/status col is changed to ok do stuff
if (e.value == "ok" && colIndex == actionCol) {
// get our target sheet name - in this example we are using the priority column
var targetSheet = s.getRange(rowIndex, nameCol).getValue();
// if the sheet exists do more stuff
if (ss.getSheetByName(targetSheet)) {
// set our target sheet and target range
var targetSheet = ss.getSheetByName(targetSheet);
var targetRange = targetSheet.getRange(targetSheet.getLastRow()+1, 1, 1, colNumber);
// get our source range/row
var sourceRange = s.getRange(rowIndex, 1, 1, colNumber);
// new sheets says: 'Cannot cut from form data. Use copy instead.'
sourceRange.copyTo(targetRange);
// ..but we can still delete the row after
s.deleteRow(rowIndex);
// or you might want to keep but note move e.g. r.setValue("moved");
}
}
}
If I understand you correctly, you want to cut & paste the edited row if:
The edited column is G, and the value is a Date corresponding to today.
The corresponding name in column F refers to the name of an existing sheet.
In order to check that the two dates correspond to the same day, you can compare the values returned by getDate(), getMonth() and getFullYear(), as in this function (credits to Pointy):
function sameDay(d1, d2) {
return d1.getFullYear() === d2.getFullYear() &&
d1.getMonth() === d2.getMonth() &&
d1.getDate() === d2.getDate();
}
Then, you can call this in your main function:
function onEdit(e) {
var ss = e.source;
var s = e.range.getSheet();
var r = e.range;
var value = r.getValue();
var actionCol = 7;
var nameCol = 6;
var rowIndex = r.getRow();
var colIndex = r.getColumn();
var colNumber = s.getLastColumn();
if (value instanceof Date && colIndex == actionCol) {
var today = new Date();
if (sameDay(value, today)) {
var targetSheetName = s.getRange(rowIndex, nameCol).getValue();
var targetSheet = ss.getSheetByName(targetSheetName);
if (targetSheet) {
var sourceRange = s.getRange(rowIndex, 1, 1, colNumber);
var targetRange = targetSheet.getRange(targetSheet.getLastRow()+1, 1);
sourceRange.copyTo(targetRange);
s.deleteRow(rowIndex);
}
}
}
}
Try it this way:
function onEdit(e) {
var ss = e.source;
var s = e.range.getSheet();
var r = e.range;
var actionCol = 10;
var nameCol = 9;
var rowIndex = r.rowStart;
var colIndex = r.columnStart;
var colNumber = s.getLastColumn()-1;
const dt=new Date(e.range.offset(0,n));//you add the column offset
const dtv=new Date(dt.getFullYear(),dt.getMonth(),dt.getDate()).valueOf();
const td=new Date();
const tdv=new Date(td.getFullYear(),td.getMonth(),td.getDate()).valueOf();
if (e.value == "ok" && colIndex == actionCol && dtv==tdv) {
var targetSheet = s.getRange(rowIndex, nameCol).getValue();
var tSh = ss.getSheetByName(targetSheet);
if (tSh) {
var targetRange = tSh.getRange(tSh.getLastRow()+1, 1, 1, colNumber);
var sourceRange = s.getRange(rowIndex, 1, 1, colNumber);
sourceRange.copyTo(targetRange);
s.deleteRow(rowIndex);
}
}
}

How to find index of the first match in the column using Google sheets script?

I'm trying to find index of the first match in the column using Google sheets script:
function getRowIndex() {
var lookupValue = "car";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("List");
var lastRow = sheet.getLastRow();
var lookupRangeValues = sheet.getRange(1, 1, lastRow, 1).getValues()[0];
var index = lookupRangeValues.indexOf(lookupValue);
Logger.log(index);
}
But my code returns -1 always. What am I doing wrong?
in
var lookupRangeValues = sheet.getRange(1, 1, lastRow, 1).getValues()[0];
you ask for first row.
getValues() return a 2D array as so:
array[rowIndex][columnIndex]
try:
function getRowIndex() {
var lookupValue = "car";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("List");
var lastRow = sheet.getLastRow();
var lookupRangeValues = sheet.getRange(1, 1, lastRow, 1).getValues();
var index = -1;
lookupRangeValues.forEach(function (row, i){
if (row[0] == lookupValue )
{
index = i;
return (false);
}
});
Logger.log(index);
}

Google script for move rows depending on checkbox - Google sheet

I've got a script that moves a row from one tab "COMMUNICATIONS" to another tab "ARCHIVE" when a cell checkbox (column AE) is true but it's only working well with the row AE2 and it's not working when I check AE3 or AE6.
function onEdit() {
var sheetNameToWatch = "COMMUNICATIONS";
var sheetNameToMoveTheRowTo = "ARCHIVE";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveCell();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName(sheetNameToWatch);
var sheet2 = ss.getSheetByName(sheetNameToMoveTheRowTo);
var cell1 = sheet1.getRange("AE2:AE1000");
var x= cell1.getValue();
Logger.log("a",x);
if(cell1.getValue()== false) {
Logger.log("box not checked");
sheet1.showSheet();
} else if (cell1.getValue() == true) {
var targetSheet = ss.getSheetByName(sheetNameToMoveTheRowTo);
var targetRange = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
sheet.getRange(range.getRow(), 1, 1,
sheet.getLastColumn()).moveTo(targetRange);
sheet.deleteRow(range.getRow());
}
}
you can try this code. I Tested it on one of my sheets and it worked fine.
function onEdit(event) {
// assumes source data in sheet named Active
// target sheet of move to named Found
// test column with yes/no is col 13 or M
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "COMMUNICATIONS" && r.getColumn() == 13 && r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("ARCHIVE");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}

Changing from getActiveCell(); to getting a range instead

This may be fairly simple for you guys.
How to replace getActiveCell() for something I dont need to be online for the script to run, so I can set it up based on a time-trigger?
Check the code block below.
function MoveRows() {
var sheetNameToWatch = "Requests";
var sheetNameToMoveTo = "Approved";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveCell();
var range = sheet.getActiveCell();
var row = range.getRow();
if (sheet.getName() == sheetNameToWatch &&
sheet.getRange(row, 8).getValue() == "Y" &&
sheet.getRange(row, 12).getValue() == "Approved") {
{
var targetSheet = ss.getSheetByName(sheetNameToMoveTo);
var targetRange = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
sheet.getRange(range.getRow(), 1, 1,
sheet.getLastColumn()).moveTo(targetRange);
sheet.deleteRow(range.getRow());
}
}}
Thank you!
After looking at your code a bit I'm guessing this maybe close to what your looking for.
function MoveRows() {
var sheetNameToWatch = "Requests";
var sheetNameToMoveTo = "Approved";
var ss = SpreadsheetApp.openById(id)
var sheet = ss.getSheetByName('Requests')
var range = sheet.getRange(sheet.getLastRow(),1,1,sheet.getLastColumn());
var values=range.getValues();
var row = range.getRow();
if (values[0][7] == "Y" && values[0][11] == "Approved") {
var targetSheet = ss.getSheetByName(sheetNameToMoveTo);
var targetRange = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
range.moveTo(targetRange);//you could also just do targetSheet.appendRow(values[0]); Your call
sheet.deleteRow(range.getRow());
}
}