Google Sheet Apps Script Exceeding maximum time - validation

I have a dynamic dropdown apps script running on only 1 cell and there are some other formulas running in my sheet. Until 2 days before i could run the script onEdit but i cant seem to do so now.
When checked inside apps script execution page it shows "Exceeded maximum execution time". What can i do to resolve this?
var mainWsName = "Print Sheet";
var mainDataName = "Orders";
var FirstLevelColumn = 1;
var SecondLevelColumn = 2;
var ThirdLevelColumn = 3;
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(mainWsName);
var wsJO = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(mainDataName);
var JO = wsJO.getRange(2,1,wsJO.getLastRow()-1,2).getValues();
function onEdit(e){
var activeCell = e.range;
var val = activeCell.getValue();
var r = activeCell.getRow();
var c = activeCell.getColumn();
var wsName = activeCell.getSheet().getName();
if(wsName === mainWsName && c === FirstLevelColumn && r > 1){
applyFirstLevelValidation(val,r);
}else if(wsName === mainWsName && c=== SecondLevelColumn && r > 1){
applysecondLevelValidation(val,r);
}
} //end onEdit
function applyFirstLevelValidation(val,r){
if(val === ""){
ws.getRange(r,SecondLevelColumn).clearContent();
ws.getRange(r,SecondLevelColumn).clearDataValidations();
} else {
ws.getRange(r,SecondLevelColumn).clearContent();
var filteredJO = JO.filter(function(o){return o[0] === val });
var listToApply = filteredJO.map(function(o){return o[1]});
var cell = ws.getRange(r,SecondLevelColumn);
applyValidationToCell(listToApply,cell);
}
}
function applyValidationToCell(list,cell){
var rule=SpreadsheetApp.newDataValidation().requireValueInList(list).setAllowInvalid(false).build();
cell.setDataValidation(rule);
}
Tried executing app script to get dynamic dropdown based on my selection.

The code you quote is suboptimal, but chances are that the bad performance you mention is caused by the spreadsheet rather than the script. To improve spreadsheet performance, see these optimization tips.
You may also want to take a look at the dependentDropDownLists_ script.

Related

cannot read property "0" of undefined error

