Google sheet not being updated by setValues - google-apps-script

I am writing a large file uploader for Google Drive and when I tried to implement writing some data to a Google Sheet I ran into a brick wall, for whatever reason I could not get it to ever write or even give a error as to why. I decided to start a whole new project and made it as simple as possible so all it does is grab similar data to what I will be grabbing and write it, but still no luck.
I am not super familiar with the Google Apps processes or the syntax of using them so I am probably just doing something really stupid.
Old code removed
I have tried removing some variables like file and email in case they needed to be written differently and changing how the form is passed to the function but the best I ever got was a "Cannot read Null" error when I passed it a form that didn't exist.
UPDATE:
Once I had it working I tried to slip it into the main script I am using (Which is basically a copy of this but now its not working, I am realizing this may be over my head unfortunately cause no matter what I try its doing the same, runs and uploads the file fine, but does not update the form.
Google Scripts:
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('Form.html');
}
function getAuth() {
return { accessToken: ScriptApp.getOAuthToken(), folderId: "1sFxs3Ga4xWFCgIXRUnQzCAAp_iRX-wdj" };
}
function setDescription({fileId, description}) {
DriveApp.getFileById(fileId).setDescription(description);
}
function updateform(formObject) {
try {
var ss = SpreadsheetApp.openById('1iCTNZ6RERnes1Y-ocfXzPN3jviwdIEK_dBKQ4LIu5KI');
var sheet = ss.getSheets()[0];
sheet.appendRow([myFile.getName(), myFile.getUrl(), formObject.myName], "If This Shows Up It Worked");
} catch (error) {
return error.toString();
}
}
HTML:
<form id="myForm" align="center" onsubmit="updatesheet(This)">
<input type="text" name="myName" placeholder="Your name..">
<input type="file" name="myFile">
<input type="submit" value="Submit Form" onclick="run(); return false;">
</form>
<div id="progress"></div>
<div id="output"></div>
<script src="https://cdn.jsdelivr.net/gh/tanaikech/ResumableUploadForGoogleDrive_js#master/resumableupload_js.min.js"></script>
<script>
function onSuccess() {
var div = document.getElementById('output');
div.innerHTML = '<a href="Spreadsheet Updated</a>';
}
function onFailure(error) {
alert(error.message);
}
function updatesheet(form) {
google.script.run.withSuccessHandler(onSuccess).withFailureHandler(onFailure).updateform(form);
}
function run() {
google.script.run.withSuccessHandler(accessToken => ResumableUploadForGoogleDrive(accessToken)).getAuth();
}
function ResumableUploadForGoogleDrive({accessToken, folderId}) {
const myName = document.getElementsByName("myName")[0].value;
const file = document.getElementsByName("myFile")[0].files[0];
if (!file) return;
let fr = new FileReader();
fr.fileName = file.name;
fr.fileSize = file.size;
fr.fileType = file.type;
fr.readAsArrayBuffer(file);
fr.onload = e => {
var id = "p";
var div = document.createElement("div");
div.id = id;
document.getElementById("progress").appendChild(div);
document.getElementById(id).innerHTML = "Initializing.";
const f = e.target;
const resource = { fileName: f.fileName, fileSize: f.fileSize, fileType: f.fileType, fileBuffer: f.result, accessToken, folderId };
const ru = new ResumableUploadToGoogleDrive();
ru.Do(resource, function (res, err) {
if (err) {
console.log(err);
return;
}
console.log(res);
let msg = "";
if (res.status == "Uploading") {
msg = Math.round((res.progressNumber.current / res.progressNumber.end) * 100) + "% (" + f.fileName + ")";
} else {
msg = res.status + " (" + f.fileName + ")";
}
if (res.status == "Done") {
google.script.run.withSuccessHandler(_ => {
document.getElementById('myForm').style.display = 'none';
document.getElementById('p').style.display = 'none';
document.getElementById('output').innerHTML = "All information submitted, thank you!";
}).setDescription({fileId: res.result.id, description: "Uploaded by " + myName});
}
document.getElementById(id).innerText = msg;
});
}
}
</script>

