I have a current Google Form and App Script where the Apps Script is taking the form data, putting it into a spreadsheet template (which does some calculations) then e-mails that spreadsheet as a PDF.
Is there a way in Google Apps Script to have this PDF displayed in the web browser rather than being sent in an e-mail?
You can use this workround .
pag.html
<html>
<input type="submit" onclick="downloadPDF()"/>
Click here to open
<script>
function sucess(e) {
alert(e);
var downloadLink = document.getElementById("myDownloadLink");
downloadLink.href=e;
downloadLink.style.display = 'block';
}
function downloadPDF() {
google.script.run.withFailureHandler(alert).withSuccessHandler(sucess).getFile();
}
</script>
</html>
code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile("pag");
}
function getFile() {
return DriveApp.getFileById("1pczv0kRvgpI87owXWUXTtm4wXXsiG8-ErVWFtv05izI").getUrl();
}
Related
I want to known is there any way to update the card when I close the dialog
//this function is called when click a button in the card
function showDialog() {
const html = HtmlService.createHtmlOutputFromFile('dialog.html')
.setWidth(600)
.setHeight(425)
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
SpreadsheetApp.getUi().showModalDialog(html, 'Select the spreadsheets');
}
//this function is called by client code
function callback(text) {
var card = CardService.newCardBuilder().build();
var navigation = CardService.newNavigation().updateCard(card);
return CardService.newActionResponseBuilder()
.setNavigation(navigation)
.setNotification('Import Succeed')
.build();
}
dialog.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
<script>
function onApiLoad() {
gapi.load('picker', {'callback': function() {
......
}});
}
function createPicker(token) {
if (pickerApiLoaded && token) {
var picker = new google.picker.PickerBuilder()
.addView(new google.picker.DocsView(google.picker.ViewId.SPREADSHEETS)
.setMode(google.picker.DocsViewMode.LIST)
.setCallback(pickerCallback)
.........
.build();
picker.setVisible(true);
} else {
showError('Unable to load the file picker.');
}
}
function pickerCallback(data) {
var action = data[google.picker.Response.ACTION];
if (action == google.picker.Action.PICKED) {
google.script.run.callback('');
google.script.host.close();
} else if (action == google.picker.Action.CANCEL) {
google.script.host.close();
}
}
</script>
</head>
<body>
<script src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
</body>
</html>
I can write the text in the current spreadsheet developer metadata, and check the developer metadata in a dead loop in the card like the below code, but if user didn't close the dialog in time, google will throw timeout error in the card
//this function is called when click a button in the card
function showDialog() {
const html = HtmlService.createHtmlOutputFromFile('dialog.html')
.setWidth(600)
.setHeight(425)
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
SpreadsheetApp.getUi().showModalDialog(html, 'Select the spreadsheets');
//But I must return a response within a certain time since google has time limit for response
var metadataList = SpreadsheetApp.getActive().getDeveloperMetadata();
//find the text in the metadataList, and return the response
}
//this function is called by client code
function callback(text) {
//updat the card with text
SpreadsheetApp.getActive().addDeveloperMetadata('text', text);
}
Tl;Dr There is no way to update a card when a dialog is closed.
While an Editor add-on and Workspace add-on might share the same Google Apps Script project / Google Cloud project they are still two different add-ons. At this time there is no way to directly communicate two add-ons.
Workspace add-ons don't have triggers for file edit / changes, only for user clicking a card button.
For your current approach, I think that the only thing that you can do is to provide instructions to the user to reopen the card.
Related
Update Google Calendar UI after changing visability setting via Workspace Add-On
How to fully refresh Google Addon Card (Google Sheets) which includes a drop down menu populated using sheet data when data changes?
Is it possible to refresh the Google Workspace Add-on sidebar card from installable trigger function?
How to run multiple scripts when we open an HTML web app...?
Below is my example script, when user opens the HTML web apps the second (function getMail) script should run and capture the email id in defined sheet
function doGet() {
return HtmlService
.createTemplateFromFile('index')
.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME);
return html;
}
function getMail() {
Logger.log(Session.getActiveUser().getEmail());
var value = Logger.getLog();
var ss = SpreadsheetApp.openById("1IRpIzJKdc50dz99hYHoUVUBuwwhZI4NGdEKbc2QWqS8").getActiveSheet();
ss.getRange(ss.getLastRow()+1,1).setValue(value);
}
function getData() {
return SpreadsheetApp
.openById('1P0Z_njzrwjiPHrynDW37OTjwaPPFvntpiyBYSNBXt40')
.getDataRange()
.getValues();
}
You can call Google Apps Script function getMail from index.html template using next syntax:
<? getMail() ?>
Detailed docs: https://developers.google.com/apps-script/guides/html/templates#calling_apps_script_functions_from_a_template
I'm writing a script for Google Sheets which opens a form for uploading a file, and calls server-side function to handle the uploaded file. The problem I have is that the server-side function does not get called and failure handler is invoked with error message saying that I have no permissions to do the operation.
If I call the server side function with null argument instead of passing in the form then the function successfully gets called.
Here is the script I have:
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var csvMenuEntries = [{name: "Process bank statement file", functionName: "openUploadPaymentsDialog"}];
ss.addMenu("AG_Menu", csvMenuEntries);
}
function openUploadPaymentsDialog(e) {
var html = HtmlService.createHtmlOutputFromFile('UploadPaymentsDialog');
SpreadsheetApp.getUi().showModalDialog(html, 'Upload .NDA file');
Logger.log('dialog opened');
}
function handleFileUpload(theForm) {
Logger.log('file uploaded');
}
And HTML form:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<form>
<input type="file" name="theFile"/><br/><br/>
<input type="button" value="Submit" onclick="onSubmit(this.parentNode);"/>
</form>
<div id="output"/>
<script>
function onSubmit(theForm) {
google.script.run
.withSuccessHandler(onSuccess)
.withFailureHandler(onFailure)
.handleFileUpload(theForm);
//if I call handleFileUpload with null as argument then call succeeds
}
function onFailure(error){
var div = document.getElementById('output');
div.innerHTML = "ERROR: " + error.message;
}
function onSuccess(f){
google.script.host.close();
}
</script>
</body>
</html>
The script is bound to the spreadsheet and I'm not the owner of the spreadsheet, but I have permissions to edit. I'm running the script from my user (not owner).
Is it so that only owner can upload files? Why is that?
I found out that it is probably some problem with browser I'm using. It is Google Chromium under Debian Linux. I have just tried it with Firefox and it works OK.
I want to http post an image from html form to google apps script web app, and then add that image to google drive.
my apps script is below.
function doPost(e){
var date = new Date();
var timestamp = date.toString()
var adress = e.parameter.adress;
var cost = e.parameter.cost;
var item = e.parameter.item;
var check = e.parameter.image;
//add file to drive
var destination_id = "some ID"
var destination = DriveApp.getFolderById(destination_id);
destination.createFile(check);
};
when I execute, it returns a error ; cannot find method: createFile(String)
I think this is because "check" is a string, and I want to convert the submitted image to Blob.
How can I do this?
How about following sample? Added "getAs()". https://developers.google.com/apps-script/reference/drive/file#getAs(String)
These are very simple html and gas script I used for this test.
HTML: This file name is "form.html".
<form>
<input type="file" name="imageFile">
<input type="button" value="ok" onclick="google.script.run.upload(this.parentNode)">
</form>
GAS script:
function doGet() {
return HtmlService.createHtmlOutputFromFile('form.html');
}
function upload(e) {
var destination_id = "some ID";
var img = e.imageFile;
var contentType = "image/jpeg";
var destination = DriveApp.getFolderById(destination_id);
var img = img.getAs(contentType);
destination.createFile(img);
}
For this sample script, if you want to save as a jpeg file, please change 'contentType' from 'image/png' to 'image/jpeg'. When you upload png file for contentType of 'image/jpeg', the png file is converted to jpeg file by 'getAs()'.
Updated: March 19, 2020
When V8 is enabled, it seems that this.parentNode cannot be sent to Google Apps Script side. I'm not sure whether this is a bug or the specification. I think that this might be resolved in the future update. But as the current workaround, I would like to add one more sample script for uploading the file using Web Apps, dialog and sidebar.
In this case, the file is sent to Google Apps Script side as the byte array. And the file is created from the byte array at Google Apps Script side.
HTML & Javascript: index.html
<input id="file" type="file" onchange="saveFile(this)" />
<script>
function saveFile(f) {
const file = f.files[0];
const fr = new FileReader();
fr.onload = function(e) {
const obj = {
filename: file.name,
mimeType: file.type,
bytes: [...new Int8Array(e.target.result)]
};
google.script.run.withSuccessHandler(e => console.log(e)).saveFile(obj);
};
fr.readAsArrayBuffer(file);
}
</script>
Google Apps Script: Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('index.html');
}
function saveFile(e) {
var blob = Utilities.newBlob(e.bytes, e.mimeType, e.filename);
DriveApp.createFile(blob);
return "Done.";
}
Updated: December 9, 2021
After V8 runtime was released, there was a bug that when the file is sent from HTML form to Google Apps Script side using google.script.run, the file blob was the invalid data.
From Apps Script Pulse by Martin Hawksey, it was found that the invalid blob of sending the file of HTML form to Google Apps Script side using google.script.run has finally been resolved. In this case, this script can be used with V8 runtime.
HTML & Javascript side: index.html
<form>
<input type="file" name="file" onchange="google.script.run.withSuccessHandler(console.log).upload(this.parentNode)">
</form>
Google Apps Script side: Code.gs
const doGet = _ => HtmlService.createHtmlOutputFromFile('index.html');
const upload = ({file}) => DriveApp.createFile(file).getId();
IMPORTANT:
As an important point, in the current stage, when the above HTML is accessed as Web Apps (doGet), this script works. But when the above HTML is accessed as a dialog and a sidebar, file at the Google Apps Script side is undefined. By this, it seems that in the current stage, this HTML can be used with only Web Apps. Please be careful about this. I would like to believe that this situation is resolved in the future update.
In my Google Script I have 2 files: Form.html and Code.gs
When user click button in Form.html, the script start code in Code.gs, but I need inform user about process.
How I can change text in Form.html from Code.gs?
Form.html crate in Code.gs by this function:
function showSidebar() {
var ui = HtmlService.createHtmlOutputFromFile('Form')
.setTitle('Report');
SpreadsheetApp.getUi().showSidebar(ui);
}
And Form.html have
<div id="report"></div>
For status report.
What you need to do is use templated HTML, see: https://developers.google.com/apps-script/guides/html/templates
Example:
function showSidebar() {
var ui = HtmlService.createTemplateFromFile('Form');
ui.message = "Hello!";
ui = ui.evaluate().setTitle('Report');
SpreadsheetApp.getUi().showSidebar(ui);
}
And in Form.html:
<div id="report"><?=message?></div>