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

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();
}

Related

How to get access new sheet, created by adding a new form to spreadsheet?

Im quite new to this thing and never had to post a question before.
Here is the situation :
I want to copy the same form over and over to the same spreadsheet('memoSs'). (original form being 'formFileSample').
I am trying to access the sheet linked to that newly added form. (form added using .setDestination()
Unfortunately that sheet is missing from the array returned by '.getSheets'!
Even though it appears in the spreadsheet 'memoSs' (checked by opening it)
I hope it is understandable with the script below.
any chance somebody might have a way in doing so?
function updateOfMemoSs() {
var memoId = 'xxxxxxxxxxxxxxxxxxxxxxxxx'
var Interface = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Interface');
var memoSs = SpreadsheetApp.openById(memoId);
var formFileSample = DriveApp.getFileById(memoSs.getSheetByName('Sample (Source)').getFormUrl().match(/[-\w]{25,}/));
var sheetsToCopy = setInstrList(); //sets a list of names for the sheets to be created
//looks like [['xxx'],['xx'],['x']]
for(var i in sheetsToCopy){
var newFormId = formFileSample.makeCopy('memo '+sheetsToCopy[i][0]).getId();
var newForm = FormApp.openById(newFormId).setDestination(FormApp.DestinationType.SPREADSHEET, memoId);
// var memoSs = SpreadsheetApp.openById(memoId); //didnt work
var sheets = memoSs.getSheets().filter(sheet => sheet.getFormUrl()); //sets a list of linked sheets
Logger.log('formIds = ');
for(var j in sheets){
Logger.log(sheets[j].getName());
Logger.log(sheets[j].getFormUrl().match(/[-\w]{25,}/));
}//returns a list that does not include the linked sheet created earlier.(even though it appears in spreadsheet)
/* for(var j in sheets){
var sheet = sheets[j];
if(sheet.getFormUrl().match(/[-\w]{25,}/) == newFormId){
var newSheet = sheet; //therefore I never find a match for newFormId
}
}*/
}
// Logger.log('newSheet = ');
// Logger.log(newSheet.getName());
}
Thanks Cooper for considering the question.
It seems i haven't been patient enough in my research as the answer had already been posted in StackOverFlow : 'getSheets() Google Apps Script multiple calls issue'
Somehow after creating a sheet.The following should be called before calling getSheets() :
SpreadsheetApp.flush()

Share drive folder to list of user from google spreadsheet

I'm trying to write a script to take a folder from my drive and share it with a list of users.
The script is scheduled to run on a sheet which collects answers from a google form and I set the trigger to run the script at every new submission of the form.
First Attempt. I think there is something wrong with how I create the array containing the list of emails, but I couldn't figure out how to fix it.
function driveShare_array() {
var getEmails =[];
var sheet= SpreadsheetApp.getActiveSheet();
var getEmails = sheet.getRange('emailstoshare').getValues(); // emailtoshare is a named range including only the one column where the sheet collects emails from the form submission
var folder = DriveApp.getFolderById('xxxx'); // added the folder ID in here
for ( i in getEmails) {
folder.addViewer(getEmails[i])
}
}
Second attempt to try to control how the array "getEmails" gets shaped by adding elements (push) one by one
function driveShare_push(){
var getEmails =[];
var sheet= SpreadsheetApp.getActiveSheet();
var range = sheet.getRange('emailstoshare'); // emailtoshare is a named range including only the one column where the sheet collects emails from the form submission
for (var i=0;i<range.getNumRows();i++){
getEmails.push(range.offset(i,0,1,1).getValue());
}
var folder = DriveApp.getFolderById('xxxx'); // added the folder ID in here
// for ( var j=0;j<range.getNumColumns();j++) {
for (var j in getEmails){
folder.addViewer(getEmails[j]) ;
}
}
Both versions (and other variations I have tested) give errors. Could someone help me understand what I'm doing wrong and how to fix it?
Thanks!!
It might be possible that the email address may not have a Google account and thus the folder could not be shared with them. You might consider adding a try/catch block to ignore such errors.
function driveShare_array() {
var getEmails =[];
var sheet= SpreadsheetApp.getActiveSheet();
var folder = DriveApp.getFolderById('xxxx');
var getEmails = sheet.getRange('emailstoshare').getValues();
getEmails.forEach(function(email) {
if (/\S+\.\S+/.test(email)) {
try {
folder.addViewer(email)
} catch (f) {
Logger.log("Cannot share with " + email);
}
}
})
}
If your triggering the function with onFormSubmit trigger then you can do something like this.
function driveShare_array(e) {
var folder=DriveApp.getFolderById('xxxx');
folder.addViewer(e.namedValues['Email Address']);
}
You will probably want to store them on some spreadsheet and retrieve them to make sure you haven’t already added it to the list. You will need to create an onFormSubmit trigger for the function in script editor Edit/Project Triggers.
Used logger.log to understand the structure of the data and the code was creating a matrix instead of an array.
Here the corrected code for reference:
function driveShare_push(){
var getEmails =[];
var sheet= SpreadsheetApp.getActiveSheet();
var range = sheet.getRange('emailstoshare');
for (var i=1;i<range.getNumRows();i++){
if(range.offset(i, 0, 1, 1).getValue().indexOf("gmail.com") > -1){
getEmails.push(range.offset(i,0,1,1).getValue());
}
}
var folder = DriveApp.getFolderById('xxxx');
folder.addViewer(getEmails[getEmails.length-1]) ;
}

Rename sheet once copied to another Spreadsheet - remove "Copy of"?

Hopefully relatively simple, but can't seem to find an answer.
I have a function that copies (archives) the current sheet to another spreadsheet, but then it's called "Copy of [sheet name]" in the destination spreadsheet.
Hoping I can get rid of the Copy of part, but setName() hasn't seemed to work.
Everything in the below code works until the last two lines.
function archiveCurrentSheet() {
SpreadsheetApp.getUi()
var areyousure = Browser.msgBox('Are you sure you want to archive this sheet?', Browser.Buttons.OK_CANCEL);
if (areyousure == "cancel" ) {
}
else {
var source = SpreadsheetApp.getActiveSpreadsheet();
var currentSheetName = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName();
var sheet = source.getActiveSheet();
var destination = SpreadsheetApp.openById("ID");
sheet.copyTo(destination);
var sheetRename = SpreadsheetApp.openById("ID").getSheets();
sheetRename.setName(currentSheetName);
}
}
It gives error: "TypeError: Cannot find function setName in object Sheet,Sheet,Sheet,Sheet,Sheet,Sheet,Sheet,Sheet."
Thanks!
p.s. bonus: would be how do I delete the current
The sheet.copyTo(destination) method returns the new sheet so you can do something like this.
sheet.copyTo(destination).setName(currentSheetName);

onEdit(e) DriveApp.getFileById

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);
};

