Exception: Invalid argument for variable in Google Apps Script - google-apps-script

I am trying to link a Google Sheets file with a Google Doc file and replace the text of the Google Docs with some custom items.
Exception: Invalid argument: sheet
autoFillGoogleDocFromForm # Code.gs:5
This error is generated by the following code. I used (name of sheet), (file id inserted), (folder id inserted) instead of showing the actual values.
function autoFillGoogleDocFromForm(e) {
var activateSheet = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSheet(activateSheet.getSheetByName('(name of sheet)'));
var sheet = SpreadsheetApp.getActiveSheet();
var row = e.range.getRowIndex();
var timestamp = sheet.getRange(row, 1).getValues();
var file = DriveApp.getFileById('(file id inserted)');
var folder = DriveApp.getFolderById('(folder id inserted)');
var copy = file.makeCopy('' + timestamp, folder);
var doc = DocumentApp.openById(copy.getId());
var header = doc.getHeader();
header.replaceText('{{TIMESTAMP}}', timestamp);
doc.saveAndClose();
}

You can simplify the way you define a Sheet:
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getSheetByName('name of the sheet')
Even if you are not going to use the Spreadsheet object any more, you can directly define the Sheet object
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('name of the sheet')
Make sure you write the name of the sheet properly.

Related

Import CSV data into Google sheet by NAME using Google Script - error Sheet is not defined

Please help - I am trying to create a Google script where I can automatically have a csv file that is emailed to me every day be imported into a google sheet by name so that way I can write another script to have a different csv file from a different daily email be imported into the same active google sheet by a different name (i.e. have 2 different sheets by 2 different names in the same Google Active Sheet).
This is my code below but it gives me the ReferenceError: Sheet is not defined for line 8
function importCSVFromGmail() {
var threads = GmailApp.search("Your Aesop Report is Ready (FC Employee Assignment & Demographic)"); // enter search criteria here
var message = threads[0].getMessages()[0];
var attachment = message.getAttachments()[0];
var sheet = SpreadsheetApp.getActiveSpreadsheet(); // runs in the current active sheet
var sheet1 = Sheet.getSheetByName('FC Employee Assignment & Demographic');
var csvData = Utilities.parseCsv(attachment.getDataAsString(), ",");
sheet.clearContents().clearFormats(); // clears target sheet
sheet1.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
GmailApp.markMessagesRead
}
Try this:
function importCSVFromGmail() {
var threads = GmailApp.search("Your Aesop Report is Ready (FC Employee Assignment & Demographic)");
var message = threads[0].getMessages()[0];
var attachment = message.getAttachments()[0];
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName('FC Employee Assignment & Demographic');
var csvData = Utilities.parseCsv(attachment.copyBlob().getDataAsString(), ",");
sheet1.clearContents().clearFormats();
sheet1.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
GmailApp.markMessagesRead(threads[0].getMessages()[0]);
}

Script To Write Auto-Gen'd Google Doc URL To Spreadsheet