Several things about your updated code.
First it should be this not This.
Second you have onsubmit and onclick events for the same form. I believe the onclick is suppressing the submit event. Remove onclick entirely.
Third you use a try catch block in updateform so withFailureHandler will never execute. Instead the error message or null is returned to the success handler onSuccess(error).
Forth, I use a paragraph <p> instead of an anchor <a>. The href is malformed in your anchor.
Last, run() can be executed in updatesheet(form). Note run() is asynchronous which means it doesn't wait for google.script.run to finish before executing.
I can simply tell you that all the alerts are displayed and the execution log shows updateform did execute. So this code works for me.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<form id="myForm" align="center" onsubmit="updatesheet(this)">
<input type="text" name="myName" placeholder="Your name..">
<input type="text" name="myFile">
<input type="submit" value="Submit Form">
</form>
<div id="progress"></div>
<div id="output"></div>
<script>
function onSuccess(error) {
if( error ) {
alert(err);
return;
}
alert("onSuccess");
var div = document.getElementById('output');
div.innerHTML = "<p>Spreadsheet Updated</p>";
}
function run() {
alert("run");
}
function updatesheet(form) {
alert("updatesheet");
google.script.run.withSuccessHandler(onSuccess).updateform(form);
run();
}
</script>
</body>
</html>

Related

Upload file and past the link into active cell a spreadsheet

Trying to make a script to upload a file and paste the downloaded file's link into the active cell of a google spreadsheet.
After clicking "Upload" in the modal window, the file is not written to Google Drive and, accordingly, the link is not written to the cell
Code.gs
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('File')
.addItem('Attach...', 'showForm')
.addToUi();
}
function showForm() {
var html = HtmlService.createHtmlOutputFromFile('index');
SpreadsheetApp.getUi().showModalDialog(html, 'Upload File');
}
function uploadFile(e) {
var newFileName = e.fileName;
var blob = e.file;
var upFile = DriveApp.getFolderById('*FolderID*').createFile(blob).setName(newFileName);
Logger.log(upFile);
var fileUrl = upFile.getUrl();
var formula = '=HYPERLINK("' + fileUrl + '","' + newFileName + '")';
SpreadsheetApp.getActiveRange().setFormula( formula );
return "Uploaded!";
}
index.html
<!DOCTYPE html>
<html>
<head>
<base target="_center">
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
</head>
<body>
<form id="myForm" >
Select File: <input type="file" name="file" accept="*" /><br>
File name: <input type="text" name="fileName" /><br><br>
<input type="button" value="Upload" onclick="upload(this.parentNode);" />
</form>
<script>
window.onload=func1;
function func1() {
document.getElementById('myForm').addEventListener('submit', function(event) {
event.preventDefault();
});
}
function upload(obj){
google.script.run.withSuccessHandler(close).withFailureHandler(close).uploadFile(obj);
}
function close(e) {
console.log(e);
google.script.host.close();
}
</script>
</body>
</html>
Issue and workaround:
On December 9, 2021, the file object got to be able to be parsed from the Javascript side to the Google Apps Script side with V8 runtime. But, in this case, this can be used for only Web Apps. In the current stage, the sidebar and dialog cannot parse the file object on the Javascript side. Ref I think that this is the reason of your issue. So, in the current stage, it is required to send the file object as the string and the byte array for the sidebar and the dialog.
In this case, in order to achieve your goal using the current workaround, I would like to propose the following 2 patterns.
By the way, I think that in your Google Apps Script, an error occurs at SpreadsheetApp.getActiveCell().setFormula( formula );. Because SpreadsheetApp has no method of getActiveCell(). In this case, I think that getActiveRange() might be suitable.
Modified script:
In this modification, the file object is converted to the byte array, and the data is sent to Google Apps Script side.
Google Apps Script side:
function showForm() {
var html = HtmlService.createHtmlOutputFromFile('index');
SpreadsheetApp.getUi().showModalDialog(html, 'Upload File');
}
function uploadFile(e) {
var blob = Utilities.newBlob(...e);
var upFile = DriveApp.getFolderById('*FolderID*').createFile(blob).setName(e[2]);
Logger.log(upFile);
var fileUrl = upFile.getUrl();
var formula = '=HYPERLINK("' + fileUrl + '","' + e[2] + '")';
SpreadsheetApp.getActiveRange().setFormula(formula);
return "Uploaded!";
}
HTML & Javascript side:
<!DOCTYPE html>
<html>
<head>
<base target="_center">
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
</head>
<body>
<form id="myForm">
Select File: <input type="file" name="file" accept="*" /><br>
File name: <input type="text" name="fileName" /><br><br>
<input type="button" value="Upload" onclick="upload(this.parentNode);" />
</form>
<script>
window.onload = func1;
function func1() {
document.getElementById('myForm').addEventListener('submit', function(event) {
event.preventDefault();
});
}
function upload(obj) {
const file = obj.file.files[0];
// --- For your additional request, I modified below script.
const extension = function(e) {
const temp = e.split(".");
return temp.length == 1 ? "" : temp.pop();
}(file.name);
const filename = `${obj.fileName.value}.${extension}`;
// ---
const fr = new FileReader();
fr.onload = e => {
const obj = [[...new Int8Array(e.target.result)], file.type, filename];
google.script.run.withSuccessHandler(close).withFailureHandler(close).uploadFile(obj);
};
fr.readAsArrayBuffer(file);
}
function close(e) {
console.log(e);
google.script.host.close();
}
</script>
</body>
</html>
Note:
In your script, I thought that the modified script might be a bit complicated. So, I posted the modified script as an answer.
Reference:
Related thread.
How do I convert jpg or png image to Blob via a Google Apps Script Web App?

