I am doing a program in which I would like to press a button and be able to send by email the information of two specific sheets as attachments in PDF, which I would also like to save it in a folder in my Drive to keep the information organize
I have checked some of your information but can't do the PDF part
function sendEmail(){
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var ss = spreadsheet.getActiveSheet()
var NoInf =ss.getRange(10, 11).getValue();
var Email = ss.getRange(12, 15).getValue();
var propietario = ss.getRange(10, 7).getValue();
var Paciente = ss.getRange(11,7).getValue();
var TipoInforme = ss.getSheetName()
var Imagen = spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Imagenes'),true);
var Asunto = NoInf + " - " + TipoInforme + " - " + propietario + " - " +Paciente;
var Mensaje = "Anexo a la presente envĂo informe: " + '\n\n' + "No de Informe: " + NoInf;
MailApp.sendEmail(Email, Asunto, Mensaje)
};
Based on your last comment I understand that you want to send two Sheets as PDF in an email attachment. If that is correct, then you can use a code like the following one.
function sendMail() {
var spreadsheet1 = DriveApp.getFileById(
'{MY FIRST SPREADSHEET ID}');
var spreadsheet2 = DriveApp.getFileById(
'{MY SECOND SPREADSHEET ID}');
MailApp.sendEmail('{EMAIL TO}', '{EMAIL SUBJECT}',
'{MESSAGE BODY}', {
name: '{MY NAME}',
attachments: [spreadsheet1.getAs(MimeType.PDF), spreadsheet2.getAs(
MimeType.PDF)]
});
}
In this example the Sheets are opened by DriveApp.getFileById() and later attached as PDF by using File.getAs(). Please, don't hesitate to ask me to further clarify.
Related
Im currently taking charts from the 2nd tab of my google sheet to embed them into an email using appscript. I was wanting to know how can I make the position of the charts permanent within the email as the images move depending on the size of the browser window. please see my current script and associated images.
function emailChartSource(){
const sheet = SpreadsheetApp.getActiveSpreadsheet();
const sheetName = sheet.getSheetByName('At a Glance');
const charts = sheetName.getCharts();
var bodyEmail = "Hi Team,<br> Below is an overview of the testing efforts for UAT Wireless<br>"
var currentDate = Utilities.formatDate(new Date(), 'America/Denver', 'M/d/yy');
var imgcontainer = {};
var bodyCharts = "";
var chartcount = charts.length
for(var chartNo=0; chartNo <=chartcount-1;chartNo++){
var img = charts[chartNo].getAs("image/png")
imgcontainer["chart" + (chartNo+1)]=img
bodyCharts = bodyCharts + "<img src='cid:chart" + (chartNo+1)+"'>";
}
bodyEmail = bodyEmail + bodyCharts;
MailApp.sendEmail({
to: "someemail#gmail.com",
subject: "UAT Wireless Testing Status Report as of " + currentDate + " - Boost Prepaid",
htmlBody: bodyEmail,
inlineImages: imgcontainer,
});
}
Incorrect Display
How I would like it to display
I'd previously written a script for a google sheet that triggered when its related google form had a form submitted. When the form was submitted, a PDF would generate and be emailed to the designated person. I created a new version to auto-generate a Digital Millennium Copyright Act notice, but something seems to not work with the script anymore (the original isn't working anymore either) and I can't figure out how to fix it.
The error I'm getting is TypeError: Cannot read property 'range' of undefined (line 2, file "Code")
9/28/2021 I added console.log(rg.getA1Notation()) to the code as instructed and submitted a form. The Execution log for it shows me the below -
Code below -
const rg = e.range;
console.log(rg.getA1Notation());
const sh = rg.getSheet();
//Get all the form submitted data
const Email= e.namedValues['Email Address'][0];
const LinkOrig = e.namedValues['Link(s) for where the original work appears'][0];
const AttachOrig = e.namedValues['Copies of the original copyrighted work'][0];
const Domain = e.namedValues['Infringing Domain'][0];
const LinkInfring = e.namedValues['Link(s) for where infringing image appears online'][0];
const Contact = e.namedValues['Contact Information'][0];
const WHOIS = e.namedValues['WHOIS Search results'][0];
const Date = e.namedValues['Date'][0];
const Location = e.namedValues['Where are you based?'][0];
//Build a new DMCA Form from the template
//Folder ID (save destination) and file IDs (template ID + new doc ID)
const DMCAFolderID = 'googledrivefolderidhere';
const DMCALibFolder = DriveApp.getFolderById(DMCAFolderID);
const TemplateFileID = 'googledrivetemplateidhere';
const newFilename = 'DMCA Notice -' + TemplateFileID + 'Domain';
//Make a copy of the template file
const newTemplateFileID = DriveApp.getFileById(TemplateFileID).makeCopy(newFilename, DMCALibFolder).getId();;
//Get the DMCA Notice body into a variable
var document = DocumentApp.openById(newTemplateFileID);
var body = document.getBody();
//Replace all the {{ }} text in the BlinkLib body
body.replaceText('{{LinkOrig}}', LinkOrig);
// body.replaceText('{{AttachOrig}}', AttachOrig);
body.replaceText('{{LinkInfring}}', LinkInfring);
body.replaceText('{{ContactInfo}}', Contact);
body.replaceText('{{WHOISResults}}', WHOIS);
body.replaceText('{{date}}', Date);
body.replaceText('{{location}}', Location);
document.saveAndClose();
// define email variables
var subject = 'DMCA Notice - ' + Domain;
var msgHtml =
"Hi " + Name + "," + "<br/>" + "<br/>" +
"Please find your DMCA Notice attached." + "<br/>" + "<br/>" +
"Sincerely," + "<br/>" +
"Your Bada** Self" + "<br/>"
;
var attachment = DriveApp.getFileById(newTemplateFileID);
//send email with the file
GmailApp.sendEmail(Email, subject, msgHtml, {htmlBody: msgHtml, attachments: [attachment.getAs(MimeType.PDF)]});
} ```
Cannot read property 'range' of undefined indicates that you are trying to run your code manually
However, const rg = e.range; indicates that you are retrieving the range as an event object - which can be retrieved only when a trigger fires
Summary:
When using event objects like e.range you cannot run your code manually, you need to let the execution be triggered automatically. This implies that your funciton is being called on a trigger - e.g. an onEdit trigger.
This is my first post so apologies in advance if I am posting to the wrong place or asking a question that has been answered elsewhere - go easy on me!
In a nutshell, I have a Google Form and a connected Google Sheet. I need to automate it so that, when a new form is submitted, an email is sent to a specific colleague (the student's supervisor). I have had a good go myself but am now totally stuck!
I have created the form, linked it to a sheet, written the code, added the trigger and tested by submitting a form. Nothing happened! No error messages, just... nothing!
Any advice hugely appreciated. I am very new to this and still taking baby steps.
The code I have cobbled together (which is probably full of errors!) is as follows:
function wa132657(e) {
//setup the spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
//get the range from OnFormSubmit
var range = e.range;
Logger.log("DEBUG: the range is "+range.getA1Notation());//DEBUG
// get the data for the range
var response = row.getValues();
// get the supervisor name from the form submission
var supervisor = response[0][1];
Logger.log("DEBUG: Supervisor = "+supervisor);// DEBUG
// get the emails list
var emailSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SupEmails");
// get ALL the data from this sheet
var emaildata = emailSheet.getDataRange().getValues();
// check how many rows of data
var emailLastRow = emailSheet.getLastRow();
// start the loop through the emails data
for (var i=1; i<emailLastRow; i++){
// if the supervisor is equal to SupervisorEmail
if (supervisor == emaildata[i][0]){
// there is a match
//Next, get the email address
var emailSupervisor = emaildata[i][1];
Logger.log("DEBUG: supervisor = "+emaildata[i][0]+", email address: "+emailSupervisor);// DEBUG
// Finally, send the Email.
var theirName = e.values[2];
var theirProgramme = e.values[3];
var theAbsenceReason = e.values[8];
var theAbsenceStart = e.values[5];
var theAbsenceEnd = e.values[6];
var subject = "Student Absence Report";
var message = "New Absence Report: " + theirName + " \n Programme: " + theirProgramme; + " \n\n
Reason for Absence: \n" + theAbsenceReason + " \n Start of Absence" + theAbsenceStart + "\n End of Absence:" + theAbsenceEnd;
MailApp.sendEmail(emailSupervisor, subject, message);
}
}
}
I have applied this solution to e-mail the rows of a google sheet as part of the HTML body.
Unfortunately, it errors out because there is a limit set on the HTML body. The number of rows in my data is dynamic.
Limit Exceeded: Email Body Size. (line 209, file "SideBar")
Is there a way of getting around this? I would be OK with providing a preview of the rows, let's say 10 rows with all columns, on the HTML body and then providing a link to view the rest. Because the content on the sheet changes, the link should not be to that sheet. Instead I was thinking of saving a copy of the sheet as a new file on their own drive and linking to that. Another option is attaching an HTML file that has all the rows.
Here is what I currently have:
function emailBreakdown(emailUser, bodyAdd){
SpreadsheetApp.getActiveSpreadsheet().toast('Please wait while information is refreshed.');
if(emailUser == null){emailUser = 'xxxxx#yyyyyy.com'}
if(bodyAdd == null){bodyAdd = 'Testing running of function on script editor'}
var ss = SpreadsheetApp.getActive();
var detailsSht = ss.getSheetByName("Details");
var dataRange = detailsSht.getDataRange();
var curDate = Utilities.formatDate(new Date(), "GMT+1", "MM/dd/yyyy");
var subject = 'Summary - Exported Data ' + curDate;
var body = '<br />---------------------------------------------------------------<br />You have received an export of a dataset from the Summary dashboard. Please see below:<br /><br />' //provide link to the whole dashboard.
convSheetAndEmail(dataRange, emailUser, body, bodyAdd, subject);
}
function convSheetAndEmail(rng, emailUser, body, bodyAdd, subject){
var HTML = SheetConverter.convertRange2html(rng);
MailApp.sendEmail(emailUser, subject, '', {htmlBody : bodyAdd + body + HTML});
}
The following is code I've been able to assemble through further research. It works well and addresses my requests. Here is what it does:
Attaches a sheet. In this case an xls file. Chose this over HTML. To allow user to manipulate in excel if needed.
Provides a preview of 10 lines as HTML in the body of the e-mail.
Preview and attached file preserves format.
What it does not address:
Save file to user's personal drive.
Here it goes:
function emailBreakdown(emailUser, bodyAdd){
SpreadsheetApp.getActiveSpreadsheet().toast('Please wait while information is refreshed.');
//If running on script editor the variables will not be transferred. Assign values below:
if(emailUser == null){emailUser = 'xxxxxx#yyyyyyy.com'}
if(bodyAdd == null){bodyAdd = 'Testing running of function on script editor'}
var ss = SpreadsheetApp.getActive();
var detailsSht = ss.getSheetByName('Details');
var dataRange = detailsSht.getRange('A1:FS11'); //For the preview we are only looking at the first 10 rows of data.
var curDate = Utilities.formatDate(new Date(), 'GMT+1', 'MM/dd/yyyy');
//Gather data to convert specific sheet to excel document so it can be attached to the e-mail
var ssID = SpreadsheetApp.getActiveSpreadsheet().getId();
var sheetID = detailsSht.getSheetId().toString()
var requestData = {'method': "GET", 'headers':{'Authorization':'Bearer ' + ScriptApp.getOAuthToken()}};
var url = 'https://docs.google.com/spreadsheets/d/' + ssID + '/export?format=xlsx&id=' + ssID + '&gid=' + sheetID;
var result = UrlFetchApp.fetch(url , requestData);
var contents = result.getContent();
//Assemble E-mail components
var subject = 'Summary - Exported Data ' + curDate;
var body = bodyAdd +
'<br /><br /><hr style="border: none;border-top: 3px double #333;color: #333;overflow: visible;text-align: center;height: 5px;"><br />' +
'You have received an export of a dataset from the Summary dashboard. Below is a preview of the dataset:<br /><br />'
var afterBody = '<br /><br /><b>You can view the full dataset through the attached XLS file.</b>'
convSheetAndEmail(ss, contents, dataRange, emailUser, body, afterBody, subject);
};
function convSheetAndEmail(ss, contents, rng, emailUser, body, afterBody, subject){
var HTML = SheetConverter.convertRange2html(rng);
//Send email
MailApp.sendEmail(
emailUser,
subject,
'',{
htmlBody : body + HTML + afterBody,
name: 'Full Data Export',
attachments:[{fileName:'Export Data - ' + ss.getName() + '.xls', content:contents, mimeType:'application//xls'}]
}
);
};
Apart from the resource listed in the question, I also borrowed code from here.
I am using a script to have form results e-mailed to me every time the form is submitted. Entire code is posted in Google Groups here:
http://groups.google.com/a/googleproductforums.com/d/topic/apps-script/1rObNfuez6k/discussion
Here's the current code:
function contactUsMailer2(e) {
// var ss = SpreadsheetApp.getActive();
// SpreadsheetApp.setActiveSpreadsheet(ss);
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Data'); //default sheets - change if you
var setup = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Setup'); //rename the sheets
var width = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Data').getLastColumn(); //get "width" of sheet, used to enumrate fields
var myEmailAddress = setup.getRange('B3').getValue(); //get email recipient(s) from "Setup" (default)
var myEmailSubject = setup.getRange('B4').getValue(); //get a subject line from "Setup" (default)
//from row 1 of "Data"
var sheetURL = SpreadsheetApp.getActiveSpreadsheet().getUrl(); //get sheet url to include in email
var formURL = SpreadsheetApp.getActiveSpreadsheet().getFormUrl(); //get form url to include in email
var column = 'A';
var message = '';
var htmlBody = '<html><body><table>'; //generated email will have both an HTML table and a plain-text part
//to be RFC compliant. beginning of html and table.
for (var c=1; c<=width; ++c) {
var data = sheet.getRange(1, c, 1, 1).getValue(); //this gets the "filed" names from the 1st row of "Sheet1"
try {
//retrieve field data and build the HTML and plain-text emails
var message = message + data + ': ' + e.namedValues[data].toString() + '\r\n'; //plain-text
var htmlBody = htmlBody + '<tr><td><b>' + data + ': </b></td><td>' + e.namedValues[data].toString() + '</td></tr>'; //HTML
}
catch (a) {
var message = message + data + ': n/a\r\n';
var htmlBody = htmlBody + '<tr><td><b>' + data + ': </b></td><td>n/a</td></tr>';
}
var column = String.fromCharCode(column.charCodeAt() + 1); //increment column letter
}
var htmlBody = htmlBody + '</table>'; //close table
var message = message + '\r\n\r\nData from form located at ' + formURL + '\r\n'; //put form url in text email
var message = message + 'Data posted to spreadsheet at ' + sheetURL; //put sheet url in text email
var htmlBody = htmlBody + '<br><br>Data from form located here<br>'; //put form url in HTML email
var htmlBody = htmlBody + 'Data posted to spreadsheet here<br>'; //put sheet url in HTML email
var htmlBody = htmlBody + '</body></html>'; //close html
MailApp.sendEmail(myEmailAddress, myEmailSubject, message, {htmlBody: htmlBody}) ; //send the email
}
function showid() {
Browser.msgBox("The sheet ID is:\r\n\r\n" + SpreadsheetApp.getActiveSpreadsheet().getId());
}
Script now works fine with the original spreadsheet, but when I try to use it with a new form and spreadsheet it fails to send the e-mail. The form fill in the spreadsheet just fine and we get the usual e-mail stating that the spreadsheet has been updated, but the script e-mail doesn't come through.
Funny thing is when I debug the script it does send the e-mail, just null entries in all fields (which is what I would expect). Debug doesn't report any errors in the script itself. What am I missing?
Have you authorized the script in your new form ? Since your script is required to send out an email it requires explicit authorization.
Try removing the quote around
for (var c=1; c<=width; ++c) {
var data = sheet.getRange(column + '1').getValue(); //this gets the "filed" names from the 1st row of "Sheet1"
I do something similar in a script and the following works for me.
var rangeval = "B"+(i+1);
var nameFld = filesheet.getRange(i+1,1).getValue();
Joe
Make sure trigger is set to "On Submit". Mine was set to "On Open".