Upload File To Google Drive Using Google Apps Script - html

Trying to created a Google Apps Script to prompt me to choose a file to upload to Google Drive as described here
But I am receiving an error
Uncaught ScriptError: TypeError: Cannot read property 'getAs' of
undefined
I have watched the YouTube video a couple of times now, but I don't see that I am doing anything incorrectly. Any ideas?
function doGet(){
return HtmlService.createHtmlOutputFromFile("form.html")
}
function upload(e){
// logic to upload the file
var destination_id = 'enter your folder id here' //folder id
var img = e.imageFile
var contentType = 'img/png'
var destination = DriveApp.getFolderById(destination_id)
var img = img.getAs(contentType)
destination.createFile(img)
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<form>
<input type="file" name="imageFile"/>
<input type="button" value="Upload" onclick="google.script.run.upload(this.parentNode)">
</form>
</body>
</html>

The code has an error
replace
var contentType = 'img/png'
by
var contentType = 'image/png'
Applyng the above fix, the code worked fine for me.
NOTE: While code doesn't throw any error using the default runtime (Chrome V8), the file was not correctly uploaded but using the old runtine (Mozilla Rhino) it works fine.
Regarding the specific error that you got, perphaps you didn't publish the code shown in the question as a new version of your web application. Try using the link to test the latest code.
Related
Google Apps script web app automatically linked to latest code?

Related

403 while opening a drive link (pdf) with google apps script

I'm trying to open a print window for a shipping label (in pdf form) from a google drive file link.
This is the .gs code I've written so far:
the drive link is being declared based on an order its associated with, that portion isn't applicable in this instance
function printPdf() {
const sheet = SpreadsheetApp.getActive().getSheets()[4];
const ui = SpreadsheetApp.getUi();
// order ID associated with the label
const orderQuery = sheet.getRange('S:S').createTextFinder(
ui.prompt('Enter an order ID', '', ui.ButtonSet.OK).getResponseText()
).matchEntireCell(true).findNext();
let url;
// drive link is in column 'O'
if (orderQuery) url = sheet.getRange(orderQuery.getRow(), 15).getValue();
const template = HtmlService.createTemplateFromFile('check-out-modeless');
template.url = url;
const html = template.evaluate();
ui.showModelessDialog(html, 'Print Label');
}
and the HTML looks like this:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<iframe src="<?= url ?>" style="width:100%; height:100%;"></iframe>
<script>
window.print();
google.script.host.close();
</script>
</body>
</html>
So far I
made sure the drive like is id-based rather than preview-based
verified that the drive link is accessible from my account
I used an incognito window as well to avoid conflicts from being logged in to more than one account
recorded network headers to see if there was any indication of why the server is declining access
Beyond those I can't think of any other way to solve this aside from maybe utilizing blobs & DriveApp

How to monitor page activity of a google site using Google Apps Script

Problem
I want to be able to monitor user activity on my google site using Apps Script, specifically which pages users are accessing. I can not use Google Analytics (it is not within my contract with Google). Apps Script has so far been able to return user ID (email address) of the user when a page is accessed, however I can not work out how to return which page(s) are activated by that user.
What I have done so far
I have created a web app and deployed / embedded it within to 2 pages in a test google site. It returns the values to a table in a linked google sheets file. Here is the script:
function doGet(event) {
return HtmlService.createHtmlOutputFromFile('UserLog.html');
}
function getPage(pageTitle) {
var user = Session.getActiveUser();
var ss = SpreadsheetApp.getActive();
var db = "Webapp Log";
var db_ss = ss.getSheetByName(db);
var now = new Date();
var page = pageTitle;
var values = [now,user,page,"User activated webapp",Session.getTemporaryActiveUserKey()];
db_ss.getRange(db_ss.getLastRow()+1, 1, 1, 5).setValues([values]);
};
The "UserLog.html" code is this:
<html>
<head>
<base target="_top">
</head>
<body>
<script>
var page = [Solution]
google.script.run.getPage(page);
</script>
</body>
</html>
And so far the return values look like this (with addresses anonymised):
Table Values
As you can see, the 'Page' field is blank.
What I need
Use the embedded web app to return the activated page URL OR to return another unique aspect of the activated page, for example the page title or "page 1", "page 2", etc. (all pages on the site have a unique title).
How can this be done? Is this even possible?
You can do it with e.parameters
E.g. incorporate a parameter page that you append at the end of the WebApp URL.
When you embedd the WebApp URL in each page, assign a unique value to page, like https://script.google.com/a/XXX/macros/s/XXX/exec?page=1, https://script.google.com/a/XXX/macros/s/XXX/exec?page=2
Now, in Apps Script you just have to slightly modify your doGet() function to retrieve the page:
function doGet(event) {
var page = event.parameter.page;
return HtmlService.createHtmlOutputFromFile('UserLog.html');
}
The rest depends on your preferences. The easiest would be to directly paste the value of page into the spreadsheet from the doGet() function - this will avoid passing the parameter to the html file and then, with google.script.run back to a .gs function.

Upload CSV/Excel File as Sheet via Google App Script

I see that the Drive Folder class has a createFile() which takes three arguments for name, content, and mimeType. Is it possible to use this as part of an upload call to have a user file uploaded and converted (to Google Docs) all in one go without having to call the REST API directly with convert=true?
For example, here's the HTML:
<html>
<head>
<base target="_top">
<script>
function handler(response) {
document.getElementById('uploader').innerHTML = "Uploaded file! " + response;
}
</script>
</head>
<body>
<div id="uploader">
<form>
<input type="file" name="theFile">
<input type="button" onclick="google.script.run.withSuccessHandler(handler).uploadFile(this.parentNode)" value="Upload!">
</form></div>
</body>
</html>
And here's the Google Script code:
function uploadFile(e) {
Logger.log("Uploading file!");
var dfolder = DriveApp.getFolderById('abcdefgh'); // replace w/ Drive FolderID
return dfolder.createFile(e.theFile).getName();
}
How would I go about changing that last line to something like:
return dfolder.createFile(newName, e.theFile, MimeType.GOOGLE_SHEETS);
Something I'm trying to figure out now is simply how to get the name of the file being uploaded (e.g. for newName). And then how to go about converting whatever form e.theFile is in to a string. If I try this as-is now I get the error:
Invalid argument: file.contentType at uploadFile(Code:31)
You want to upload CSV and Excel files using google.script.run.
When the file is uploaded, you want to convert to Google Spreadsheet.
You want to retrieve the filename of the uploaded file.
If my understanding is correct, how about this modification? Please think of this as just one of several answers.
I think that in your script, it is required to modify the Google Apps Script.
Modification points:
Value of e.theFile of uploadFile(e) is the blob. So you can retrieve the filename using getName().
You can convert the CSV and Excel format to Google Spreadsheet using Drive API. In this case, I used Drive API v2 at Advanced Google Services.
The reason of the error of Invalid argument: file.contentType at uploadFile is that the mimeType of MimeType.GOOGLE_SHEETS cannot be used with createFile().
Modified script:
Please modify uploadFile() as follows. Before you use this script, please enable Drive API at Advanced Google Services, and set the folder ID to folderId.
function uploadFile(e) {
Logger.log("Uploading file!");
// I modified below script.
var folderId = "###"; // Please set the folder ID here.
var blob = e.theFile;
var filename = blob.getName();
var mimeType = blob.getContentType();
if (mimeType == MimeType.CSV || mimeType == MimeType.MICROSOFT_EXCEL || mimeType == MimeType.MICROSOFT_EXCEL_LEGACY) {
return Drive.Files.insert({title: filename, mimeType: MimeType.GOOGLE_SHEETS, parents: [{id: folderId}]}, blob).title;
}
return "";
}
References:
Class Blob
Advanced Google Services
Files: insert of Drive API v2
If I misunderstood your question and this was not the result you want, I apologize.

Auto submit google form after a time limit

I want to use app script in my Google form to automatically submit the form in 20 minutes if the user doesn't click on submit within 20 minutes. Anyway to implement this????
No, you cannot control the client-side of Google Forms, even if you add an Apps Script to it, because Apps Script runs on the server.
One possible solution is to serve your form as a Google Apps Script web app. At that point you can write client-side JavaScript and use window.setTimeout to submit the form after 20 minutes.
Here are some example files, Code.gs and quiz.html, that can provide a basic skeleton to start the web app. A blank project will have Code.gs as the default file, then you have to add File > New > HTML file to start the other file.
You can enter the id of any spreadsheet you own in the commented out lines in Code.gs to append the response into that spreadsheet. (You can also automate that process by creating a new spreadsheet as needed. Example of creating spreadsheet to hold data for Apps Script example can be found here.
// file Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile("quiz");
}
function doPost(request) {
if (request.answer) {
console.log(request.answer); // View > Execution transcript to verify this
//var ss = SpreadsheetApp.openById(id).getSheetByName("Quiz Responses");
//ss.appendRow([request.answer /* additional values comma separated here */ ]);
}
}
<!DOCTYPE html>
<!-- file quiz.html -->
<html>
<head>
<base target="_top">
</head>
<body>
<h1>Quiz</h1>
<form>
What is Lorem Ipsum?
<input name="loremipsum" type="text"/>
<button>Submit</button>
</form>
<script>
const button = document.querySelector("button");
const timeLimitMinutes = 1; // low number for demo; change to 20 for application
const timeLimitMilliseconds = timeLimitMinutes * 60 * 1000;
// For this demo we are not going to serve a response page, so don't try to.
button.addEventListener("submit", submitEvent => submitEvent.preventDefault());
// attach our custom submit to both the button and to the timeout
button.addEventListener("click", submitForm)
window.setTimeout(submitForm, timeLimitMilliseconds)
function submitForm() {
button.setAttribute("disabled", true);
document.querySelector("h1").textContent = "Quiz submitted";
// for demo: submitting just a single answer.
// research Apps Script documentation for rules on submitting forms, certain values not allowed
// consider a helper function `makeForm()` that returns a safe object to submit.
const answer = document.querySelector("input").value;
google.script.run.doPost({ answer });
}
</script>
</body>
</html>
Test with Publish > Deploy as web app...

Google App Script Form not working

I am using google app script to create a form for uploading file. This is my Code.gs file:
var SPREADSHEET_FILE_ID = '1oQn6OLMzys8tVk1FLriOAmpzFJNazLRP-SwM7--eA58';
var folderId = "0B9TN_-yt-h0WZ0dnWndGWkw3UkE";
function doGet() {
var template = HtmlService.createTemplateFromFile('index');
// Build and return HTML in IFRAME sandbox mode.
return template.evaluate()
.setTitle('Web App Window Title')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
};
And I am using all other codes almost similar to the url https://script.google.com/d/125dG42eB9lM4SPq64p0dpR2CBH4ohfHiqu9TvFNM8s4Ra7pt-7kHXoTM/edit?usp=sharing.
I am getting the following error.
3402363213-mae_html_user_bin_i18n_mae_html_user.js:42 Uncaught ReferenceError: "doc" is not defined.
Can anyone please help why this error is coming and how to prevent this. No for is not being submitted. It is hanged after I click the button of submission.
Since the problem started when you added these values, I think you need to recheck them.
var SPREADSHEET_FILE_ID = '1oQn6OLMzys8tVk1FLriOAmpzFJNazLRP-SwM7--eA58';
var folderId = "0B9TN_-yt-h0WZ0dnWndGWkw3UkE";
var SPREADSHEET_FILE_ID is expecting an spreadsheet ID like "1386834576" where as you provided "1oQn6OLMzys8tVk1FLriOAmpzFJNazLRP-SwM7--eA58", which is wrong. I think you got that from something like "https://docs.google.com/forms/d/1BqxyEG8RhtlM3MNuSbln6C1L1GLl3axdiSEijcwB5gY/edit" that's why it's asking you "doc" is not defined.