Auto-Fill using TextBox - google-apps-script

I had this working using a listbox, but now I want to change it to a textbox and I keep getting the error: "Error encountered: Cannot read property "1" from undefined." I am not sure of the issue. I had this same code working with a listbox and just tweaked it. I am needing help to solve the problem and wondering if I am down the wrong path.
EDIT - ERROR OCCURANCE
The error occurs when I put in a Student ID Number on the form, that references a Google Spreadsheet. When I hit Enter, I get the error and nothing auto-fills the other fields I have setup.
Form Build (part)
//Create the form elements
//Set DateBox to Today's Date
var date = new Date()
var txtDate = app.createTextBox().setName("txtDate").setId("txtDate").setValue(Utilities.formatDate(date, 'America/New_York', 'MM/dd/yyyy | hh:mm a')).setReadOnly(true).setEnabled(false).setStyleAttributes(lockedStyle);
var lblStudentNumber = app.createLabel('Student ID#:');
var hdlStudentInfo = app.createServerHandler('getStudentInfo').addCallbackElement(vrtMainPanel);
var lbxStudentInfo = app.createTextBox().setId('lbxStudentInfo').setName('lbxStudentInfo').addChangeHandler(hdlStudentInfo).addChangeHandler(alertHideHandler);
// var txtStudentNumber = app.createTextBox().setName("txtStudentNumber").setId("txtStudentNumber").setReadOnly(false).setEnabled(true).setStyleAttributes(normalStyle);
var lblStudentName = app.createLabel('Student Name:');
var txtStudentName = app.createTextBox().setName("txtStudentName").setId("txtStudentName").setText("Student Name").setReadOnly(true).setEnabled(false).setStyleAttributes(lockedStyle);
getStudentInfo Function
function getStudentInfo(e){
var spSheet = SpreadsheetApp.openById('1OhR5i8B89uK7XXW2Izdzim0LSngSr6KQPqL5ToeZTbo');
var spStudentList = spSheet.getSheetByName('Schedule');
var lstStudentID = spStudentList.getRange(2,1,spStudentList.getLastRow(),18).getValues();
var app = UiApp.getActiveApplication();
// var currTime = new Date();
// var formattedTime = Utilities.formatDate(currTime,"hh:mm a");
var txtStudentName = app.getElementById('txtStudentName');
var txtTeacherName = app.getElementById('txtTeacherName');
// var txtExt = app.getElementById('txtExt');
var txtEmail = app.getElementById('txtEmail');
var txtPeriod = app.getElementById('txtPeriod');
var txtSubject = app.getElementById('txtSubject');
txtStudentName.setText(lstStudentID[e.parameter.lbxStudentInfo][1] + " " + lstStudentID[e.parameter.lbxStudentInfo][2]);// sets Student's Name
txtPeriod.setText("1st Period");// sets Period
txtSubject.setText(lstStudentID[e.parameter.lbxStudentInfo][6]);// sets Subject
txtTeacherName.setText(lstStudentID[e.parameter.lbxStudentInfo][7]);// sets Teacher's Name
txtEmail.setText(lstStudentID[e.parameter.lbxStudentInfo][8]);// sets Email
// txtExt.setText(lstStudentID[e.parameter.lbxStudentInfo][1]);// sets Ext
return app;
}

Related

How can I use a variable as a parameter in getSheetByName?

