I make a form with Google script
but I don't know how to make it's field to be REQUIRED
following is my script but my gbchk(form) didn't work
The script will add a line in my excel in my google dive
but even there is no data in the form
How to make a required area in google script?
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('form.html');
}
function uploadFiles(form) {
try {
var folderName = "Upload";
var sheetName = "ulist";
var folder;
var folders = DriveApp.getFoldersByName(folderName);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(folderName);
}
//handling uploading file
var blob = form.myFile;
var file = folder.createFile(blob);
file.setDescription("Uploaded by "+ form.myName);
var fileUrl = file.getUrl();
var FileIterator = DriveApp.getFilesByName(sheetName);
var sheetApp = "";
while (FileIterator.hasNext())
{
var sheetFile = FileIterator.next();
if (sheetFile.getName() == sheetName)
{
sheetApp = SpreadsheetApp.open(sheetFile);
}
}
if(sheetApp == "")
{
sheetApp = SpreadsheetApp.create(sheetName);
}
var sheet = sheetApp.getSheets()[0];
var lastRow = sheet.getLastRow();
var targetRange = sheet.getRange(lastRow+1, 2, 1, 1).setValues([[lastRow+1,form.myName]]);
return "Upload Success!"
} catch (error) {
return "Upload fail because:"+error.toString();
}
}
function gbchk(form)
{
if (form.myName.value == "")
{
alert("Enter your name!!");
form.myName.focus();
return (false);
}
return (true);
}
I would put a required tag on the html form input. The docs for this can be found here:
https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms/Data_form_validation#The_required_attribute
example:
<form>
<label for="choose">Would you prefer a banana or cherry?</label>
<input id="choose" name="i_like" pattern="banana|cherry" required>
<button>Submit</button>
</form>
I'm looking for a solution too.
Putting a required tag on the input fields would work. But the user can simply remove it throught the dev tools.
A slightly better approach is to set the required tags by JS. Users can still get around it, but this time they need to modify the JS itself.
Related
To preface, I'm super new to programming in general, nevermind javascript.
I'm developing a web application where a user can upload a picture by clicking on a button. This action will upload pictures into a certain directory in my google drive with a unique folder and name.
Now, I'm trying to copy and paste the google drive link of a picture any time it has been uploaded.
I am able to successfully get the ID of the picture URL in my getFileUrl() method. But when I call that method within my doStuff1() function then later insert that info into userInfo.fileUrl, I am getting https://docs.google.com/document/d/undefined/ as the output in my spreadsheet.
How can call that value?
Updated: I am realizing that when I use "google.script.run.getFileUrl("fn","i"), that is when I'm getting "undefined". When I run the getFileUrl() function locally, I do get the value that I want. Please advise how I can use .WithSuccessHandler(function) correctly so that I can return the value of "fileId0".
This is the front end, where a user uploads the picture
page.html
<html>
<head>
<body>
<form action="#" method="post" enctype="multipart/form-data">
<div class="row">
<div class="file-field input-field">
<div class="waves-effect waves-light btn-small">
<i class="material-icons right">insert_photo</i>
<span>Import Picture</span>
<input id="files" type="file" name="image">
</div>
<div class="file-path-wrapper">
<input disabled selected type="text" class="file-path
validate" placeholder="Choose an image">
</div>
</div>
</div>
</form>
<?!= include("page-js"); ?>
</div> <!-- CLOSE CONTAINER-->
</body>
</html>
This is part of the javascript to put relevant info in an array, which will later be used to append a row in the google sheet
page-js.html
<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/1.0.0/js/materialize.min.js"></script>
<script src="https://gumroad.com/js/gumroad.js"></script>
<script>
document.getElementById("addAnother").addEventListener("click",doStuff1);
var i=1;
var num={};
function doStuff1(){
num.picNum2=i;
var personName=document.getElementById("fn").value;
var fileId00=google.script.run.getFileUrl("fn","i");
var userInfo ={};
userInfo.firstName= document.getElementById("fn").value;
userInfo.number=i;
userInfo.fileUrl="https://docs.google.com/document/d/"+fileId00
+"/";
i++;
google.script.run.userClicked(userInfo);
}
This is part of the javascript to upload picture file into the Google drive
(still part of page-js.html)
var file,
reader = new FileReader();
var today = new Date();
var date = today.getFullYear()+'-'+(today.getMonth()+1)+'- '+today.getDate();
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,num.picNum,date,$('input#fn')
.val(),$('input#date').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("Please select a image to upload");
return;
}
file = files[0];
if (file.size > 1024 * 1024 * 5) {
showError("The file size should be < 5 MB.");
return;
}
showMessage("Uploading file..");
reader.readAsDataURL(file);
}
function showError(e) {
$('#progress').addClass('red-text').html(e);
}
function showMessage(e) {
$('#progress').removeClass('red-text').html(e);
}
</script>
This part grabs the array "userInfo" and appends the content in a row within a designated google sheet. Any time, I click on the button in the front end, it creates a new row.
Code.gs
//google sheet web script
var url="https://docs.google.com/spreadsheets/d/XXXXX";
function getFileUrl(fn,i){
try{
var today0 = new Date();
var date0 = today0.getFullYear()+'-'+(today0.getMonth()+1)+'-'
+today0.getDate();
var dropbox0 = "OE Audit Pictures";
var folder0,folders0 = DriveApp.getFoldersByName(dropbox0);
while (folders0.hasNext())
var folder0=folders0.next();
var dropbox20=[date0,fn].join(" ");
var folder20,folders20=folder0.getFoldersByName(dropbox20);
while (folders20.hasNext())
var folder20=folders20.next();
var file0, files0= folder20.getFilesByName(i);
while (files0.hasNext())
var file0=files0.next();
var fileId0=file0.getUrl();
return fileId0;
} catch(f){
return f.toString();
}
}
function userClicked(userInfo){
var ss= SpreadsheetApp.openByUrl(url);
var ws=ss.getSheetByName("Data");
ws.appendRow([userInfo.number,new Date(),
userInfo.firstName,userInfo.fileUrl]);
}
function include(filename){
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
function uploadFileToGoogleDrive(data, file, fn, date) {
try {
var dropbox = "OE Audit Pictures";
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)
var dropbox2=[fn,date].join(" ");
var folder2, folders2=folder.getFoldersByName(dropbox2)
if (folders2.hasNext()){
folder2=folders2.next().createFile(blob);
} else {
file = folder.createFolder([fn,date].join(" ")).createFile(blob);
}
return "OK";
} catch (f) {
return f.toString();
}
}
In doStuff1() of "page-js.html", you want to give a value returned from getFileUrl() of "Code.gs" to userInfo.fileUrl.
If my understanding is correct, how about this modification?
Modification point:
google.script.run.getFileUrl() doesn't return values. When you want to use the values from getFileUrl(), you can use withSuccessHandler() as following modified script.
Modified script:
Please modify doStuff1() as follows.
function doStuff1() {
num.picNum2 = i;
var personName = document.getElementById("fn").value;
google.script.run.withSuccessHandler(doStuff2).getFileUrl("fn","i"); // Modified
}
// Added
function doStuff2(fileId00) {
var userInfo = {};
userInfo.firstName = document.getElementById("fn").value;
userInfo.number = i;
userInfo.fileUrl = "https://docs.google.com/document/d/"+fileId00 +"/";
i++;
google.script.run.userClicked(userInfo);
}
Note:
In this modification, I used doStuff2() for retrieving the values from getFileUrl(). If you want to modify the function name, please modify it.
Reference:
Class google.script.run
If I misunderstood your question and this was not the result you want, I apologize.
I'm a little worried and in a hurry and I'm not sure if this is the right place to ask this, but I literally have no idea where else to ask.
Long story short, I wanted to clear my gmail account from spam and found the following link while searching for a way to do this:
https://www.labnol.org/internet/gmail-unsubscribe/28806/
Like a complete idiot, I followed the instructions blindly without suspecting anything. After completing the steps, nothing really happened (the spreadsheet wasn't filling) so I stopped the script and removed it from my google accounts permissions and started inspecting the code that was used. It consists of three files, the google script:
function getConfig() {
var params = {
label:doProperty_("LABEL") || "Unsubscribe"
};
return params;
}
function config_() {
var html = HtmlService.createHtmlOutputFromFile('config')
.setTitle("Gmail Unsubscriber")
.setWidth(300).setHeight(200).setSandboxMode(HtmlService.SandboxMode.IFRAME);
var ss = SpreadsheetApp.getActive();
ss.show(html);
}
function help_() {
var html = HtmlService.createHtmlOutputFromFile('help')
.setTitle("Google Scripts Support")
.setWidth(350).setHeight(120);
var ss = SpreadsheetApp.getActive();
ss.show(html);
}
function createLabel_(name) {
var label = GmailApp.getUserLabelByName(name);
if (!label) {
label = GmailApp.createLabel(name);
}
return label;
}
function log_(status, subject, view, from, link) {
var ss = SpreadsheetApp.getActive();
ss.getActiveSheet().appendRow([status, subject, view, from, link]);
}
function init_() {
Browser.msgBox("The Unsubscriber was initialized. Please select the Start option from the Gmail menu to activate.");
return;
}
function onOpen() {
var menu = [
{name: "Configure", functionName: "config_"},
null,
{name: "☎ Help & Support",functionName: "help_"},
{name: "✖ Stop (Uninstall)", functionName: "stop_"},
null
];
SpreadsheetApp.getActiveSpreadsheet().addMenu("➪ Gmail Unsubscriber", menu);
}
function stop_(e) {
var triggers = ScriptApp.getProjectTriggers();
for(var i in triggers) {
ScriptApp.deleteTrigger(triggers[i]);
}
if (!e) {
Browser.msgBox("The Gmail Unsubscriber has been disabled. You can restart it anytime later.");
}
}
function doProperty_(key, value) {
var properties = PropertiesService.getUserProperties();
if (value) {
properties.setProperty(key, value);
} else {
return properties.getProperty(key);
}
}
function doGmail() {
try {
var label = doProperty_("LABEL") || "Unsubscribe";
var threads = GmailApp.search("label:" + label);
var gmail = createLabel_(label);
var url, urls, message, raw, body, formula, status;
var hyperlink = '=HYPERLINK("#LINK#", "View")';
var hrefs = new RegExp(/<a[^>]*href=["'](https?:\/\/[^"']+)["'][^>]*>(.*?)<\/a>/gi);
for (var t in threads) {
url = "";
status = "Could not unsubscribe";
message = threads[t].getMessages()[0];
threads[t].removeLabel(gmail);
raw = message.getRawContent();
urls = raw.match(/^list\-unsubscribe:(.|\r\n\s)+<(https?:\/\/[^>]+)>/im);
if (urls) {
url = urls[2];
status = "Unsubscribed via header";
} else {
body = message.getBody().replace(/\s/g, "");
while ( (url === "") && (urls = hrefs.exec(body)) ) {
if (urls[1].match(/unsubscribe|optout|opt\-out|remove/i) || urls[2].match(/unsubscribe|optout|opt\-out|remove/i)) {
url = urls[1];
status = "Unsubscribed via link";
}
}
}
if (url === "") {
urls = raw.match(/^list\-unsubscribe:(.|\r\n\s)+<mailto:([^>]+)>/im);
if (urls) {
url = parseEmail_(urls[2]);
var subject = "Unsubscribe";
GmailApp.sendEmail(url, subject, subject);
status = "Unsubscribed via email";
}
}
if (status.match(/unsubscribed/i)) {
UrlFetchApp.fetch(url, {muteHttpExceptions: true});
}
formula = hyperlink.replace("#LINK", threads[t].getPermalink());
log_( status, message.getSubject(), formula, message.getFrom(), url );
}
} catch (e) {Logger.log(e.toString())}
}
function saveConfig(params) {
try {
doProperty_("LABEL", params.label);
stop_(true);
ScriptApp.newTrigger('doGmail')
.timeBased().everyMinutes(15).create();
return "The Gmail unsubscriber is now active. You can apply the Gmail label " + params.label + " to any email and you'll be unsubscribed in 15 minutes. Please close this window.";
} catch (e) {
return "ERROR: " + e.toString();
}
}
function parseEmail_(email) {
var result = email.trim().split("?");
return result[0];
}
And two other .html files called config.html:
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
<script>
function closeWindow() {
google.script.host.close();
}
function showError(error) {
document.getElementById("error").innerHTML = error;
}
function showConfig(params) {
if (params.label !== "")
document.getElementById("label").value = params.label;
return;
}
function validate() {
var label = document.getElementById("label").value;
if (label.trim() === "") {
showError("Please enter a Gmail label name..");
return;
} else {
showError("Saving configuration, please wait..");
var params = {
label: label
};
google.script.run.withSuccessHandler(showError).saveConfig(params);
}
}
</script>
<form>
<div class="form-group block">
<p style="margin-bottom:4px;">Enter Gmail Label Name:</p>
<input type="text" id="label" name="label" placeholder="Your email address.." style="width: 250px;" />
</div>
<p>
<input class="blue" type="button" value="Save configuration" onclick="validate()" />
<input class="green" type="button" value="Close window" onclick="google.script.host.close()" />
</p>
<p class="error" id="error"></p>
</form>
<script>
google.script.run.withSuccessHandler(showConfig).getConfig();
</script>
And lastly help.html:
<head>
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
<base target="_blank">
</head>
<div class="block">
<p>If you are need help with the program, please refer to the online tutorial. For support and customization, please submit your requirements at <strong>ctrlq.org</strong>.</p>
</div>
<div class="block">
<a class="button blue" href="mailto:amit#labnol.org" style="width:120px;">amit#labnol.org</a>
<a class="button green" href="https://twitter.com/labnol" style="width:120px;margin-right:10px">Tweet #labnol</a>
<input class="red" type="button" value="Close" onclick="google.script.host.close()" />
</div>
Is there any way that my account could be in any danger?
I am the author of this Google Script and it is completely safe. In fact, you have access to the full source code so you know exactly what it is doing.
Also, if you like to remove any Google Script from your account, here's how:
Go to https://security.google.com/settings/security/permissions
Click the script you wish to uninstall
Next click Remove and you are done.
I have a form, which allows to select an item from a dropdown list and upload a file. The name and the ID of the item are saved in a Spreadsheet document. Works with one file...but I want to upload multiple files. Could you help me fixing the script?
The HTML part looks like this
<div class="col-md-4 col-sm-6 ">
<div class="caption">
<h3>Bildauswahl</h3>
<p align="center"><input type="file" name="myFiles[]" id="myFiles" multiple></p>
</div>
</div>
My script, which is not working, is the following:
var dropBoxId = "XYZ";
var logSheetId = "ABC";
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('InputForm.html');
}
function uploadFiles(formObject) {
try {
// Create a file in Drive from the one provided in the form
var folder = DriveApp.getFolderById(dropBoxId);
var input = document.getElementById('myFiles');
for (i = 0; i<input.files.length; i++) {
var blob = input.files[i];
var file = folder.createFile(blob);
var ss = SpreadsheetApp.openById(logSheetId);
var sheet = ss.getSheets()[0];
sheet.appendRow([file.getName(), file.getUrl(), formObject.myName]);
}
// Return the new file Drive URL so it can be put in the web app output
return file.getUrl();
} catch (error) {
return error.toString();
}
}
Thanks.
As of right now you have to use a work around to work with multiple files. The multiple attribute only works in IFRAME mode, but file inputs are broken in IFRAME mode.
To see this workaround take a look at the bug submission for this issue:
https://code.google.com/p/google-apps-script-issues/issues/detail?id=4610
Also in your code you have some mixing of server side and client side code that will not work:
var folder = DriveApp.getFolderById(dropBoxId); //server side
var input = document.getElementById('myFiles'); //client side
You will need to do your multiple file processing on the client side
I came up with a nice solution for multi-file uploading. Limitations are files must be under 10 MB.
CODE.GS
function doGet() {
return HtmlService.createHtmlOutputFromFile('index').setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function saveFile(data,name,folderId) {
var contentType = data.substring(5,data.indexOf(';'));
var file = Utilities.newBlob(Utilities.base64Decode(data.substr(data.indexOf('base64,')+7)), contentType, name);
DriveApp.getFolderById(folderId).createFile(file);
}
index.html
<div>
<input type="file" id="myFiles" name="myFiles" multiple/>
<input type="button" value="Submit" onclick="SaveFiles()" />
</div>
<script>
var reader = new FileReader();
var files;
var fileCounter = 0;
var folderId = "";
reader.onloadend = function () {
google.script.run
.withSuccessHandler(function(){
fileCounter++;
postNextFile();
}).saveFile(reader.result,files[fileCounter].name,folderId);
}
function SaveFiles(){
var folderSelect = document.getElementById("folderSelectId");
folderId = folderSelect.options[e.selectedIndex].value;
files = document.getElementById("myFiles").files;
postNextFile();
}
function postNextFile(){if(fileCounter < files.length){reader.readAsDataURL(files[fileCounter]);}else{fileCounter=0;alert("upload done")}}
</script>
I created this function for next and previous button, in other words there are 2 buttons in my html page and when i click next or previous the pages in the monocle will also move accordingly,
i read that i have to use a custom page flipper for this but they have not provided an example of how to create one.
this is what i've tried and fails:
function fileSelected(event,str) {
var thefile = document.getElementById('file');
var tval = thefile.value;
var ext = tval.split('.').pop();
var files = event.target.files;
var fname = tval.split(/(\\|\/)/g).pop();
if (ext == "epub" || ext == "EPUB"){
function createReader(bookData) {
Monocle.Reader("reader", bookData);
}
new Epub(files[0], createReader);
}else if(ext == "htm" || ext == "htm" || ext == "html" || ext == "HTML"){
var bookData = {
getComponents: function () {
return [
fname
];
},
getContents: function () {
return [
{title: "test", src: fname}
]
},
getComponent: function (componentId) {
return {url:componentId};
},
getMetaData: function(key) {
return {
title: "Test documents",
creator: "Aron Woost"
}[key];
}
}
window.reader = Monocle.Reader('reader', bookData);
}else{
return false;
}
}
function next(){
Monocle.Reader('reader', {}, {}, function (reader) {
reader.moveTo({ direction: 1 });
});
}
when clicking next will give an undefined error in my console.
any idea as how to implement a custom page flipper?
https://github.com/joseph/Monocle/wiki/Page-flippers
I am not that savvy in JS. sorry :(
I think the problem is in this block of variable declaration:
var thefile = document.getElementById('file');
var tval = thefile.value;
var ext = tval.split('.').pop();
var files = event.target.files;
var fname = tval.split(/(\\|\/)/g).pop();
Is there any input field with 'value' property applicable, like <input type="text" id="file"> ?
You sure the filename will certainly have a dot in it, i.e. extension?
Also event.target.files looks suspicious.
If there's nothing wrong, please tell which line the console shows error at. You can double click on the error to have the erroneous line highlighted.
hello guys..
I am making a page in which i have to take excel file from user and read that file ..but all i know is to read a particular file by giving its address..for this i am using javascript and html ..here is my code for reading excel file
<input type="button" id="btnSubmit" onclick="readdata(1, 2)" value="Submit" />
<script>
function readdata(x,y) {
try {
var excel = new ActiveXObject("Excel.Application");
excel.Visible = false;
var excel_file = excel.Workbooks.Open("D:\\Test.xls");//
alert(excel_file.worksheets.count);
var excel_sheet = excel_file.Worksheets("Sheet1");
var data = excel_sheet.Cells(x, y).Value;
//alert(data);
drawWithexcelValue(data);
}
catch (ex) {
alert(ex);
}
// return data;
}
</script>
This is my code for reading excel file by defining path of a particular excel file...now i have to do is take the excel file from user..guys please help..
And any kind of help through code wil be really appreciated..
someone please help me
As #Alex K mentioned, this would work only in IE.
Here a possible solution:
Put all of your Excel files in the same folder. For example: C:\sheets\
(Edit: I think this is the easiest solution since I don't know of a way to get the full and real path of a file via javascript)
Now change your code to something along these lines:
<input type="file" id='excelFile' />
<button id='loadExcel'>Load Excel File</button>
<script type="text/javascript">
var EXCELDIR = "C:\\sheets\\";
var loadExcel = document.getElementById('loadExcel');
loadExcel.onclick = function() {
var filepath = EXCELDIR + document.getElementById('excelFile').value.split('\\')[2];
readdata(1,2, filepath);
}
function readdata(x,y,filepath) {
try {
var excel = new ActiveXObject("Excel.Application");
excel.Visible = false;
var excel_file = excel.Workbooks.Open(filepath);
alert(excel_file.worksheets.count);
var excel_sheet = excel_file.Worksheets("Sheet1");
var data = excel_sheet.Cells(x, y).Value;
//alert(data);
drawWithexcelValue(data);
}
catch (ex) {
alert(ex);
}
// return data;
}
</script>
Disclaimer: I didn't check the code since I'm on mac, hopefully this works.