I want to create a WebApp, that does the following:
User clicks button on WebApp to run script
Get User eMail
Create new Google Spreadsheet (name=eMail)
get Url of that Spreadsheet
Automatically open Url in new Tab
Step 5 is where I am stuck.
I have used window.open(url) before, however that only seems to work when you run code via a Spreadsheet. What I wanna do is displaying the button on my .html and run everything only with the WebApp but I can't do that because I can not use SpreadsheetApp.getUi() from that context.
Is there another way to do this?
Here is the Error im getting:
EDIT: Seems I had some minor mistakes in my Code.gs I think i fixed that now. Still same issue tho
Thank you guys in advance! :)
Here is some sample code:
Code.gs
function doGet(e) {
return HtmlService.createHtmlOutputFromFile("page");
}
function clickEvent () {
const lock = LockService.getScriptLock();
lock.tryLock(5000);
if (lock.hasLock()){
var email = Session.getActiveUser().getEmail();
var url = createFile(email);
openUrl(url); //THIS ONLY WORKED FROM WITHIN SPREADSHEET
lock.releaseLock();
}
}
function createFile(email){
var newSS= SpreadsheetApp.create(email);
var file = DriveApp.getFileById(newSS.getId());
var url = file.getUrl();
return url
}
function openUrl( url ){ //HAS TO CHANGE
var html = HtmlService.createHtmlOutput('<html><script>'
+'window.close = function(){window.setTimeout(function(){google.script.host.close()},9)};'
+'var a = document.createElement("a"); a.href="'+url+'"; a.target="_blank";'
+'if(document.createEvent){'
+' var event=document.createEvent("MouseEvents");'
+' if(navigator.userAgent.toLowerCase().indexOf("firefox")>-1){window.document.body.append(a)}'
+' event.initEvent("click",true,true); a.dispatchEvent(event);'
+'}else{ a.click() }'
+'close();'
+'</script>'
// Offer URL as clickable link in case above code fails.
+'<body style="word-break:break-word;font-family:sans-serif;">Failed to open automatically. Click here to proceed.</body>'
+'<script>google.script.host.setHeight(40);google.script.host.setWidth(410)</script>'
+'</html>')
.setWidth( 90 ).setHeight( 1 );
SpreadsheetApp.getUi().showModalDialog( html, "Opening ..." );
}
}
page.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h1>Click Button!</h1>
<button id="btn">Run</button>
<script>
document.getElementById("btn").addEventListener("click",sendRequest);
function sendRequest(){
google.script.run.clickEvent();
}
</script>
</body>
</html>
Get url from app script and open spreadsheet in new tab wit JavaScript
Update app script function
function clickEvent () {
const lock = LockService.getScriptLock();
lock.tryLock(5000);
if (lock.hasLock()){
var email = Session.getActiveUser().getEmail();
lock.releaseLock();
return createFile(email);
}
}
Also update JavaScript Code
function sendRequest(){
google.script.run.withSuccessHandler(
function (link) {
window.open(link, '_blank').focus();
}
).testCSV3();
}
Reference: Communicate with Server Functions
This is my first question here and I am pretty new to js and html so please excuse if I'm missing something obvious.
Goal: I want to create a script, that creates a Folder in your Google Drive but only if it's not already existing. In that folder it should create a .txt that contains certain information. After that, I want a new Tab to automatically open the URL of the newly created txt-file.
If I insert a normal URL in my .html (like "https://www.google.com") it all works perfectly fine. However I'm stuck at the part where the Apps Script hands over the grabbed Url of the newly created file to my html.
Any help is appreciated!
Google Apps Script Code (Code.gs):
function myFunction() {
var FData = "Very important Data"
var destFolder = DriveApp.getFoldersByName("Folder"); //create Drive folder if not already created
var destFolder = destFolder.hasNext() ?
destFolder.next() : DriveApp.createFolder("Folder");
var fileName = "Status.txt"; //create txt file in that folder and add data to it
var newFile = destFolder.createFile(fileName,FData);
var url = newFile.getUrl(); //?GIVE THIS URL TO openUrl.html?
var htmlOutput = HtmlService.createHtmlOutputFromFile('openUrl').setHeight(100);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'Opening...');
}
HTML (openUrl.html):
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
var urlToOpen = url; //insert grabbed Url here
var winRef = window.open(urlToOpen);
google.script.host.close();
</script>
</head>
<body>
</body>
</html>
In your script, how about the following modification?
Google Apps Script side:
function myFunction() {
var FData = "Very important Data"
var destFolder = DriveApp.getFoldersByName("Folder");
var destFolder = destFolder.hasNext() ? destFolder.next() : DriveApp.createFolder("Folder");
var fileName = "Status.txt";
var newFile = destFolder.createFile(fileName, FData);
var htmlOutput = HtmlService.createTemplateFromFile('openUrl');
htmlOutput.url = newFile.getUrl();
SpreadsheetApp.getUi().showModalDialog(htmlOutput.evaluate().setHeight(100), 'Opening...');
}
HTML & Javascript side:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
var urlToOpen = "<?!= url ?>";
var winRef = window.open(urlToOpen);
google.script.host.close();
</script>
</head>
<body>
</body>
</html>
When myFunction() is run, a dialog is opened by HTML including url using HTML template.
Reference:
HTML Service: Templated HTML
I am creating an online HTML form that gives people the option to upload a file. I am using google sheets to collect the data so I am using their google scripts feature. When I run my code everything works, meaning I get data inserted into cells, but not the file upload. Here is my Google Scripts code for the file upload:
function doGet(request) {
return HtmlService.createTemplateFromFile('Index')
.evaluate();
}
/* #Include JavaScript and CSS Files */
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename)
.getContent();
}
function uploadFiles(data){
var folder = DriveApp.getFolderById('1pp1ELzGa2fZqU4IHAasZMHsmYx19pnYv');
var createFile = folder.createFile(data.image);
return createFile.getUrl();
}
From what I can tell the problem is at the data.image. This is where I am trying to retrieve my image so I can upload it into the folder. It must be that uploadFiles(data) is not properly bringing in data.
Here is the HTML and JavaScript:
<form id="myForm" onsubmit="handleFormSubmit(this)">
<h1 class="h4 mb-4 text-center" style="text-align:center"> <center>File Upload Testing</center></h1>
<table>
<tr>
<td colspan="11"><input type="file" id="image"></td>
</tr>
<input type="hidden" id="fileURL" name="fileURL">
</table>
<button type="submit" class="button button1" id="submitBtn">Submit</button>
</form>
<script>
document.getElementById('submitBtn').addEventListener('click',
function(e){
google.script.run.withSuccessHandler(onSuccess).uploadFiles(this.parentNode);;}
)
function onSuccess(data){
document.getElementById("fileURL").value = data;
}
</script>
I have a feeling that the e parameter is not retrieving the data above, however I don't really understand how it works. It could also be this.parentNode that's not grabbing the fike.
I am using the onSuccess function to retrieve the link so I can put it into my google sheet for quick access.
This is the error I receive;
Here is a link to the google sheet. To reach google scripts go to 'Tools -> Script Editor'.
https://docs.google.com/spreadsheets/d/16w8uB4OZHCeD7cvlrUv5GHP72CWxQhO1AAkF9MMSpoE/edit?usp=sharing
Here is another technique I attempted to use:
Javascript:
function uploadthis(fileForm){
const file = fileForm.image.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)).uploadFiles(obj);
};
fr.readAsArrayBuffer(file);
}
Google Script:
function uploadFiles(data){
var file = Utilities.newBlob(data.bytes, data.mimeType); // Modified
var folder = DriveApp.getFolderById('1pp1ELzGa2fZqU4IHAasZMHsmYx19pnYv');
var createFile = folder.createFile(file);
return createFile.getId(); // Added
}
Thank you!
I want to create a new sheet in my spreadsheet with the sidebar. I'm new to working with the sidebar so I'm not sure how to do it.
Code.gs:
function createSheet(sheetName) {
var sheet = ss.getSheetByName(sheetName)
if (!sheet) {
ss.insertSheet('Lookup: ' + sheetName)
}
}
Page.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h3>Create Partial Vlookup Table</h3>
<input id="myData">
<button onclick="createLookup()">Click</button>
<script>
function createLookup(){
var myData = document.getElementById('myData').value
google.script.run.withSuccessHandler(createSheet(myData))
}
</script>
</body>
</html>
I'd appreciate any help I can get with this issue!
I believe your goal as follows.
You want to insert new sheet in the active Spreadsheet using the sidebar.
Modification points:
In order to run the function at Google Apps Script side, please modify google.script.run.withSuccessHandler(createSheet(myData)) to google.script.run.withSuccessHandler(function).createSheet(myData).
In your script of createSheet, it seems that ss is not declared.
When your script is modified with above points, it becomes as follows.
Modified script:
HTML & Javascript side:
In this case, please modify createLookup as follows.
function createLookup(){
var myData = document.getElementById('myData').value;
google.script.run.withSuccessHandler(alert).createSheet(myData); // Modified
}
Google Apps Script side:
function createSheet(sheetName) {
var ss = SpreadsheetApp.getActiveSpreadsheet(); // Added
var sheet = ss.getSheetByName(sheetName);
if (!sheet) {
ss.insertSheet('Lookup: ' + sheetName);
}
return "ok"; // Added
}
By above modification, when the button on the side bar by inputting a value is clicked, a new sheet is inserted in the active Spreadsheet. And, ok is returned and you can see it at the alert dialog on the browser.
When you want the script for opening the side bar, how about the following script?
function openSidebar() {
SpreadsheetApp.getUi().showSidebar(HtmlService.createHtmlOutputFromFile("Page"));
}
Reference:
Class google.script.run
I found a lot of good suggestions on how to load a csv/txt file into a html page into a table, but none of the solutions are working for me. Here is the code I am working with. I have both files located in my C: drive and basically would like to load this csv/txt file and show it on as a table in index.html. Thanks so much!
data.txt
heading1,heading2,heading3,heading4,heading5
value1_1,value2_1,value3_1,value4_1,value5_1
value1_2,value2_2,value3_2,value4_2,value5_2
index.html
<!DOCTYPE html>
<!-- saved from url=(0014)about:internet -->
<html lang="en">
<html>
<head>
<title>Test</title>
</head>
<body>
<script type="text/javascript">
$(document).ready(function() {
$.ajax({
type: "GET",
url: "data.txt",
dataType: "text",
success: function(data) {processData(data);}
});
});
function processData(allText) {
var allTextLines = allText.split(/\r\n|\n/);
var headers = allTextLines[0].split(',');
var lines = [];
for (var i=1; i<allTextLines.length; i++) {
var data = allTextLines[i].split(',');
if (data.length == headers.length) {
var tarr = [];
for (var j=0; j<headers.length; j++) {
tarr.push(headers[j]+":"+data[j]);
}
lines.push(tarr);
}
}
\\ alert(lines);
}
</script>
</body>
</html>
You can't access local files with JS. That would be serious security vulnerability, because you could send a malicious webpage to a user, which would download their files and send them to someone. As midrizi mentioned in the comments, you'll need a server to download files from there.
As others have noted, you can't automatically read a local file into the browser.
But you can prompt the user to select a file, using the <input type="file"> element.
Once a file has been selected via that input, it can be read via JavaScript.
<label for="file">Select a Text File:</label><br />
<input id="file" type="file" /><br/>
<button onclick="readFile()">Read File</button><br/>
let input = document.getElementById('file');
let contents = document.getElementById('contents');
function readFile () {
let file = input.files[0];
const reader = new FileReader();
reader.onload = function (evt) {
console.log('reader.onload');
contents.innerHTML = String(evt.target.result);
};
reader.readAsText(file);
}
If you can modify the data.txt a bit you can just load it as another script file without need for a server.
Change data.txt to this
var data = `heading1,heading2,heading3,heading4,heading5
value1_1,value2_1,value3_1,value4_1,value5_1
value1_2,value2_2,value3_2,value4_2,value5_2`
And load it as a javascript file before your actual script
<script type="text/javascript" src="data.txt"></script>
Then you can use the variable data which holds your file content without any ajax call.
There is no way you can retrieve a local file if you don't serve it, as pointed out in the comments to your question.
There are approaches you can take to that, though. If you can't serve it by any means, you could create a GitHub repo and upload your file there. Then you can use the link to your raw file:
And you can also take steps to automate that, but it should be easy enough committing your file locally whenever you update it and push it to GitHub. Just in case you're not familiar with Git and GitHub, here's a handy ref.
A word of caution: unless you have total control over the characters that you include in your CSV, parsing them by naively splitting commas like that might result in ugly stuff if the values within contain commas themselves. Some CSV files also come with extra stuff in the beginning of the file (like the sep indicator in the first row, which defines what character to interpret as separator). You may completely ignore these warnings if you're producing the CSV yourself.
Also I noticed your function does not take care of building the actual table, so I changed it so it does. I also used Fetch API to retrieve the data:
<!DOCTYPE html>
<!-- saved from url=(0014)about:internet -->
<html lang="en">
<html>
<head>
<title>Test</title>
</head>
<body>
<script type="text/javascript">
function processData(csv) {
let data = csv.split(/\r\n|\n/).map(v => v.split(','));
let headers = data.shift();
let table = document.createElement('table');
let thead = document.createElement('thead');
table.appendChild(thead);
thead.innerHTML = '<tr><th>' + headers.join('</th><th>') + '</th></tr>';
let tbody = document.createElement('tbody');
table.appendChild(tbody);
for (let row of data) {
tbody.innerHTML += '<tr><td>' + row.join('</td><td>') + '</td></tr>';
}
document.body.appendChild(table);
}
// I uploaded the CSV to a personal repo for this example,
// but you CAN use a local file as long as you *serve* it
fetch("https://raw.githubusercontent.com/gyohza/test/master/so/data.txt")
.then(res => res.text())
.then(text => processData(text));
</script>
</body>
</html>