I am trying to make web app as a sidebar in spreadsheet using HTML5, Bootstrap 5 & JavaScript to make entry of data easier . I managed to go through the entire process But the problem that I can't make the button upload files into google drive folder and return with the url back.
the link of sheet working with.
I think the problem in this variable from html script but I don't know what is it
var url = document.getElementById("transaction-file").addEventListener('click',
function(a){
google.script.run.uploadFiles(this.parentNode)
});
https://docs.google.com/spreadsheets/d/1D-tEPsUJqGbCHrF8CYQlPu_ZhmVIGDYEojHfO0_7rW4/edit?usp=sharing
google script code
function loadForm() {
const htmlForSidebar = HtmlService.createTemplateFromFile("uform");
const htmlOutput = htmlForSidebar.evaluate();
htmlOutput.setTitle("Winter 2021");
const ui = SpreadsheetApp.getUi();
ui.showSidebar(htmlOutput);
}
function createMenu(){
const ui = SpreadsheetApp.getUi();
const menu = ui.createMenu("My Forms");
menu.addItem("Show UserForm", "loadForm");
menu.addToUi();
}
function onOpen(){
createMenu();
}
function uploadFiles(files){
var file = files.myFile;
var folder = DriveApp.getFolderById('1gaNAb1s8j7wmotvRUJbg4yfJOFNdZYo5');
var createFile = folder.createFile(file);
return createFile.geturl();
}
function addNewRow(rowData) {
const currentDate = new Date();
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getSheetByName("Sheet1");
ws.appendRow([currentDate, rowData.trxDate, rowData.account, rowData.trxID, rowData.amount, rowData.url, rowData.comment]);
return true;
}
function getDropDownArray(){
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getSheetByName("Ref");
return ws.getRange(2, 1, ws.getLastRow()-1, 1).getValues();
}
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<div class="container pt-3">
<h4 class="border-bottom pb-2 mb-4">Donations' Registration <span class="badge bg-secondary">Form</span></h4>
<div id="userform">
<div class="mb-3">
<label for="transaction-date" class="form-label">Transaction Date</label>
<input type="date" class="form-control" id="transaction-date" required>
<div class="invalid-feedback">Please enter valid date.</div>
</div>
<div class="mb-3">
<label for="transaction-account" class="form-label">Account</label>
<select class="form-select" id="transaction-account" required aria-label="select account" required>
</select>
<div class="invalid-feedback">Please enter valid account.</div>
</div>
<div class="mb-3">
<label for="transaction-id" class="form-label">Transaction ID</label>
<input type="text" class="form-control" id="transaction-id" required>
<div class="invalid-feedback">Please enter valid ID.</div>
</div>
<div class="mb-3">
<label for="transaction-amount" class="form-label">Amount</label>
<input type="number" class="form-control" id="transaction-amount" required>
<div class="invalid-feedback">Please enter valid amount without any service fees.</div>
</div>
<div class="mb-3">
<label for="transaction-file" class="form-label">url</label>
<input type="file" class="form-control" id="transaction-file" name="myFile" aria-label="file example" required>
<div class="invalid-feedback">Please upload right file.</div>
</div>
<div class="mb-3">
<label for="transaction-memo" class="form-label">Memo</label>
<textarea class="form-control" id="transaction-memo" rows="1"></textarea>
</div>
<div class="mb-3">
<button class="btn btn-primary" id="mainButton">Add to Database</button>
</div>
</div>
</div>
<!-- Optional JavaScript; choose one of the two! -->
<!-- Option 1: Bootstrap Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<!-- Option 2: Separate Popper and Bootstrap JS -->
<!--
<script src="https://cdn.jsdelivr.net/npm/#popperjs/core#2.10.2/dist/umd/popper.min.js" integrity="sha384-7+zCNj/IqJ95wo16oMtfsKbZ9ccEh31eOz1HGyDuCQ6wgnyJNSYdrPa03rtR1zdB" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
-->
<script>
function afterButtonClicked(){
if(validate()){
var trxDate = document.getElementById("transaction-date");
var account = document.getElementById("transaction-account");
var trxID = document.getElementById("transaction-id");
var amount = document.getElementById("transaction-amount");
var url = document.getElementById("transaction-file");
var comment = document.getElementById("transaction-memo");
var rowData = {trxDate: trxDate.value, account: account.value, trxID: trxID.value, amount: amount.value, url: url.value, comment: comment.value};
google.script.run.withSuccessHandler(afterSubmit).addNewRow(rowData);
} else {
//handle this later
}
}
function afterSubmit(e){
clearFields(["transaction-date", "transaction-account", "transaction-id", "transaction-amount", "transaction-file", "transaction-memo"]);
}
function clearFields(fields){
fields.forEach(function(field){
var el = document.getElementById(field);
el.value = "";
});
}
function validate(){
var fieldsToValidate = document.querySelectorAll("#userform input, #userform select");
//is-invalid
Array.prototype.forEach.call(fieldsToValidate,function(el){
if(el.checkValidity()){
el.classList.remove("is-invalid");
} else {
el.classList.add("is-invalid");
}
});
return Array.prototype.every.call(fieldsToValidate,function(el){
return el.checkValidity();
});
}
function afterSidebarLoads(){
google.script.run.withSuccessHandler(afterDropDownArrayReturned).getDropDownArray();
}
function afterDropDownArrayReturned(arrayOfArrays){
var account = document.getElementById("transaction-account");
arrayOfArrays.forEach(function(r){
var option = document.createElement("option");
option.textContent = r[0];
account.appendChild(option);
});
}
document.getElementById("mainButton").addEventListener("click",afterButtonClicked);
google.script.run.uploadFiles(this.parentNode);
document.addEventListener("DOMContentLoaded",afterSidebarLoads);
</script>
</body>
</html>
I try to get the contents of 3 arrays from spreadsheet in 3 vars when the page is loaded in DOMContentLoaded. But I get nothing (look the picture)
I deployed the test project here: https://script.google.com/a/fmlogistic.com/macros/s/AKfycbxROleHY3u69jTpdVZjLOfDTzY9c5q1S4kwm0ctTFzU/dev
and test-spreadsheet with script of this is here
https://docs.google.com/spreadsheets/d/1qxr91eiLUykfLS0zKq3D4Dn206vnEkVqxDo6ZQF1rU4/edit#gid=0
I tried to write something like here, but this way with variantes Apps script return values from server function to html form
const inputs = document.querySelector('.dws-input');
const formControl = document.querySelectorAll('.form-control');
let findData;
let curInpID;
let firstValid, secValid, thirdValid, allValid;
formControl[0].focus();
function callBack(e) {
var Logs = e.ListLogins;
var Tabs = e.ListTables;
var Ords = e.ListOrders;
}
document.addEventListener("DOMContentLoaded", function(){
google.script.run.withSuccessHandler(callBack).sendData();
var Logs = e.ListLogins;
var Tabs = e.ListTables;
var Ords = e.ListOrders;
console.log(Logs);
console.log(Tabs);
console.log(Ords);
});
<!doctype html>
<html lang="en">
<head>
<title>CLR: PACKING</title>
<meta charset = "UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
<div class="conteiner">
<form novalidate>
<h6 class="title">PACKING</h6>
<div class="dws-input">
<div class="col-md-3"></div>
<div>
<div class="form-floating mb-3 mt-3">
<input type="text" class="form-control" novalidate id="tLogin" name= "username" placeholder= "Login:" autofocus >
<label for="tLogin">Login:</label>
</div>
<div class="form-floating mb-3 mt-3">
<input type="text" class="form-control" novalidate id="tTable" name= "text" placeholder= "Table:" >
<label for="tTable">Table:</label>
</div>
</div>
<div class="form-floating mb-3 mt-3">
<input type="text" novalidate class="form-control" id="tOrder" name= "text" placeholder= "Order:" >
<label for="tOrder">Order:</label>
</div>
</div>
</form>
</div>
<?!= include("index-js"); ?>
</body>
</html>
In actions.gs at server I wrote this:
const url = SpreadsheetApp.getActiveSpreadsheet().getUrl();
var htmlServ = HtmlService.createTemplateFromFile("index");
let ss = SpreadsheetApp.openByUrl(url);
let sheetTo = ss.getSheetByName("#sistem");
let sheetIn = ss.getSheetByName("#packing");
function doGet(e){
return htmlServ.evaluate();
}
function include(filename){
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
function sendData(){
var lrLogins = sheetTo.getRange("A:A").getValues().filter(String).length;
var arrLogins = sheetTo.getRange(1, 1, lrLogins, 1).getValues().flat();
var lrTMPLORDS = sheetTo.getRange("K:K").getValues().filter(String).length;
var curTMPLORDS = sheetTo.getRange(1, 11, lrTMPLORDS, 1).getValues();
var lrTABLES = sheetTo.getRange("R:R").getValues().filter(String).length;
var curTABLES = sheetTo.getRange(1, 18, lrTABLES, 1).getValues().flat();
var objDataInfo = {};
objDataInfo.ListLogins = arrLogins;
objDataInfo.ListTables = curTABLES;
objDataInfo.ListOrders = curTMPLORDS;
return objDataInfo;
}
Are there any ways to get the contents of these arrays when the page is loaded
Try this:
function callBack(e) {
var Logs = e.ListLogins;
var Tabs = e.ListTables;
var Ords = e.ListOrders;
console.log(Logs);
console.log(Tabs);
console.log(Ords);
}
document.addEventListener("DOMContentLoaded", function(){
google.script.run.withSuccessHandler(callBack).sendData();
//the following code is not in the callback function and it get's executed probably before the callback is returned.
var Logs = e.ListLogins;
var Tabs = e.ListTables;
var Ords = e.ListOrders;
console.log(Logs);
console.log(Tabs);
console.log(Ords);
});
It could have been written like this:
document.addEventListener("DOMContentLoaded", function () {
google.script.run.withSuccessHandler(function(e){
var Logs = e.ListLogins;
var Tabs = e.ListTables;
var Ords = e.ListOrders;
console.log(Logs);
console.log(Tabs);
console.log(Ords);
}).sendData();
});
I would like to create a script to receive expense receipts in a Google drive, and log details provided by a Google Form (date, vendor, amount, and picture of the receipt...)
I've tried to replicate the script and html from How do I rename files uploaded to an apps script web app form?, and end up with error 400 with no details...
Also tried to merge Amit Agarwal's script
https://www.labnol.org/internet/receive-files-in-google-drive/19697/
with https://github.com/dwyl/learn-to-send-email-via-google-script-html-no-server
Second example logs entries into google sheets, but also sends email : Perfect! Amit's example allows to create named folders and I can rename the file with some additionnal code, love it!
But in my try to merge both, I end up with two buttons at the bottom of the form... one sends the rows, the other sends the file! :D
Here's my actual script.gs
// if you want to store your email server-side (hidden), uncomment the next line
//var TO_ADDRESS = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// spit out all the keys/values from the form in HTML for email
// uses an array of keys if provided or the object to determine field order
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('index.html').setTitle("envoyez vos pièces jointes");
}
// this is from Amit Agarwal's example
function uploadFileToGoogleDrive(data, file, prenom, nom) {
try {
var dropbox = "Justificatifs reçus";
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var contentType = data.substring(5,data.indexOf(';')),
bytes = Utilities.base64Decode(data.substr(data.indexOf('base64,')+7)),
blob = Utilities.newBlob(bytes, contentType, file),
file = folder.createFolder([prenom, nom].join(" ")).createFile(blob);
//this is an addition i've made to rename the files upon submission, used to work in previous tries, but now gives "null null.pdf'
//var newFileName = [prenom +'_'+ nom +".pdf"];
//file.setName(newFileName);
return "OK";
} catch (f) {
return f.toString();
}
}
// Here stops Amit Agarwal's script, below is the following of
//https://github.com/dwyl/learn-to-send-email-via-google-script-html-no-server
function formatMailBody(obj, order) {
var result = "";
if (!order) {
order = Object.keys(obj);
}
// loop over all keys in the ordered form data
for (var idx in order) {
var key = order[idx];
result += "<h4 style='text-transform: capitalize; margin-bottom: 0'>" + key + "</h4><div>" + sanitizeInput(obj[key]) + "</div>";
// for every key, concatenate an `<h4 />`/`<div />` pairing of the key name and its value,
// and append it to the `result` string created at the start.
}
return result; // once the looping is done, `result` will be one long string to put in the email body
}
// sanitize content from the user - trust no one
// ref: https://developers.google.com/apps-script/reference/html/html-output#appendUntrusted(String)
function sanitizeInput(rawInput) {
var placeholder = HtmlService.createHtmlOutput(" ");
placeholder.appendUntrusted(rawInput);
return placeholder.getContent();
}
function doPost(e) {
try {
Logger.log(e); // the Google Script version of console.log see: Class Logger
record_data(e);
// shorter name for form data
var mailData = e.parameters;
// names and order of form elements (if set)
var orderParameter = e.parameters.formDataNameOrder;
var dataOrder;
if (orderParameter) {
dataOrder = JSON.parse(orderParameter);
}
// determine recepient of the email
// if you have your email uncommented above, it uses that `TO_ADDRESS`
// otherwise, it defaults to the email provided by the form's data attribute
var sendEmailTo = (typeof TO_ADDRESS !== "undefined") ? TO_ADDRESS : mailData.formGoogleSendEmail;
// send email if to address is set
if (sendEmailTo) {
MailApp.sendEmail({
to: String(sendEmailTo),
subject: "Contact form submitted",
// replyTo: String(mailData.email), // This is optional and reliant on your form actually collecting a field named `email`
htmlBody: formatMailBody(mailData, dataOrder)
});
}
return ContentService // return json success results
.createTextOutput(
JSON.stringify({"result":"success",
"data": JSON.stringify(e.parameters) }))
.setMimeType(ContentService.MimeType.JSON);
} catch(error) { // if error return this
Logger.log(error);
return ContentService
.createTextOutput(JSON.stringify({"result":"error", "error": error}))
.setMimeType(ContentService.MimeType.JSON);
}
}
/**
* record_data inserts the data received from the html form submission
* e is the data received from the POST
*/
function record_data(e) {
var lock = LockService.getDocumentLock();
lock.waitLock(30000); // hold off up to 30 sec to avoid concurrent writing
try {
Logger.log(JSON.stringify(e)); // log the POST data in case we need to debug it
// select the 'responses' sheet by default
var doc = SpreadsheetApp.getActiveSpreadsheet();
var sheetName = e.parameters.formGoogleSheetName || "responses";
var sheet = doc.getSheetByName(sheetName);
var oldHeader = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
var newHeader = oldHeader.slice();
var fieldsFromForm = getDataColumns(e.parameters);
var row = [new Date()]; // first element in the row should always be a timestamp
// loop through the header columns
for (var i = 1; i < oldHeader.length; i++) { // start at 1 to avoid Timestamp column
var field = oldHeader[i];
var output = getFieldFromData(field, e.parameters);
row.push(output);
// mark as stored by removing from form fields
var formIndex = fieldsFromForm.indexOf(field);
if (formIndex > -1) {
fieldsFromForm.splice(formIndex, 1);
}
}
// set any new fields in our form
for (var i = 0; i < fieldsFromForm.length; i++) {
var field = fieldsFromForm[i];
var output = getFieldFromData(field, e.parameters);
row.push(output);
newHeader.push(field);
}
// more efficient to set values as [][] array than individually
var nextRow = sheet.getLastRow() + 1; // get next row
sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
// update header row with any new data
if (newHeader.length > oldHeader.length) {
sheet.getRange(1, 1, 1, newHeader.length).setValues([newHeader]);
}
}
catch(error) {
Logger.log(error);
}
finally {
lock.releaseLock();
return;
}
}
function getDataColumns(data) {
return Object.keys(data).filter(function(column) {
return !(column === 'formDataNameOrder' || column === 'formGoogleSheetName' || column === 'formGoogleSendEmail' || column === 'honeypot');
});
}
function getFieldFromData(field, data) {
var values = data[field] || '';
var output = values.join ? values.join(', ') : values;
return output;
}
And here's the index.html
<!DOCTYPE html>
<html>
<head>
<base target="_blank">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Envoyez vos justificatifs</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.min.css">
<style>
.disclaimer{width: 480px; color:#646464;margin:20px auto;padding:0 16px;text-align:center;font:400 12px Roboto,Helvetica,Arial,sans-serif}.disclaimer a{color:#009688}#credit{display:none}
</style>
</head>
<!-- START HERE -->
<link rel="stylesheet" href="https://unpkg.com/purecss#1.0.0/build/pure-min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
<!-- Style The Contact Form How Ever You Prefer -->
<link rel="stylesheet" href="style.css">
<form class="gform pure-form pure-form-stacked" method="POST" data-email="example#email.net"
action="https://script.google.com/macros/s/AKfycbzSlohhLp27NcnG8lBt13GUm4PblUMTL9uU1CTgcOBohz1iH0k/exec"
id="form" novalidate="novalidate" style="max-width: 480px;margin: 40px auto;">
<div id="forminner">
<div class="row">
<div class="col s12">
<h5 class="center-align teal-text">Envoyez vos justificatifs</h5>
<p class="disclaimer">This File Upload Form (tutorial) is powered by Google Scripts</p>
</div>
</div>
<fieldset class="pure-group">
<legend><H5>Vous êtes</H5></legend>
<input id="radio-group--madame" type="radio" name="radio-group" value="madame"> <label for="radio-group--madame">Madame</label>
<input id="radio-group--monsieur" type="radio" name="radio-group" value="monsieur"> <label for="radio-group--monsieur">Monsieur</label>
</fieldset>
<div class="form-elements">
<fieldset class="pure-group">
<label for="firstname">Votre prénom</label>
<input id="firstname" name="Prénom" placeholder="indiquez votre prénom" />
</fieldset>
<div class="form-elements">
<fieldset class="pure-group">
<label for="name">Votre nom</label>
<input id="name" name="Nom" placeholder="indiquez votre nom" />
</fieldset>
<fieldset class="pure-group">
<label for="email"><em>Votre</em> Adresse email</label>
<input id="email" name="Votre adresse email" type="email" value=""
required placeholder="Alice#paydesmerv.... ou votre vrai adresse pour recevoir la confirmation"/>
</fieldset>
<fieldset class="pure-group">
<legend><H5>Votre dépense</H5></legend>
<label for="date">Date</label>
<input id="date" type="date" name="date de la dépense" value="">
</fieldset>
<fieldset class="pure-group">
<label for="time">Heure de la dépense</label>
<input id="time" type="time" name="Heure de la dépense" value="">
</fieldset>
<fieldset class="pure-group">
<label for="menu">Type de dépense</label>
<select id="menu" name="Type de dépense">
<option selected="">Je ne sais pas quel type de dépense choisir</option>
<option>Carburant (essence, diesel, gasoil)</option>
<option>Location de matériel (voiture, informatique, photocopieur)</option>
<option>Voyages et déplacements (train, transports, taxi, VTC, péages, parking, avion)</option>
<option>Frais postaux (La Poste, timbres, colis, lettre recommandée)</option>
<option>Frais de mission (repas, restaurants)</option>
<option>Frais de missions (logement, hôtel)</option>
<option>Divers</option>
</select>
</fieldset>
<fieldset class="pure-group">
<label for="number">Montant de la dépense en €</label>
<input id="number" type="number" name="Montant de la dépense" min="0" step="0.01" value="0.00">
</fieldset>
<fieldset class="pure-group">
<label for="message">Message: </label>
<textarea id="message" name="Message Facultatif" rows="10"
placeholder="Vous pouvez apporter des précisions sur la dépense ici..."></textarea>
</fieldset>
<fieldset class="pure-group honeypot-field">
<label for="honeypot">To help avoid spam, utilize a Honeypot technique with a hidden text field; must be empty to submit the form! Otherwise, we assume the user is a spam bot.</label>
<input id="honeypot" type="text" name="honeypot" value="" />
</fieldset>
<legend><H5>Ajoutez le justificatif</H5></legend>
<p> Pas de remboursement possible sans justificatif</p>
<!-- Here is the issue: code below sends the file to my drive but no new row is added to the spreadsheet. -->
<div class="row">
<div class="file-field input-field col s12">
<div class="btn">
<span>Fichier</span>
<input id="files" type="file" name="Fichier reçu" multiple>
</div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text" placeholder="choisissez un fichier sur votre ordinateur">
</div>
</div>
</div>
<!-- code below creates new row with filename but does not upload the file to drive...
exemple from : https://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_input_type_file -->
<form action="/action_page.php">
Select files: <input type="file" name="Fichier reçu"><br><br>
<input type="submit">
</form>
<button class="waves-effect waves-light btn submit-btn" type="submit" onclick="submitForm(); return false;">Submit</button>
</div>
<!-- Customise the Thankyou Message People See when they submit the form: -->
<div class="thankyou_message" style="display:none;">
<h2><em>Thanks</em> for contacting us!
We will get back to you soon!</h2>
</div>
</form>
<!-- Submit the Form to Google Using "AJAX" -->
<script data-cfasync="false" src="form-submission-handler.js"></script>
<!-- END -->
<div class="row">
<div class="input-field col s12" id = "progress">
</div>
</div>
<div id="success" style="display:none">
<h5 class="left-align teal-text">File Uploaded</h5>
<p>Your file has been successfully uploaded.</p>
<p>The pro version (see demo form) includes a visual drag-n-drop form builder, CAPTCHAs, the form responses are saved in a Google Spreadsheet and respondents can upload multiple files of any size.</p>
<p class="center-align"><a class="btn btn-large" href="https://gum.co/GA14?wanted=true" target="_blank">Upgrade to Pro</a></p>
</div>
</form>
<div class="fixed-action-btn horizontal" style="bottom: 45px; right: 24px;">
<a class="btn-floating btn-large red">
<i class="large material-icons">menu</i>
</a>
<ul>
<li><a class="btn-floating red" href="shorturl" target="_blank" title="Buy License - File Upload Form"><i class="material-icons">monetization_on</i></a></li>
<li><a class="btn-floating blue" href="shorturl" target="_blank" title="Video Tutorial"><i class="material-icons">video_library</i></a></li>
<li><a class="btn-floating green" href="http://www.labnol.org/internet/file-upload-google-forms/29170/" target="_blank" title="How to Create File Upload Forms"><i class="material-icons">help</i></a></li>
</ul>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/js/materialize.min.js"></script>
<script src="https://gumroad.com/js/gumroad.js"></script>
<script>
var file,
reader = new FileReader();
reader.onloadend = function(e) {
if (e.target.error != null) {
showError("File " + file.name + " could not be read.");
return;
} else {
google.script.run
.withSuccessHandler(showSuccess)
.uploadFileToGoogleDrive(e.target.result, file.name, $('input#nom').val(), $('input#prenom').val());
}
};
function showSuccess(e) {
if (e === "OK") {
$('#forminner').hide();
$('#success').show();
} else {
showError(e);
}
}
function submitForm() {
var files = $('#files')[0].files;
if (files.length === 0) {
showError("Choisissez un fichier a télécharger");
return;
}
file = files[0];
if (file.size > 1024 * 1024 * 5) {
showError("The file size should be < 5 MB. Please <a href='http://www.labnol.org/internet/file-upload-google-forms/29170/' target='_blank'>upgrade to premium</a> for receiving larger files in Google Drive");
return;
}
showMessage("Téléchargement du fichier");
reader.readAsDataURL(file);
}
function showError(e) {
$('#progress').addClass('red-text').html(e);
}
function showMessage(e) {
$('#progress').removeClass('red-text').html(e);
}
</script>
So, I'd like to have a unique form to send emails, log into sheets and save file in drive.
Additionally, that would be perfect is the file link could appear inside sheets and if the uploaded file could also be sent as attachment with the email.
Thanks a lot for proof reading my codes and putting me on the right direction!
Collecting Receipt Information
This function collects Date,Vendor,Amount and Uploads an image. It runs as both a dialog and/or a webapp. The spreadsheet displays the images url which allows you to hover over in order to get a link to the image which can be view in a default viewer.
This is the form:
Here's the code:
Code.gs:
function onOpen() {
SpreadsheetApp.getUi().createMenu('Receipt Collection')
.addItem('Get Receipt', 'showAsDialog')
.addToUi();
}
function uploadTheForm(theForm) {
Logger.log(JSON.stringify(theForm));
var rObj={};
rObj['vendor']=theForm.vendor;
rObj['amount']=theForm.amount;
rObj['date']=theForm.date;
rObj['notes']=theForm.notes;
var fileBlob=Utilities.newBlob(theForm.bytes, theForm.mimeType, theForm.filename);
var fldr = DriveApp.getFolderById(receiptImageFolderId);
rObj['file']=fldr.createFile(fileBlob);
rObj['filetype']=fileBlob.getContentType();
Logger.log(JSON.stringify(rObj));
var cObj=formatFileName(rObj);
Logger.log(JSON.stringify(cObj));
var ss=SpreadsheetApp.openById(SSID);
ss.getSheetByName('Receipt Information').appendRow([cObj.date,cObj.vendor,cObj.amount,cObj.notes,cObj.file.getUrl()]);
var html=Utilities.formatString('<br />FileName: %s',cObj.file.getName());
return html;
}
function formatFileName(rObj) {
if(rObj) {
Logger.log(JSON.stringify(rObj));
var mA=rObj.date.split('-');
var name=Utilities.formatString('%s_%s_%s.%s',Utilities.formatDate(new Date(mA[0],mA[1]-1,mA[2]),Session.getScriptTimeZone(),"yyyyMMdd"),rObj.vendor,rObj.amount,rObj.filetype.split('/')[1]);
rObj.file.setName(name);
}else{
throw('Invalid or No File in formatFileName() upload.gs');
}
return rObj;
}
function doGet() {
var output=HtmlService.createHtmlOutputFromFile('receipts').setTitle('Receipt Information');
return output.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL).addMetaTag('viewport', 'width=360, initial-scale=1');
}
function showAsDialog() {
var ui=HtmlService.createHtmlOutputFromFile('receipts');
SpreadsheetApp.getUi().showModelessDialog(ui, 'Receipts')
}
receipts.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$(function(){
google.script.run
.withSuccessHandler(function(rObj){
$('#dt').val(rObj.date);
//$('#vndr').val(rObj.vendor);
//$('#amt').val(rObj.amount);
//$('#notes').val(rObj.notes);
})
.initForm();
});
function fileUploadJs(frmData) {
var amt=$('#amt').val();
var vndr=$('#vndr').val();
var img=$('#img').val();
if(!amt){
window.alert('No amount provided');
$('#amt').focus();
return;
}
if(!vndr) {
window.alert('No vendor provided');
$('#vndr').focus();
return;
}
if(!img) {
window.alert('No image chosen');
$('#img').focus();
}
document.getElementById('status').style.display ='inline';
const file = frmData.receipt.files[0];
const fr = new FileReader();
fr.onload = function(e) {
const obj = {vendor:frmData.elements.vendor.value, date:frmData.elements.date.value, amount: frmData.elements.amount.value, notes: frmData.elements.notes.value, filename: file.name, mimeType:file.type, bytes:[...new Int8Array(e.target.result)]};
google.script.run
.withSuccessHandler(function(hl){
document.getElementById('status').innerHTML=hl;
})
.uploadTheForm(obj);
};
fr.readAsArrayBuffer(file);
}
console.log('My Code');
</script>
<style>
input,textarea{margin:5px 5px 5px 0;}
</style>
</head>
<body>
<h3 id="main-heading">Receipt Information</h3>
<div id="formDiv">
<form id="myForm">
<br /><input type="date" name="date" id="dt"/>
<br /><input type="number" name="amount" placeholder="Amount" id="amt" />
<br /><input type="text" name="vendor" placeholder="Vendor" id="vndr"/>
<br /><textarea name="notes" cols="40" rows="2" placeholder="NOTES" id="notes"></textarea>
<br/>Receipt Image
<br /><input type="file" name="receipt" id="img" />
<br /><input type="button" value="Submit" onclick="fileUploadJs(this.parentNode)" />
</form>
</div>
<div id="status" style="display: none">
<!-- div will be filled with innerHTML after form submission. -->
Uploading. Please wait...
</div>
</body>
</html>
global.gs
var receiptImageFolderId='your receipt image folder id';
var SSID='your spreadsheet id';
The Spreadsheet Looks Like this:
Note I changed image Id to image Url so that you can just click on the url to get a viewer to look at the image. I think this is much cleaner than trying to put images of varying sizes into the spreadsheet.
I need to scrape private data from a Japanese site.
But I can't login into the site and receive error code 422.
How can I login?
I need to log in into this website:
https://moneyforward.com/users/sign_in
The form on this site is:
<form class="form-horizontal mf-mb40" id="new_sign_in_session_service" action="/session" accept-charset="UTF-8" method="post">
<input name="utf8" type="hidden" value="✓" />
<input type="hidden" name="authenticity_token" value="OGuijdFq6M1xngenCHi0BgZh9x0Nniw2HxiRhC9H2T0vbgWcWNRz+fmi5wxEdk4ua5TL9/UF7BapR2Af8CdILQ==" />
<div class="a-text--f14 mb3">e-mail</div><div class="a-text-box">
<input placeholder="entry" class="js-focus-form" type="email" name="sign_in_session_service[email]" id="sign_in_session_service_email" />
</div>
<div class="a-text--f14 mb3 mt20">password</div><div class="a-text-box">
<input placeholder="entry" type="password" name="sign_in_session_service[password]" id="sign_in_session_service_password" />
</div>
<div class="m-password-support">
<div class="a-checkbox password-show">
<label><input class="checkbox" id="show-ps" name="new1" type="checkbox" value="1" />
<span class="checkbox-icon"></span>
<span class="checkbox-txt">password</span></label>
</div>
<div class="password-forget">
forgot password
</div>
</div>
<div class="a-button primary">
<input type="submit" name="commit" value="login" id="login-btn-sumit" data-disable-with="login" />
</div>
</form>
I receive the error on last row "var response = UrlFetchApp.fetch(url, options)" below code.
function Login() {
var account ='***';
var password = '***';
var response = UrlFetchApp.fetch("https://moneyforward.com/users/sign_in");
var regexp = /<input type=\"hidden\" name=\"authenticity_token\" value=\"(.*?)\" \/>/;
var elements = response.getContentText().match(regexp);
var headers = response.getAllHeaders();
var cookies = [];
if ( typeof headers['Set-Cookie'] !== 'undefined' ) {
var cookies = typeof headers['Set-Cookie'] == 'string' ? [ headers['Set-Cookie'] ] : headers['Set-Cookie'];
for (var i = 0; i < cookies.length; i++) {
cookies[i] = cookies[i].split( ';' )[0];
};
};
var payload = {
utf8: "✓",
authenticity_token : elements[1],
email : "account",
password : password
};
var headers = { 'Cookie' : cookies };
options = {
method : "post",
headers : headers,
followRedirects: true,
contentType: "application/x-www-form-urlencoded",
//muteHttpExceptions : true,
payload : payload,
};
var url = "https://moneyforward.com/session";
var response = UrlFetchApp.fetch(url, options);
}
I have this next page, on which a user can create a new account. My question now is how can i make sure the user inserts a username that doesn't already exist in my MySQL database. The page is available on http://webs.hogent.be/kevinbaeyens/gebruiker.html
the code of this page is:
<!doctype html>
<html class="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Nieuwe gebruiker | Sociale buurt</title>
<link href="boilerplate.css" rel="stylesheet" type="text/css">
<link href="onzebuurt.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="jquery-1.7.1.min.js"></script>
<script type="text/javascript" language="javascript">
window.onload = function() {
document.getElementById("Username").focus();
};
function formulierValideren() {
if (document.getElementById('Username').value == '' || document.getElementById('Username').value == null)
{
alert ('Gebruikersnaam is verplicht.');
document.getElementById('Username').style.borderColor = "red";
return false;
}
else if (document.getElementById('Wachtwoord').value == '' || document.getElementById('Wachtwoord').value == null)
{
alert ('Wachtwoord is verplicht.');
document.getElementById('Wachtwoord').style.borderColor = "red";
return false;
}
else if (document.getElementById('Wachtwoord2').value == '' || document.getElementById('Wachtwoord2').value == null)
{
alert ('Bevestig wachtwoord.');
document.getElementById('Wachtwoord2').style.borderColor = "red";
return false;
}
else if (document.getElementById('Wachtwoord2').value != document.getElementById('Wachtwoord').value)
{
alert ('Wachtwoorden komen niet overeen.');
document.getElementById('Wachtwoord2').style.borderColor = "red";
return false;
}
else
{
var url = "http://localhost:8080/OnzeBuurt2/resources/gebruikers";
var reminder = {};
reminder.naam = jQuery.trim($("#Username").val());
reminder.wachtwoord = jQuery.trim($("#Wachtwoord").val());
var request = new XMLHttpRequest();
request.open("POST", url);
request.onload = function() {
if (request.status === 201) {
reminder.id = request.getResponseHeader("Location").split("/").pop();
} else {
console.log("Error creating reminder: " + request.status + " " + request.responseText);
}
};
request.setRequestHeader("Content-Type", "application/json");
request.send(JSON.stringify(reminder));
var msg = "Registratie succesvol. Klik op OK om u aan te melden op de site.";
if(confirm(msg)){
setTimeout(function() {window.location.href = "http://localhost:8080/OnzeBuurt2/"})
}
}
//end if
}//end function
</script>
</head>
<body class="body2">
<div class="gridContainer clearfix">
<div class="header2">
<center>
Nieuwe gebruiker
</center>
</div>
<div id="formulier2">
<form method="post" name="form" action="">
<p class="labels"><center>Gebruikersnaam *</center></p><input id="Username" type="text" name="Username" placeholder="Gebruikersnaam" size="50">
<p class="labels"><center>Wachtwoord *</center></p><input id="Wachtwoord" type="password" name="Wachtwoord" placeholder="Wachtwoord" size="50">
<p class="labels"><center>Bevestig wachtwoord *</center></p><input id="Wachtwoord2" type="password" name="Bevestig wachtwoord" placeholder="Bevestig wachtwoord" size="50">
<br />
<center><img id="return" name="jsbutton" src="return.png" alt="Terug" /></center>
<br />
<center><input id="bevestig" type="image" src="Bevestig.png" width="200" height="50" border="0" alt="SUBMIT!" onclick="formulierValideren()"></center>
<br />
</form>
</div>
</div>
</body>
</html>
Some notes you need to know:
1) since it's an assignment for school, I can't use PHP.
2) The primary key in my database table 'Gebruiker' is 'ID', the field of 'username' is the field which has to be unique
thanks in advance!