GUI apps script, returning "undefined " value - google-apps-script

i've created simple GUI with a flow panel name and ID main panel, a label name Label1 a textbox name myTextBox and a button with ID getETA.
my aim is if i enter a value in text box and click submit den the value should write in spreadsheet.
my problem is the script is returning undefined in spreadsheet not the actual value i've entered.
var app = UiApp.createApplication();
app.setTitle("My Application");
app.add(app.loadComponent("MyGui"));
SpreadsheetApp.getActiveSpreadsheet().show(app);
var clickHandler = app.createServerHandler('clickGetETA');
clickHandler.addCallbackElement(app.getElementById('mainPanel'));
app.getElementById('getETA').addClickHandler(clickHandler);
var doc = SpreadsheetApp.getActive();
doc.show(app);
}
// this function responds to submit button
function clickGetETA(e) {
var app = UiApp.getActiveApplication();
var textBoxValue = e.parameter.myTextBox;
var sheet = SpreadsheetApp.getActiveSheet();
var lastRow = sheet.getLastRow()+1;
var lastCell = sheet.getRange("A"+lastRow);
lastCell.setValue(textBoxValue);
return app.close();
}
I'm new to stackoverflow dont have enough reputations to post image so posting links of images
image1
image2
image3
image4
image5
image6
image7

I see that you defined the clickHandler in the script AND in the GUI builder... that is one too much, that's probably the cause of the issue
Please try to remove the one in the GUI builder and test again, I don't see any other problem in your test ;-)
You could also of course remove the handler in the script but in that case you should add the callbackelement in there too by developing the smal '+' near the handler name and put your panel there.
EDIT : Sorry, there are 2 handlers in the GUI builder, so that is two too much ! you cannot use a single handler with a single name on 2 different handler type (click & key) if you want to have multiple handlers on a button you should define as many handlers you need, each of the type you want, eventually calling the same function but with different variable names.
Edit 2 the line SpreadsheetApp.getActiveSpreadsheet().show(app); in the begining of the main function souldn't be there either, just remove it since you call the spreadsheet later with var doc = SpreadsheetApp.getActive();
Working code with GUI here
EDIT 3 : issue solved by sharing the questioner sheet, the panel name was not correctly written : mainPanel in the script and mainpanel in the GUI ...
Aaaah, case sensitiveness ! ;-) (visible in image6)

Related

Add a new row based on the custom image button's current position

I recently started learning scripts. I've come to a dead end where I can't think of the logic on how I would implement my script where once i click the button it would automatically add a row above the button. Here is sample picture of my spreadsheet I use it to fix my finances.
Here is my current code but its nowhere near what I wanted to do. Kindly help please to lead me to the proper script. Thank you!
function addRow() {
var sheet = SpreadsheetApp.getActiveSheet();
sheet.insertRowAfter(22);
}
If I understand correctly, you want to add a row above the button you have in your sheet. If that is the case, you can try with the following:
function addRow(){
var sheet = SpreadsheetApp.getActiveSheet();
//Use this if the button is an image
var image = sheet.getImages();
var imageRow = image[0].getAnchorCell().getRow();
sheet.insertRowBefore(imageRow);
//Use this if the button is a drawing
/*
var drawings = sheet.getDrawings();
var row = drawings[0].getContainerInfo().getAnchorRow();
sheet.insertRowBefore(row);
*/
}
Note: In the sample provided, I only have one image in the sheet and that's why I have specified image[0].
Remember to assign the script to the button by clicking in the three dots of the drawing, select "Assign script" and add the name of the function.

Get the row/col of a clicked drawing?

