How to display month fetched via JS in html email contents.? - javascript

code.gs
function showMonth() {
var recipient1 = 'user#gmail.com';
var subject = "email subject";
// send email using html page
var emailTemplate = HtmlService.createTemplateFromFile('file');
MailApp.sendEmail(recipient1, subject,'',{'htmlBody': emailTemplate.evaluate().getContent(), 'cc': '', 'bcc': ''});
}
file.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h2>My First Web Page</h2>
<p>My First Paragraph.</p>
<p id="displaymonth"> </p>
<script>
var d = new Date();
var mnth = getMonthDetails();
function getMonthDetails() {
switch (d.getMonth()) {
case 9 :
return "October";
break;
}
document.getElementById("displaymonth").innerHTML = "Current month is " + mnth;
</script>
</body>
</html>
Output in email:
My First Web Page
My First Paragraph.
I'm trying to get date and month in JS script tag and posting them to HTML content.
Later fetching the same HTML content using email template service of Google Apps Script and sending an email to user to show the current month.
When I run the code on other online editor like jsfiddle.net, it is showing the month details on the results page. However, I cannot get the expected result in the email upon running the code on Google Apps Script.
Let me know a way to fix my code to see the expected results. Thanks!

This way your email and your webapp get the same contents
Most of the contents comes from a text file that's written in html. And then in the function getContents() I append the line with the month in it. That function provides content to the doGet() and the sendEmail().
aq1.gs
function getContents() {
var folder=DriveApp.getFolderById('folderId');
var file=folder.getFiles().next();//assume only one
var contents=file.getBlob().getDataAsString()+Utilities.formatString('<p>This month is %s</p>',Utilities.formatDate(new Date(), Session.getScriptTimeZone(),"MMMM" ));//get content from file and append the date to it as a string
return contents;
}
function sendEmail() {
var recipient1 = 'recipient email';
var subject = "Combining Email and Website Contents";
var html=getContents();
MailApp.sendEmail(recipient1, subject,'',{htmlBody:html});
}
function doGet() {
return HtmlService.createHtmlOutputFromFile('aq5');
}
function launchDiaog() {
var userInterface=HtmlService.createHtmlOutputFromFile('aq5');
SpreadsheetApp.getUi().showModelessDialog(userInterface, "My Dialog");
}
aq5.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$(function() {
console.log('Ready State Function');
google.script.run
.withSuccessHandler(function(hl){
console.log(hl);
$('#mydiv').html(hl);
})
.getContents();
});
console.log("My Code");
</script>
</head>
<h1>Testing</h1>
<div id="mydiv"></div>
</html>
This is the contents of the ascii text file:
<h2>My First Web Page</h2><p>My First Paragraph.</p><p>My second paragrah</p>
But it could be anything upto 50MB

Try getting the date on the app script then passing it as a variable into your HTML file.
I don't think your client side js code will be executed by the Apps Script.

Related

what is the error in this web app script to give the desired effect?

enter image description herewe've tried to write a script for a web app to a specific spreadsheet
the code is 2 files one in js
function doGet() {
return HtmlService.createHtmlOutputFromFile("page");
}
//function userClicked(name) {
//var url = "https://docs.google.com/spreadsheets/d/1T3AX_YBC8703g6N7sKot41tXUh6XN4zpcBF2V-_7iJ8/edit#gid=0";
//var ss = SpreadsheetApp.openByUrl(url);
//var ws = ss.getSheetByName("Data");
//ws.appendRow([name])
//Logger.log(name + "Clicked Run Button");
//}
function userClicked() {
Logger.log("Someone Clicked the button");
}
and the other in html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h1>Welcome</h1>
<button id="btn">RUN !!</button>
<script>
function doSomething() {
google.script.run.code.userClicked();
}
document.getElementById("btn").addEventListener("click", doSomething());
</script>
</body>
</html>
we can't get the desired action when run button is clicked
we don't know if it's the declaration of functions or summoning them
please help guide to rectify the error
this is yje project link for further analysis
https://script.google.com/d/1daP7bLBlL46av4Wc6-Pr9-z9lg6JyMY44FUtfA08fnKRKLeMuCTxH3LY/edit?usp=sharing
According to the Google Script client side API documentation, the path to call the App Script function is google.script.run.yourFunction() so in your html file. Also you are invoking the function straight away and passing the result of it to addEventListener(), instead of passing the function itself. The script should be this:
function doSomething() {
google.script.run.userClicked();
}
document.getElementById("btn").addEventListener("click", doSomething);

use value from input field in html dialog box to var in code.gs using Google Apps Script

I have a dialog box where user can select a year. Then I want the server to process the selected value in the function doSomethingWithCompetitionYear(theYear).
Looked at several discussions, but can't get it working. Looks like I need to do something with .withSuccesHandler().
Code.gs
function fncOpenMyDialog() {
//Open a dialog
var htmlDlg = HtmlService.createTemplateFromFile('DropDown_NewCompetitionFile');
thisYear = new Date();
htmlDlg.thisYear = thisYear.getFullYear();
htmlDlg.nextYear = htmlDlg.thisYear + 1;
htmlDlg = htmlDlg.evaluate()
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setWidth(200)
.setHeight(150);
SpreadsheetApp.getUi()
.showModalDialog(htmlDlg, 'Make selection');
};
function doSomethingWithCompetitionYear(theYear) {
var ui = SpreadsheetApp.getUi();
ui.alert(theYear);
}
HTML doc
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
Year
<select name="Competition_year" id="Competition_year" type="integer">
<option value=<?= thisYear?>><?= thisYear?></option>
<option value="nextYear"><?= nextYear?></option>
</select>
<hr/>
<button onmouseup="closeDia()">Submit</button>
<script>
var theYear = document.getElementById("Competition_year").value;
google.script.run.doSomethingWithCompetitionYear();
window.closeDia = function() {
google.script.host.close();
};
</script>
</body>
</html>
Here's a simple boiler plate for doing something with .withSuccessHandler
I added some JQuery, a msgdiv, withSuccessHandler() and a doSomethingWithCompetitionYear() server function.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
Year
<select name="Competition_year" id="Competition_year" type="integer">
<option value=<?= thisYear?>><?= thisYear?></option>
<option value="nextYear"><?= nextYear?></option>
</select>
<hr/>
<button onmouseup="closeDia()">Submit</button>
<div id="msgdiv"></div>
<script>
var theYear = document.getElementById("Competition_year").value;
google.script.run
.withSuccessHandler(function(msg){
document.getElementById("msgdiv").innerHTML=msg;
}))
.doSomethingWithCompetitionYear();
window.closeDia = function() {
google.script.host.close({year:$("#competition_year").val()});
};
</script>
</body>
</html>
code.gs:
function doSomethingWithCompetitionYear(obj) {
return Utilities.formatString('I did something with this year: %s',obj.year);
}
Situation:
If I understand you correctly you have a dialog box with two options, and you want to pass information on the selected option (in this case, 2020 or 2021) to the server-side function doSomethingWithCompetitionYear(); when the Submit button is clicked.
Issues:
If that's the case, you don't actually need a success handler. You just need to pass the selected value as a parameter of doSomethingWithCompetitionYear(theYear);.
Also, if you want this to happen when the Submit button is clicked. You should add this to the closeDia function. Otherwise, doSomethingWithCompetitionYear(); will run before submission.
Finally, if you want to pass the next year (2021), and not the string "nextYear", you'll have to use scriplets on the element's value.
Modification 1. Next year value:
Replace this:
<option value="nextYear"><?= nextYear?></option>
For this:
<option value=<?= nextYear?>><?= nextYear?></option>
Modification 2. Calling server-side function when button is clicked:
Replace this:
<script>
var theYear = document.getElementById("Competition_year").value;
google.script.run.doSomethingWithCompetitionYear();
window.closeDia = function() {
google.script.host.close();
};
</script>
For this:
<script>
window.closeDia = function() {
var theYear = document.getElementById("Competition_year").value;
google.script.run.doSomethingWithCompetitionYear(theYear); // theYear parameter has to be passed to server-side function
google.script.host.close();
};
</script>
Note:
If you want to use information coming from doSomethingWithCompetitionYear(theYear); in the client-side, you should use a success handler, which can call a client-side function that will get this data as a parameter (the server-side function, called by google.script.run doesn't return anything by itself, it needs a callback function). It would be something like this:
google.script.run.withSuccessHandler(yourClientSideFunction).doSomethingWithCompetitionYear(theYear);
Reference:
Class google.script.run (Client-side API)

Passing JS variable to HTML in Google Scripts

I am trying to change text in the html that is sent via email to a JS variable that I have defined. It is important that I am doing this in Google Scripts and have 2 files Code.gs & Email.html.
It seems like my html is not able to access the JS variable but I am not sure where I am going wrong here. I have referenced somewhat similar posts and tried a could different ways but cant get it to work. If anyone ha suggestions, that would be fantastic.
Code.gs
var JSname;
function Email() {
JSname = 'It works!'
var theEmail = 'myemail#gmail.com';
var theSubject = 'Email subject line';
var template = HtmlService.createTemplateFromFile('Email');
var message = template.evaluate().getContent();
MailApp.sendEmail({ to: theEmail, subject: theSubject, htmlBody: message });
return
}
Email.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<span id="HTMLname">[Text here]</span>
<script type="text/javascript" src="Code.gs">
document.getElementById("HTMLname").innerHTML = JSname;
</script>
</body>
</html>
Issue:
You're using a variable out of scope, simple as that
Fix:
Use template vars:
code.gs
function doGet(e) {
var template = HtmlService.createTemplateFromFile('Index'); // Or whatever you have
var JSname = 'It works!' // Ideally var names should start with lowercase
template.JSname = JSname // This is the IMPORTANT change
// Build and return HTML in IFRAME sandbox mode. (Copied from GS directly)
return template.evaluate()
.setTitle('Web App Window Title')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function Email() {
var theEmail = 'myemail#gmail.com';
var theSubject = 'Email subject line';
var template = HtmlService.createTemplateFromFile('Email');
var message = template.evaluate().getContent();
MailApp.sendEmail({
to: theEmail,
subject: theSubject,
htmlBody: message
});
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<span id="HTMLname"><?= JSname ?></span>
</body>
</html>
Source: https://script.google.com/u/1/home/start

Google Apps Script: passing error into templated HTML

I have the following code:
code.gs:
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('My Menu')
.addItem('Test', 'showTestForm')
.addToUi();
}
function showTestForm() {
var html = HtmlService.createHtmlOutputFromFile('TestForm');
SpreadsheetApp.getUi().showModalDialog(html, 'TEST');
}
function Test(formObject){
Logger.log("TEST")
var a = new Error( "Allready present "+ formObject);
a.error_code = 99;
Logger.log(JSON.stringify(a));
throw a;
}
TestForm.html
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<base target="_top">
<script>
function onFailure(error) {
var keys = Object.keys(error);
alert(JSON.stringify(keys));
alert(JSON.stringify(error.message));
alert(JSON.stringify(error.error_code));
}
function onSuccess() {
alert("Success");
}
</script>
</head>
<body>
<input type="submit" value="Save" onclick="google.script.run.withFailureHandler(onFailure).withSuccessHandler(onSuccess).Test('1')" />
<input type="button" value="Close" onclick="google.script.host.close()" />
</body>
</html>
When I open TestForm from menu and press "Save" I've got following log from Logger:
[18-12-24 23:08:24:765 PST] TEST
[18-12-24 23:08:24:766 PST] {"message":"Allready present 1","error_code":99}
So I see, that error object have properties 'message' and 'error_code'. But in browser I've got following alerts:
["name"]
"Error: Allready present 1"
undefined
So I see, that recived error object has only one empty (i've checked) property "name". But if I but refer to the property "message, I've got string like in original object (but not the same). And it looks like that object haven't poperty "error_code".
What's the matter?
I thought you might like a complete working example as I know this stuff can be quite frustrating.
This a simple example templated HTML file that can be used as a dialog or a webapp. All it does is create a Google Doc file with todays date in the header and footer of each page and it puts the file into the same directory as the spreadsheet which contains the script. That's it. I use the Chrome Browser. I don't even care if my scripts won't run on another browser.
Here's the HTML: (FileName:'docwithdate.html')
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<?!= include('resources') ?>
<?!= include('css') ?>
</head>
<body>
<?!= include('form') ?>
<?!= include('script') ?>
</body>
</html>
The Resources: (FileName: 'resources.html')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
The CSS: (FileName: 'css.html')
<style>
body {background-color:#ffffff;}
input[type="button"]{padding:0 0 2px 0;}
</style>
The Form: (FileName: form.html) This is probably push the templating idea a little far.
<form id="myForm" onsubmit="event.preventDefault();processForm(this);" >
<input type="text" id="txt1" name="filename" />
<input id="btn" type="submit" value="Submit" />
</form>
The Javascript: [FileName: 'script.html')
<script>
function createFile(){
var name=document.getElementById('filename').value;
google.script.run
.withSuccessHandler(function(rObj){
var html='<br />Go To File:' + rObj.filename + '';
$(html).appendTo("body");
})
.createTemplatedGoogleDoc(name);
}
function getInputObject(obj) {//I'm probably doing something wrong here. But this is what I had to do to get the object with the properties that I desired. So if you have another way. Go for it.
var rObj={};
for(var i=0;i<Object.keys(obj).length;i++){
if(obj[i].type=="text"){
rObj[obj[i].name]=obj[i].value;
}
console.log('Object.keys(rObj): %s',Object.keys(rObj).join(', '));
}
return rObj;
}
function processForm(obj){
var fObj=getInputObject(obj);
var name=fObj.filename;
google.script.run
.withSuccessHandler(function(rObj){
document.getElementById("btn").disabled=true;
var html='<br />Go To File:' + rObj.filename + '';
$(html).appendTo("body");
})
.createTemplatedGoogleDoc(name);
}
console.log('My Code');
</script>
The Google Script: (FileName: Code.gs)
function onOpen(){
SpreadsheetApp.getUi().createMenu('My Menu')
.addItem("Open Templated Google Doc", 'showMyDialog')
.addToUi()
}
function createTemplatedGoogleDoc(name){
Logger.log(name);
var doc=DocumentApp.create(name);//Creates a google doc
var fldrs=DriveApp.getFileById(SpreadsheetApp.getActive().getId()).getParents();
while(fldrs.hasNext()){
var fldr=fldrs.next();
if(fldr.getName()=="Create Templated Google Doc App"){
var folder=fldr;
}
}
Drive.Files.update({"parents": [{"id": folder.getId()}]}, doc.getId());//puts doc file into same directory as the spreadsheet that contains the script
doc.addHeader().appendParagraph(Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "E MMM dd, yyyy"));
doc.addFooter().appendParagraph(Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "E MMM dd, yyyy"));
//doc.getBody().getChild(0).removeFromParent();
doc.saveAndClose()
var rObj={url:doc.getUrl(),filename:doc.getName()}
return rObj;
}
function showMyDialog(){
var ui=HtmlService.createTemplateFromFile('docwithdate').evaluate();
SpreadsheetApp.getUi().showModelessDialog(ui, 'My Doc with Date');
}
function doGet(){//if you want a web app this is helpful
return HtmlService.createTemplateFromFile('docwithdate').evaluate();
}
function include(filename){//this is the include that the template uses
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
It's a pretty simple script. I hope it helps you get a start.
In accordance with the proposal of #TheMaster it is necessary to do this:
code.gs
function Test(formObject){
var a = new Error( JSON.stringify({msg:"Allready present "+ formObject,code:99}));
throw a;
}
TestForm.html
// removing "Error: " from message string to get our json back
var json = error.message.replace("Error: ",'')
var msg = JSON.parse(json).msg;
var code = JSON.parse(json).code;
That is, we put json into the attribute message of the Error object, and then, by cutting our json, we parse it and get the necessary values.
This is not exactly the answer to the question, but a good way to solve the problem.

How to get JavaScript text to show?

This is for a class I'm taking. Its homework out of the book for a particular chapter. The book provides some code that is purposly not working and you have to fix it. I've got it all working exept for this part where youre supposed to get some text to show up at the bottom of the screen that displays the last time the document was modified.
Ive gone over it repeatably and cant find whats wrong. Im wondering if the book has it wrong.
<head>
<script type="text/javascript">
function CopyRight() {
var lastModDate = document.lastModified
var lastModDate = lastModDate.substring(0,10)
xxx.innerHTML = "<p style='font-size:8pt;'>The URL of this document is "+document.URL+"<br />Copyright Frank's Fix-t Hardware. This document was last modified "+lastModDate+".</p>"
</script>
</head>
<body>
<div id="xxx"></div>
</body>
The mistakes are in your program
Missing closing curly } brace.
Not invoking the function CopyRight()
Inside CopyRight() not getting the xxx element to work on this.
Script should be invoked when the dom is ready (so placed script after xxx tag)
Correct version of your program is
<html>
<head>
</head>
<body>
<div id="xxx"></div>
<script type="text/javascript">
function CopyRight() {
var xxx = document.getElementById('xxx'); //mistake 3
var lastModDate = document.lastModified
var lastModDate = lastModDate.substring(0,10)
xxx.innerHTML = "<p style='font-size:8pt;'>The URL of this document is "+document.URL+"<br />Copyright Frank's Fix-t Hardware. This document was last modified "+lastModDate+".</p>"
} //mistake 1
CopyRight(); //mistake 2
</script>
</body>
</html>
This is the working one. The code works fine but you forgot to call the CopyRight function.
<head>
<script type="text/javascript">
function CopyRight() {
var lastModDate = document.lastModified
var lastModDate = lastModDate.substring(0,10)
xxx.innerHTML = "<p style='font-size:8pt;'>The URL of this document is "+document.URL+"<br />Copyright Frank's Fix-t Hardware. This document was last modified "+lastModDate+".</p>"
}
CopyRight(); // Call Copyright function
</script>
</head>
<body>
<div id="xxx"></div>
</body>

Categories