Copy rows from one sheet to another - google-apps-script

I need to create a master sheet for our managers that only include activity happening in their areas (I have a script for this that does what I need). These sheets are populated from my master sheet (and are not in the same workbook).
I need to have rows copy to the applicable sheet when there is a new submission. My code below dumps them all to one sheet and I'm not sure why. I'm assuming I don't have the right condition but how do you say "move rows to this sheet when it's this manager"? I thought calling the sheet ID by row would be enough, but I guess not.
Would I then have to do an if else statement for every manager? That will get tedious since I have about 80 managers.
Below is my current code. Any help or advice is appreciated!
function moveRows(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName("Form Responses 1");
var data = sh.getDataRange().getValues();
// Grab the Headers
var headers = sh.getRange(1,1,1,sh.getLastColumn()).getValues();
var nameCol = headers[0].indexOf('Enter Your Name');
var candCol = headers[0].indexOf('Choose Candidate');
var typeCol = headers[0].indexOf('Merged Experience');
var docCol = headers[0].indexOf('Document Link');
var timeCol = headers[0].indexOf('Timestamp');
var subjectCol = headers[0].indexOf('Choose the Content Area');
var ratingsCol = headers[0].indexOf('Ratings Summary');
var accessCol = headers[0].indexOf('Access');
var activityCol = headers[0].indexOf('Copied to Activity Sheet');
var masterCol = headers[0].indexOf('Master Activity Sheet');
var target = [];
// Loop over the values line by line
for (var i = 0; i < data.length; i++) {
var row = data[i];
var name = row[nameCol];
var activity = row[activityCol];
var master = row[masterCol];
var candidate = row[candCol];
var type = row[typeCol];
var subject = row[subjectCol];
var ratings = row[ratingsCol];
var access = row[accessCol];
var guide = row[docCol];
var time = row[timeCol];
if (activity == "") { // if condition is true copy the whole row to target
target.push([time,name,candidate,subject,type,guide,ratings]);
Logger.log(target);
var ss2 = SpreadsheetApp.openById(master);
var sh2 = ss2.getSheetByName("Sheet1");
sh2.getDataRange().offset(sh2.getLastRow(), 0, target.length, target[0].length).setValues(target);
}
}
}
Note: I have a bunch of different scripts that move rows from one tab to another, but I couldn't find anything where I move it across multiple workbooks.

What you can do is to have an array with for each manager the sheet where to copy the data.
var managerSheet = {
"manager1":"SheetAzerty",
"manager2":"SheetQwerty"
};
to select the sheet just do :
var manager = "manager1"; //This is the value you retrieve
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(managerSheet[manager]);
Stéphane

Related

Copying Data from One Spreadsheet to Several Others with Array and For Loop - Repost as suggested did not solve

The following appears to work, however the code times out. A portion of the data is transferred to the 1st sheet of the loop and then the following error occurs: "Exception: Service Spreadsheets failed while accessing document with id "Y". CopyCmpstrs # Code.gs:33" For the purpose of the post, I removed the actual spreadsheetIDs.
The following has been suggested as a solution, however this only deals with data within the same spreadsheet and is a separate issue. The issue that I am having, I think, is that the dataset is large and the 2nd sheet being pasted to is freezing: Is possible to copy a data range from one spreadsheet to another?
Is possible to copy a data range from one spreadsheet to another?
function CopyCmpstrs() {
var DashboardSSID = "X";
var PaymentSSID = "Y";
var SalesSSID = "Z";
var FormsSSID = "A";
var ProductSSID = "B";
var InvoiceSSID = "C";
var TargetSSID = [PaymentSSID,SalesSSID,FormsSSID,ProductSSID,InvoiceSSID];
var ssSource = SpreadsheetApp.openById(DashboardSSID);
var CmpstrsSheet = ssSource.getSheetByName("Cmpstrs");
var CmpstrsSheetName = CmpstrsSheet.getName();
var RowCountSource = CmpstrsSheet.getRange(1, 2).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
var CustomerData = CmpstrsSheet.getSheetValues(1,1,RowCountSource,176);
var ArraySize = TargetSSID.length;
for (var i=0; i<= ArraySize; i++){
var TargetSS = SpreadsheetApp.openById(TargetSSID[i]);
var TargetSheet = TargetSS.getSheetByName(CmpstrsSheetName);
var MaxRow = TargetSheet.getMaxRows();
var MaxCol = TargetSheet.getMaxColumns();
var TargetFullRange = TargetSheet.getRange(1,1,MaxRow,MaxCol);
TargetFullRange.clearContent();
var TargetRange = TargetSheet.getRange(1,1,RowCountSource,176);
TargetRange.setValues(CustomerData);
}
}

