onEdit(e) DriveApp.getFileById - google-apps-script

Having issues getting the following to work.
The intent was on edit to push information from the specific cell or cells of active sheet to specific cells on a separate worksheet.
Note: I am new to google sheets
function onEdit(e) {
var source = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Working");
var cell = source .getActiveCell();
if (cell.getRow() == 9 && cell.getColumn() == 2) {
var target = DriveApp.getFileById("1biaIVlafaNQTHjtR8ctASCpDmC2O1wwfJfAUCmzIztI")
.getSheetByName("Master_Sheet");
target.getRange("A1").setValue(cell.getValue());
}
}

The reason it does not work is because you are using onEdit(). This is a simple trigger that will fire off whenever you edit the sheet. Since simple triggers cannot perform operations that require authorization you are limited to working only in the Spreadsheet and cannot access any other files.
Read up on restrictions here

I am now able to push information to the target sheet using the following code.
function myFunction() {
var sourceSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Source");
var sourceData = sourceSheet.getRange("A3:C3").getValues();
sourceData.splice(0,1); // Remove header
var targetSS = SpreadsheetApp.openById("1pyJzZ86WDh2FNXFufUAt2SkAUod32i7AzvG0EKmnvEU").getSheetByName("Destination");
var targetRangeTop = targetSS.getLastRow(); // Get # rows currently in target
targetSS.getRange(targetRangeTop+1,1,sourceData.length,sourceData[0].length).setValues(sourceData);
};

Related

Script to Move Data in One Workbook to Another Workbook Within Google Sheets [duplicate]