Create a copy of a Google Sheet with Google Apps Script

I am new in google apps script. I need help for creating new spreadsheet by using existing spreadsheet and copy and sort the data into newly created spreadsheet using google apps script. Can anyone help me?
this does the trick:
function copySpreadSheet(newSpreadSheetName) {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var data = sheet.getSheetValues(1, 1, 1000, 26);
var newSheet = SpreadsheetApp.create(newSpreadSheetName)
newSheet.getSheetByName("Sheet1")
.getRange(1,1,1000,26).setValues(data);
}
function main() {
copySpreadSheet("some_Spreadsheet");
}
After executing main, you can find the new spreadsheet in your drive file list. If you want to change the range of the data that should be copied, adjust the getSheetValues() method like this: getSheetValues(startRow, startColumn, numRows, numColumns). Don't forget to do the same for the getRange method a few lines below, otherwise you will get an error.
You can use this simpler code:
function copySpreadSheet() {
var s = SpreadsheetApp.openById("id");
var destination = DriveApp.getFolderById("idOfFolder");
DriveApp.getFileById("id_ofFile").makeCopy("New name", destination);
}
This will create a copy of your file in a new destination.
The SpreadsheetApp#spreadsheet class has a method copy:
var wb = SpreadsheetApp.getActiveSpreadsheet();
var new = wb.copy("Copy of " + wb.getName());
This copy method copies the current spreadsheet and returns a reference to the new one, so additional tasks (such as removing unneeded sheets, formatting ranges, adding additional values, etc.) can be performed.