How to compare values from a google sheets column to an array and send to specific emails based on column data

I'm automating my google sheets to send out emails automatically and I can't figure out how to compare a variable array to a column in my google sheets. I keep getting all values returned rather than just the ones in my array when I put it in an 'IF' statement.
I want my code to only show data that is in my gEnglish variable but instead shows me all data. I was also wondering how I'd be able to send emails based on regions to users.
function sendEmails() {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Main").activate();
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr = ss.getLastRow();
var decisionOne = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Templates").getRange(1,1).getValue();
var decisionTWO = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Templates").getRange(2,1).getValue();
var decisionThree = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Templates").getRange(3,1).getValue();
var decisionFour = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Templates").getRange(5,1).getValue();
var decisionFive = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Templates").getRange(4,1).getValue();
var gEnglish = ["IT","US","GB","UK"];
var gSpanish = ["SP"];
var user1 = ["JP","SK","IND","RU"];
var user2 = [gEnglish,"UK"];
var user3 = [gSpanish, "BR", "PT"];
var user4 = ["FR", "DE","IT"];
for (var i = 2;i<=lr;i++){
var type = ss.getRange(i,6).getValue();
var region = ss.getRange(i, 5).getValue();
var decision = ss.getRange(i,15).getValue();
//I used to have if(region == gEnglish)
if(gEnglish.includes(region[i]) ){
var channel = ss.getRange(i,3).getValue();
var decision = ss.getRange(i,15).getValue();
var url = ss.getRange(i, 9).getValue();
var name = ss.getRange(i,11).getValue();
var messageBody = {};
var subjectLine = "blahblahblah";
}
}
}
If my array only has one value inside it works fine but as soon as I put more I just get all values returned.
What am I doing wrong?
Putting a column into a flat array.
function col2array() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName('Sheet1');
const vA=sh.getRange(1,1,sh.getLastRow(),1).getValues().flat();
}
In Google Apps Script a column looks like:
[[Row1],[Row2],[Row3],[Row4]....]
function lookingforarrayvaluesinacolumn() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName('Sheet1');
const vA=sh.getRange(1,1,sh.getLastRow(),1).getValues();
const coolpeople = ["p1","p2"];
vA.forEach(function(r,i){
if(coolpeople.indexOf(r[0])!=-1) {
//the r[0] is a cool person
}
});
}

Move Rows En Masse Contingent on Value in One Column