I have a code that pulls information from all excel type files in some folders on google drive. The problem is that there are over 100 files and the code only pulls data from around 30 files and shows the following error: "TypeError: Cannot read property '0' of undefined" The error is in line 12, "console.log(lista_carpetas_ok2[i][0]) // Here, you can see the folder ID in the log."
function listfechas() {
var ss2 = SpreadsheetApp.getActiveSpreadsheet();
var carpetasSheet = ss2.getSheetByName("carpetas");
var lista_carpetas = carpetasSheet.getRange("C2:C" + carpetasSheet.getLastRow()).getValues();
var lista_carpetas_ok2 = lista_carpetas.filter(([a]) => a);
var sheet2 = ss2.getSheetByName("SS23");
sheet2.clear();
sheet2.appendRow(["Folder", "Name", "SMS","rec SMS", "FIT", "rec FIT", "2FIT", "rec 2FIT" ,"3FIT" ,"rec 3FIT" ,"PP" ,"rec PP" ,"2PP" ,"rec 2PP", "3PP", "rec 3PP","SHIP", "rec SHIP", "2SHIP","rec 2SHIP"]);
for (var i = 0; i < 5; i++) {
console.log(lista_carpetas_ok2[i][0]) // Here, you can see the folder ID in the log.
var folderid = lista_carpetas_ok2[i][0];
try {
var parentFolder =DriveApp.getFolderById(folderid);
listFiles(parentFolder,parentFolder.getName())
listSubFolders(parentFolder,parentFolder.getName());
} catch (e) {
Logger.log(e.toString());
}
}
function listSubFolders(parentFolder,parent) {
var childFolders = parentFolder.getFolders();
while (childFolders.hasNext()) {
var childFolder = childFolders.next();
Logger.log("Fold : " + childFolder.getName());
listFiles(childFolder,parent)
listSubFolders(childFolder,parent + "|" + childFolder.getName());
}
}
function listFiles(fold,parent){
var data = [];
var files = fold.getFilesByType(MimeType.GOOGLE_SHEETS);
try {
while (files.hasNext()) {
var file = files.next();
var sms = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("A2").getValue();
var recsms = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("B2").getValue();
var fit = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("C2").getValue();
var recfit = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("D2").getValue();
var dfit = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("E2").getValue();
var recdfit = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("F2").getValue();
var tfit = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("G2").getValue();
var rectfit = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("H2").getValue();
var pp = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("I2").getValue();
var recpp = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("J2").getValue();
var dpp = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("K2").getValue();
var recdpp = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("L2").getValue();
var tpp = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("M2").getValue();
var rectpp = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("N2").getValue();
var ship = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("O2").getValue();
var recship = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("P2").getValue();
var dship = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("Q2").getValue();
var recdship = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("R2").getValue();
var fullRange = sheet2.getRange("A1:Z1001");
fullRange.setVerticalAlignment(DocumentApp.VerticalAlignment.TOP);
data = [
fold.getName(),
file.getName(),
sms,
recsms,
fit,
recfit,
dfit,
recdfit,
tfit,
rectfit,
pp,
recpp,
dpp,
recdpp,
tpp,
rectpp,
ship,
recship,
dship,
recdship,
];
sheet2.appendRow(data);
};
} catch (e) {
// In this modification, when your folder ID cannot be used, that folder ID is skipped. At that time, an error message can be seen in the log.
console.log(e.message);
}
}
}
When I wrote the code, I added catch (e) which I thought skipped the folder if there was no excel file in that folder, but the code stops at folder "QM0201" which does not have an excel file in it.
Does anybody know how I can fix it? I would like the code to run even if some folders don't have an excel files in them, those should just be skipped.
Thank you so much in advance! Any help is appreciated.
To avoid the error, replace
for (var i = 0; i < 5; i++) {
by
for (var i = 0; i < lista_carpetas_ok2.length; i++) {
This might also help to avoid the code to stop at certain folder.
Regarding the error
> Info Cannot read property 'getRange' of null"
This occurs because the spreadsheet hasn't a sheet named fechas
to avoid this error you might add
if(!SpreadsheetApp.open(file).getSheetByName("fechas")) break;
above of
var sms = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("A2").getValue();
if(
Debugging tips:
To verify that the correct values are assigned to lista_carpetas_ok2, add console.log(JSON.stringify(lista_carpetas_ok2)); just below lista_carpetas_ok2 declaration so you can review the values assigned to the variable.
To have more informative logs when an error occurs, instead of
} catch (e) {
Logger.log(e.toString()); // or console.log(e.message);
}
use
} catch (e) {
console.log(e.message, e.stack);
}
This is hardly a cause of the error but who knows, the code has the very unefficient part — 72 calls to the server. It can be greatly improved if you change this:
var sms = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("A2").getValue();
var recsms = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("B2").getValue();
var fit = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("C2").getValue();
var recfit = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("D2").getValue();
var dfit = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("E2").getValue();
var recdfit = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("F2").getValue();
var tfit = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("G2").getValue();
var rectfit = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("H2").getValue();
var pp = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("I2").getValue();
var recpp = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("J2").getValue();
var dpp = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("K2").getValue();
var recdpp = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("L2").getValue();
var tpp = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("M2").getValue();
var rectpp = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("N2").getValue();
var ship = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("O2").getValue();
var recship = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("P2").getValue();
var dship = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("Q2").getValue();
var recdship = SpreadsheetApp.open(file).getSheetByName("fechas").getRange("R2").getValue();
To this:
var values = SpreadsheetApp.open(file).getSheetByName("fechas").getRange('A2:R2').getValues().flat();
var [sms,recsms,fit,recfit,dfit,recdfit,tfit,rectfit,pp,recpp,dpp,recdpp,tpp,rectpp,ship,recship,dship,recdship] = values;
It will reduce the quantity of calls to 4!
It should work faster and, if the real cause of the error is exceed of time limit (~6 min) this improvement can help. Try it.
Probably you could simplify the code further. Instead of this:
data = [
fold.getName(),
file.getName(),
sms,
recsms,
fit,
recfit,
dfit,
recdfit,
tfit,
rectfit,
pp,
recpp,
dpp,
recdpp,
tpp,
rectpp,
ship,
recship,
dship,
recdship,
];
You can use this:
var values = SpreadsheetApp.open(file).getSheetByName("fechas").getRange('A2:R2').getValues().flat();
var data = [fold.getName(), file.getName(), ...values];
No need to use the 18 variables, as far as I can see. It barely affects on the speed, though.

Is there a way I can make my script more efficient?

I have created the below script to add a timestamp when a cell equals a specific value. This script repeats for each row but it is not efficient. How can I make this simpler and quicker? Below is an extract of the script, it repeats for each row
function MyFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getSheetByName('Overview')
var cell = sheet.getRange('H3').getValue()
var sent = sheet.getRange('p3').getValue()
if (cell == "Full" && sent == "") {
sheet.getRange('p3').setValue(new Date())
}
else if (cell == "Open" && sent == "") {
sheet.getRange('p3').setValue("")
}
}
Try this.
function MyFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Overview');
// get range H3:P were H=8, P=16, 9 columns total or index 0 to 8
var data = sheet.getRange(3,8,sheet.getLastRow()-2,9).getValues(); // get range H3:P
var i = 0;
var row = null;
for( i=0; i<data.length; i++ ) {
row = data[i];
if( ( row[0] === "Full" ) && ( row[8] === "" ) ) {
row[8] = new Date();
}
// Your else doesn't do anything if blank set blank ??
row.splice(0,8); // extract only column P
}
sheet.getRange(3,16,data.length,1).setValues(data);
}
Try using setvalues() method of class range
function MyFunction() {
const ss = SpreadsheetApp.getActive()
const sh = ss.getSheetByName('Overview');
const rg = sh.getDataRange();
const vs = rg.getValues();
let vo = vs.map(r => {
if( r[7] == "Full") r[15]=new Date()
if( r[7] == "Open") r[15]='';
return [r[15]];
});
sh.getRange(2,16,vo.length,1).setValues(vo);
}