I have a Google Form that does two things upon hitting the Submit button. First, it dumps that data into a Spreadsheet, then it autofills a Google Doc Template with the info from the Form.
In my script to autofill the Google Doc, I've grabbed the URL for the Google Doc. But I need to write this URL into the last row of Column J in my Google Sheet. Correction: using the getActiveSheet functions are fine, I forgot this script is running from the (Active) Google Sheet (apologies!).
Can anyone assist with this? Here's a snippet of the script to get the URL:
function autoFillGoogleDocFromForm(e) {
//e.values is an array of form values
var TimeStamp = e.values[0];
var Technician = e.values[1];
var Vendor = e.values[2];
var xxx = e.values[3];
var yyy = e.values[4];
var SerialNumber = e.values[5];
var AssetTag = e.values[6];
var TicketNumber = e.values[7];
var HostName = e.values[8];
var DocumentLink = e.values[9];
var Return = e.values[10];
var Platform = e.values[11];
var Summary = e.values[12];
var URL = "";
//file is the template file, and you get it by ID
var file = DriveApp.getFileById('aaa');
//Put auto filled Google Doc into the appropriate Vendor Folder
//file.makeCopy will return a Google Drive file object
if (Vendor == "111") {
var folder = DriveApp.getFolderById('bbb')
var copy = file.makeCopy(TicketNumber + ' - ' + SerialNumber, folder);
}
if (Vendor == "222") {
var folder = DriveApp.getFolderById('ccc')
var copy = file.makeCopy(TicketNumber + ' - ' + SerialNumber, folder);
}
if (Vendor == "333") {
var folder = DriveApp.getFolderById('ddd')
var copy = file.makeCopy(TicketNumber + ' - ' + SerialNumber, folder);
}
//Once we've got the new file created, we need to open it as a document by using its ID
var doc = DocumentApp.openById(copy.getId());
//Get the url of the newly created Google Doc
var url = doc.getUrl();
//Script to write this URL into the Shared Google Sheet will go here
//Since everything we need to change is in the body, we need to get that
var body = doc.getBody();
//Then we call all of our replaceText methods
body.replaceText('{{EmailAddress}}', Technician);
body.replaceText('{{TicketNumber}}', TicketNumber);
body.replaceText('{{HostName}}', HostName);
body.replaceText('{{SerialNumber}}', SerialNumber);
body.replaceText('{{AssetTag}}', AssetTag);
body.replaceText('{{Summary}}', Summary);
body.replaceText('{{Vendor}}', Vendor);
body.replaceText('{{URL}}', url);
//Lastly we save and close the document to persist our changes
doc.saveAndClose();
Thanks in advance!
From your following situation in your question,
Also this is a shared Google Sheet, so I can't use the getActiveSheet function, I'd need to reference the Google Sheet URL, I believe.
If you have the permission to write the values to the shared Google Spreadsheet, how about the following modification?
From:
var url = doc.getUrl();
//Script to write this URL into the Shared Google Sheet will go here
To:
var url = doc.getUrl();
//Script to write this URL into the Shared Google Sheet will go here
var sheet = SpreadsheetApp.openById("### Spreadsheet ID ###").getSheetByName("### sheet name ###");
sheet.appendRow([url]);
In this modification, please set the Spredsheet ID and sheet name. By this, the value of url is appended to the next row of the last row of the sheet in the Google Spreadsheet.
If you want to use the Spreadsheet URL instead of Spreadsheet ID, please modify openById("### Spreadsheet ID ###") to openByUrl("### Spreadsheet URL ###").
References:
openById(id)
openByUrl(url)
appendRow(rowContents)
Edit:
From the following replying,
That doesn't seem to work to insert the URL into the last row of column J unfortunately. It looks like this script can use the Active Sheet afterall, I'll edit the OP.
In this case, how about the following modification?
From:
var url = doc.getUrl();
//Script to write this URL into the Shared Google Sheet will go here
To:
var url = doc.getUrl();
//Script to write this URL into the Shared Google Sheet will go here
// var sheet = SpreadsheetApp.openById("### Spreadsheet ID ###").getSheetByName("### sheet name ###");
var sheet = SpreadsheetApp.getActiveSheet(); // or SpreadsheetApp.getActiveSpreadsheet().getSheetByName("sheetname")
sheet.getRange("J" + (sheet.getLastRow() + 1)).setValue(url);
Or
var url = doc.getUrl();
//Script to write this URL into the Shared Google Sheet will go here
// This is from https://stackoverflow.com/a/44563639/7108653
Object.prototype.get1stEmptyRowFromTop = function (columnNumber, offsetRow = 1) {
const range = this.getRange(offsetRow, columnNumber, 2);
const values = range.getDisplayValues();
if (values[0][0] && values[1][0]) {
return range.getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow() + 1;
} else if (values[0][0] && !values[1][0]) {
return offsetRow + 1;
}
return offsetRow;
};
// var sheet = SpreadsheetApp.openById("### Spreadsheet ID ###").getSheetByName("### sheet name ###");
var sheet = SpreadsheetApp.getActiveSheet(); // or SpreadsheetApp.getActiveSpreadsheet().getSheetByName("sheetname")
sheet.getRange("J" + sheet.get1stEmptyRowFromTop(10)).setValue(url);
Suggestion:
If you need to write the URL value into the last row of Column J in a shared Google Spreadsheet file, you can try this sample below:
function sample() {
var ss = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/SHEET_ID_IS_HERE/edit#gid=0');
var sheet = ss.getSheets()[0]; // access first sheet
var activeSheet = ss.setActiveSheet(sheet);
//Sample setValue() action to the shared sheet file
activeSheet.getRange("A1").setValue("URL");
}
NOTE: You would need to have an editor permission on the Shared Google Sheet file that you're accessing
References:
openByUrl(url)
getSheets()
setActiveSheet(sheet)
Here's the code that ended up working for me.
//Get the url of the newly created Google Doc
var url = doc.getUrl();
// var sheet = SpreadsheetApp.openById("### Spreadsheet ID ###").getSheetByName("### sheet name ###");
var sheet = SpreadsheetApp.getActiveSheet(); // or SpreadsheetApp.getActiveSpreadsheet().getSheetByName("sheetname")
sheet.getRange("J" + (sheet.getLastRow())).setValue(url);

Copy Value from a Spreadsheet to another based on a Template

With this script ( Generate new spreadsheet from a selected row based on template ) I can generate a new spreadsheet (and so not a tab), based on a template tab (in this case, the tab "xxx") only when I select a specific row and rename this Spreadsheet as the value in the cell in column B for that corresponding row.
Now, I would copy the value of the cell A2 from the source spreadsheet into the tab "xxx" in the cell A3.
How to do that?
function onOpen() {
SpreadsheetApp.getUi().createMenu('Genera Scheda')
.addItem('Genera Scheda', 'createSpreadsheet')
.addToUi()}
function createSpreadsheet() {
var ss = SpreadsheetApp.getActive();
// the following line means that the function will search for the spreadsheet name in the active sheet, no matter which one it is
var sheet = ss.getActiveSheet();
//the selected row
var row = sheet.getActiveCell().getRow();
// column 2 corresponds to "B"
var name = sheet.getRange(row, 2).getValue();
var templateSheet1 = ss.getSheetByName('xxx');
var templateSheet2 = ss.getSheetByName('xxx2');
var newSpreadsheet = SpreadsheetApp.create(name);
var fileId = newSpreadsheet.getId();
var file = DriveApp.getFileById(fileId);
var folderId ="-----";
var folder = DriveApp.getFolderById(folderId);
templateSheet1.copyTo(newSpreadsheet).setName("Scheda");
templateSheet2.copyTo(newSpreadsheet).setName("Import")
newSpreadsheet.deleteSheet(newSpreadsheet.getSheetByName("Foglio1"));
folder.addFile(file);
DriveApp.getRootFolder().removeFile(file);
}
To copy individual cell values between tabs and spreadsheets, a good solution is to use getValue() and setValue()
This methods must be applied to range objects (that is the cells).
Sample:
...
// define sheet either as the active sheet or specify it with sheet = ss.getSheetByName("XXX");
var myValue = sheet.getRange("A2").getValue();
newSpreadsheet.getSheetByName("xxx").getRange("A3").setValue(myValue);
...
Note that if you want to get / set values of more than one cell simulataneously, you need to use getValues() and setValues() instead.
UPDATE
Full code based on your situation:
function onOpen() {
SpreadsheetApp.getUi().createMenu('Genera Scheda')
.addItem('Genera Scheda', 'createSpreadsheet')
.addToUi()}
function createSpreadsheet() {
var ss = SpreadsheetApp.getActive();
// the following line means that the function will search for the spreadsheet name in the active sheet, no matter which one it is
var sheet = ss.getActiveSheet();
//the selected row
var row = sheet.getActiveCell().getRow();
// column 2 corresponds to "B"
var name = sheet.getRange(row, 2).getValue();
var templateSheet1 = ss.getSheetByName('xxx');
var templateSheet2 = ss.getSheetByName('xxx2');
var newSpreadsheet = SpreadsheetApp.create(name);
var fileId = newSpreadsheet.getId();
var file = DriveApp.getFileById(fileId);
var folderId ="-----";
var folder = DriveApp.getFolderById(folderId);
templateSheet1.copyTo(newSpreadsheet).setName("Scheda");
templateSheet2.copyTo(newSpreadsheet).setName("Import")
var myValue = sheet.getRange("A2").getValue();
newSpreadsheet.getSheetByName("Scheda").getRange("A3").setValue(myValue);
newSpreadsheet.deleteSheet(newSpreadsheet.getSheetByName("Foglio1"));
folder.addFile(file);
DriveApp.getRootFolder().removeFile(file);
}

Trying to delete named external sheets from a container script

My first time scripting, I'm trying to create an order sheet for outside sales reps, that they can fill out, and click a button to submit a template file. Sheets 0 & 1 are survey questions that fill in references on sheet 2 (Final Product). Sheets 3 & 4 are data validation fields for sheets 0 & 1 including email addresses for recipients.
I am trying to copy a spreadsheet to a new spreadsheet, --> converting a specific sheet from the copy to text so that I can delete all sheets except the converted sheet and not get reference errors --> email converted sheet via pdf format to contacts on sheet 3. My code does it all except delete the 4 sheets that I want to(0,1,3,4). The script is a container script, so whenever I try to call SpreadsheetApp.getActiveSpreadsheet(); It automatically grabs the container file and deletes the 'template' sheets. I need to know how to delete indexes 0,1,3,4 of an external spreadsheet, in a different folder of my drive.
The code below is a hodgepodge of snippets I have butchered and pieced together.
I hope you can understand all of this.
Here is what I have:
function SubmitOnClicks() {
// Set the Active Spreadsheet so we don't forget
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var orderSheet = ss.getSheetByName("Order Sheet");
var ValidationRef = ss.getSheetByName("Validation References");
orderSheet.activate();
// Set the message to attach to the email.
var message = "Please see attached";
// Get Project Name from Range B3:D3
var projectname = ss.getRange("B3").getValues();
// Get BFS Size from Range C25:E25
var size = ss.getRange("C25:E25").getValues();
// Construct the Subject Line
var subject = projectname + " " + size;
// Get contact details from "Validation References" sheet and construct To: Field
var numRows = ValidationRef.getLastRow();
var emailTo = ValidationRef.getRange(2, 12, 5, 2).getValues();
// Google scripts can't export just one Sheet that I know of
var submittalDate = orderSheet.getRange(17, 2).getValues();
var submittalName = "BFS Submittal"
var folderID = "My Drive Folder ID"; // Folder id to save Copy to: MyDrive/_Sheets/Shared/BFS Exports
var folder = DriveApp.getFolderById(folderID);
var sourceSheet = ss.getSheetByName("Order Sheet");
var sourceRange = sourceSheet.getRange(1,1,sourceSheet.getMaxRows(),sourceSheet.getMaxColumns());
var sourcevalues = sourceRange.getValues();
var destSpreadsheet = SpreadsheetApp.open(DriveApp.getFileById(ss.getId()).makeCopy(submittalName, folder))
var destSheet = destSpreadsheet.getSheets()[2];
var destRange = destSheet.getRange(1, 1, destSheet.getMaxRows(), destSheet.getMaxColumns());
// Replace cell values with text (to avoid broken references)
destRange.setValues(sourcevalues);
var files = DriveApp.searchFiles(
'mimeType = "BFS Submittal' + MimeType.GOOGLE_SHEETS + '"');
while (files.hasNext()) {
var spreadsheet = SpreadsheetApp.open(files.next()); //I'm stuck after this Line
var sheet = spreadsheet.getSheets()[0, 1, 3, 4];
}
// Make the PDF, currently called "BFS Submittal.pdf"
var pdf = DriveApp.getFileById(ss.getId()).getAs('application/pdf').getBytes();
var attach = {fileName:'BFS Submittal',content:pdf, mimeType:'application/pdf'};
// Send the freshly constructed email
MailApp.sendEmail(emailTo, subject, message, {attachments:[attach]});
}

google script access spreadsheet by ss name

I am scraping a few pages every day and need to create a new google sheet in order to put the scraped data in it.
I am looping through the pages and if it is the first page, I create a new ss with the date as a name.
Then for subsequent pages, I am trying to get this same page by name reference in order to add the data from page 2,3,...
Here is the code:
if(start==1){
// Create new ss in current folder
var ss = SpreadsheetApp.create(full_d);
var id = ss.getId();
var file = DriveApp.getFileById(id);
var folder = DriveApp.getFolderById('ABC');
folder.addFile(file);
DriveApp.getRootFolder().removeFile(file);
}else{
var ss = SpreadsheetApp.getSheetByName(full_d);
}
ss.getRange(ss.getLastRow() + 1, 1, res.length, res[0].length).setValues(res);
If I delete the if statement and just put var ss = Spreadsheet.getActiveSheet(), my code works.
Thanks
How about this modification?
Modification points :
The sheet in the created Spreadsheet using getSheets() was given.
When start is not 1, an error occurs at var ss = SpreadsheetApp.getSheetByName(full_d);. So it was modified that the spreadsheet with the filename of full_d is opened.
The scope of ss was considered. But in GAS, this may not be a problem.
Modified script :
var ss; // <--- Added
if(start==1){
// Create new ss in current folder
ss = SpreadsheetApp.create(full_d);
var id = ss.getId();
var file = DriveApp.getFileById(id);
var folder = DriveApp.getFolderById('ABC');
folder.addFile(file);
DriveApp.getRootFolder().removeFile(file);
ss = ss.getSheets()[0]; // <--- Added
}else{
var file = DriveApp.getFilesByName(full_d).next(); // <--- Added
ss = SpreadsheetApp.open(file).getSheets()[0]; // <--- Added
}
ss.getRange(ss.getLastRow() + 1, 1, res.length, res[0].length).setValues(res);
If I misunderstand your question, I'm sorry. At that time, please tell me.