I have the following code which generates some gslides slides from data in a spreadsheet. The code is attached to the gslides file and it works when the parameters for link/year are entered as strings. However, these parameters will sometimes vary from a set list (e.g. pull from a different sheet or from a different file) so the code sometimes needs to be edited.
I want to share this with colleagues who don't know how to use app scripts and so tried to edit it so that the link/year can be pulled from a textbox in one of the slides in the gslides file. They are pulling through ok but when I try to use it as a parameter I get an error for line 11 (var values = sheet.getRange('F2:aa2').getValues();) as the sheet returns as null.
I've tried wrapping it in quotes (" ' " + year + " ' ") but that doesn't work either.
Please let me know if I need to include more info or a link to the sheets/slides files.
function generateStarters() {
var deck = SlidesApp.getActivePresentation();
var slides = deck.getSlides();
var link = slides[2].getPageElements()[2].asShape().getText().asString()
var year = slides[2].getPageElements()[4].asShape().getText().asString()
var dataSpreadsheetUrl = link
var ss = SpreadsheetApp.openByUrl(dataSpreadsheetUrl);
var sheet = ss.getSheetByName(year);
var values = sheet.getRange('F2:aa2').getValues();
var templateSlide = slides[1];
var presLength = slides.length;
values.forEach(function(page){
if(page[0]){
var Q1 = page[0];
var A1 = page[1];
var Q2 = page[4];
var A2 = page[5];
var Q3 = page[8];
var A3 = page[9];
var Q4 = page[12];
var A4 = page[13];
var QK = page[16];
var AK = page[17];
var QF = page[20];
var AF = page[21];
templateSlide.duplicate(); //duplicate the template page
slides = deck.getSlides(); //update the slides array for indexes and length
newSlide = slides[3]; // declare the new page to update
var shapes = (newSlide.getShapes());
shapes.forEach(function(shape){
shape.getText().replaceAllText('{{q1}}',Q1);
shape.getText().replaceAllText('{{a1}}',A1);
shape.getText().replaceAllText('{{q2}}',Q2);
shape.getText().replaceAllText('{{a2}}',A2);
shape.getText().replaceAllText('{{q3}}',Q3);
shape.getText().replaceAllText('{{a3}}',A3);
shape.getText().replaceAllText('{{q4}}',Q4);
shape.getText().replaceAllText('{{a4}}',A4);
shape.getText().replaceAllText('{{qk}}',QK);
shape.getText().replaceAllText('{{ak}}',AK);
shape.getText().replaceAllText('{{qf}}',QF);
shape.getText().replaceAllText('{{af}}',AF);
});
presLength = slides.length;
newSlide.move(presLength);
}
});
} ```
The string from the slides file seems to always have a space at the end (from the textbox) so I just needed to add an extra line of code to remove that space.

Directly Update Doc Template from Form

Is it possible to submit a form and update a Doc template from the form contents? The only way I have seen for doing anything similar was submitting the form to a spreadsheet and having an onFormsubmit function within the spreadsheet update the template.
Is this not possible via forms and a container bound script?
Thanks
yes it's possible, but it's not easy (essentially using doc as template, there is no evident tools for that)
I have initially gotten this to work replacing a few lines in my document template, but now nothing is working for some reason. I did edit the text in the template at one point so I am not sure if that changes the file ID. It creates the copy, but the replaceText is not working. Code attached:
`function onFormSubmit(e) {
var dt = Utilities.formatDate(new Date(), 'GMT', "MM/dd/yyyy")
var submitter = Session.getActiveUser().getEmail();
var copyDoc = DriveApp.getFileById('1t5r8IxLgunJ17J2tXkHfw3LRfuXQeTlP5MZURC-23e0').makeCopy('tmpAddress').getId();
var newDoc = DocumentApp.openById(copyDoc);
var body = newDoc.getBody();
var itemResponse = e.response;
var name = itemResponse.getItemResponses()[0].getResponse();
var email = itemResponse.getItemResponses()[1].getResponse();
var pphone = itemResponse.getItemResponses()[2].getResponse();
var paddress = itemResponse.getItemResponses()[3].getResponse();
var palot = itemResponse.getItemResponses()[4].getResponse();
var pcity = itemResponse.getItemResponses()[5].getResponse();
var pstate = itemResponse.getItemResponses()[6].getResponse();
var pzip = itemResponse.getItemResponses()[7].getResponse();
var nphone = itemResponse.getItemResponses()[8].getResponse();
var naddress = itemResponse.getItemResponses()[9].getResponse();
var nalot = itemResponse.getItemResponses()[10].getResponse();
var ncity = itemResponse.getItemResponses()[11].getResponse();
var nstate = itemResponse.getItemResponses()[12].getResponse();
var nzip = itemResponse.getItemResponses()[13].getResponse();
body.replaceText('#{name}', name);
body.replaceText('#{email}', email);
body.replaceText('#{pphone}', pphone);
body.replaceText('#{paddress}', paddress);
body.replaceText('#{palot}', palot);
body.replaceText('#{pcity}', pcity);
body.replaceText('#{pstate}', pstate);
body.replaceText('#{pzip}', pzip);
body.replaceText('#{nphone}', nphone);
body.replaceText('#{naddress}', naddress);
body.replaceText('#{nalot}', nalot);
body.replaceText('#{ncity}', ncity);
body.replaceText('#{nstate}', nstate);
body.replaceText('#{nzip}', nzip);
body.replaceText('#{dt}', dt)
body.replaceText('#{submitter}',submitter)
newDoc.saveAndClose();
}
`

Google Script Error - Cannot find method add

I have been puzzled by this error. I have not been able to figure out what I am missing. Without the calls to headPanel the UI was working but would not insert the title or text label so I added the Horizontal panel in hopes of adding the text, but alas error. Please help me with this problem and I need to know what I am messing up.
function doGet(e){
var app = UiApp.createApplication();
var headPanel = app.createHorizontalPanel().setId('headPanel');
var header = app.setTitle('Detention Attendance');
var label = app.createLabel("Please enter attendance for Detention by clicking the checkbox next to the student's name if they were present. Then click Sumbit.");
headPanel.add(header); //* ERROR OCCURS HERE
headPanel.add(label);
app.add(pane);
var panel = app.createVerticalPanel();
var flexTable = app.createFlexTable().setStyleAttribute('border', '2px solid black')
.setStyleAttribute('borderCollapse','collapse')
.setBorderWidth(2);
//Get Data from spreadsheet
var spreadsheetId = 'xxxxxxxxxxxxxxxxxxxxxxxx';//Change it to your Spreadsheet ID
var dataArray = getData(spreadsheetId);
//Load data into table cells
Logger.log(dataArray);
for (var row = 0; row<dataArray.length; row++){
if (row > 0) {
var ticketDate = dataArray[row] [0];
var dateStamp = Utilities.formatDate(ticketDate, "America/Chicago", "MM/dd/yyyy");
Logger.log("dateStamp = " +dateStamp);
dataArray[row] [0] = dateStamp;
var ticketDate2 = dataArray[row] [16];
var dateStamp2 = Utilities.formatDate(ticketDate2, "America/Chicago", "MM/dd/yyyy");
dataArray[row] [16] = dateStamp2;
Logger.log("DateStamp = " +dateStamp2);
}
flexTable.setStyleAttribute("color", "purple").setText(row, 2, dataArray[row][2].toString()).setWidth('300px');
flexTable.setText(row, 0, dataArray[row][0].toString()).setWidth('600px');
flexTable.setText(row, 4, dataArray[row][16].toString()).setWidth('300px');
}
panel.add(flexTable);
app.add(panel);
return app;
}
function getData(spreadsheetId){
var ss = SpreadsheetApp.openById(spreadsheetId);
var sheet = ss.getSheets()[0].getDataRange();
Logger.log(sheet);
return sheet.getValues();
}
Your header var is a UiInstance - in fact it's the same instance as app, returned as a convenience for chaining by the call to .setTitle().
The .add() method is looking for a Widget as a parameter, and not finding it.
You don't need to keep that header var - it's only causing you trouble. In fact, you could set the Title as you create the UiApp instance:
var app = UiApp.createApplication().setTitle('Detention Attendance');

Parsing XML Data that I receive from UrlFetch

I want to parse the data I get from UrlFetch into a spreadsheet, but all I'm getting is undefined can someone show me what i'm doing wrong
The xml is at the address https://dl.dropbox.com/u/11787731/Minecraft/bans.xml
function runevery15mins() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("MC Bans");
sheet.clearContents();
var banURL = "https://dl.dropbox.com/u/11787731/Minecraft/bans.xml";
var banXML = UrlFetchApp.fetch(banURL).getContentText();
var banDOC = Xml.parse(banXML, false);
var mcuser = banDOC.bans;
var x = 0;
for(var c=0; c>mcuser.length;c++){
var name = mcuser.getElement("username")[c].getText();
var date = mcuser.getElement("date")[c].getText();
var reason = mcuser.getElement("reason")[c].getText();
var duration = mcuser.getElement("duration")[c].getText();
}
sheet.appendRow([name, date, reason, duration]);
}
You have some small errors in your code.
For example, the second argument in the for loop needs to be c<mcuser.length.
Using the Xml service documentation, this worked for me
function runevery15mins() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("MC Bans");
sheet.clearContents();
var banURL = "https://dl.dropbox.com/u/11787731/Minecraft/bans.xml";
var banXML = UrlFetchApp.fetch(banURL).getContentText();
var banDOC = Xml.parse(banXML, false);
// Get all the child nodes from the document element that are 'user' nodes
var mcusers = banDOC.getElement().getElements('user');
for(var c=0; c<mcusers.length;c++){
var user = mcusers[c];
var name = user.getElement('username').getText();
var date = user.getElement('date').getText();
var reason = user.getElement('reason').getText();
var duration = user.getElement('duration').getText();
sheet.appendRow([name, date, reason, duration]);
}
}
Note for example that the sheet.appendRow line is INSIDE the loop, not outside as you had it before. I also deleted the X variable, since I didn't see any purpose for it.
I also created a user variable, which is an XmlElement, to make it easier to understand how to get the different contents of each node.
You were almost there.
Looks like there was another array you needed to drill down into. Also, your call back to the spreadsheet should be in the loop. Try this:
...
var mcuser = banDOC.bans.user;
for(var i in mcuser){
var name = mcuser[i].getElement("username").getText();
var date = mcuser[i].getElement("date").getText();
var reason = mcuser[i].getElement("reason").getText();
var duration = mcuser[i].getElement("duration").getText();
sheet.appendRow([name, date, reason, duration])
}

Error occured: TypeError: Cannot call method "createEvent" of undefined via Google Script

Within the second half of my script and function, I keep getting this Cannot call method error, and I do not know why. I mimic'd the template script exactly, but I am unsure why it does not call the method.
Any insight would be greatly appreciated.
Thanks.
function createEvents(e){
//Get the active application
var app = UiApp.getActiveApplication();
try{
//get the entries;
var eventDate = e.parameter.eventDate;
var eventPeople = e.parameter.eventPeople;
var eventCompany = e.parameter.eventCompany;
var eventName = e.parameter.eventName;
var eventTime = e.parameter.eventTime;
var eventPhone = e.parameter.eventPhone;
var eventEmail = e.parameter.eventEmail;
var eventTaken = e.parameter.eventTaken;
//Get the calendar
var cal = CalendarApp.getCalendarsByName('Phoenix Reservations')[0];//Change the calendar name
var eventStartTime = eventDate;
//End time is calculated by adding an hour in the event start time
var eventEndTime = new Date(eventDate.valueOf()+60*60*1000);
//Create the events
cal.createEvent(eventPeople,eventCompany,eventName,eventTime,eventPhone,eventEmail,eventTaken);
//Log the entries in a spreadsheet
var ss = SpreadsheetApp.openById('KEY_TAKEN_OUT');//Change the spreadhseet key to yours
var sheet = ss.getSheets()[0];
sheet.getRange(sheet.getLastRow()+1, 1, 1, 5).setValues([[new Date(), eventDate,eventPeople,eventCompany,eventName,eventTime,eventPhone,eventEmail,eventTaken, 'Event created']]);
//Show the confirmation message
app.add(app.createLabel('Event created Successfully'));
//make the form panel invisible
app.getElementById('panel').setVisible(false);
return app;
}
//If an error occurs, show it on the panel
catch(e){
app.add(app.createLabel('Error occured: '+e));
return app;
}
}
This line probably returns nothing :
var cal = CalendarApp.getCalendarsByName('Phoenix Reservations')[0];//Change the calendar name
You could log it to confirm like this Logger.log(cal)
Is 'Phoenix Reservations' a calendar name that you own or that you have write access to ?
EDIT : could you test this simple function to see if everything is ok with this calendar?
It will create an event just now.
function testcal(){
var cal = CalendarApp.openByName('Phoenix Reservations');// or you can replace this with your var definition : same result normally ;-)
if (cal) {
var title = 'Test Event';
var start = new Date();
var end = new Date(start.valueOf()+60*60*1000);
Logger.log(cal.getName()+' '+start+' '+end)
var desc = 'Created using Google Script';
var loc = 'there';
var event = cal.createEvent(title, start, end, {
description : desc,
location : loc
});
}
}
EDIT 2 : I modified the logger to make it show the calendar name.