Dependent Data Validation column script not rejecting input (Apps Script)

I made the following script to have a dependent dropdown data validation list for an entire column, however I can't seem to find a way to reject input if it's not valid, even with setAllowInvalid(), which I suspect is because I'm doing an offset.
Any help would be greatly appreciated.
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Cost Centers");
var ui = SpreadsheetApp.getUi();
var activeCell = ss.getActiveCell();
if(activeCell.getColumn() == 4 && activeCell.getRow() > 1) {
if(activeCell.isBlank()){
activeCell.offset(0,1).clearContent().clearDataValidations();
}
var departments = data.getRange(3,26,1,20).getValues();
var departmentIndex = departments[0].indexOf(activeCell.getValue()) + 26;
if(departmentIndex != 0) {
var validationRange = data.getRange(4,departmentIndex,60);
var validationRule = SpreadsheetApp.newDataValidation().requireValueInRange(validationRange).setAllowInvalid(true).build();
activeCell.offset(0,1).setDataValidation(validationRule);
} }
}
setAllowInvalid(false)
setAllowInvalid(allowInvalidData)
true if the rule should allow input that fails data validation; false if not.

Form Validation Before Submission

I can't get my form to validate before it is submitted to my spreadsheet. Once I click submit it does nothing...
I also am not sure how to validate the Date to make sure it is in the correct format before submission. I have tried to setup the validation but before I can test it, i have to be able to submit and get validation results.
What am I doing wrong? I have included the code below:
function doGet() {
var app = UiApp.createApplication().setTitle('DHS: Kurzweil Calendar');
//Create a panel which holds all the form elelemnts
var vrtMainPanel = app.createVerticalPanel().setId('vrtMainPanel');
//Create Spreadsheet Source
var spSheet = SpreadsheetApp.openById('0Aur3owCpuUY-dFF0dVZXb3I1Yjlpbzg3SXFIaklEcUE');
var spTeacherList = spSheet.getSheetByName('TeacherList');
var spSubjectList = spSheet.getSheetByName('SubjectList');
var spPeriodList = spSheet.getSheetByName('PeriodList');
var spCountList = spSheet.getSheetByName('CountList');
//Create the form elements
var hdlTeacherName = app.createServerHandler('getTeacherName').addCallbackElement(vrtMainPanel);
var lbxTeacherName = app.createListBox().setId('lbxTeacherName').setName('lbxTeacherName').addChangeHandler(hdlTeacherName);
var lstTeacherNames = spTeacherList.getRange(1,1,spTeacherList.getLastRow(),1).getValues();
lstTeacherNames.sort();
for (var l = 0; l < lstTeacherNames.length; l++) {
lbxTeacherName.addItem(lstTeacherNames[l],l);
}
var lblTeacherName = app.createLabel('Teacher Name:');
var txtTeacherName = app.createTextBox().setName('txtTeacherName').setId('txtTeacherName').setVisible(false);
var lblExt = app.createLabel('Ext:');
var txtExt = app.createTextBox().setName('txtExt').setId('txtExt');
//Set DateBox to Tomorrow's Date
var tomorrow =new Date(new Date(new Date().setHours(0,0,0,0)).setDate(new Date().getDate() + 1));// set hours, min, sec & milliSec to 0 and day=day+1
//Logger.log(tomorrow);
var lblDate = app.createLabel('Date of Test:');
var boxDate = app.createDateBox().setId('boxDate').setName('boxDate').setFormat(UiApp.DateTimeFormat.DATE_SHORT).setValue(tomorrow);
var lbxSubject = app.createListBox().setId('lbxSubject').setName('lbxSubject');
var lstSubjects = spSubjectList.getRange(1,1,spSubjectList.getLastRow(),1).getValues();
lstSubjects.sort();
for (var l = 0; l < lstSubjects.length; l++) {
lbxSubject.addItem(lstSubjects[l]);
}
var lbxPeriod = app.createListBox().setId('lbxPeriod').setName('lbxPeriod');
var lstPeriods = spPeriodList.getRange(1,1,spPeriodList.getLastRow(),1).getValues();
lstPeriods.sort();
for (var l = 0; l < lstPeriods.length; l++) {
lbxPeriod.addItem(lstPeriods[l]);
}
var lblStudentNum = app.createLabel('Number of Students:');
var lbxStudentNum = app.createListBox().setId('lbxStudentNum').setName('lbxStudentNum');
var lstStudentNums = spCountList.getRange(1,1,spCountList.getLastRow(),1).getValues();
lstStudentNums.sort();
for (var l = 0; l < lstStudentNums.length; l++) {
lbxStudentNum.addItem(lstStudentNums[l]);
}
var txtSourceGrp = app.createTextBox().setName('txtSourceGrp').setVisible(false);
var txtTypeGrp = app.createTextBox().setName('txtTypeGrp').setVisible(false);
var txtElementsID = app.createTextBox().setName('txtElementsID').setText('Elements Test ID').setVisible(false);
var txtQuiaLink = app.createTextBox().setName('txtQuiaLink').setText('Quia Test Link').setVisible(false);
var txtQuiaPass = app.createTextBox().setName('txtQuiaPass').setText('Quia Test Passphrase').setVisible(false);
//Create Source Radio Button Group
var radHCopy = app.createRadioButton('group1', 'Hard-Copy').setFormValue('Hard-Copy').addClickHandler(app.createClientHandler().forTargets(txtSourceGrp).setText('Hard-Copy'));
var radECopy = app.createRadioButton('group1', 'Electronic-Copy').setFormValue('Electronic-Copy').addClickHandler(app.createClientHandler().forTargets(txtSourceGrp).setText('Electronic-Copy'));
//Create Type Radio Button Group
var radTExam = app.createRadioButton('group2', 'Teacher-Made Exam').setFormValue('Teacher-Made Exam').addClickHandler(app.createClientHandler().forTargets(txtTypeGrp).setText('Teacher-Made Exam'));
var radEExam = app.createRadioButton('group2', 'Elements Exam').setFormValue('Elements Exam').addClickHandler(app.createClientHandler().forTargets(txtTypeGrp).setText('Elements Exam'));
var radQExam = app.createRadioButton('group2', 'Quia Exam').setFormValue('Quia Exam').addClickHandler(app.createClientHandler().forTargets(txtTypeGrp).setText('Quia Exam'));
var btnValidate = app.createButton('Create Event');
//Client Handlers for textBoxes
var showTxtElementHandler = app.createClientHandler().forTargets(txtElementsID).setVisible(true);
var hideTxtElementHandler = app.createClientHandler().forTargets(txtElementsID).setVisible(false);
radEExam.addClickHandler(showTxtElementHandler);
radTExam.addClickHandler(hideTxtElementHandler);
radQExam.addClickHandler(hideTxtElementHandler);
var showTxtQuiaLinkHandler = app.createClientHandler().forTargets(txtQuiaLink).setVisible(true);
var hideTxtQuiaLinkHandler = app.createClientHandler().forTargets(txtQuiaLink).setVisible(false);
radQExam.addClickHandler(showTxtQuiaLinkHandler);
radTExam.addClickHandler(hideTxtQuiaLinkHandler);
radEExam.addClickHandler(hideTxtQuiaLinkHandler);
var showTxtQuiaPassHandler = app.createClientHandler().forTargets(txtQuiaPass).setVisible(true);
var hideTxtQuiaPassHandler = app.createClientHandler().forTargets(txtQuiaPass).setVisible(false);
radQExam.addClickHandler(showTxtQuiaPassHandler);
radTExam.addClickHandler(hideTxtQuiaPassHandler);
radEExam.addClickHandler(hideTxtQuiaPassHandler);
//Create validation handler
var valSubmit = app.createServerClickHandler('valSubmit');
valSubmit.addCallbackElement(vrtMainPanel);
//Add this handler to the button
btnValidate.addClickHandler(valSubmit);
//Add all the elemnts to the panel
var formGrid = app.createGrid(12,3).setCellPadding(3);
vrtMainPanel.add(formGrid);
formGrid
.setWidget(0,0,lbxTeacherName)
.setWidget(0,1,txtExt)
.setWidget(0,2,txtTeacherName)
.setWidget(1,0,lbxPeriod)
.setWidget(1,1,lbxSubject)
.setWidget(2,0,lblDate)
.setWidget(2,1,boxDate)
.setWidget(3,0,lblStudentNum)
.setWidget(3,1,lbxStudentNum)
.setWidget(4,0,radHCopy)
.setWidget(4,1,radECopy)
.setWidget(5,0,radTExam)
.setWidget(6,0,radEExam)
.setWidget(6,1,txtElementsID)
.setWidget(7,0,radQExam)
.setWidget(7,1,txtQuiaLink)
.setWidget(8,1,txtQuiaPass)
.setWidget(9,0,txtSourceGrp)
.setWidget(9,1,txtTypeGrp)
.setWidget(10,0,btnValidate)
//Add this panel to the application
app.add(vrtMainPanel);
//Return the application
return app;
}
function valSubmit(e) {
var flag = 0;
var app = UiApp.getActiveApplication();
var Teacher = e.parameter.txtTeacherName;
var Ext = e.parameter.txtExt;
var Subject = e.parameter.lbxSubject;
var Period = e.parameter.lbxPeriod;
var Date = e.parameter.boxDate;
var StudentNum = e.parameter.lbxStudentNum;
var Source = e.parameter.txtSourceGrp;
var Type = e.parameter.txtTypeGrp;
var ElementsID = e.parameter.txtElementsID;
var QuiaLink = e.parameter.txtQuiaLink;
var QuiaPass = e.parameter.txtQuiaPass;
if (Teacher == '' || Teacher == '-- Select Teacher --') {
app.getElementById('vldTeacherName').setText('* Select Teacher').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (Ext == '') {
app.getElementById('vldExt').setText('* Select Teacher Again').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (Subject == '' || Subject == '-- Select Subject --') {
app.getElementById('vldSubject').setText('* Select Subject').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (Period == '' || Period == '-- Select Period --') {
app.getElementById('vldPeriod').setText('* Select Period').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (Date == '' || Date == Utilities.formatDate(Date, 'EST', 'yyyy-mm-dd')) {
app.getElementById('vldDate').setText('* Date must be entered as yyyy-mm-dd').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (StudentNum == '' || StudentNum == '-- Select # --') {
app.getElementById('vldStudentNum').setText('* Select Student #').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (Source == '' || Source == false) {
app.getElementById('vldSourceGrp').setText('* Select either Hard Copy or Electronic Copy').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (Type == '' || Type == false) {
app.getElementById('vldTypeGrp').setText('* Select either Teacher-Made Exam, Elements Exam, or Quia Exam').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (ElementsID == '' && Type == 'Elements Exam') {
app.getElementById('vldElementsID').setText('* Enter Elements ID').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (QuiaLink == '' || QuiaPass == '' && Type == 'Quia Exam') {
app.getElementById('vldQuia').setText('* Enter Quia Link and/or Passphrase').setStyleAttribute("color", "#F00").setVisible(true);
app.getElementById('lblNoSuccess').setStyleAttribute("color", "#F00").setVisible(true);
flag = 1;
}
if (flag == 0) {
app.getElementById('lblSuccess').setStyleAttribute("color", "#F00").setVisible(true);
//Create handler which will execute 'createEvents(e)' on clicking the button
var evtHandler = app.createServerClickHandler('createEvents');
var vrtMainPanel = app.getElementById(vrtMainPanel);
evtHandler.addCallbackElement(vrtMainPanel);
}
}
function valHandler(e) {
var app = UiApp.createApplication().setTitle('DHS: Kurzweil Calendar');
//Create a panel which holds all the form elelemnts
var vrtMainPanel = app.createVerticalPanel().setId('vrtMainPanel');
var lblSuccess = app.createLabel('Check your information below, if everything looks correct you may confirm your event...').setName('lblSuccess').setId('lblSuccess').setVisible(false);
var lblNoSuccess = app.createLabel('There were issues with the creation of your event... click BACK, and make the following corrections:').setName('lblNoSuccess').setId('lblNoSuccess').setVisible(false);
var vldTeacherName = app.createLabel().setId('vldTeacherName').setVisible(false);
var vldExt = app.createLabel().setId('vldExt').setVisible(false);
var vldDate = app.createLabel().setId('vldDate').setVisible(false);
var vldSubject = app.createLabel().setId('vldSubject').setVisible(false);
var vldPeriod = app.createLabel().setId('vldPeriod').setVisible(false);
var vldStudentNum = app.createLabel().setId('vldStudentNum').setVisible(false);
var vldSourceGrp = app.createLabel().setId('vldSourceGrp').setVisible(false);
var vldTypeGrp = app.createLabel().setId('vldTypeGrp').setVisible(false);
var vldElementsID = app.createLabel().setId('vldElementsID').setVisible(false);
var vldQuia = app.createLabel().setId('vldQuia').setVisible(false);
var btnCreate = app.createButton('Corfirm Event');
//Add this handler to the button
var evtHandler = app.getElementById('evtHandler');
btnCreate.addClickHandler(evtHandler);
//Add all the elemnts to the panel
var formGrid = app.createGrid(13,3).setCellPadding(3);
vrtMainPanel.add(formGrid);
formGrid
.setWidget(0,0,lblSuccess)
.setWidget(1,0,lblNoSuccess)
.setWidget(2,0,vldTeacherName)
.setWidget(3,0,vldExt)
.setWidget(4,0,vldDate)
.setWidget(5,0,vldSubject)
.setWidget(6,0,vldPeriod)
.setWidget(7,0,vldStudentNum)
.setWidget(8,0,vldSourceGrp)
.setWidget(9,0,vldTypeGrp)
.setWidget(10,0,vldElementsID)
.setWidget(11,0,vldQuia)
.setWidget(12,0,btnCreate)
//Add this panel to the application
app.add(vrtMainPanel);
//Return the application
return app;
}
I've been spending a lot of time on form validation and I ended up with 2 possible solutions that work pretty well but since I can't decide which one is the best I use sometimes the first... and sometimes the second...
I'll show the idea of both solution, make your choice.
The 'logical' one : use client validation to enable the submit button and a few other client handler validations to show/hide warning labels near the fields that have to be filled. It works great but I must admit it can be tricky to write the script for it and needs quite a lot of code. (see examples in these post among others : Form validation on fields and FileUpload
Form validation using client handler : why does input sequence order change the result?
Use a server handler like you did in your code but replace the "createEvent" button with an intermediate button that instead of sending you directly to the event creation function calls a "fake" function that shows a summary of the requested data in a HTML widget with a nice looking presentation and another button that one use to confirm the event creation (and actually create the event) making a sort of 2 steps confirmation that is definitely user friendly. (and includes a way to go back one step to change/append the submitted data.
Both solution as I already said have pro and cons, the second one is just probably easier to write a script for it.
feel free to comment and/or ask for further details if the references I mentioned are not clear enough.
EDIT : here is an example of the 2cond approach and the spreadsheet with the included script (read only, make a copy to view/edit script and change the spreadsheet ID in the script if you want to run your own version))
The instructions are in french but it shouldn't be too hard to translate ... sorry about that :-) The SS has a marter sheet where you can define the question in the form and the script generates a custom form. There are tools to count responses, print log sheet per day and send confirmation emails.

How to pass a input value into a function using GAS

I will try and keep this brief. I am attempting to make a google web app in google spreadsheet that will allow me to enter a values for min and max.
I have been able to create the GUI and add it to the panel. But I can't seem to pass the integer being entered into another function. I've tried everything, I'm relatively new to creating Google Script so I'm sorry if this comes across as a bit of a noobish problem.
Here is all the code so far :
function onOpen() {
var ss = SpreadsheetApp.getActive();
var menuEntries = [];
menuEntries.push({name: "Open Dialog", functionName: "showDialog"});
ss.addMenu("Min/Max", menuEntries);
}
//creating a panel to add the min and max of low to high for scoring
function showDialog() {
max = 10;
var app = UiApp.createApplication();
app.setTitle("My Applicaition");
var panel = app.createVerticalPanel();
var textBox = app.createTextBox();
var label = app.createLabel("Set the min value for 'Low'");
//had to create a hidden element with id="min" for a global value that can be updated
var min = app.createHidden().setValue('0').setName('min').setId('min');
textBox.setName('myTextBox').setId('myTextBox');
var button = app.createButton('Submit');
panel.add(label);
panel.add(textBox);
panel.add(min);
panel.add(button);
//click handler for setting the value of min to the new value
var clickHandler = app.createServerClickHandler("responedToSubmit");
button.addClickHandler(clickHandler);
clickHandler.addCallbackElement(panel);
app.add(panel);
var doc = SpreadsheetApp.getActive();
doc.show(app);
}
function responedToSubmit(e) {
var app = UiApp.getActiveApplication();
var textBoxValue = e.parameter.myTextBox;
Logger.log(e.parameter.min);
if (typeof textBoxValue != "number") {
var num = parseInt(textBoxValue);
app.getElementById('min').setValue(num);
Logger.log("textBoxValue is = "+textBoxValue+"\n min value is = "+e.parameter.min);
} else {
throw "value needs to be set as number";
}
return app.close();
}
This is where I believe things aren't going according to plan :
function responedToSubmit(e) {
var app = UiApp.getActiveApplication();
var textBoxValue = e.parameter.myTextBox;
Logger.log(e.parameter.min);
if (typeof textBoxValue != "number") {
var num = parseInt(textBoxValue);
app.getElementById('min').setValue(num);
Logger.log("textBoxValue is = "+textBoxValue+"\n min value is = "+e.parameter.min);
} else {
throw "value needs to be set as number";
}
return app.close();
}
I find that each time I test the .setValue() will not update the value of 'min' and I cannot see why. Can you please help?
You need to add textBox element to callBack elements list of your clickHandler.
Try this:
//click handler for setting the value of min to the new value
var clickHandler = app.createServerClickHandler("responedToSubmit");
clickHandler.addCallbackElement(panel);
clickHandler.addCallbackElement(textBox);
button.addClickHandler(clickHandler);
app.add(panel);

Resources