I have a Google Sheets trigger function that on form submit places submissions in sheets based on the value selected for one of my questions. I'm trying to test my function with "Test as an Add-On" feature, but when I submit a form, I receive an error within my onSubmit function with the error message No item with the given ID could be found, or you do not have permission to access it. (line 9, file "Code") from trigger formSubmit
This is the line of the error,
var form = FormApp.openById(ss.getFormUrl());
which makes me think there is an authentication issue, but I'm not sure how to debug this further
Full code:
function onSubmit(e) {
//Open Marketing - Discoveries and Changes - v1
var sheet = e.range.getSheet();
//Return Spreadsheet that contains this sheet
var ss = sheet.getParent();
//Open Marketing - Discoveries and Changes - v1
var form = FormApp.openById(ss.getFormUrl());
//Destination sheet based on "Location of Change"
var destSheet = getSheet(ss, e.namedValue['Location of Change']);
//Store response in destination sheet
destSheet.appendRow(e.values);
function getSheet( spreadsheet, sheetName, headings) {
spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName(sheetName);
if (sheet == null) {
sheet = spreadsheet.insertSheet(sheetName);
if (headings && headings.constructor === Array) {
sheet.getRange(1,1,1, headings.length).setValues([headings]);
}
}
return sheet;
}
}
The combination of openById() and ss.getFormUrl() isn't right. In the answer to Adding Tabs to Google Sheets Based on Form Response, openByUrl() was used:
var form = FormApp.openByUrl(ss.getFormUrl());
If you want to use openById(), you'll need to extract the ID from the URL. (See Easiest way to get file ID from URL on Google Apps Script.)
Related
I am trying to write an App Script that takes string data from multiple different spreadsheets (completely separate documents) and puts them all in a new spreadsheet. When I run the logger, it shows me all the data I want. I want each piece of data to show up in Column A, but when I run my script, it only puts 1 data point in the spreadsheet instead of all of them. Can someone give me some guidance? Here is my code:
function pullTogether() {
var files = DriveApp.getFolderById('Folder ID').searchFiles('title != "nothing"');
const rangeName = 'Sheet1!B2:C';
while(files.hasNext()){
var xFile = files.next();
var name = xFile.getId();
const values = Sheets.Spreadsheets.Values.get(name, rangeName).values;
for (const row in values) {
var a1 = (values[row][0]);
Logger.log(a1);
var ss = SpreadsheetApp.openById("ID of new spreadsheet"); //I have the real ID in my code
var cell = ss.getRange("A2");
cell.setValue(a1);
}
}
}
I believe your goal is as follows.
You want to retrieve the values from the column "B" of each Spreadsheet under the specific folder.
You want to put the retrieved values to the column "A" of the destination sheet.
Modification points:
About but when I run my script, it only puts 1 data point in the spreadsheet instead of all of them., when I saw your script, the retrieved value is always put to the cell "A2" of the destination sheet. I think that this might be the reason for your issue.
In your script, I thought that when the following flow is used, the process cost will become low. By this flow, your issue can be also removed.
In your situation, even when Sheets API is not used, the script might work using getValues().
When these points are reflected in your script, it becomes as follows.
Modified script:
Please set the folder ID and the destination Spreadsheet ID.
function pullTogether() {
// Retrieve values from each Spreadsheet.
var values = [];
var files = DriveApp.getFolderById('Folder ID').searchFiles(`title != 'nothing' and mimeType='${MimeType.GOOGLE_SHEETS}'`);
var sheetName = 'Sheet1'
while (files.hasNext()) {
var xFile = files.next();
var sheet = SpreadsheetApp.open(xFile).getSheetByName(sheetName);
if (sheet) {
var v = sheet.getRange("B2:B" + sheet.getLastRow()).getValues();
values = [...values, ...v];
}
}
// Put values to the destination sheet.
var ss = SpreadsheetApp.openById("ID of new spreadsheet"); //I have the real ID in my code
var dstSheet = ss.getSheets()[0];
dstSheet.getRange(2, 1, values.length, values[0].length).setValues(values);
}
Note:
Although I'm not sure about your actual situation, when the above script didn't work by the large data, please modify as follows.
From
dstSheet.getRange(2, 1, values.length, values[0].length).setValues(values);
To
Sheets.Spreadsheets.Values.update({ values }, ss.getId(), `'${dstSheet.getSheetName()}'!A2`, { valueInputOption: "USER_ENTERED" });
References:
getValues()
setValues(values)
i'm trying to call a function from the menu bar to copy a set of values in google sheets to an "archive" tab. The error i'm getting is "Exception: The parameters (SpreadsheetApp.Range) don't match the method signature for SpreadsheetApp.Range.setValues." here is the code:
function archiveCompleted () {
var spreadsheet = SpreadsheetApp.getActive();
var copyFrom = spreadsheet.getSheetByName("completed autofill");
var copyDest = spreadsheet.getSheetByName("Completed Orders");
var sourceRange = copyFrom.getRange(1,1,copyFrom.getLastRow(),copyFrom.getLastColumn());
var destRange = copyDest.getRange(copyDest.getLastRow() + 1,1,copyFrom.getLastRow(),copyFrom.getLastColumn());
//1,1,copyFrom.getLastColumn());
sourceRange.copyValuesToRange(destRange);
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Copy From Feildpine'),true);
}
thanks for any help!
I thought that about your error message of Exception: The parameters (SpreadsheetApp.Range) don't match the method signature for SpreadsheetApp.Range.setValues., unfortunately, I cannot find setValues in your showing script. So I'm worried that you miscopied your current script.
But, when I saw your script, I thought that sourceRange.copyValuesToRange(destRange); is required to be modified. Because the arguments of copyValuesToRange are gridId, column, columnEnd, row, rowEnd or sheet, column, columnEnd, row, rowEnd. Ref1, Ref2
So, in this modification, I would like to propose modifying the line as follows.
From:
sourceRange.copyValuesToRange(destRange);
To:
sourceRange.copyTo(destRange, {contentsOnly: true});
Reference:
copyTo(destination, options)
I am running a app script that works perfectly and exports a PDF from a organic sheet within a spreadsheet.
The problem is that the spreadsheet copies and throws a #REF error in all the cells.
Is there any way around this? I did see this SO question but I couldn't work my way around it. Code below:
I would assume one needs to use the range. Copy to function? but I couldn't figure it out.
// Simple function to send Weekly Status Sheets to contacts listed on the "Contacts" sheet in the MPD.
// Load a menu item called "Project Admin" with a submenu item called "Send Status"
// Running this, sends the currently open sheet, as a PDF attachment
function onOpen() {
var submenu = [{name:"Send Status", functionName:"exportSomeSheets"}];
SpreadsheetApp.getActiveSpreadsheet().addMenu('Project Admin', submenu);
}
function exportSomeSheets() {
// Set the Active Spreadsheet so we don't forget
var originalSpreadsheet = SpreadsheetApp.getActive();
// Set the message to attach to the email.
var message = "Daily Sales Snapshot"; // Could make it a pop-up perhaps, but out of wine today
// Get Project Name from Cell A1
var projectname = originalSpreadsheet.getRange("A1:A1").getValues();
// Get Reporting Period from Cell B3
var period = originalSpreadsheet.getRange("B3:B3").getValues();
// Construct the Subject Line
var subject = projectname + " - Daily Status Sheet - " + period;
// Get contact details from "Contacts" sheet and construct To: Header
// Would be nice to include "Name" as well, to make contacts look prettier, one day.
var contacts = originalSpreadsheet.getSheetByName("Contacts");
var numRows = contacts.getLastRow();
var emailTo = contacts.getRange(2, 2, numRows, 1).getValues();
// Google scripts can't export just one Sheet from a Spreadsheet
// So we have this disgusting hack
// Create a new Spreadsheet and copy the current sheet into it.
var newSpreadsheet = SpreadsheetApp.create("Spreadsheet to export");
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var projectname = SpreadsheetApp.getActiveSpreadsheet();
sheet = originalSpreadsheet.getActiveSheet();
sheet.copyTo(newSpreadsheet);
//create temp sheet that lets us copy the values
sheet = originalSpreadsheet.getActiveSheet();
var temp = originalSpreadsheet.duplicateActiveSheet();
//copy the values
range = temp.getDataRange();
range.copyTo(range, {contentsOnly: true});
//copy the values to a new spreadsheet
temp.copyTo(newSpreadsheet);
//delete our temp sheet.
ss.deleteSheet(temp);
// Find and delete the default "Sheet 1", after the copy to avoid triggering an apocalypse
newSpreadsheet.getSheetByName('Sheet1').activate();
newSpreadsheet.deleteActiveSheet();
// Make zee PDF, currently called "Weekly status.pdf"
// When I'm smart, filename will include a date and project name
var pdf = DriveApp.getFileById(newSpreadsheet.getId()).getAs('application/pdf').getBytes();
var attach = {fileName:'Daily Status.pdf',content:pdf, mimeType:'application/pdf'};
// Send the freshly constructed email
MailApp.sendEmail(emailTo, subject, message, {attachments:[attach]});
// Delete the wasted sheet we created, so our Drive stays tidy.
DriveApp.getFileById(newSpreadsheet.getId()).setTrashed(true);
}
This worked for me if any unfortunate soul lands on this page.
// Simple function to send Weekly Status Sheets to contacts listed on the "Contacts" sheet in the MPD.
// Load a menu item called "Project Admin" with a submenu item called "Send Status"
// Running this, sends the currently open sheet, as a PDF attachment
function onOpen() {
var submenu = [{name:"Send Status", functionName:"exportSomeSheets"}];
SpreadsheetApp.getActiveSpreadsheet().addMenu('Project Admin', submenu);
}
function exportSomeSheets() {
// Set the Active Spreadsheet so we don't forget
var originalSpreadsheet = SpreadsheetApp.getActive();
// Set the message to attach to the email.
var message = "Daily Sales Snapshot"; // Could make it a pop-up perhaps, but out of wine today
// Get Project Name from Cell A1
var projectname = originalSpreadsheet.getRange("H1:H1").getValues();
// Get Reporting Period from Cell B3
var period = originalSpreadsheet.getRange("B3:B3").getValues();
// Construct the Subject Line
var subject = projectname + " - Daily Status Sheet - " + period;
// Get contact details from "Contacts" sheet and construct To: Header
// Would be nice to include "Name" as well, to make contacts look prettier, one day.
var contacts = originalSpreadsheet.getSheetByName("Contacts");
var numRows = contacts.getLastRow();
var emailTo = contacts.getRange(2, 2, numRows, 1).getValues();
// Google scripts can't export just one Sheet from a Spreadsheet
// So we have this disgusting hack
var newSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheets = newSpreadsheet.getSheets;
for (var i = 5; i < sheets.length; i++) {
if (sheets[i].getSheetName() != sheetName) {
sheet[i].hideSheet();
}
}
// Make zee PDF, currently called "Weekly status.pdf"
// When I'm smart, filename will include a date and project name
var pdf = DriveApp.getFileById(newSpreadsheet.getId()).getAs('application/pdf').getBytes();
var attach = {fileName:'Daily Status.pdf',content:pdf, mimeType:'application/pdf'};
// Send the freshly constructed email
MailApp.sendEmail(emailTo, subject, message, {attachments:[attach]});
}
I'm stuck on this web form after submitting. The below code worked in a previous web form I created with the help of Serge and a few others here some time ago. I'm attempting to re-purpose the code to make a PTO request web form. Right now, when submitting it spits out a "unexpected error encountered error and I'm lost on attempting to locate the issue. I'm thinking it may be how I've added panels together and their relationship? This is a work in progress, so i know clickhandlers will be added to provide response after submit etc. At the moment I'm looking to make sure it's passing entries in form to the spreadsheet. Thanks for any assistance.
//Setting the spreadshet ID and style of the form
var submissionSSkey = 'PUT YOUR KEY HERE'
var PanelStyle = {'background':'#c0d6e4','padding':'40px','borderStyle':'ridge','borderWidth':'15PX','borderColor':'#31698a'}
// Script-as-app template.
function doGet(e) {
//Creating the Appplication
var app = UiApp.createApplication();
//Creating panels to house the web form, instructional text, data pickers and setting style
var vertPanel = app.createVerticalPanel().setTitle('XYX Company PTO Request Form').setStyleAttributes(PanelStyle).setPixelSize(350,250);
var mainPanel = app.createFormPanel().setPixelSize(350,150);
var grid = app.createGrid(4,4).setId('ptogrid');
var ptoStart = app.createDateBox().setWidth('200').setName('ptoStartDate');
var ptoEnd = app.createDateBox().setWidth('200').setName('ptoEndDate');
var submitButton = app.createSubmitButton('<B>Submit</B>');
//Assigning widgets to the grid for positioning
grid.setText(1, 0, 'PTO Start Date')
.setWidget(1, 1, ptoStart)
.setText(2, 0, "PTO End Date")
.setWidget(2, 1, ptoEnd)
.setText(3, 0, '')
.setWidget(3, 1, submitButton)
//Instructions for completion of the PTO form by users.
vertPanel.add(app.createHTML("<b>PTO Request Form</b>"));
vertPanel.add(mainPanel);
vertPanel.add(app.createHTML("<br><b>Instructions:</b></br>" +
"<p>Select the starting date and the ending date for your PTO request. "+
"If you are taking a single day of PTO enter the starting and ending date as the same date. "+
"Click Submit once you've enter the dates. A request will be sent to your manager for reivew / approval.</p>"));
//Grabbing active users session information in order to look up user group assignment and manager
var employee = Session.getActiveUser().getEmail();
//Uses the UserManager class to get info by passing in the getActive user from base class
var userFirst = UserManager.getUser(Session.getActiveUser()).getGivenName();
var userLast = UserManager.getUser(Session.getActiveUser()).getFamilyName();
var wholeName = userFirst +" "+ userLast;
mainPanel.add(grid);
app.add(vertPanel);
return app;
}
function doPost(e) {
var app = UiApp.getActiveApplication();
var ptoStart = e.parameter.ptoStartDate;
var ptoEnd = e.parameter.ptoEndDate;
//var wholeName = e.parameter;
var timeStamp = new Date();
//Access spreadsheet store values
var sheet = SpreadsheetApp.openById(submissionSSkey).getSheetByName('PTO Requests');
var lastRow = sheet.getLastRow();
var targetRange = sheet.getRange(lastRow+1, 1, 1, 11).setValues([[timeStamp,ptoStart,ptoEnd]]);
app.close();
return app;
}
I'm pretty sure the error comes from the spreadsheet ID, the sheet name or the range definition, please double check these parameters and see if it solves the issue.
I checked on my account with wrong values and it generated the same issue you have, it works as expected with correct values.
Edit: your comment seems to confirm that...( didn't see it when I answered...)
Note: the error was easy to find by looking at the execution transcript in the script editor UI, it would even give you the line of code where the error occured.
I have edited a script I found to Email a PDF created from the spreadhseet to recipients in the spreadsheet. It is working as I need it to however I need to delete some of the cells before the PDF is created. What would the correct code be to add in to delete from row 194 or cells a194:j200. Code attached below.
Thanks for your help
// Simple function to send Weekly Schedule Sheets to contacts listed on the "Tutors" sheet in the Spreadsheet.
// Load a menu item called "Admin Tasks" with a submenu item called "Email Schedule"
// Running this, sends the currently open sheet, as a PDF attachment
function onOpen() {
var submenu = [{name:"Email Schedule", functionName:"tempsheet"}];
SpreadsheetApp.getActiveSpreadsheet().addMenu('Admin Tasks', submenu);
}
function tempsheet() {
// Set the Active Spreadsheet so we don't forget
var originalSpreadsheet = SpreadsheetApp.getActive();
// Set the message to attach to the email.
var message = "Please find weekly schedule attached. Contact office for any changes as soon as possible";
// Get Project Name from Cell A1
var projectname = originalSpreadsheet.getRange("A1:A1").getValues();
// Get Reporting Period from Cell B3
var period = originalSpreadsheet.getRange("F2:F2").getValues();
// Construct the Subject Line
var subject = projectname + " - Weekly Schedule Sheet - " + period;
// Get contact details from "Tutors" sheet and construct To: Header
var contacts = originalSpreadsheet.getSheetByName("Tutors");
var numRows = contacts.getLastRow();
var emailTo = contacts.getRange(2, 5, numRows, 1).getValues();
// Create a new Spreadsheet and copy the current sheet into it.
var newSpreadsheet = SpreadsheetApp.create("Temporary Schedule");
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var projectname = SpreadsheetApp.getActiveSpreadsheet();
sheet = originalSpreadsheet.getActiveSheet();
sheet.copyTo(newSpreadsheet);
// Make PDF, currently called "Weekly Schedule.pdf"
var pdf = DocsList.getFileById(newSpreadsheet.getId()).getAs('application/pdf').getBytes();
var attach = {fileName:'Weekly Schedule.pdf',content:pdf, mimeType:'application/pdf'};
// Send the freshly constructed email
MailApp.sendEmail(emailTo, subject, message, {attachments:[attach]});
// Find and delete the default "Sheet 1", after the copy
newSpreadsheet.getSheetByName('copy of MASTERPLAN').activate();
newSpreadsheet.deleteActiveSheet();
// Delete the temporary sheet
DocsList.getFileById(newSpreadsheet.getId()).setTrashed(true);
}
Following should work to clear A194:J200
var range = sheet.getRange(194,1,7,10);
range.clear();