I have a script setup that moves all the records in a sheet into another sheet. However, I would like to add functionality to only move records that have the value "Approved" in a specific column (column I for my current situation). I've seen some other questions/answers to move individual rows based on values, but I haven't figured out how to leverage these scripts to run across a full spreadsheet. My guess is I can use a for loop but how?
Current script:
function MoveRecords(){
//Original Sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Example Input")
//Calculate # of Rows Ignoring Blank Array Values
var Rows = ss.getRange("A2:A").getValues();
var NumRows = Rows.filter(String).length;
/*Add a For Loop here to only get the rows with Approved in Column I?*/
//Parsed Data to Move
var rangeValues1 = sheet.getRange(2,1,NumRows,1).getValue();
var rangeValues2 = sheet.getRange(2,2,NumRows,5).getValues();
//Destination of Parsed Data
var DestinationSS = SpreadsheetApp.openById('ID');
var DestinationSheet = DestinationSS.getSheetByName('Approved');
var DestinationLastRow = DestinationSheet.getLastRow()+1;
//Move the Data
DestinationSheet.getRange(DestinationLastRow,3,NumRows,1).setValue(rangeValues1);
DestinationSheet.getRange(DestinationLastRow,5,NumRows,5).setValues(rangeValues2);
};
Any help is greatly appreciated!
You can get all values, filter every row for Approved then write those rows into destination sheet.
function MoveRecords() {
//Original Sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Example Input');
var values = sheet.getDataRange().getValues();
/*Add a For Loop here to only get the rows with Approved in Column I?*/
// col I = index 8
var res = values.filter(function(row) {
return row[8] == 'Approved';
});
//Parse Data to Move
var rangeValues1 = res.map(function(row) {
return [row[0]];
});
var rangeValues2 = res.map(function(row) {
row.shift();
while (row.length > 5) row.pop();
return row;
});
//Destination
var DestinationSS = SpreadsheetApp.openById('ID');
var DestinationSheet = DestinationSS.getSheetByName('Approved');
var DestinationLastRow = DestinationSheet.getLastRow() + 1;
//Move the Data
DestinationSheet.getRange(DestinationLastRow, 3, rangeValues1.length, 1).setValues(rangeValues1);
DestinationSheet.getRange(DestinationLastRow, 5, rangeValues2.length, 5).setValues(rangeValues2);
}

getValues and getBackgrouds not returning data in Google Apps Script