Direct to a new page after form submission

Currently I've developed a Google Scripts API which is used for people to upload files to a shared Google Drive folder. After the file are uploaded successfully, I want them to be taken to a separate "Thank you" page so it is clear their upload has worked. Currently I only have a message on the same page to this effect and I cannot figure out how to direct to a new page that I have created.
This is the additional bit I found from different questions to try direct to a new page however this is not working so far, as it remains on the same upload form page. I have included it at the bottom of my code.gs file. Any ideas on how to direct to a custom page that just says "thank you" or something similar would be great!
function doPost(e) {
var template = HtmlService.createTemplateFromFile('Thanks.html');
return template.evaluate();
}
The rest of my code is as follows:
Code.gs:
function doGet() {
return HtmlService.createHtmlOutputFromFile('form').setSandboxMode(
HtmlService.SandboxMode.IFRAME);
}
function createFolder(parentFolderId, folderName) {
try {
var parentFolder = DriveApp.getFolderById(parentFolderId);
var folders = parentFolder.getFoldersByName(folderName);
var folder;
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = parentFolder.createFolder(folderName);
}
return {
'folderId' : folder.getId()
}
} catch (e) {
return {
'error' : e.toString()
}
}
}
function uploadFile(base64Data, fileName, folderId) {
try {
var splitBase = base64Data.split(','), type = splitBase[0].split(';')[0]
.replace('data:', '');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var ss = Utilities.newBlob(byteCharacters, type);
ss.setName(fileName);
var folder = DriveApp.getFolderById(folderId);
var files = folder.getFilesByName(fileName);
var file;
while (files.hasNext()) {
// delete existing files with the same name.
file = files.next();
folder.removeFile(file);
}
file = folder.createFile(ss);
return {
'folderId' : folderId,
'fileName' : file.getName()
};
} catch (e) {
return {
'error' : e.toString()
};
}
}
function doPost(e) {
var template = HtmlService.createTemplateFromFile('Thanks.html');
return template.evaluate();
}
Form.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div align="center">
<p><img src="https://drive.google.com/uc?export=download&id=0B1jx5BFambfiWDk1N1hoQnR5MGNELWRIM0YwZGVZNzRXcWZR"
height="140" width="400" ></p>
<div>
<form id="uploaderForm">
<label for="uploaderForm"> <b> Welcome to the Tesco's animal welfare and soy reporting system. </b> </label>
<BR>
<BR>
<div style="max-width:500px; word-wrap:break-word;">
Please add your contact information below and attach a copy of your company's animal welfare standard before clicking submit. Wait for the browser to confirm your submission and you may then close this page.
<BR>
<BR>
Thank you very much for your submission.
</div>
<BR>
<BR>
<div>
<input type="text" name="applicantName" id="applicantName"
placeholder="Your Name">
</div>
<BR>
<div>
<input type="text" name="applicantEmail" id="applicantEmail"
placeholder="Your Company">
</div>
<BR>
<BR>
<div>
<input type="file" name="filesToUpload" id="filesToUpload" multiple>
<input type="button" value="Submit" onclick="uploadFiles()">
</div>
</form>
<br>
<br>
<br>
<br>
<br>
<br>
<div id="output"></div>
<script>
var rootFolderId = '1-aYYuTczQzJpLQM3mEgOkWsibTak7KE_';
var numUploads = {};
numUploads.done = 0;
numUploads.total = 0;
// Upload the files into a folder in drive
// This is set to send them all to one folder (specificed in the .gs file)
function uploadFiles() {
var allFiles = document.getElementById('filesToUpload').files;
var applicantName = document.getElementById('applicantName').value;
if (!applicantName) {
window.alert('Missing applicant name!');
}
var applicantEmail = document.getElementById('applicantEmail').value;
if (!applicantEmail) {
window.alert('Missing applicant email!');
}
var folderName = applicantEmail;
if (allFiles.length == 0) {
window.alert('No file selected!');
} else {
numUploads.total = allFiles.length;
google.script.run.withSuccessHandler(function(r) {
// send files after the folder is created...
for (var i = 0; i < allFiles.length; i++) {
// Send each file at a time
uploadFile(allFiles[i], r.folderId);
}
}).createFolder(rootFolderId, folderName);
}
}
function uploadFile(file, folderId) {
var reader = new FileReader();
reader.onload = function(e) {
var content = reader.result;
document.getElementById('output').innerHTML = 'uploading '
+ file.name + '...';
//window.alert('uploading ' + file.name + '...');
google.script.run.withSuccessHandler(onFileUploaded)
.uploadFile(content, file.name, folderId);
}
reader.readAsDataURL(file);
}
function onFileUploaded(r) {
numUploads.done++;
document.getElementById('output').innerHTML = 'uploaded '
+ r.fileName + ' (' + numUploads.done + '/'
+ numUploads.total + ' files).';
if (numUploads.done == numUploads.total) {
document.getElementById('output').innerHTML = 'All of the '
+ numUploads.total + ' files are uploaded';
numUploads.done = 0;
}
}
</script>
<label for="uploaderForm">
Powered by 3Keel
</label>
</body>
</html>
Thanks.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
Thank you for submitting!
</body>
</html>
EDIT:
I have changed this function as recommended:
if (numUploads.done == numUploads.total) {
window.location = 'Thanks.html';
numUploads.done = 0;
Now it is redirecting to another page but I am faced with this error:
That’s an error.
The requested URL was not found on this server. That’s all we know.
If you are looking for the solution of your issue yet, how about this answer?
You want to open Thanks.html when the process at Form.html is finished.
Form.html and Thanks.html are put in a project.
If my understanding is correct, how about this workaround? I have ever experienced with your situation. At that time, I could resolve this issue by this workaround.
Modification points:
It is not required to use doPost() to access to Thanks.html. I think that you can achieve what you want using doGet().
I think that #Scott Craig's answer can be also used for this situation. In my workaround, the URL of window.location = 'Thanks.html'; is modified.
Uses the URL of deployed Web Apps. In your script, when users access to your form, they access to the URL of the deployed Web Apps. In this workaround, it is used by adding a query parameter.
Modified scripts:
Form.html
For the script added in your question as "EDIT", please modify as follows.
From:
window.location = 'Thanks.html';
To:
window.location = 'https://script.google.com/macros/s/#####/exec?toThanks=true';
https://script.google.com/macros/s/#####/exec is the URL of the the deployed Web Apps. Please add a query parameter like toThanks=true. This is a sample query parameter.
Code.gs
Please modify doGet() as follows.
From:
function doGet() {
return HtmlService.createHtmlOutputFromFile('form')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
To:
function doGet(e) {
if (e.parameter.toThanks) {
return HtmlService.createHtmlOutputFromFile('Thanks')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
} else {
return HtmlService.createHtmlOutputFromFile('form')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
}
Note:
When the script of the deployed Web Apps was modified, please redeploy it as new version. By this, the latest script is reflected to Web Apps.
The flow of this modified script is as follows.
When users access to the Form.html, because the query parameter of toThanks=true is not used, Form.html is returned.
When onFileUploaded() is run and if (numUploads.done == numUploads.total) {} is true, it opens the Web Apps URL with the query parameter of toThanks=true. By this, if (e.parameter.toThanks) {} of doGet() is true, and Thanks.html is returned and opened it.
In my environment, I could confirm that this modified script worked. But if this didn't work in your environment, I'm sorry. At that time, I would like to think of about the issue.
I might be misunderstanding your question, but from what I understand, instead of this line:
document.getElementById('output').innerHTML = 'All of the '
+ numUploads.total + ' files are uploaded';
You want to redirect to Thanks.html. If that's correct, just replace the above line with:
window.location = 'Thanks.html';

Apps Script dialog box - HTML Service - Apply "withSuccessHandler" Properly - google.script.run

Background
I'm fairly new to coding in general and as I've gone through building this little UI for Google Sheets using GAS, this is one of the concepts that has just has me stumped. I've tried and tried reading, understand conceptually and apply withSuccessHandler(function) to all sorts of examples but I just can't seem to get it to work.
Here's what I understand so far:
When you run the following on the client side (e.g. Index.html):
google.script.run.withFailureHandler(CallbackFunction).ServerSideFunction(aVariable)
a. ServerSideFunction(aVariable): This function from your Code.gs is first called and returns a value, "OutputA," back to Index.html.
b. CallbackFunction: Then, this function is called and uses "OutputA" as its input and returns another value which you can use for whatever purpose.
Goal
Open Dialog Box asking for "Name" and "E-mail." DONE
Once user hits "Submit" the input is populated in the spreadsheet. DONE
The form is then cleared so they can potentially add another person or exit if they want.
Question
For that last piece, I can't seem to get withSuccessHandler to return a value back from my script, confirming that the inputs were entered properly, and I really don't know how to proceed.
I've included a working version of the code below without withSuccessHandler for reference. Any help at all in better understanding this and how I can incorporate it into the code below would be greatly appreciated!
Google Script
function onOpen(e) {
SpreadsheetApp.getUi()
.createMenu('Menu')
.addItem('Add Member', 'createDialog')
.addToUi();
}
function createDialog() {
var htmlOutput = HtmlService
.createHtmlOutputFromFile('Index')
.setWidth(300)
.setHeight(300);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, " ");
}
function addAName(bName, bEmail) {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var ControlSheet = sheet.getSheetByName('Control Sheet');
var lRow = ControlSheet.getRange(1, 1, ControlSheet.getLastRow(), 1).getValues().filter(String).length;
var Name = ControlSheet.getRange(lRow + 1, 1);
var Email = ControlSheet.getRange(lRow + 1, 2);
var ValidName = /(^[A-Za-z]+)\s([A-Za-z]{1}[.]{1}\s)?([A-Za-z]+$)/g;
var ValidEmail = /(^[A-Za-z]+)([.]{1})([A-Za-z]{1}[.]{1})?([A-Za-z]+)(#google.com|#yahoo.com)$/g;
if (bName.match(ValidName) && bEmail.match(ValidEmail)) {
Name.setValue(bName);
Email.setValue(bEmail);
}
}
HTML
<body>
<h2>Add New Member</h2>
<div class="mdc-layout-grid">
<div class="mdc-layout-grid__cell mdc-layout-grid__cell--span-12">
<div class="mdc-text-field mdc-text-field--upgraded" data-mdc-auto-init="MDCTextField">
<input class="mdc-text-field__input" id="Name" type="text" aria-controls="name-validation-message" pattern="(^[A-Za-z]+)\s([A-Za-z]{1}[.]{1}\s)?([A-Za-z]+$)">
<label for="Name" class="mdc-floating-label">Name</label>
<div class="mdc-line-ripple"></div>
</div>
<p class="mdc-text-field-helper-text mdc-text-field-helper-text--validation-msg" id="name-validation-message" aria-hidden="true">
Please enter your full name.
</p>
</div>
<div class="mdc-layout-grid__cell mdc-layout-grid__cell--span-12">
<div class="mdc-text-field" data-mdc-auto-init="MDCTextField">
<input class="mdc-text-field__input" id="Email" type="text" aria-controls="name-validation-message" pattern="(^[A-Za-z]+)([.]{1})([A-Za-z]{1}[.]{1})?([A-Za-z]+)(#google.com|#yahoo.com)$">
<label for="Email" class="mdc-floating-label">Email Address</label>
<div class="mdc-line-ripple"></div>
</div>
<p class="mdc-text-field-helper-text mdc-text-field-helper-text--validation-msg" id="name-validation-message" aria-hidden="true">
Please enter a valid Google or Yahoo email address.
</p>
</div>
</div>
<div class="Right_Side">
<button class="mdc-button mdc-button--unelevated secondary-filled-button" OnClick="google.script.host.close()">Cancel
</button>
<button class="mdc-button mdc-button--unelevated primary-filled-button" OnClick="sendInputToGS()">Submit
</button>
</div>
<script>
window.sendInputToGS = function() {
var aName = document.getElementById("Name").value;
var aEmail = document.getElementById("Email").value;
google.script.run.addAName(aName, aEmail);
}
</script>
<script type="text/javascript">
window.mdc.autoInit();
</script>
</body>
Only one parameter can be added to the server function being called. But you can use an array as the one parameter and put multiple values into the array.
var data_Array = [aName, aEmail];
google.script.run
.withSuccessHandler(myClientSideFunction)
.addAName(data_Array);
A value is not automatically returned, you must add a return myValue statement.
function addAName(data) {
var bName, bEmail;
bName = data[0];//Arrays in JavaScript are zero indexed
bEmail = data[1];
//code
return "something";
}
Client Code
<script>
window.sendInputToGS = function() {
var aName = document.getElementById("Name").value;
var aEmail = document.getElementById("Email").value;
var data_Array = [aName, aEmail];
google.script.run
.withSuccessHandler(confirmationBack)
.addAName(data_Array);
}
window.confirmationBack = function(rtrn) {
if (rtrn === 'success') {
}
}
</script>
The success and failure handlers for the async communication between the Apps Script instance and the client-side HTML code are functions in the client-side code, not written in Apps Script (.gs).
When calling your server-side function foo(input), it can be used to call other server-side functions (bar(), baz()) as desired, and use their outputs to form the value that is sent to the client-side success handler.
Example:
.gs
function foo(valFromClient) {
var firstPart = bar(valFromClient);
var secondPart = baz(valFromClient);
return {input: valFromClient, first: firstPart, second: secondPart};
}
function bar(input) {
return "'bar' called, input '" + String(input) + "'.";
}
function baz(val) {
return "'baz' called, input '" + String(val) + "'.";
}
.html
...
<script>
function getServerStuff() {
google.script.run
.withFailureHandler(serverThrewException)
.withSuccessHandler(serverFunctionCalledReturn)
.foo("Hi");
}
function serverThrewException(err) {
console.log(err);
}
function serverFunctionCalledReturn(value) {
console.log(value);
}
</script>
In this example, because our code does not throw any exceptions, the failure handler will never be called, and only the success handler will be called. The browser console would log the object {input: "Hi", first: "'bar' called, input 'Hi'.", second: "'baz' called, input 'Hi'."}.

google.script.run is not working when using shared script from library

I am working on a script, for which I am calling a function from a library with standalone scripts:
HTML file looks like this:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/themes/cupertino/jquery-ui.css">
<style type="text/css"> .demo { margin: 0px ; color : #AAA ; font-family : arial sans-serif ;font-size : 10pt }
p { color : black ; font-size : 11pt }
.ui-datepicker th {padding:5px;}
.ui-datepicker table {font-size:10px;}
.ui-widget {font-size:12px;}
input{width:100%;}
</style>
<base target="_top">
</head>
<body>
<div class="demo" >
<div style="width:30%;text-align:left;float:left;">
<p> Candidate Email : </p>
<p> Updated Status : </p>
<p> Assigned To :</p>
<p> Date :</p>
</div>
<div style="width:70%;text-align:left;float:left;">
<p> <input class="email" type="text" /></p>
<p><input class="status" type="text" /></p>
<p><input class="assigned" type="text" /></p>
<p><input type="text" name="StartDate" id="startdatepicker" /> </p>
</div>
<input class="submit" type="button" value="Submit" disabled=""/>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/jquery-ui.min.js"></script>
<script>
$(document).ready(function(){
$(".email").val(email);
$(".status").val(status);
$(".assigned").val(assigned);
$(document).on('click','input.submit',function(){
submitDates();
});
$( "#startdatepicker" ).datepicker({
showWeek: true,
firstDay: 0,
});
$(document).on('change','#startdatepicker',function(){
if($("#startdatepicker").val()!='')
{
$("input.submit").removeAttr("disabled");
}
else {
$("input.submit").attr("disabled","true");
}
});
});
</script>
<script>
function submitDates() {
var startDate = $("#startdatepicker").val();
var email = $(".email").val();
var status = $(".status").val();
var assigned = $(".assigned").val();
google.script.run
.withSuccessHandler(
// Dates delivered, close dialog
function() {
google.script.host.close();
})
// Display failure messages
.withFailureHandler(
function() {
var div = $('<div id="error" class="error">' + "Please enter the correct Date" + '</div>');
div.after($("#demo"));
})
.statusLogger(email, status, assigned, startDate);*/
}
</script>
</body>
</html>
And gs file looks like this:
function onEdit(event) {
var lSheet = SpreadsheetApp.getActive().getSheetByName("Status Logs");
var sheet = event.source.getSheetByName('Tracker');
var actRng = event.source.getActiveRange();
var editColumn = actRng.getColumn();
var index = actRng.getRowIndex();
var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues();
var dateCol = headers[0].indexOf("Status Change Date");
var updateCol = headers[0].indexOf("Application Status");
var emailCol = headers[0].indexOf("Email");
var assignCol = headers[0].indexOf("Assigned To");
var intType = sheet.getRange(index,updateCol+1).getValue();
var email = sheet.getRange(index,emailCol+1).getValue();
var assignedTo = sheet.getRange(index,assignCol+1).getValue();
if (dateCol > -1 && index > 1 && editColumn == updateCol+1) {
//lSheet.appendRow([email, intType, sheet.getRange(index, dateCol + 1).getValue(),assignedTo]);
var html = HtmlService.createHtmlOutputFromFile('dateDialogue')
.setWidth(300)
.setHeight(200)
.getContent();
var html2 = HtmlService.createHtmlOutput(html + '<script>var email= "'+ email +'";var status="'+ intType +'";var assigned="'+ assignedTo +'";</script>');
SpreadsheetApp.getUi()
.showModalDialog(html2, 'Please enter the Date');
}
}
statusLogger function just append a row in a sheet.
The issue is, google.script.run is not working although google.script.host.close() is working. Any help?
From your question I am concluding you have 2 scripts. One is a document bound script and the another one is stand alone script included in your document bound script as a library.
When you add a script in your project as a library you assign an identifier to it. The library functions can then be called from code.gs using this identifier.
Example:
I have a stand alone script named stackflow which I included in my project as an external library.
The identifier I gave to the library is stackflow
In my standalone script (which is included as a library)
function testLibraryFunction(){
return "successful execution of library function";
}
In my actual project I will try to access library function like this
code.gs
function executeLibraryCode(){
var result = stackflow.testLibraryFunction();
Logger.log(result);
return result
}
In my html file, I will call executeLibraryCode() which will call testLibraryFunction() function from library.
HTML file:
google.script.run
.withSuccessHandler(
// callback function
)
.withFailureHandler(
// callback function
)
.executeLibraryCode();
Also please remove */ from your html file after .statusLogger as mentioned by #ocordova in the comments.

calling function in window addEventListener popstate, not working

The problem i am facing is in the GetAjaxPageBack function whenever i try to write any function in it, like split, or any other function it do nothing and if i commented out the line
var url = url.split("?"); is start working fine, but why i need to split the url and want to get the query string and want to resend it using ajax to fetch the records.
<script language="javascript">
function GetAjaxPageBack(url) {
//this line is not working
var url = url.split("/");
alert(url);
/* $.post(url,
function(data){
if (data != "")
{
}
});
*/}
function GetAjaxPage(value)
{
if(value=='n')
{
val = $('#abc').val()+1;
$('#abc').val(val);
}else
{
val = $('#abc').val()-1;
$('#abc').val(val);
}
history.pushState(null, null, "?abc="+$('#abc').val());
window.addEventListener("popstate", function(e) {
GetAjaxPageBack(location);
});
}
</script>
</head>
<body><br />
Prev |
Next
<br /><br />
<input type="text" name="abc" id="abc" value="1" >
please help out, thanks
The location isn't a string but a Location object. Try using it's native functions or converting it to a string first.
location.toString().split('/')