fileUpload in GAS with the same name and extension - google-apps-script

I hope that you can help me, I have a issue.
I need a form in GAS that can upload a file to google drive with the original name. but I canĀ“t make work. I don't know that is wrong, but the file not have extention and the name is Undefined..
this is my simple code;
thanks for all.
function doGet(p) {
var app = UiApp.createApplication();
var flow = app.createFlowPanel().setId('flow');
var gridfile = app.createGrid(5,3);
var flabel0 = app.createLabel('Upload the file');
var flabel1 = app.createLabel('Select file: ');
var thefile = app.createFileUpload().setName('thefile').setId('thefile');
var handlerxx = app.createServerHandler('uploadfile').addCallbackElement(flow);
thefile.addChangeHandler(handlerxx);
gridfile.setWidget(0, 0, flabel0)
.setWidget(2, 0, flabel1)
.setWidget(2, 1, thefile);
flow.add(gridfile);
app.add(flow);
return app;
}
function uploadfile(e) {
var app = UiApp.getActiveApplication();
var fileBlob = Utilities.newBlob(e.parameter.thefile,"application/zip",e.parameter.thefile);
var doc = DocsList.createFile(fileBlob);
app.getElementById('flow').add(app.createLabel('File Uploaded successfully'));
return app;
}

You can only upload a file in a doGet / doPost form structure.
Instead of explaining in details I thought it would be easier to show a working example (honestly it's also simpler ...)
so there it is, note that I had to add a submit button to trigger the form submission.
By the way I added a 'loading' label shown by a client handler because otherwise nothing happens during upload and users can be worrying !!
I commented out the line about zip type and fileName since the uploaded file will keep the name and type automatically.
function doGet() {
var app = UiApp.createApplication();
var form = app.createFormPanel();
var flow = app.createFlowPanel().setId('flow');
form.add(flow);
var gridfile = app.createGrid(5,3);
var flabel1 = app.createLabel('Select file: ');
var lab = app.createLabel('LOADING').setStyleAttributes({'color':'red'}).setVisible(false).setId('lab');
var cliHandler = app.createClientHandler().forTargets(lab).setVisible(true);
var thefile = app.createFileUpload().setName('thefile').setId('thefile');
var button = app.createSubmitButton('Upload the file').addClickHandler(cliHandler);
gridfile.setWidget(2, 0, flabel1)
.setWidget(2, 1, thefile)
.setWidget(2, 2, button);
flow.add(gridfile).add(lab);
app.add(form);
return app;
}
function doPost(e) {
var app = UiApp.getActiveApplication();
Logger.log('doPost');
// var fileBlob = Utilities.newBlob(e.parameter.thefile,"application/zip",e.parameter.thefile);
var doc = DocsList.createFile(e.parameter.thefile);
app.getElementById('lab').setVisible(false);
app.add(app.createLabel('File Uploaded successfully'));
return app;
}

Related

Message Box in popup form

I have a doubt,
I make a Button for Submit form and when I press the first button appear to me a message of confirmation to continue or not, but when I press "no" and the message disappear and return to form,but the first button doesn't work more.
You known that I make wrong.
thanks for all.
function doGet(){
var app = UiApp.createApplication().setTitle('Request Form');
var flow = app.createFlowPanel().setStyleAttribute("textAlign", "center").setWidth("900px");
var buttons = app.createButton('Print and Save').setId('buttons');
var handlers = app.createServerClickHandler('question').addCallbackElement(flow);
buttons.addClickHandler(handlers);
flow.add(buttons);
app.add(flow);
return app;
}
function question(e){
var app = UiApp.getActiveApplication();
var dialog = app.createPopupPanel().setModal(true).setSize(700, 100).setPopupPosition(10, 400);
var closeHandler = app.createClientHandler().forTargets(dialog).setVisible(false);
var handlersend = app.createServerClickHandler('Send');
var handleract =app.createServerClickHandler('activateAgain');
var labelp = app.createLabel('Are you sure that this information is correct?')
var buttonp1= app.createButton('yes, continue').addClickHandler(closeHandler).addClickHandler(handlersend);
var buttonp2= app.createButton('No, I want correct').addClickHandler(closeHandler).addClickHandler(handleract);
app.getElementById('buttons').setEnabled(false);
var gridp = app.createGrid(1,5);
gridp.setWidget(0, 0, labelp)
.setWidget(0,1,buttonp1)
.setWidget(0,2,buttonp2);
dialog.add(gridp)
dialog.show();
return app;
}
function activateAgain(e){
var app = UiApp.getActiveApplication();
app.getElementById('buttons').setEnabled(true);
return app;
}
function Send(e){
}
You are trying to make it happen in clientHandler which is basically a good idea but the problem is that some methods are not available in clientHandlers, for example hide() is not !
So you used setVisible(false) to hide the dialog but then you can't get it visible again easily...
All in all, I found it was easier with serverHandler and a few modifications.
Since you seem to be quite comfortable with UiApp I don't need to explain further, the code is self explanatory enough (I hope :-)
Code below : (and test HERE)
function doGet(){
var app = UiApp.createApplication().setTitle('Request Form');
var flow = app.createFlowPanel().setStyleAttribute("textAlign", "center").setWidth("900px");
var buttons = app.createButton('Print and Save').setId('buttons');
var handlers = app.createServerClickHandler('question').addCallbackElement(flow);
buttons.addClickHandler(handlers);
flow.add(buttons);
app.add(flow);
return app;
}
function question(e){
var app = UiApp.getActiveApplication();
var dialog = app.createPopupPanel().setModal(true).setSize(700, 100).setPopupPosition(10, 400).setId('dialog');
var button = app.getElementById('buttons').setEnabled(true);
var closeHandler = app.createClientHandler().forTargets(button).setEnabled(true);
var correctHandler = app.createServerHandler('hideDialog');
var handlersend = app.createServerClickHandler('Send');
var labelp = app.createLabel('Are you sure that this information is correct?')
var buttonp1= app.createButton('yes, continue').addClickHandler(handlersend);
var buttonp2= app.createButton('No, I want correct').addClickHandler(closeHandler).addClickHandler(correctHandler);
app.getElementById('buttons').setEnabled(false);
var gridp = app.createGrid(1,5);
gridp.setWidget(0, 0, labelp)
.setWidget(0,1,buttonp1)
.setWidget(0,2,buttonp2);
dialog.add(gridp)
dialog.show();
return app;
}
function hideDialog(){
var app = UiApp.getActiveApplication();
var dialog = app.getElementById('dialog');
dialog.hide();
return app;
}
function Send(e){
var app = UiApp.getActiveApplication();
var dialog = app.getElementById('dialog');
dialog.hide();
app.getElementById('buttons').setEnabled(false);
app.add(app.createLabel('send'));
return app;
}

GUI form does not show up

I'm stuck... My code doesn't want to show me my GUI form.
If I'm trying to add this line: sh=SpreadsheetApp.getActive() before sh.show(app) - script works fine in the script editor. But! If I'm trying to deploy as a web app - script doesn't work.
function doGet() {
var app = UiApp.createApplication().setTitle('test online').setHeight(400).setWidth(600);
var dFormat = UiApp.DateTimeFormat.DATE_LONG
var sh = SpreadsheetApp.openById(spreadsheetID);
var settings = sh.getSheetByName('Name');
var lastrowTime = sh.getSheetByName('Name').getLastRow();
var settings = settings.getRange("A2:A" + lastrowTime).getValues();
var main2 = app.createGrid(1, 4);
var status = app.createLabel().setId('status').setWidth('200');
var card = app.createTextBox().setName('card').setId('card').setWidth('50');
var main1 = app.createGrid(6, 3);
var placeA = app.createTextBox().setId('placeA').setName('placeA').setWidth('400');
var placeB = app.createTextBox().setId('placeB').setName('placeB').setWidth('400');
var phone = app.createTextBox().setId(('phone')).setName('phone').setWidth('200');
var timeTo = app.createListBox(false).setWidth(200).setName('timeTo').addItem("...").setVisibleItemCount(1);
for (var i = 0; i < settings.length; i++) {
timeTo.addItem(settings[i]);
}
var main = app.createGrid(4, 5);
var date = app.createDateBox().setName('date').setFormat(dFormat);
var hour = app.createListBox().setName('hour').setWidth('100');
var min = app.createListBox().setName('min').setWidth('100');
for (h=0;h<24;++h){
if(h<10){var hourstr='0'+h}else{var hourstr=h.toString()}
hour.addItem(hourstr)
}
for (m=0;m<60;++m){
if(m<10){var minstr='0'+m}else{var minstr=m.toString()}
min.addItem(minstr)
}
var refresh = app.createButton('Refresh')
var button = app.createButton('Submit')
var main3 = app.createGrid(1,3);
var price = app.createLabel().setId('price').setWidth('400');
var finalStatus = app.createLabel().setId('finalPrice').setWidth('400');
main2.setWidget(0,0, app.createLabel('Client card: ')).setWidget(0,1, card).setWidget(0,3, status);
main1.setWidget(1,0, app.createLabel('From')).setWidget(1,1,placeA);
main1.setWidget(2,0, app.createLabel('To')).setWidget(2,1,placeB);
main1.setWidget(4,0, app.createLabel('Mobile')).setWidget(4,1,phone);
main1.setWidget(5,0, app.createLabel('Make a call?')).setWidget(5,1,timeTo);
main.setWidget(1,0,app.createLabel('Data')).setWidget(1,1,app.createLabel('hour')).setWidget(1,2,app.createLabel('min'))
main.setWidget(2,0,date).setWidget(2,1,hour).setWidget(2,2,min)
main.setWidget(2,3,refresh).setWidget(2,4, button)
main3.setWidget(0,0, price);
main3.setWidget(0,1, finalStatus);
var serverHandler = app.createServerHandler('show').addCallbackElement(main).addCallbackElement(main1).addCallbackElement(main2).addCallbackElement(main3);
button.addClickHandler(serverHandler)
var handler1 = app.createServerHandler('refresh').addCallbackElement(main).addCallbackElement(main1).addCallbackElement(main2).addCallbackElement(main3);
refresh.addClickHandler(handler1)
var handler2 = app.createServerHandler('checkDate').addCallbackElement(main).addCallbackElement(main1).addCallbackElement(main2).addCallbackElement(main3);
date.addValueChangeHandler(handler2)
app.add(main2)
app.add(main1)
app.add(main)
app.add(main3)
sh.show(app)
}
The methods that you are using to show your UI are specifically for Spreadsheet containers. You've probably read this, to get where you are, but re-read Creating User Interface Elements in UI Service, especially the examples of doGet().
function doGet() { // A script with a user interface that is published as a web app
// must contain a doGet(e) function.
...
return myapp;
}
At the end of the function, you simply need to return your UI App instance. No need to call show, or reference the spreadsheet at all.

how do I request information before starting to use the spreadsheet, such as a date range

I need request information before start to use my spreadsheet it is a date range, if you dont enter the date range the spreadsheet must be closed.
Thanks for your help.
You can implement an onOpen() function that would trigger the opening of a dialog and have the dialog remain open as long as the user does not enter the date range you want. I don't think you could force the closing of the spreadsheet if no value is entered though.
You can do that in a UI using UiApp, it would show a link to your spreadsheet only if a condition is validated,else it would reject the request.
EDIT : Here is an example to let you start with :
(the condition has to be defined, I commented the part that must be completed by you...
function doGet() {
var app = UiApp.createApplication().setStyleAttribute('padding', '15').setStyleAttribute('background', 'beige').setWidth('300').setHeight('140');// adjust dimensions to your needs
var mygrid = app.createGrid(3, 2);
mygrid.setWidget(0, 0, app.createLabel('StartDate:'));
mygrid.setWidget(0, 1, app.createDateBox().setId('dateA'));
mygrid.setWidget(1, 0, app.createLabel('EndDtate:'));
mygrid.setWidget(1, 1, app.createDateBox().setId('dateB'));
var mybutton = app.createButton('OK');
mybutton.setId("mybutton");
var mypanel = app.createVerticalPanel();
mypanel.setId('mypanel');
mypanel.add(mygrid);
var label = app.createHTML('<BR>Your request has been approved, <BR><BR>thanks for submitting').setId('Label').setStyleAttribute('padding', '15').setVisible(false).setWidth('300').setHeight('120');// adjust dimensions to your needs
var anchor = app.createAnchor('Open the Spreadsheet', 'https://docs.google.com/spreadsheet/ccc?key=0AnqSFd3iikE3dDljeXhtY3lacUtxdllQbGNHREY0VUE#gid=0').setId('anchor').setVisible(false)
mypanel.add(label).add(anchor)
mypanel.add(mybutton);
app.add(mypanel).add(label);
var handler = app.createServerHandler('checkDates');
handler.addCallbackElement(mypanel);
mybutton.addClickHandler(handler);
var Chandler = app.createClientHandler();
Chandler.forTargets(mygrid,mybutton).setVisible(false)
mybutton.addClickHandler(Chandler)
return app;
}
function checkDates(e) {
var app = UiApp.getActiveApplication();
var Label = app.getElementById('Label');
var anchor = app.getElementById('anchor');
Label.setVisible(true);// show the masking label with message
var dateA = e.parameter.dateA;
var dateB = e.parameter.dateB;
// write your condition...
// if(dateA)...&& dateB== ...
anchor.setVisible(true);
return app
// }else{
app.close
//return app}
}

Is there a way to turn off Auto Fill for users when filling out a form?

I think this is a quick one for you, Folks:
I am collecting data in a UiApp built form, and using validation before enabling them to continue. My problem is that often auto-fill will have different format than what is required in my form (such as the state written out instead of a postal abbreviation). I think this may lead to confusion, so I would love to force the users to fill out each box by hand.
Is there a way to turn off the auto-fill function of browsers?
If I were to build in html, would it give me more control of this?
Thanks for the help~
Martin
NOTE: I am using the "ChangeHandler" as it will at least update the validator when autofill is used.
Here's an example code which is of the style I am using. It includes multiple field validation and a review panel. Relevant to my question, but also may be useful for those building forms.
function doGet(e){
var app = UiApp.createApplication().setTitle("Review and Validation");
var appPanel = app.createVerticalPanel();
var form = app.createFormPanel();
var panel1 = app.createGrid(4,5).setId('panel1');
var firstNameLabel = app.createLabel("First Name:");
var firstName = app.createTextBox().setName('firstName').setId('firstName');
var lastNameLabel = app.createLabel("Last Name:");
var lastName = app.createTextBox().setName('lastName').setId('lastName');
var emailLabel = app.createLabel('Your Email');
var email = app.createTextBox().setName('email').setId('email');
var button1 = app.createButton('Go to Review').setEnabled(false);
var info1 = app.createLabel("Please Enter First Name")
.setVisible(false)
.setStyleAttribute('color', 'red');
var info2 = app.createLabel("Please Enter Last Name")
.setVisible(false)
.setStyleAttribute('color', 'red');
var info3 = app.createLabel("Please Enter Email")
.setVisible(false)
.setStyleAttribute('color', 'red');
var syncChangeHandler = app.createServerHandler('syncText').addCallbackElement(form)
.validateLength(firstName, 2, 30).validateLength(lastName, 2, 30).validateEmail(email);
var onValidInput =
app.createClientHandler().validateLength(firstName,2,30).validateLength(lastName,2,30).validateEmail(email).forTargets(
button1).setEnabled(true);
var onInvalidInput1 =
app.createClientHandler().validateNotLength(firstName, 2, 30).forTargets(button1).setEnabled(false).forTargets(info1).setVisible(true);
var onValidInput1 =
app.createClientHandler().validateLength(firstName, 2, 30).forTargets(info1).setVisible(false);
var onInvalidInput2 =
app.createClientHandler().validateNotLength(lastName, 2, 30).forTargets(button1).setEnabled(false).forTargets(info2).setVisible(true);
var onValidInput2 =
app.createClientHandler().validateLength(lastName, 2, 30).forTargets(info2).setVisible(false);
var onInvalidInput3 =
app.createClientHandler().validateNotEmail(email).forTargets(button1).setEnabled(false).forTargets(info3).setVisible(true);
var onValidInput3 =
app.createClientHandler().validateEmail(email).forTargets(info3).setVisible(false);
firstName.addChangeHandler(onInvalidInput1);
firstName.addChangeHandler(onValidInput1);
lastName.addChangeHandler(onInvalidInput2);
lastName.addChangeHandler(onValidInput2);
email.addChangeHandler(onInvalidInput3);
email.addChangeHandler(onValidInput3);
firstName.addChangeHandler(onValidInput);
lastName.addChangeHandler(onValidInput);
email.addChangeHandler(onValidInput);
panel1.setWidget(0,0, firstNameLabel);
panel1.setWidget(0,1, firstName);
panel1.setWidget(0,2, lastNameLabel);
panel1.setWidget(0,3, lastName);
panel1.setWidget(1,1, info1);
panel1.setWidget(1,3, info2);
panel1.setWidget(2,0, emailLabel);
panel1.setWidget(2,1, email);
panel1.setWidget(2,3, button1);
panel1.setWidget(3,1, info3);
app.add(form);
appPanel.add(panel1);
form.add(appPanel);
var panel2 = app.createGrid(4,5).setId('panel2').setVisible(false);
var reviewFirstNameLabel = app.createLabel("First Name:");
var reviewFirstName = app.createLabel().setId('reviewFirstName');
var reviewLastNameLabel = app.createLabel("Last Name:");
var reviewLastName = app.createLabel().setId('reviewLastName');
var reviewEmailLabel = app.createLabel('Your Email:');
var reviewEmail = app.createLabel().setId('reviewEmail');
var submitButton = app.createSubmitButton('Submit');
var button2 = app.createButton('Edit Response');
panel2.setWidget(0,0, reviewFirstNameLabel);
panel2.setWidget(0,1, reviewFirstName);
panel2.setWidget(0,2, reviewLastNameLabel);
panel2.setWidget(0,3, reviewLastName);
panel2.setWidget(1,0, reviewEmailLabel);
panel2.setWidget(1,1, reviewEmail);
panel2.setWidget(2,0, button2);
panel2.setWidget(3,0, submitButton);
appPanel.add(panel2);
//
var editResponse = app.createClientHandler()
.forTargets(panel1).setVisible(true)
.forTargets(panel2).setVisible(false);
button1.addClickHandler(syncChangeHandler);
button2.addClickHandler(editResponse);
return app;
}
function syncText(e){
var app = UiApp.getActiveApplication();
app.getElementById('reviewFirstName').setText(e.parameter.firstName);
app.getElementById('reviewLastName').setText(e.parameter.lastName);
app.getElementById('reviewEmail').setText(e.parameter.email);
app.getElementById('panel1').setVisible(false);
app.getElementById('panel2').setVisible(true);
return app;
}
function doPost(e){
var ss = SpreadsheetApp.openById('0Aiapuj1KtAujdHYzZzNzMEsxMUtranZhaXhiSFFnanc').getSheets()[0];
var range = ss.getRange(ss.getLastRow()+1, 1, 1,4);
var values = [[new Date(),e.parameter.firstName, e.parameter.lastName, e.parameter.email]];
range.setValues(values);
var app = UiApp.getActiveApplication();
var label = app.createLabel('Thank You!');
app.add(label);
return app;
}
GAS is globally browser independent since the app is running on Google's Server and doesn't interact directly with your browser... I don't think it is possible to tell the browser to do anything like that and I haven't seen any trick that would make that possible... If I'm wrong then I'd be very curious about it ;-)
Edit : I played with your code and I was wondering if it might not be a solution to use a key press handler instead of click handler so users would be forced to use keyboard to fill the form instead of mouse click. I've seen scripts that check if an 'enter' was pressed to validate an answer. (just an idea)
EDIT 2 : Well, Browsers are too smart, I tested it but autocomplete simulates keypress quite efficiently... too bad :-/

Detecting a null value using a ClientHandler in a Google Apps Scripts GUI

I'm coding a GUI using Google Apps Scripts. I have a text box, for example txtLastName and I would like to add a Client Handler to detect a null value. Essentially, I want to make this a required field.
I guess there are a few possibilities, one of them is to use a length validator
var clientHandler = app.createClientHandler().validateLength(widget, min, max)
and to use this to setVisible a warning message and to disable the 'submit button' eventually...
the documentation on clientHandlers is quite explicit
Here is an example in a simple form that checks question 1 and displays a warning message :
function BuildForm() {
var text= new Array();
text =['question 1','question 2','question 3','question 4','question 5','question 6'];
var textBox = new Array();
var app=UiApp.createApplication().setTitle('Form');
var panel = app.createVerticalPanel().setId('panel');
var btn = app.createButton('process');
var warning = app.createLabel('You forgot to fill in question 1').setVisible(false)
for (nn=0;nn<text.length;++nn){
var label = app.createLabel(text[nn]);
textBox[nn] = app.createTextBox().setName(text[nn].replace(' ',''));
panel.add(label).add(textBox[nn])
}
var cliH1 = app.createClientHandler().validateLength(textBox[0], 0, 1)
.forTargets(btn).setEnabled(false)
.forTargets(warning).setVisible(true)
var cliH2 = app.createClientHandler()
.forTargets(btn).setEnabled(true)
.forTargets(warning).setVisible(false)
var servH = app.createServerHandler('process').addCallbackElement(panel).validateLength(textBox[0], 1, 40)
btn.addClickHandler(cliH1)
textBox[0].addClickHandler(cliH2)
btn.addClickHandler(servH)
panel.add(btn).add(warning)
app.add(panel)
var doc = SpreadsheetApp.getActive();
doc.show(app)
}
function process(e){
var app = UiApp.getActiveApplication()
Browser.msgBox(e.parameter.question1+' '+e.parameter.question2+' '+e.parameter.question3+' '+e.parameter.question4+' '+e.parameter.question5+' '+e.parameter.question6)
app.close()
return app
}
EDIT : here is another version using another validation (validateMatches) and checking all answers
function BuildForm2() {
var text= new Array();
text =['question 1','question 2','question 3','question 4','question 5','question 6'];
var textBox = new Array();
var app=UiApp.createApplication().setTitle('Form');
var panel = app.createVerticalPanel().setId('panel');
var btn = app.createButton('process').setWidth('240');
var warning = app.createLabel('You forgot to fill at least one question').setVisible(false)
for (nn=0;nn<text.length;++nn){
var label = app.createLabel(text[nn]);
textBox[nn] = app.createTextBox().setName(text[nn].replace(/ /g,''));
panel.add(label).add(textBox[nn])
}
var servH = app.createServerHandler('process').addCallbackElement(panel).validateLength(textBox[0], 1, 40).validateLength(textBox[1], 1, 40).validateLength(textBox[2], 1, 40)
.validateLength(textBox[3], 1, 40).validateLength(textBox[4], 1, 40).validateLength(textBox[5], 1, 40);
var cliH = app.createClientHandler().validateMatches(textBox[0],'').validateMatches(textBox[1],'').validateMatches(textBox[2],'').validateMatches(textBox[3],'')
.validateMatches(textBox[4],'').validateMatches(textBox[5],'')
.forTargets(warning).setVisible(true)
btn.addClickHandler(servH).addClickHandler(cliH)
panel.add(btn).add(warning)
app.add(panel)
var doc = SpreadsheetApp.getActive();
doc.show(app)
}