My application is designed to create a table which is later edited by the user. After this I need my application to send the page content via email.
I used URLHelper's trigger email() but through this I am able to trigger the email with to, cc, subject, text body but my ui5 application is not able to insert the table into the email.
Can someone please suggest something? or is it even possible?
I won't mind using plain javascript either, Point is I need to do this without using the backend.
We do something similar on one of our apps. I added a button to the screen which when clicked invokes a 'mailto', and populates the email client with the to, subject and body. The body is created as part of the script. We basically read the table contents into an array, then loop through the entries using a forEach. Keep in mind using mailto or even the URLHelper does not allow you to use HTML formatted text in the 'body' of the email. So, if you're looking for something pretty, you may be out of luck.
onNotifyUserPress: function(oEvent) {
var oItem = oEvent.getSource();
var oBinding = oItem.getBindingContext();
// Set some vars for the email package
var sEmpEmail = oBinding.getProperty("Smtp");
var sEmpName = oBinding.getProperty("STEXT_2");
var sEmailSubject = "Your Subject " + sEmpName;
// Create DateFormat Object
var oDateFormat = DateFormat.getDateTimeInstance({pattern: "dd/MM/yyyy"});
// Retrieve Table Data
var oTable = this.getView().byId("yourTable");
var aTableData = oTable.getBinding("items").getContexts();
// Build the email body
var sBody = sEmpName + " - Some Body Text\n\n";
sBody += "Field 1 | " + "Field 2 | " + "Field 3 | " + "Field 4" + "\n";
// Loop through table data and build the output for the rest of the email body
aTableData.forEach(function(oModel) {
var oModelData = oModel.getObject();
var sEndDate = oDateFormat.format(oModelData.Vendd);
var sStatus = this._formatStatus(oModelData.ZQ_STAT);
sBody += (oModelData.Essential === "X" ? "Yes" : "No") + " | " + oModelData.Ttext + " | " + sEndDate + " | " + sStatus + "\n";
}.bind(this));
// Open email client window and prepopulate with info
window.open("mailto:" + sEmpEmail + "&subject=" + sEmailSubject + "&body=" + encodeURIComponent(sBody), "_self");
},
You'll obviously need to update the code to point to your table data. In this particular instance, we have an object page with a couple of sections. Each section contains a table which loads a list of entities that are associated with the user. As the data is already loaded and exists in the model, this may not work in the same fashion as what you're trying to do (if I understand correctly), as you need to send an email after the data is entered/modified?
Hopefully this can at least get you started!
Cheers!
Related
I have created a spreadsheet for our coaches. They choose a sport and then spreadsheet fills with a roster of possible students. They click the check box next to the name of the student(s) attending the event, type the date, and click the Send button. It sends an email to the teachers listed (2nd tab has all rosters and emails). The script I wrote does all this no problem. The issue I am having deals with formatting. The names print out horizontally with a comma separating each name:
Student One, Student Two (etc.)
[This was in the original post, but I figured out how to skip blank spots in an array
If a student in the roster is skipped the printout looks like this:
Student One,,Student Three, Student Four,,Student Six (etc.) ]
I don't want the name to print if the checkbox isn't checked but I would like for the printout to look a little cleaner on an email. I used an array to read the names and I realize it's just printing out the array and it has an empty box. (solved the empty name part) I would like the email to look like:
Student One
Student Two
I am unsure how to accomplish this and have searched around quite a bit. What I have is functional, but doesn't look great. Another loop could accomplish this but I don't know how to do that while also formatting the email. It definitely doesn't like when I try to put a loop inside of there.
Here's the spreadsheet: Sample Sports Email Spreadsheet
Here is the code I have typed:
function emailRoster()
{
var teacher = SpreadsheetApp.getActive().getRange("Rosters!J2:J4").getValues();
var roster = SpreadsheetApp.getActive().getRange("Sheet1!A6:B").getValues();
var sport = SpreadsheetApp.getActive().getRangeByName("Sport").getValue();
var date = SpreadsheetApp.getActive().getRangeByName("Date").getValue();
var lenT = teacher.length;
var lenR = roster.length;
var playerTrue = [];
for(var i=0; i<lenR; i++){
if(roster[i][1])
playerTrue[i] = roster[i][0];
}
playerTrue = playerTrue.filter(String); //recently added...fixed the printout so it ignores blank parts of the array
playerTrue.forEach(function(name) {
Logger.log(name);
});
for(var p=0; p<lenT-1; p++){
var email = teacher[p];
var subject = "Students out for " + sport;
var body = "Teachers,\nThe following students will be out for " +sport+ " on " +date +": \n\n" + playerTrue +"\n";
GmailApp.sendEmail(email,subject,body);
}
};
EDIT
I have created another function to try and get it to return each name with a return after each name, but I can only get it to do the first name:
function createRoster(){
var roster = SpreadsheetApp.getActive().getRange("Sheet1!A6:B").getValues();
var playerTrue = [];
var lenR=roster.length;
for(var i=0; i<lenR; i++){
if(roster[i][1])
playerTrue[i] = roster[i][0]; }
playerTrue = playerTrue.filter(String);
Logger.log(playerTrue);
for(var b=0; b<lenR-1; b++){
return playerTrue[b] + "\n";
}
Logger.log(playerTrue);
};
So now the body variable in the original function looks like this:
var body = "Teachers,\nThe following students will be out for " +sport+ " on " +date +": \n\n" + createRoster() +"\n";
From your showing script, it seems that playerTrue is an array. When the array is directly used as the text body, such a situation occurs. When you want to align the value to the vertical direction, how about the following modification using join?
From:
var body = "Teachers,\nThe following students will be out for " +sport+ " on " +date +": \n\n" + playerTrue +"\n";
To:
var body = "Teachers,\nThe following students will be out for " + sport + " on " + date + ": \n\n" + playerTrue.join("\n") + "\n";
Or, when you want to put the value every 2 lines, how about the following modification?
var body = "Teachers,\nThe following students will be out for " + sport + " on " + date + ": \n\n" + playerTrue.join("\n\n") + "\n";
Reference:
join()
I am having problems with getting the current row information to be included in my email message when the email address that I'm sending to is listed on another spreadsheet. It works when I define the email address within the script.
I have 3 spreadsheets. The spreadsheet sheet names are Team, Issues, and Watchers. The Issues spreadsheet is the main sheet. When a new row is added on the Issues spreadsheet, column 34 is marked as "Ready to Email". If Column 34 is set to "Ready to Email" and Column 35 is not marked as "SENT", then I want to send an email notification using the email addresses listed on the WATCHERS spreadsheet then mark column 35 as "SENT". In the body of the email I want to include the URL of the main spreadsheet Issues spreadsheet) and information from the current row. I also want to include the value that is in cell "B2"on the TEAM spreadsheet. If no email addresses exist in the WATCHERS spreadsheet I want to mark column 35 as "No EMAIL ADDRESS EXIST".
Again, I'm able to send emails but the problem is that I'm not getting the subject info or the current row information in body of the email. Here is my script....
function sendEmail()
{
//setup function
var ActiveSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Issues"); //the issues spreadsheet
var StartRow = 2; //first row of data to process
var LastRow = ActiveSheet.getLastRow();
var RowRange = LastRow - StartRow + 1;
var WholeRange = ActiveSheet.getRange(StartRow,1,RowRange,35);
var AllValues = WholeRange.getValues(); //getting the values defined in the range of the issues spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet(); //this is so that I can use the getUrl function to get the URL of the ISSUES spreadsheet
for (var i=0;i<AllValues.length;i++)
{
var watchers = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Watchers"); //the watchers spreadsheet
var wdata = watchers.getRange("A2:B" + watchers.getLastRow()).getValues(); //getting the values defined in the range in the watchers spreadsheet
var team = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Team"); //the team spreadsheet
var tdata = team.getRange("B2").getValues(); //getting the value defined in cell B2 in the team spreadsheet.
var CurrentRow = AllValues[i];
var EmailSent = CurrentRow[34]; //the value of column 35 on the issues spreadsheet
if (CurrentRow[33] == "Ready to Email" && EmailSent!= "sent")
{
wdata.forEach(function(row,CurrentRow,tdata,ss) //I think this is my problem. I'm trying to pass in CurrentRow, tdata, and ss so that I can use in my email.
{
var Subject = "New Issue reported: Issue# " + CurrentRow[3]; //set subject line
var message = "";
message += //CurrentRow, ss, and tdata is not working.
"<p><b>A new issue has been reported for </b>" + tdata + "<p><b> Reference the SRD for more details. </b>" + ss.getUrl() + "</p>" +
"<p><b>Issue Status: </b>" + CurrentRow[0] + "</p>" +
"<p><b>Group: </b>" + CurrentRow[1] + "</p>" +
"<p><b>LifeCycle Status: </b>" + CurrentRow[2] + "</p>" +
"<p><b>Issue Number: </b>" + CurrentRow[3] + "</p>" +
"<p><b>Priority: </b>" + CurrentRow[4] + "</p>" +
"<p><b>Description: </b>" + CurrentRow[6] + "</p>" +
"<p><b>Opened By: </b>" + CurrentRow[10] + "</p>";
MailApp.sendEmail
({
to: row[1],
subject: Subject,
htmlBody: message,
});
});
var setRow = i + StartRow;
ActiveSheet.getRange(setRow, 35).setValue("sent"); //update the row if email is sent
}
}
}
Note that for the first line of the message, "ss.getUrl()" is failing with TypeError: Cannot call method "getUrl" of undefined.
This is what the body of the email looks like when I received it.
I feel like this should be so easy and obvious, but I cannot figure it out...
I am working with 2 forms and 2 spreadsheets. Form 1 submits to Sheet 1. On Sheet 1, for each record, there is a link that takes the user to Form 2, which is half pre-populated with data from Sheet 1. When the user submits Form 2, it populates Sheet 2.
I have a couple of scripts that are supposed to be triggered when Form 1 is submitted. I am using the "From Spreadsheet" "OnFormSubmit" trigger. The scripts, however, are also triggering when Form 2 is submitted.
How can I make it so the scripts only execute when Form 1 is submitted? Also, is there a way to ensure that scripts trigger in a specific order?
If it helps, the scripts are below. They all work properly as is, except for the triggering issue. I know that I can merge the 2nd and 3rd script, and I will, but I'd like to fix this triggering issue first, as I'm getting double the emails every time I test.
1st script:
function onFormSubmit(e) {
//Uses time in milleseconds to create unique ID #
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("ComplaintLog");
var d = new Date();
var n = d.getTime();
var lastRow = sheet.getLastRow();
var cell = sheet.getRange("BA" + lastRow);
cell.setValue(n);
var cell = sheet.getRange("BB" + lastRow);
cell.setFormula("=right(BA"+lastRow+",6)");
sheet.getRange("BB"+lastRow).copyTo(sheet.getRange("BC"+lastRow), +
{contentsOnly:true});
}
2nd script:
function formSubmitReply(e) {
//Sends email to certain users when a new complaint has been entered
var emailAddresses = 'person#organzation.com';
MailApp.sendEmail(emailAddresses,
"person#organzation.com",
"New Guest Complaint",
"A new guest complaint has been entered into the database."
+ "\n\n To vew the database, click here: http://goo.gl/DI33EC");
}
3rd script:
function createResolutionForm() {
var ss = SpreadsheetApp.getActive()
var sheet = ss.getSheetByName("ComplaintLog")
var lastRow = sheet.getLastRow();
var data = ss.getSheetByName("ComplaintLog") +
.getRange("A"+lastRow+":Z"+lastRow).getValues();
var form = FormApp.openById('The form's ID goes here. that part works.');
var items = form.getItems();
for (var i = 0; i < data.length; i++) {
var formResponse = form.createResponse();
//ID
var formItem = items[1].asTextItem();
var response = formItem.createResponse(data[i][0]);
formResponse.withItemResponse(response);
//Guest Name
var formItem = items[2].asTextItem();
var response = formItem.createResponse(data[i][3]);
formResponse.withItemResponse(response);
//email
var formItem = items[3].asTextItem();
var response = formItem.createResponse(data[i][4]);
formResponse.withItemResponse(response);
// The pre-populated form is being created here. I didn't include every
// form item for brevity's sake.
}
//Create Link
var formUrl = formResponse.toPrefilledUrl();
//Enable Clickable ID
var idNum = sheet.getRange("BC"+lastRow).getValues();
sheet.getRange("A"+lastRow).setFormula +
('=HYPERLINK("' + formUrl + '","' + idNum + '")');
var sheetUrl = "The URL to the spreadsheet goes here - that part works.";
//Send Email to assigned managers
var j,tempname=[],name, subject, managername, message;
managername = sheet.getRange("P"+lastRow).getValue();
tempname=managername.split(" ");
Logger.log(managername)
if (tempname.length==2) {
name=tempname[0].slice(0,1) + tempname[1] + '#organization.com';
subject = 'Action Required';
var message = "<html><body>"
+ "<p> You have been assigned to follow-up on a complaint,"
+ "or your contact information has been given to a customer in"
+ "regards to a complaint."
+ "<p><p>The complaint ID number is " + idNum +"."
+ "<p>To go directly to this complaint,"
+ "<b>click here</b>."
+ "<p>To vew the database so that you can take action,"
+click here."
+ "</body></html>";
MailApp.sendEmail(name, subject,"",{htmlBody : message});
}
}
Setting up the triggers from within the script might be what you're looking for. You can create triggers that respond to form submission events on a per-form basis like so:
function setup () {
ScriptApp.newTrigger('onForm1ResponseHandler').forForm(form1).onFormSubmit().create();
ScriptApp.newTrigger('onForm2ResponseHandler').forForm(form2).onFormSubmit().create();
}
where form1 and form2 are Form objects and 'onForm1ResponseHandler' is the name of the handler function.
With a handler function set up like this:
function onForm1ResponseHandler (e) {
...
}
e will be an object with properties documented here (for the Form Submit event).
So I am using a script i found on line to send an email everytime a Google Form is completed, which includes the data in the form via a Google Sheet.
function sendFormByEmail(e)
{
var email = “email#address.com”;
var s = SpreadsheetApp.getActiveSheet();
var headers = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
var message = "A new travel request has been submitted.";
var subject = "New Travel Justification Request: ";
for(var i in headers)
message += headers[i] + ': '+ e.namedValues[headers[i]].toString() + "\n\n";
subject += e.namedValues[headers[2]].toString() + " - starts " + e.namedValues[headers[15]].toString();
MailApp.sendEmail(email, subject, message);
// Based off of a script originally posted by Amit Agarwal - www.labnol.org
// Credit to Henrique Abreu for fixing the sort order
}
It works well, but I want it to exclude the headers for empty cells, as not all parts of the form require completion.
I know very little, so all help is appreciated.
I have updated the original Google Form script to not include fields that are empty. You can add a simple condition in the for loop:
for(var i in headers) {
if ( e.namedValues[headers[i]].toString() != "") {
message += headers[i] + ': '+ e.namedValues[headers[i]].toString() + "\n\n";
}
}
I see some question closed by administrator with similar question.
I will try to explain in detail the solution I'm looking for:
First I'm trying to develop a windows console application.
Sending frequency: monday to friday
How many users: from 5 to 20
Format of data:
A table where rows are countries and columns different types of products and the cells represent the sale of that country-product
Limitation:
Service users prefer not to use a pdf or excel or attachment of any type should be a html format possible to show in the body of mail
Currently I am creating the report almost artisan with something like:
.....
var myStringBuilder = new StringBuilder("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">");
myStringBuilder.Append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">");
myStringBuilder.Append("</head><body>");
myStringBuilder.AppendLine();
myStringBuilder.Append("<table style=\"font-family: Calibri; text-align: right; font-size: x-small;\">");
myStringBuilder.AppendLine();
var header = new StringBuilder("<tr><th>a</th><th>CATEG1</th><th>CATEG2</th><th>CATEG3</th><th>CATEG4</th><th>TOTAL</th></tr>");
var line = new StringBuilder("<tr><td>a</td><td>b</td><td>c</td><td>z</td><td>e</td><td>f</td></tr>");
foreach (var a in _actuals)
{
line.Replace("a", a.CountryName);
if(a.Segment.ToLowerInvariant().Equals("categ1")) {
line.Replace("b", "[" + string.Format("{0:0,#}", a.LsvLcFact / 1000) + "]"); }
else if (a.Segment.ToLowerInvariant().Equals("categ2")) {
line.Replace("c", "[" + string.Format("{0:0,#}", a.LsvLcFact / 1000) + "]"); }
else if (a.Segment.ToLowerInvariant().Equals("categ3")) {
line.Replace("z", "[" + string.Format("{0:0,#}", a.LsvLcFact / 1000) + "]"); }
else {
line.Replace("e", "[" + string.Format("{0:0,#}", a.LsvLcFact / 1000) + "]"); }
}
.....
And in the class to send mail something like:
public void SendResumen(string subject ,StringBuilder content)
{
var oMsg = new MailMessage...;
... add users
oMsg.Subject = subject;
var mimeType = new ContentType("text/html");
var alternate = AlternateView.CreateAlternateViewFromString(content.ToString(), mimeType);
oMsg.AlternateViews.Add(alternate);
oMsg.IsBodyHtml = true;
var cli = Client();
cli.Send(oMsg);
}
Finally, I hope you understand what I'm doing and the question is:
Is there a tool I can use to not generate as crafted the message body?
I have a VB application that can send out messages that have an HTML payload, and it doesn't use the AlternateView functionality.
Dim mail As New MailMessage(fromUser.Email, toUser.Email)
mail.Subject = subject
mail.IsBodyHtml = True
mail.Body = message
While it would be nice to use the AlternateView functionality for those email clients that can't read the HTML payload, your code can't really use it because you're only supplying an HTML message. If you did manage to get the AlternateView functionality to work here, any client that couldn't read HTML would see the HTML markup instead of just simple message text. For this to truly work, I think you would need to provide both a text and HTML email message body.
I Accept the suggest from #Jim-Mischel