Hi everyone,
I want to copy the data from source sheet to destination sheet. When the data reached the destination sheet, the script able to loop through row 2 in destination sheet to see whether any same ID already existed. If the ID already existed in row 2, then it will overwrite the data in the column, if not, the script will find the last empty column based on row 2 and paste the data there.
So in the screenshot above, since there is no 1004 in destination sheet, then it will paste the data in column E.
This is my code:
function onEdit(e){
var ss = SpreadsheetApp.getActiveSheet ();
var targetfile = SpreadsheetApp.openById("11tpC8SNZ5XB35n7GON0St3ZQ37dIbM8UbXRjmkVAeJQ");
var target_sheet = targetfile.getSheetByName("Sheet1");
var target_range = target_sheet.getRange(3, ss.getLastColumn() + 1);
if (e.range.columnStart == 3 && e.range.rowStart == 16){
if (e.value == 'Submit'){
var source_range = ss.getRange("C4:C14")
source_range.copyTo(target_range);
e.range.clearContent()
}
}
}
My current problems are:
The script is not working when I triggered it in cell C16 (couldn't find the reason)
I'm not sure how to add the checking for ID in destination sheet into my script.
This are my google files
Source sheet: https://docs.google.com/spreadsheets/d/12kKQKT2XSdPkJ46LSV9OiI167NKBdwKkpkOtOf_r_jI/edit#gid=0
Destination sheet:
https://docs.google.com/spreadsheets/d/11tpC8SNZ5XB35n7GON0St3ZQ37dIbM8UbXRjmkVAeJQ/edit#gid=0
Hope to get some advice and help from expert. Any help will be greatly appreciated!
Explanation:
I see a couple problems with the existing script:
Simple Triggers only have authorization on the container Spreadsheet, so to access another Spreadsheet you need to create an Installable Trigger:
// Creates an edit trigger for a spreadsheet identified by ID.
function createTrigger() {
ScriptApp.newTrigger('copyFunction')
.forSpreadsheet('source-sheet-id')
.onEdit()
.create();
}
copyTo() only works when copying to the same Spreadsheet. You would need to use getValues() and setValues() to copy across spreadsheets. The caveat is that formatting is not copied. You would need to manually format the columns if a new column is filled up.
function copyFunction(e) {
var ss = SpreadsheetApp.getActiveSheet();
var targetfile = SpreadsheetApp.openById('dest-sheet-id');
var target_sheet = targetfile.getSheetByName("Sheet1");
var id_table = target_sheet.getRange(2,2,1,target_sheet.getLastColumn()-1).getValues();
if (e.range.getA1Notation() == 'C16') {
if (e.value == 'Submit') {
var source_values = ss.getRange("C3:C14").getValues();
for (i = 0; i < id_table[0][i]; i++) {
if (id_table[0][i] == ss.getRange("C3").getValue())
break;
}
target_sheet.getRange(2,i+2,12).setValues(source_values);
e.range.clearContent();
}
}
}

Apps script copy multiple range from 1 sheet to another spreadsheet

I am trying to copy data from 1 spreadsheet to another, I have successfully implemented something i found online that works with a specific range
function cloneGoogleSheet() {
// source doc
var sss = SpreadsheetApp.openById("spreadsheetkey1");
// source sheet
var ss = sss.getSheetByName('_tab_name_source');
// Get full range of data
var SRange = ss.getRange(7,3,5,1);
// get A1 notation identifying the range
var A1Range = SRange.getA1Notation();
// get the data values in range
var SData = SRange.getValues();
// target spreadsheet
var tss = SpreadsheetApp.openById("spreadsheetkey2");
// target sheet
var ts = tss.getSheetByName('tab_name_destination');
// Clear the Google Sheet before copy
//ts.clear({contentsOnly: true});
// set the target range to the values of the source data
ts.getRange(A1Range).setValues(SData);
};
The above piece coding work perfectly however I need to copy 18 different ranges that i cant just merge into 1 range. I considered the option of using the above however "multiplying" it 18 times for each range that however seems like a very inelegant solution.
I found a working solution that works if it stays within the same spreadsheet since it uses copyto instead of get/set values. The values part works perfectly since it doesnt mess with merge cells formatting. I have been struggling past 2-3 hours in merging the below-working code with elements from the first code to make a working script.
function test () {
try {
var spread = SpreadsheetApp.openById("spreadsheetkey");
var sheet = spread.getSheetByName("tab_name_source");
var rlist = sheet.getRangeList(["c7:c11", "g7:g11", "k7:k11"]);
sheet = spread.getSheetByName("tab_name_destination");
for( var i=0; i<rlist.getRanges().length; i++ ) {
var r1 = rlist.getRanges()[i];
var r2 = sheet.getRange(r1.getA1Notation());
r1.copyto(r2);
}
}
catch(err) {
Logger.log(err);
}
}
I tried initially to adapt the 2nd piece of coding to using setvalues however i had not been able to succesfully implement the part of getvalues within the scope of this code. I figured once I got this piece of code working with get and set values instead of Copyto i would only need to add the spreadsheetid of the other spreadsheet to get the final result
Try this:
function myFunction() {
var sourceSS = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = sourceSS.getSheetByName("sheetname");
var targetSS = SpreadsheetApp.openById("spreadsheet id here");
var targetSheet = targetSS.getSheetByName("Sheet1");
var ranges = ["C7:C11", "G7:G11", "K7:K11"];
ranges.forEach(range => {
var data = sourceSheet.getRange(range).getValues();
targetSheet.getRange(range).setValues(data);
})
}
Source sheet:
Destination sheet:
References:
setValues()
getValues()

User/Email stamp with onEdit Google Sheets

What I want to do is to place the user's email who is clicking the checkbox to true in the cell directly next to the checkbox that they're clicking on. I've got the code so that I can place my own email there. I've even played with it to the point where it will remove the "#gmail.com," but I cannot get this to show for other users.
I had it, at one point, placing the current users emails in the box, but then it would quickly change to my own. However, I don't remember the state of the code as it was then, and haven't been able to replicate it.
I've tried everything suggested here.
I've also referenced this post here.
Here is my code:
function createTrigger(){
ScriptApp.newTrigger('myFunction').forSpreadsheet(SpreadsheetApp.openById('1Y0-bpAhGzPSS5DIPnoZH4OcY2b9IL8LhvBfc2is0zVU')).onEdit().create();
}
function myFunction(e) {
var groupOneCheck = 3;
var groupTwoCheck = 7;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var checkCell = ss.getActiveCell();
if (checkCell.getColumn() == groupOneCheck) {
var dateTimeCell = checkCell.offset(0,2);
var userCell = checkCell.offset(0,1);
dateTimeCell.setValue(new Date());
userCell.setValue([Session.getEffectiveUser().getEmail()]);
}
if (checkCell.getColumn() == groupTwoCheck) {
var dateTimeCell = checkCell.offset(0,2);
var userCell = checkCell.offset(0,1);
dateTimeCell.setValue(new Date());
userCell.setValue([Session.getEffectiveUser().getEmail()]);
}
}
I want to do the same thing for both of the if statements because they correspond to different columns.
Here is a link to the sheet that I am currently testing with.
It works for me if I use an installable trigger because simple triggers cannot perform functions that require permission.

Google Scripts - Can't Find Destination Sheet After Form Creation

My script creates a Google Form programmatically and sets the destination to the current Spreadsheet:
var sheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
var form = FormApp.create(acctName).setTitle(acctName).setDestination(FormApp.DestinationType.SPREADSHEET, sheetId);
// several form items added here
Next, I'd like to rename the destination Sheet and make a few formatting edits. When I do, however, the sheet doesn't seem to exist. For example, getSheets() does not contain the new Sheet! (And yes, ideally I'd like to open the sheet by ID; see function below which also doesn't work.)
var sheets = SpreadsheetApp.openById(form.getDestinationId()).getSheets();
SpreadsheetApp.setActiveSheet(sheets[0]);
The above code opens what I would consider index 1, not index 0, because the sheet isn't indexed. I even tried creating a few second delay (hoping that it was just a matter of time to allow the sync to happen between the client and server) but without any success.
I have also tried something like the following, as suggested elsewhere here on Stack Overflow, but the destination Sheet doesn't come up in getSheets() even when called through a separate function:
function getFormDestinationSheetId(form) {
var destinationId = form.getDestinationId();
if(destinationId) {
var spreadsheet = SpreadsheetApp.openById(destinationId);
spreadsheet.getSheets().forEach(
function(sheet) {
var sheetFormUrl = sheet.getFormUrl();
if(sheetFormUrl) {
var sheetForm = FormApp.openByUrl(sheetFormUrl);
if(sheetForm.getId() == form.getId()) {
return sheet.getSheetId();
}
}
}
);
}
return null;
}
I haven't been able to find anyone have a similar problem on the webs. Any advice would be appreciated. Thanks!
Welcome to Stack!
I assume your script is bound to a sheet? Depending on how you're calling the script you may not see the new sheets because of browser caching.
function myFunction() {
var sheet = SpreadsheetApp.getActive();
var sheetId = sheet.getId();
var form = FormApp.create('acctName').setTitle('acctName').setDestination(FormApp.DestinationType.SPREADSHEET, sheetId);
var ssSheets = sheet.getSheets();
var respSheet = ssSheets[0]
respSheet.getRange('A1').setBackground('RED');
respSheet.getRange('C1').setFormula('=COUNTA($C$2:$C)');
respSheet.setColumnWidth(2, 100);
SpreadsheetApp.flush();
}

Google Sheets Script - Reference a specific cell in a row

I have a sheet where when I change a specific cell to "YES", I need a template sheet to be copied to a new version and named as per the value of a cell on the current row.
I'm having trouble working out how to get the value of the first cell in the row selected. This is what I have so far (I know this is wrong):
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var currentCell = sheet.getCurrentCell();
if (currentCell = "YES")
{
SpreadsheetApp.getActiveSpreadsheet().toast("New change control sheet added to workbook.","Change Control",15);
var sourceRow = ss.getActiveRange().getRowIndex();
var tabName = ss.getRange(cell,1).getValues();
ss.getSheetByName("CCTemplate").showSheet()
.activate();
ss.setActiveSheet(ss.getSheetByName('CCTemplate'), true);
ss.duplicateActiveSheet();
ss.setActiveSheet(ss.getSheetByName('CCTemplate'), true);
ss.getActiveSheet().hideSheet();
ss.setActiveSheet(ss.getSheetByName('Copy of CCTemplate'), true);
ss.getActiveSheet().setName("CC" & tabName);
}
}
Any ideas?
function onEdit(e) {
var sh=e.range.getSheet();
if(sh.getName()=='Your Sheet Name' && e.value=="YES") {
e.source.toast="New change control sheet added to workbook.","Change Control",15);
var tabName=sh.getRange(e.range.rowStart,1).getValue();
var tsh=e.source.getSheetByName('CCTemplate');
var csh=tsh.copyTo(e.source);
csh.setName('CC'+tabName);
}
}
You should avoid using activate in your scripts especially in simple triggers where you have to finish in 30 seconds. I think this code does the same thing that you intended for your code. One significant difference is that I use the information that comes in the event object that comes with the trigger. You should add the code Logger.log(JSON.stringify(e)) and then look at the logs you will see that there is a lot of information available to you which removes the need to run extra functions to get things like a spreadsheet.
Use event objects
onEdit offers among others the event objects range and value which are helpful to retrieve the range that has been edited and its value.
Also
When you want to a cell and compare it against a value, like in if (currentCell = "YES") - you need to retrive its value (either currentCell.getValue() or just event.value) and you need to use == instead of = for comparison.
Be careful with getValues() vs getValue(). The former gives you a 2D array and is not necessary if you want to retrieve the value of a single cell.
There is no need to set your sheet to active in order to change its name.
You can rewrite your code as following:
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var currentCell = event.range;
var value = event.value;
if (value == "YES")
{
...
var sourceRow = range.getRowIndex();
var tabName = ss.getRange(sourceRow, 1).getValue();
...
ss.getSheetByName('Copy of CCTemplate').setName("CC" + tabName);
}
}