I am having trouble setting up a script to iterate through a Google spreadsheet and email to the employees the lines that contain the reports about them.
In my tests The email address and subject lines are being emailed but depending on what I try the email is either blank or says "[object Object]".
I am viewing emails from the Gmail site in Chrome.
The HTML code does not have any variables yet. I am still working on getting it to email correctly and then I will try working in scriplets to build a table for the report.
Code.gs
function changeName() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var shA = ss.getSheets()[0]; // Report download
var shB = ss.getSheets()[1]; // Names & email address
var alRow = shA.getLastRow();
var blRow = shB.getLastRow();
var data = shA.getRange(1, 1, alRow, 14).getValues(); // Array of all employees reports
var employees = shB.getRange(1, 1, 2, 2).getValues(); // List of employees [i][0] and email address [i][1] in Scorecard data
for(i=0;i<employees.length;i++){
var html = HtmlService.createTemplateFromFile('Index').evaluate();
MailApp.sendEmail(employees[i][1], employees[i][0] + ' Scorecards Test', {htmlbody: html.getContent()});
Logger.log(html.getContent());
}
}
Index.html
<body>
<p1>Test 5062</p1>
<table>
<tr>
<td>Test Cell 1</td>
<td>Test Cell 2</td>
<td>Test Cell 3</td>
</tr>
</table>
</body>
When I view the log, it shows the HTML file.
What I am doing wrong?
How about a following modification?
From :
function changeName() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var shA = ss.getSheets()[0]; // Report download
var shB = ss.getSheets()[1]; // Names & email address
var alRow = shA.getLastRow();
var blRow = shB.getLastRow();
var data = shA.getRange(1, 1, alRow, 14).getValues(); // Array of all employees reports
var employees = shB.getRange(1, 1, 2, 2).getValues(); // List of employees [i][0] and email address [i][1] in Scorecard data
for(i=0;i<employees.length;i++){
var html = HtmlService.createTemplateFromFile('Index').evaluate();
MailApp.sendEmail(employees[i][1], employees[i][0] + ' Scorecards Test', {htmlbody: html.getContent()});
Logger.log(html.getContent());
}
}
To :
function changeName() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var shA = ss.getSheets()[0]; // Report download
var shB = ss.getSheets()[1]; // Names & email address
var alRow = shA.getLastRow();
var blRow = shB.getLastRow();
var data = shA.getRange(1, 1, alRow, 14).getValues(); // Array of all employees reports
var employees = shB.getRange(1, 1, 2, 2).getValues(); // List of employees [i][0] and email address [i][1] in Scorecard data
for(i=0;i<employees.length;i++){
var html = HtmlService.createTemplateFromFile('Index').evaluate();
MailApp.sendEmail({
to: employees[i][1],
subject: employees[i][0] + ' Scorecards Test',
htmlBody: html.getContent()
});
Logger.log(html.getContent());
}
}
If this didn't work, I'm sorry.
I find it a lot easier to build the html right in the file like this:
var s='<table>';
s+='Utilities.formatString('<tr><td>%s</td><td>%s</td><td>%s</td></tr>',data[i][0],data[i][1],data[i][2]);
s+='</table>'`;
MailApp.sendMail({to:emailAddress, subject: subj, htmlBody: s});
And keep in mind your html doesn't have to be complete.
Often I actually build the email this way and disable the sendEmail while I'm building it and just do this to view my results.
var ui=HtmlService.createHtmlOutput(s);
SpreadsheetApp.getUi().showModeLessDialog(ui,title);
And that way I can see what I'm doing while I built it without having to send emails. Some people use the logger but I like doing it this way.
And often people end up wanting to put some conditions on sending the email.
Email Address is not empty
Body is not empty
The email hasn't already been sent
You haven't exceeded your remaining daily quota
But hey everyone is different and you can choose to do it whatever way that makes you happy.
Related
I have created a data entry form in google sheets, now I am having trouble saving said entry to an external sheet so far this is what I have, I do not know if I am using the right method to reference sheet.
please look at comments, thank you
Everytime I am trying to submit the form it is giving lastRow Null
function submitData() {
//variable declaration for referenceing the active google sheet
var myGoogleSheet = SpreadsheetApp.getActiveSpreadsheet();
var shUserForm = myGoogleSheet.getSheetByName('MasterSheet');
//open external sheet
var extSS = SpreadsheetApp.openById("1U9SmfPCH9v8maqh6XL0dmRL85TJZfckUV7SAEGM3pQo");
var datasheet= extSS.getSheetByName("Mastersheet");
var srcData = shUserForm.getDataRange().getValues();
//to create the instance of the ui environment to use the alert features
var ui = SpreadsheetApp.getUi();
var response = ui.alert("Submit", "Do you want to submit the data?", ui.ButtonSet.YES_NO);
//checking the user response
if ( response == ui.NO) {
return; // to ext from this function
}
if ( validateEntry()== true) {
var blankRow =datasheet.getLastRow() + 1; //identify the next blank row
//'code to update the database sheet ( write data entry to DB sheet)
datasheet.getRange(blankRow,1).setValue(srcData.getRange("C7").getValue()); //input number
datasheet.getRange(blankRow,2).setValue(srcData.getRange("C9").getValue()); //Department
datasheet.getRange(blankRow,3).setValue(srcData.getRange("C11").getValue()); //Agent Name
datasheet.getRange(blankRow,4).setValue(srcData.getRange("C13").getValue()); //Hub location
datasheet.getRange(blankRow,9).setValue(srcData.getRange("C15").getValue()); //order ID
datasheet.getRange(blankRow,10).setValue(srcData.getRange("C20").getValue()); //type of entry
datasheet.getRange(blankRow,5).setValue(Session.getActiveUser().getEmail()); //Submitted By, this will automatically get user email
datasheet.getRange(blankRow,7).setValue(new Date()).setNumberFormat('yyyy-mm-dd h:mm:');
datasheet.getRange(blankRow,8).setValue(new Date()).setNumberFormat('yyyy-mm-dd h:mm:');
datasheet.getRange(blankRow,6).setValue(srcData.getRange("C17").getValue()); //comments
ui.alert(' "New Data Saved - Input #' + shUserForm.getRange("C7").getValue() + '"');
shUserForm.getRange("C7").clear();
shUserForm.getRange("C9").clear();
shUserForm.getRange("C11").clear();
shUserForm.getRange("C13").clear();
shUserForm.getRange("C15").clear();
shUserForm.getRange("C17").clear();
}
}
To save data to another Spreadsheet, You need to open it first by using either openById("insert sheet id here") or openByUrl("insert sheet URL here"). This will return a Spreadsheet class which has getSheetByName("sheet name") method you can use to access the Sheet.
ID of the spreadsheet can be found in the url. This can be found after /d/ or before /edit
Example ID:
https://docs.google.com/spreadsheets/d/12345/edit#gid=0
12345 is the Spreadsheet ID
Example:
Code:
function saveData() {
//open current sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName("Sheet1");
//open external sheet
var extSS = SpreadsheetApp.openById("Insert External Spreadsheet ID here");
var extSH = extSS.getSheetByName("Sheet1 External");
//get data from current Sheet.
var srcData = sh.getDataRange().getValues();
//write to external sheet
extSH.getRange(extSH.getLastRow()+1, 1, srcData.length, srcData[0].length).setValues(srcData);
}
This script will paste the values from Sheet1 to Sheet2
Before:
Sheet1 Data:
Sheet2 Data:
After:
Sheet1 Data:
Sheet2 Data:
SpreadsheetApp.openByID()
SpreadsheetApp.openByURL()
Spreadsheet.getSheetByName()
Class Sheet
Class Range
I have "to" in column A & "message/body" in column "B". I have a code which sends an email. However in my message I have a word hyperlinked to another sheet, while sending the email, the hyperlink is not considered. Please find the screenshot below.
However when the email is sent, the hyperlink is not visible. Please the image below
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2;
var numRows = 1;
var dataRange = sheet.getRange(startRow, 1, numRows, 2);
var data = dataRange.getValues();
for (var i in data) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var subject = 'Sending emails from a Spreadsheet';
MailApp.sendEmail(emailAddress, subject, message);
}
}
Use Templated HTML
var htmlBody = HtmlService.createTemplate('Email with <a href=<?=link?>> Some link </a>');
htmlBody.link = row[1];
MailApp.sendEmail({
to: row[0],
subject: 'Sending emails from a Spreadsheet',
htmlBody: htmlBody.evaluate().getContent()
});
If you have embedded cell links, you can extract them using Advanced Sheets services, as describe here, for example
var values = Sheets.Spreadsheets.get(SpreadsheetApp.getActive().getId(), {ranges: "Sheet1!B1:B10", fields: "sheets/data/rowData/values/hyperlink"})
var links = values.sheets[0].data[0].rowData.map(v => v.values[0].hyperlink);
them use them in templated HTML example I provided.
I am trying to write a code that transfers data from gmail to spreadsheet. Here is the code:
function mailToStudio() {
var label = GmailApp.getUserLabelByName('GmailToStudio');
var threads = label.getThreads();
for (var i = threads.length - 1; i>=0; i--){
var msg = threads[i].getMessages()[0];
extractDetails(msg);
GmailApp.markMessageRead(msg);
}
}
function extractDetails(msg) {
var dateTime = msg.getDate();
var subjectText = msg.getSubject();
var senderDetails = msg.getFrom();
var body = msg.getPlainBody();
Logger.log(body);
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
activeSheet.appendRow([dateTime, subjectText, senderDetails, body]);
}
My issue is with gmail body part. I want the data starting "Client Time" text and ending "Total" to be copied to spreadsheet in rows and columns same as given in gmail body.
Here is what I get:
1- When there are only few data lines in gmail body then the code works in such a way that it puts whole body content in a single cell instead of copying it to different rows and columns according to data structure.
2- When there are more data lines like 50+ lines in gmail body then the code does not work and all I get from body is an error "To view the message, please use an HTML compatible email viewer!".
Can anybody help how I can move gmail data to spreadsheet in proper rows and columns?
Thank you
Right now, my code is sending my entire Google Sheet file as a PDF attachment. I am needing it, though, to only send my one tab entitled "PO Template". Let me know if you can help:
function emailGoogleSpreadsheetAsPDF() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var email = ss.getRange("A19").getValue();
var PO = ss.getRange("N3").getValue();
var subject = "PO No. " + PO;
var blob =
DriveApp.getFileById(shs.getId()).getAs("Application/pdf");
var body = "Install the <a href='http://www.labnol.org/email-
sheet'>Email Spreadsheet add-on</a> for one-click conversion.";
blob.setName(ss.getName()+".pdf");
if(MailApp.getRemainingDailyQuota()>0)
GmailApp.sendEmail(email, subject, body, {
htmlBody: body,
attachments:[blob]
});
}
Don't think there's an adhoc method to do this. You'll have to resort to a workaround as suggested by this github tutorial:
// 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);
// Find and delete the default "Sheet 1", after the copy to avoid triggering an apocalypse
newSpreadsheet.getSheetByName('Sheet1').activate();
newSpreadsheet.deleteActiveSheet();
I am using Google Scripts UiApp in order to gather availability information. I want to send this information to a spreadsheet. I have used the example here: http://www.googleappsscript.org/advanced-examples/insert-data-in-sheet-using-ui-forms
to get me started in the right direction.
The Web App looks good and when clicking submit, the appropriate message displays. However, the values that are transferred to the spreadsheet say "undefined" for all of the entries.
How can I convince it to link the textbox entered data to the variables so that I can transfer to the spreadsheet?
Thanks!!
Here is some code:
var submissioSSKey = // Key removed
function doGet() {
var rows = 15
var columns = 15
var mygrid = UiApp.createApplication().setTitle("MLC Walk Ins Scheduling")
var panel = mygrid.createSimplePanel();
// Define the grid layout
var grid = mygrid.createGrid(rows, columns).setCellPadding(2).setCellSpacing(8)
// Create the text at the top
var Title = mygrid.createLabel("Walk-In Scheduling")
grid.setWidget(1, 1, Title)
(snip) - creating various checkboxes and textboxes
var text1 = mygrid.createTextBox().setName('name1')
grid.setWidget(3,9,text1)
var text6 = mygrid.createTextBox().setName('message1')
grid.setWidget(4,9,text6)
// Create the "submit" button
var submit_button = mygrid.createButton("Submit")
grid.setWidget(12,9,submit_button)
var infoLabel = mygrid.createLabel('Availability inserted successfully.').setVisible(false).setId('info');
grid.setWidget(13,9,infoLabel)
var handler = mygrid.createServerClickHandler('insertInSS');
handler.addCallbackElement(panel);
submit_button.addClickHandler(handler);
panel.add(grid);
mygrid.add(panel);
mygrid.add(grid);
return mygrid
}
Then the function call for the button:
//Function to insert data in the sheet on clicking the submit button
function insertInSS(e){
var mygrid = UiApp.getActiveApplication()
var name1 = e.parameter.name1
var message1 = e.parameter.message1
mygrid.getElementById('info').setVisible(true).setStyleAttribute('color','blue')
var sheet = SpreadsheetApp.openById(submissioSSKey).getActiveSheet()
var lastRow = sheet.getLastRow()
var targetRange = sheet.getRange(lastRow+1, 1, 1, 2).setValues([[name1,message1]])
return mygrid
}
Ahh! A simple fix for a big headache.
I had an extra line:
mygrid.add(grid);
that was breaking it.