I assign to a cell in each row a png icon and a script with
sheet.insertImage(blob, 11, i).assignScript("ClickMe");
At the end of the process I have a few hundred rows with buttons at the end. What I'm struggling to do at the moment is work out which row gets clicked on. I've tried a few likely candidates like
var ss = SpreadsheetApp.getActiveSheet();
var sheetName = ss.getSheetName();
var activeRange = ss.getActiveRange();
var selection = ss.getSelection();
var ar = activeRange.getA1Notation();
var cc = ss.getCurrentCell().getA1Notation();
var scr = selection.getCurrentCell().getA1Notation();
var ac = ss.getActiveCell().getA1Notation();
Logger.log("scr=%s, ar=%s, cc=%s, ac=%s", scr, ar, cc, ac);
but having clicked on the 9th line, the Logger.log says
[19-06-20 22:39:01:123 HKT] scr=A1, ar=A1, cc=A1, ac=A1
So the question is this: if someone clicks on the button on the 21st line, can the script figure out what line the click occurred on?
The other answer is that you need to make 21 helper functions,
what I imagine you have now (> binding script)
Button1 > script
Button2 > script
Button3 > script
Button4 > script
function script(){
//Do something
}
Instead you need
Button1 > scriptOne
Button2 > scriptTwo
Button3 > scriptThree
Button4 > scriptFour
with carrier functions:
function scriptOne (){script(1);}
function scriptTwo (){script(2);}
function scriptThree (){script(3);}
function scriptFour(){script(4);}
and then you have that info in the script function
function script(input){
var row = input;
//Do something
}
This does get tedious, and isn't exactly easy to generate in bulk, but if you have a fixed sheet, that might work.
You can also consider making the button a checkbox, and then making your script be "onEdit" and checking for which row the change occurred in. But the way you are currently thinking won't work because there is no way to bind the scripts passing a variable from the button itself. The script will see all of your current buttons as the exact same thing.
It’s not possible to achieve exactly what you want in your code. This is because when you use the functions “getActiveRange” and “getSelection” [1], it returns the cell or cells that are being selected (have the focus on it). When you click in the inserted image, you’re not clicking the cell but only the image, so the focus is still in the first cell.
To obtain the cell where the image is anchored you can use the following snippet:
var image = sheet.insertImage(blob, 11, i).assignScript("ClickMe");
image.getAnchorCell().getA1Notation());
The problem is that you can’t pass any parameters in the assignScript function (like the cell position in this case), only the name of the function to run [2].
A possible workaround is to adjust the size of the cell to contain the complete image. Once this is done, request to your users that they must first click in the cell and then in the image:
var image = sheet.insertImage(blob, 11, i).setHeight(20).setWidth(20).assignScript("ClickMe");
[1] https://developers.google.com/apps-script/reference/spreadsheet/range
[2] https://developers.google.com/apps-script/reference/spreadsheet/over-grid-image

GAS - define listBox() displayed value