I'm trying to create a code that checks to see if a cell has a checkbox checked (or unchecked) and then copies data from a corresponding cell on that row onto another "Summary" sheet. The "if checked then copy data" portion has not been included below.
The problem I'm having is that neither getValues nor getBackgound seems to be returning data.
When I run my code, the Logger shows that every checkbox value is "false" (even though some are checked and I have their values set to 1 (checked) and 0 (unchecked) using the data validation in the spreadsheet settings.
If I switch to getBackgrounds, the Logger shows that every cell's background is white "#ffffff", even though the cells are red.
[[I want my code to iterate over every sheet, row, and column. It seems to be iterating fine, but not retrieving the data.]]
What I am doing wrong? Here's my full code:
function MAPSuccess() {
var app = SpreadsheetApp;
var ss = SpreadsheetApp.openByUrl(
'https://docs.google.com/spreadsheets/d/1UUdiLsz2OvKdqnr2KB0Tx74gzrGx0m4XUA5oNMUB06k/edit');
var allsheets = ss.getSheets();
var s = ss.getNumSheets();
var master = app.getActiveSpreadsheet().getSheetByName("Master");
var masterLastRow = master.getLastRow();
for (var s = 2; s < allsheets.length; s++) {
var sheet = app.getActiveSpreadsheet().getActiveSheet();
var r = sheet.getCurrentCell().getRow();
var lastrow = sheet.getLastRow();
var lastcol = sheet.getLastColumn();
var temail = sheet.getRange(1,2);
var tSJCOE = sheet.getRange(2,2);
var c = sheet.getActiveCell().getColumn();
for(var r = 4;r<=lastrow;r++){
var name= sheet.getRange(r,1).getValue();
var lname= sheet.getRange(r,2).getValue();
var email= sheet.getRange(r,3).getValue();
var pemail= sheet.getRange(r,4).getValue();
var info = [
[name, lname, email, pemail]
]
var range = sheet.getRange(r,1,1,lastcol);
var rowValues = range.getValues();
var cell = [
[s,r,c]
];
Logger.log(rowValues);
Logger.log(name);
// Logger.log(checkRow);
Logger.log(cell);
It looks like you are always performing your actions on the active sheet, instead of accessing the sheets in "allsheets".
var sheet = app.getActiveSpreadsheet().getActiveSheet();
should be
var sheet = allsheets[s];
You may also be misusing "getCurrentCell" on the next line, since that will return whichever cell is currently selected in the spreadsheet, of which there is always only one, regardless of which sheet you are accessing.

If column has value do ______

How to search a column on a sheet for a value, and if the value is there continue code? I am trying to make an update system to check to see if their email is on a sheet. If their email is on a sheet then it will check if their system version is up to date. If the system is not to up to date it will then copy their data, delete their current sheet, create a copy from an example then put in their data. If the user does not have the system it will create one for them. It seems to continuously skip Checking their email.
My code uses URLs and IDs but I have taken them out for obvious reasons. Below is an example of the beginning of my code.
function readlog()
var user = Session.getEffectiveUser().getUsername();
var email = Session.getEffectiveUser().getEmail();
var ss = SpreadsheetApp.openByUrl(URL_);
SpreadsheetApp.setActiveSpreadsheet(ss);
var sheet = SpreadsheetApp.getActiveSpreadsheet()
var sheet = sheet.getSheetByName('8th grade')
var active = sheet.getRange('8th grade!b3:b').getValues()
if (email == active) {
//do something
}
Here is a full version of my code:
function readlog(){
var user = Session.getEffectiveUser().getUsername();
var email = Session.getEffectiveUser().getEmail();
var timezone= "CST";
var date = Utilities.formatDate(new Date(),timezone, "E MMM dd,yyyy HH:mm:ss");
var ss = SpreadsheetApp.openByUrl(URL_);
SpreadsheetApp.setActiveSpreadsheet(ss);
var sheet = SpreadsheetApp.getActiveSpreadsheet()
var sheet = sheet.getSheetByName('8th grade')
var active = sheet.getRange('8th grade!b3:b').getValues()
if (email == active) {
var container = DriveApp.getFoldersByName('Reading Log')
var fid = DriveApp.getFoldersByName('Reading Log').getId()
var version = sheet.getRange('8th grade!a1')
var update = container.getDescription();
if (update == version) {
var ui = SpreadsheetApp.getUi();
var response = ui.alert('You already have a reading log, and you have the most recent update!', ui.ButtonSet.OK);
} else {
var contents = container.getFiles();
var files = DriveApp.getFolderById(fid).searchFiles(
'title contains "Reading log"');
while (files.hasNext()) {
var file = files.next();
var logtoupdate = file.getUrl;
}
var ss = SpreadsheetApp.openByUrl(logtoupdate);
SpreadsheetApp.setActiveSpreadsheet(ss);
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var logrange = sheet.getRange('8th Grade!e5:o').getValues()
SpreadsheetApp.getActiveSpreadsheet().deleteActiveSheet();
var master = DriveApp.getFileById(URL_);
var read = master.makeCopy("Reading Log",container);
var target = read.getRange('8th Grade e5:o').setValues(logrange);
var range = sheet.getRange("A1:B2");
range.setValues([[50, 100]]);
var ss = SpreadsheetApp.openByUrl(URL_);
SpreadsheetApp.setActiveSpreadsheet(ss);
var sheet = SpreadsheetApp.getActiveSpreadsheet()
}
} else {
var ss = SpreadsheetApp.openByUrl(URL_);
SpreadsheetApp.setActiveSpreadsheet(ss);
var sheet = SpreadsheetApp.getActiveSpreadsheet()
var targetFolder = DriveApp.createFolder("Reading Log");
var eighth = DriveApp.getFileById(URL_);
var share = eighth.makeCopy("(Name): 8th Grade Reading Log",targetFolder);
var master = DriveApp.getFileById(URL_);
var read = master.makeCopy("Reading Log",targetFolder);
var folder = sheet.getRange('8th grade!a1');
targetFolder.setDescription(folder);
var idsheet = read.getUrl();
var idshare = share.getUrl();
var idfolder = targetFolder.getUrl()
sheet.appendRow([user,email,date,idfolder,idsheet,idshare]);
var ui = SpreadsheetApp.getUi();
var response = ui.alert('Your Reading log is created. There is now a folder in your google drive called Reading log. Have Fun Reading!', ui.ButtonSet.OK);
}
}
Short answer
Instead of email == active use active.join('|').split('|').indexOf(email)
Explanation
getValues() return a two dimensional array.
join('|') convert this array into an string using | as separator.
split('|') convert the above string into an (one dimension) array.
indexOf(email) returns the index of the email value on the above array. If the email value is not found, -1 is returned.
On a comparison -1 is parsed as false.