I have a form built and displayed in UiApp which uses the listBox class. My listBoxes are created as in the example below:
var yearText = app.createListBox().setName("yearText")
.addItem("")
.addItem("Reception")
.addItem("Nursery");
When the form loads for the first time they default to display blank (the value at index 0). What I am trying to do is reload the form with stored data, populating the listBox with it's saved value whilst still offering the same options as above (blank, Reception, Nursery).
I have tried using the various setValue methods available to the listBox class but I am not making any progress (variations of setValue are working fine for textArea, checkBox and dateBox classes elsewhere in the form). Any help or guidance gratefully received!
The method for that is setItemSelected(index,Boolean), example below
function doGet(){
var app = UiApp.createApplication();
var list = app.createListBox().addItem('').addItem('v2').addItem('v3').addItem('v4').setItemSelected(2,true);
app.add(list);
return app;
}
Or also : setSelectedIndex(index) (same link for doc
example below too
function doGet(){
var app = UiApp.createApplication();
var list = app.createListBox().addItem('').addItem('v2').addItem('v3').addItem('v4').setSelectedIndex(2);
app.add(list);
return app;
}

Google SpreadSheet saving "undefined" values

My case is this, I'm Trying to save data or values taken from a form created on GUI Builder, the first time I've used the example script posted on [link to google script documentation ][1]
It worked good, I was able to take values typed at the form, but when I decided to use the GUI Builder because, we need more text fields and stuff, It stop working, Every time that I click the button, my spreadsheet gets an "Undefined" value.
I've checked all the IDs and all of them are exactly as the script.
The code:
_guardar : This function inserts textfield values to the spreadsheet.
celda means cell in english
ultimaFila means lastRow
function doGet(e) {
var doc = SpreadsheetApp.openById('0Au-gVDPWE5-bdDhJQzc2N2U4Q2l3LVY2cWpkbHdXMVE');
var app = UiApp.createApplication();
app.add(app.loadComponent("MyForm"));
return app;
}
function _guardar(e){
var app = UiApp.getActiveApplication();
var doc = SpreadsheetApp.openById('0Au-gVDPWE5-bdDhJQzc2N2U4Q2l3LVY2cWpkbHdXMVE');
var ultimaFila = doc.getLastRow();
var celda = doc.getRange('a1').offset(ultimaFila, 0);
celda.setValue(e.parameter.nombre);
celda.offset(0, 1).setValue(e.parameter.empresa);
celda.offset(0, 2).setValue(e.parameter.nit);
celda.offset(0, 3).setValue(e.parameter.sector);
celda.offset(0, 4).setValue(e.parameter.telefono);
celda.offset(0, 5).setValue(e.parameter.email);
celda.offset(0, 6).setValue(e.parameter.web);
celda.offset(0, 7).setValue(e.parameter.descripcion);
app.close();
return app;
}
This is similar to the example code at the google documentation site.![enter image description here][2]
Also I've checked that the "OnClick" event ,is it set on "_enviar" function.
All the textboxs and labels are contained in a Absolute panel, including the buttons.
It is not the IDs that have to correspond to the parameter but the names.
These are defined in another tab in the GUI builder and are used to get the values with e.parameter.name
see screen capture below :
EDIT : following your comment, did you check the callback element in the GUI ? is it the parent panel ?

Replicate tab Panel in GUI Builder google apps

I think I've seen this answer, but I can't remember where for certain.
I'm trying to to create a tabbed panel interface using the GUI Builder, but don't see that option. The part I seem to recall is someone having an approach to replicate that in the GUI Builder. I just can't seem to find that information in my brain, the old google groups or here.
Can someone jog my memory?
Thank you...
Maybe the post you were referring to was this one ? Anyway, no matter how much panels you have, yo could design them in the GUI, one on top of the other or (more simply) one under each other in a 'parent' vertical panel and play with client handlers to show/hide the one you need.
I have an example here with 2 panels in an UI, the UI is designed with script but that is not important, look at the client handlers to see how it works.
If I have some free time tonight I'll make a demo script for 4 panels in GUI ;-).
EDIT : here is a test example (standalone) or embedded in a Google site + link to the script (make a copy to edit)
Note that in the GUI builder you'l have to 'play' with visibility of each panel to work on it, I used a main panel large enough to hold 2 panels together so you can have a better vision of "harmony" between panels (which is not the case in my test;-))
and the code (very simple basic example 4 panels with each of them a textBox & a Label, just to test the handlers on the buttons):
function doGet() {
var app = UiApp.createApplication();
var UI=app.loadComponent('multiUi')
var panel1 = app.getElementById('panel1')
var panel2 = app.getElementById('panel2')
var panel3 = app.getElementById('panel3')
var panel4 = app.getElementById('panel4')
var Button1 = app.getElementById('Button1')
var Button2 = app.getElementById('Button2')
var Button3 = app.getElementById('Button3')
var Button4 = app.getElementById('Button4')
var pHandler1 = app.createClientHandler()
.forTargets(panel1).setVisible(true).forTargets(panel2,panel3,panel4).setVisible(false)
Button1.addClickHandler(pHandler1)
var pHandler2 = app.createClientHandler()
.forTargets(panel2).setVisible(true).forTargets(panel1,panel3,panel4).setVisible(false)
Button2.addClickHandler(pHandler2)
var pHandler3 = app.createClientHandler()
.forTargets(panel3).setVisible(true).forTargets(panel2,panel1,panel4).setVisible(false)
Button3.addClickHandler(pHandler3)
var pHandler4 = app.createClientHandler()
.forTargets(panel4).setVisible(true).forTargets(panel2,panel3,panel1).setVisible(false)
Button4.addClickHandler(pHandler4)
app.add(UI)
return app;
}
The following code makes the tabs, based on the array you put in, dynamically:
function doGet() {
// create application
var app = UiApp.createApplication();
// set array
var aTabs = ['donald','katrijn','dagobert'];
// create tab panel
var pTab = app.createTabPanel();
// add tabs to panel
for(var k=0; k<pTabs.length; k++) {
pTab.add(app.createLabel("This tab is reserved for " + aTabs[k]), aTabs[k]);
}
// add panel to application
app.add(pTab);
// set focus to first tab
pTab.selectTab(0);
// return to application
return app;
}
See link for tabPanel reference.
Publishing your script as a web-app, allows you to insert the script on a google sites.