I have an existing code which looks like,
var copyPageNumbers = [5, 7, 9];
I have the same number 5, 7, 9 in a column on my google sheet and have set up a variable to get value,
var credentials = ss.getRange(i, 11).getValue(); // The value of this is 5, 7, 9
Based on the variables above. I want to use a code which uses the credentials variable in the copyPageNumbers variable to look something like this,
var copyPageNumbers = [credentials];
For example, the below chunk of code works,
var credentials = ss.getRange(i, 11).getValue();
var copyPageNumbers = [2, 4];
var offset = 1;
var slides = otherPresentation.getSlides();
var page = 0;
slides.forEach(function(slide, i) {
if (copyPageNumbers.indexOf(i + 1) != -1) {
currentPresentation.insertSlide(offset + page, slide);
page++;
}
});
However when I try both the methods stated below - it doesnt work,
var credentials = ss.getRange(i, 11).getValue().split(", ");
var copyPageNumbers = credentials
var offset = 1;
var slides = otherPresentation.getSlides();
var page = 0;
slides.forEach(function(slide, i) {
if (copyPageNumbers.indexOf(i + 1) != -1) {
currentPresentation.insertSlide(offset + page, slide);
page++;
}
});
var credentials = ss.getRange(i, 11).getValue();
var offset = 1;
var copyPageNumbers = []
copyPageNumbers.push(credentials);
var slides = otherPresentation.getSlides();
var page = 0;
slides.forEach(function(slide, i) {
if (copyPageNumbers.indexOf(i + 1) != -1) {
currentPresentation.insertSlide(offset + page, slide);
page++;
}
});
var credentials = ss.getRange(i, 11).getValue(); return the string "5, 7, 9", but you need that as an array.
Assuming that the format is consistent (i.e., [number][comma][space]), you can use split() to turn it into an array.
var credentials = ss.getRange(i, 11).getValue().split(", "); // [5, 7, 9]
var copyPageNumbers = credentials;
var copyPageNumbers = [];
var credentials = ss.getRange(i, 11).getValue();
copyPageNumbers.push(credentials);
You want an array ([5,7,9]), 'credentials' is a string (5,7,9). With the (javascript) push() method that string is added to the array 'copyPageNumbers'. If I understand it well.
Thanks to the above answers and thanks to Pattern 2 here, I have managed to solve this.
See updated script below. The reason it was not working before was because of the For each loop which was looping the slide and the number and the array was not working.
var credentials = ss.getRange(i, 11).getValue().split(", ");
var offset = 0;
var slides_stack = otherPresentation.getSlides();
var page = 0;
credentials.forEach(function(p, i) {
currentPresentation.insertSlide(offset + i, slides_stack[p - 1]);
});
Related
Let me just preface this with I know this script could probably be better but I'm very new to scripting in any language and I'm just playing around with an idea for work. This is essentially just a frankensteined combination of google results for what I want to accomplish but I've hit a deadend.
I'm using an aspect from another script to return contentservice in JSON format for a webapp except it's not working in this case
As far as I can tell it should work perfectly fine and if I replace the return contentservice with the browser.msgbox below I get the values returned that I want but when using contentservice and going to my scripts Web App URL with the action pointing to range I get the error The script completed but did not return anything.
var mysheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1sPuqdg0Va9LLQudl2ta23b-CGEF_-FFSTeggRw3J4L4/edit").getSheetByName('Sheet3');
var sheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1sPuqdg0Va9LLQudl2ta23b-CGEF_-FFSTeggRw3J4L4/edit").getSheetByName('Sheet1');
function doGet(e){
var action = e.parameter.action;
if(action == 'Range'){
return Range(e);
}
}
function Range(e) {
let term = 'Customer 6';
var sdata = mysheet.getRange("A:A").getValues();
sdata.forEach((val, index) => {
if(val == term){
var msgr = "B" + (index+1)
var msgc = "D" + (index+1)
var rrow = mysheet.getRange(msgr).getValue();
var ccol = mysheet.getRange(msgc).getValue();
var data = sheet.getRange("E" + rrow + ":I"+ccol);
var records={};
var rows = sheet.getRange("E" + rrow + ":I"+ccol).getValues();
data = [];
for (var r = 0, l = rows.length; r < l; r++) {
var row = rows[r],
record = {};
record['Product'] = row[0];
record['Case']=row[2];
record['Order QTY']=row[3];
record['Packed']=row[4];
data.push(record);
}
records.items = data;
var result=JSON.stringify(records);
return ContentService.createTextOutput(result).setMimeType(ContentService.MimeType.JSON);
// Browser.msgBox(result);
}})}
I can't figure out why I'm getting the correct returned values for the msgBox, but no results for the ContentService.
Any help would be greatly appreciated. Thanks in advance.
Edit: I have been publishing new webapp versions every revision
This breaks because you're returning from within a forEach() loop. Check out the MDN web docs:
There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behavior, the forEach() method is the wrong tool.
The simplest fix is to use a for loop instead.
function Range(e) {
let term = 'Customer 6';
var sdata = mysheet.getRange("A:A").getValues();
for (var index = 0; index < sdata.length; index++) {
var val = sdata[index];
if(val == term){
var msgr = "B" + (index+1)
var msgc = "D" + (index+1)
var rrow = mysheet.getRange(msgr).getValue();
var ccol = mysheet.getRange(msgc).getValue();
var data = sheet.getRange("E" + rrow + ":I"+ccol);
var records={};
var rows = sheet.getRange("E" + rrow + ":I"+ccol).getValues();
data = [];
for (var r = 0, l = rows.length; r < l; r++) {
var row = rows[r],
record = {};
record['Product'] = row[0];
record['Case']=row[2];
record['Order QTY']=row[3];
record['Packed']=row[4];
data.push(record);
}
records.items = data;
var result=JSON.stringify(records);
return ContentService.createTextOutput(result).setMimeType(ContentService.MimeType.JSON);
}
}
}
I have a Google Apps Script that automatically extracts data from a Google Sheet and inserts it into a pre specified template. The data is found using unique tagNumbers/identifiers.
The data being extracted includes 3 signatures. I can only extract one of these signatures before I encounter the aforementioned error: TypeError: Cannot read property 'getBlob' of undefined.
This code is being used in two different functions, using all the same variables and names. I have tried changing variable names but this has resulted in the same TypeError.
The spreadsheet can be found here.
The script is here.
And the document template being filled is here.
Here is the code.
function electInstallSignature(row, body){
var signature = row[17];
var sign = signature.substring(signature.indexOf("/") + 1);
var sigFolder = DriveApp.getFolderById("16C0DR-R5rJ4f5_2T1f-ZZIxoXQPKvh5C");
var files = sigFolder.getFilesByName(sign);
var n = 0;
var file;
while(files.hasNext()){
file = files.next();
n++;
} if(n>1){
SpreadsheetApp.getUi().alert('there is more than one file with this name' + sign);
}
var sigElectInstaller = "%SIGNELECTINSTALL%";
var targetRange = body.findText(sigElectInstaller); // Finding the range we need to focus on
var paragraph = targetRange.getElement().getParent().asParagraph(); // Getting the Paragraph of the target
paragraph.insertInlineImage(1, file.getBlob());// As there are only one element in this case you want to insert at index 1 so it will appear after the text // Notice the .getBlob()
paragraph.replaceText(sigElectInstaller, ""); // Remove the placeholder
}
function commEngineerSignature(row, body){
var signature = row[35];
var sign = signature.substring(signature.indexOf("/") + 1);
var sigFolder = DriveApp.getFolderById("16C0DR-R5rJ4f5_2T1f-ZZIxoXQPKvh5C");
var files = sigFolder.getFilesByName(sign);
var n = 0;
var file;
while(files.hasNext()){
file = files.next();
n++;
} if(n>1){
SpreadsheetApp.getUi().alert('there is more than one file with this name' + sign);
}
var sigCommEngineer = "%SFCE%";
var targetRange = body.findText(sigCommEngineer); // Finding the range we need to focus on
var paragraph = targetRange.getElement().getParent().asParagraph(); // Getting the Paragraph of the target
paragraph.insertInlineImage(1, file.getBlob());// As there are only one element in this case you want to insert at index 1 so it will appear after the text // Notice the .getBlob()
paragraph.replaceText(sigCommEngineer, ""); // Remove the placeholder
}
As you can see, the code is the exact same in both functions, but only works in the electInstallSignature(row, body) function.
Below you can find where the row and body parameters are declared.
function chooseRowMethodI(templateId, rowNumber){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var dataRange = sheet.getDataRange();
var values = dataRange.getValues();
var data = sheet.getRange(2, 2, 10, 41).getValues();//starting with row 2 and column 1 as our upper-left most column, get values from cells from 1 row down, and 15 columns along - hence (2,1,1,15)
var docTitle = sheet.getRange(2, 2, 10, 1).getValues();//this is grabbing the data in field B2
var docTitleTagNumber = sheet.getRange(2, 5, 11, 1).getValues();
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth() + 1;
var yyyy = today.getFullYear();
today = dd + '/' + mm + '/' + yyyy;
for(var i = 0; i < values.length; i++){
for(var j = 0; j < values[i].length; j++){
if(values[i][j] == response){
Logger.log(i);
var row = data[rowNumber];
var docId = DriveApp.getFileById(templateId).makeCopy().getId();
var doc = DocumentApp.openById(docId);
var body = doc.getActiveSection();
//************************** All Instruments data in here**********************
instrumentDetails(body, row);
electInstallSignature(row, body);
commEngineerSignature(row, body);
doc.saveAndClose();
var file = DriveApp.getFileById(doc.getId());
var newFolder = DriveApp.getFolderById("1Jylk3uO_WU0ClLQdm9y-mwRfHxlh2Ovn");
newFolder.addFile(file);
var newDocTitle = docTitle[i - 1][0];
var newDocTagNumber = docTitleTagNumber[i - 1][0];
doc.setName(newDocTitle + " " + newDocTagNumber + " " + today);
}
}
}
}
Should it be required, I have included the function where everything is run from (note that any ui and user input code is tabbed out to avoid having to navigate back to the spreadsheet every time the code is run).
var response = "FT101";
function chooseRow(){
// var ui = SpreadsheetApp.getUi(); // Same variations.
// var result = ui.prompt('Please enter the Tag number of the row you wish to print.', ui.ButtonSet.OK_CANCEL);
//
// // Process the user's response.
// var button = result.getSelectedButton();
// response = result.getResponseText();
// if (button == ui.Button.OK) {
// // User clicked "OK".
// ui.alert('Your tag number is' + response + '.');
// } else if (button == ui.Button.CANCEL) {
// // User clicked X in the title bar.
// ui.alert('You closed the dialog.');
// return 'the end';
// }
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var dataRange = sheet.getDataRange();
var values = dataRange.getValues();
var category = sheet.getRange(2, 3, 11, 1).getValues();//Needs to be verified to ensure correct cell is chosen by script
var tags = sheet.getRange(2, 5, 11, 1).getValues();//Needs to be verified to ensure correct cell is chosen by script
for(var i = 0; i < tags.length; i++){
if(tags[i][0] == response && category[i][0] == "Instrument"){
var templateId = "1N3o951ECS5CAVGE6UgqBiCPC7H7LiJbL7Cd59G1xTnA";
chooseRowMethodI(templateId, i);
return "";
} else if(tags[i][0] == response && category[i][0] == "Motor" || tags[i][0] == response && category[i][0] == "Valve"){
var templateId = "1cSPD23qFd-34-IIr5eJ5a5OgHp9YR6xav9T28Y4Msec";
chooseRowMethodMV(templateId, i);
return "";
}
}
}
This errors TypeError: Cannot read property 'getBlob' of undefined means that the object you are trying to getBlob from it does not have any blob data.
The only difference with the frist function and the second one is the first line: row[17] instead of row[35] this means the following:
var signature = row[17];
var sign = signature.substring(signature.indexOf("/") + 1);
var sigFolder = DriveApp.getFolderById("16C0DR-R5rJ4f5_2T1f-ZZIxoXQPKvh5C");
var files = sigFolder.getFilesByName(sign);
var n = 0;
var file;
while(files.hasNext()){
file = files.next();
n++;
} if(n>1){
SpreadsheetApp.getUi().alert('there is more than one file with this name' + sign);
}
So, you are probably never accessing to the while loop:
while(files.hasNext())
because var files = sigFolder.getFilesByName(sign); never had a next, and thus, as file is not initialized, it is undefined.
In summary, the error you are getting is:
file is undefined
This means that you never assigned anything on this variable, which only happens if you never accessed the while, which only happens if files never had a next.
Which happens because there aren't any files at all there, this means that there isn't any file with the name sign on the sigFolder. Or that the row[17] does not contain any substantial information about the filename you want to access.
So, check this.
Also, take into account the following documentation about iterators like the one you are handling on files:
When you do files.next() you are accesing the first element of the iterator:
File iterator
General documentation on JavaScript iterators:
Iterators and generators on Javascript
I am just starting Google Forms. I need to email the form owner (myself and some others) a response as soon the the user submit the data. I need the data in the email which would include fields and their values that were submitted by the user as soon as they submit the form.
I am unable to use add-on as per my google account settings via my employer where add-on are blocked.
I am exploring app scripts but with little success as I am very new. As there some sample codes to help me get started with create a basic script to send email.
I have the following Code:
function sendFormByEmail(e)
{
var email = "ownersemail#host.ca";
var s = SpreadsheetApp.getActiveSheet();
var headers = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
var message = "";
var subject = "New Hire: ";
for(var i in headers)
message += headers[i] + ': '+ e.namedValues[headers[i]].toString() + "\n\n";
subject += e.namedValues[headers[2]].toString() + " - starts " + e.namedValues[headers[15]].toString();
MailApp.sendEmail(email, subject, message);
}
Then I added this script in the form trigger like so:
I tried submitting the form but nothings heppens. How do I know that the script ran or there was a problem?
If I try to run this in the script editor :
It gives me an error :
TypeError: Cannot call method "getRange" of null. (line 7, file "Code")
Update
I tested the email functionality and it worked. So the problem has to be in Spread Sheet value retrieval.
function sendFormByEmail(e)
{
var email = "ownersemail#host.ca";
MailApp.sendEmail(email, "Test", "Test");
}
I also created a excel file on my google drive that holds these response from google form
Final Solution
function testExcel() {
var email = "ownersemail#host.ca";
var s = SpreadsheetApp.openById("GoogleDocsID");
var sheet = s.getSheets()[0];
var headers = sheet.getRange(1,1,1,sheet.getLastColumn()).getValues()[0];
var datarow = sheet.getRange(sheet.getLastRow(),1,1,sheet.getLastColumn()).getValues()[0];
var message = "";
for(var i in headers)
{
message += "" + headers[i] + " : " + datarow[i] + "\n\n";
//Logger.log(message);
}
MailApp.sendEmail(email, "Submitted Data Test", message);
}
Here is a shell for you to start with. I use this code for a very similar reason. This shell includes creating a Google Doc from template and adding data from the sheet into that Doc. You can use similar methods to set variables and add them into the email. I use an html template file(s) to manage exactly what is being sent each time.
The merge portion checks through the Doc (you can set it to look through html file) and finds my tags using RegEx; structed as so: <<columnHeader>>. In this way, You have a consistent template that replaces those tags with the data, in that column, for that row. Modify to your needs as you see fit.
This also displays the progress of the merge. That way, it won't repeat your emails/ merge.
NOTE: There are several data points missing as I removed the personal information; it won't run straight from this sample. You will have to add your document IDs, correct for variable placement, etc.
function mergeApplication() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("");
var formSheet = ss.getSheetByName("");
var lastRow = formSheet.getLastRow();
var lastColumn = sheet.getMaxColumns();
function checkAndComplete() {
var urlColumn = lastColumn;
var checkColumn = (urlColumn - 1);
var checkRange = sheet.getRange(2, checkColumn, (lastRow - 1), 1);
var check = checkRange.getBackgrounds();
var red = "#ff0404";
var yellow = "#ffec0a";
var green = "#3bec3b";
for (var i = 0; i < check.length; i++) {
if (check[i] == green) {
continue;
} else {
var statusCell = sheet.getRange((i+2), checkColumn, 1, 1);
var urlCell = sheet.getRange((i+2), urlColumn, 1, 1);
var dataRow = sheet.getRange((i+2), 1, 1, (lastColumn - 2));
function mergeTasks() {
function docCreator() {
var docTemplate1 = DriveApp.getFileById("");
var docTemplate2 = DriveApp.getFileById("");
var folderDestination = DriveApp.getFolderById("");
var clientName = sheet.getRange((i+2), 2, 1, 1).getValue();
var rawSubmitDate = sheet.getRange((i+2), 1, 1, 1).getValue();
var submitDate = Utilities.formatDate(rawSubmitDate, "PST", "MM/dd/yy");
var typeCheck = sheet.getRange((i+2), (checkColumn - 1), 1, 1).getValue();
if (typeCheck == "Type 1") {
var docToUse = docTemplate1;
var emailBody = HtmlService.createHtmlOutputFromFile("").getContent();
} else {
var docToUse = docTemplate2;
var emailBody = HtmlService.createHtmlOutputFromFile("").getContent();
}
var docName = "" + clientName + " - " + submitDate;
var docCopy = docToUse.makeCopy(docName, folderDestination);
var docId = docCopy.getId();
var docURL = DriveApp.getFileById(docId).getUrl();
var docToSend = DriveApp.getFileById(docId);
var docInUse = DocumentApp.openById(docId);
var docBody = docInUse.getBody();
var docText = docBody.getText();
function tagReplace() {
var DOBCell = sheet.getRange((i+2), 3, 1, 1);
var rawDOB = DOBCell.getValue();
if (rawDOB !== "") {
var DOB = Utilities.formatDate(rawDOB, "PST", "MM/dd/yy");
} else {
var DOB = ""
}
var taggedArray = docText.match(/\<{2}[\w\d\S]+\>{2}/g);
var headerArray = sheet.getRange(1, 1, 1, (lastColumn - 2)).getValues();
var dataArray = dataRow.getValues();
dataArray[0][2] = DOB;
var strippedArray = [];
function tagStrip() {
for (var t = 0; t < taggedArray.length; t++) {
strippedArray.push(taggedArray[t].toString().slice(2, -2));
}
}
function dataMatch() {
for (var s = 0; s < strippedArray.length; s++) {
for (var h = 0; h < headerArray[0].length; h++) {
if (strippedArray[s] == headerArray[0][h]) {
docBody.replaceText(taggedArray[s], dataArray[0][h]);
}
}
}
docInUse.saveAndClose();
}
tagStrip();
dataMatch();
}
function emailCreator() {
var emailTag = sheet.getRange((i+2), (checkColumn - 9)).getValue();
var emailSubject = "" + clientName;
MailApp.sendEmail({
to: emailTag,
subject: emailSubject,
htmlBody: emailBody,
attachments: [docToSend.getAs(MimeType.PDF)],
replyTo: "",
});
}
tagReplace();
statusCell.setBackground(yellow);
emailCreator();
urlCell.setValue(docURL);
}
statusCell.setBackground(red);
docCreator();
statusCell.setBackground(green);
}
mergeTasks();
}
}
}
checkAndComplete();
}
I am trying to update my code to work with the new DriveApp API update. I got most of it working (I think) but it is hanging up on line 68 saying that it can't getFilesByType. I did try and change the loop for adding to be based off the iterator (I think) but still get this error: TypeError: Cannot find function getFilesByType in object FolderIterator
Any help would be appreciated thanks!
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
Template Generator By: Andre Fecteau - klutch2013#gmail.com
Original Code From: kiszal#gmail.com (Found in the template gallery by searching "Templates" It is the first One.
Major Help from: Serge Insas On Stack Overflow (He did most of the work.)
Link 1: http://stackoverflow.com/questions/18147798/e-undefined-google-script-error
Link 2: http://stackoverflow.com/questions/18132837/have-a-listbox-populate-with-every-folder-in-mydrive
How To Use:
First: each column is designated in your Template by {Column Letter} for example for column A it would be {A}
Second: You can change this, but your Template must be in a folder called "Templates." This folder can be anywhere in your drive.
Third: Click "Generate Documents Here!" Then click "Export Row to Document"
Fourth: Type in the row you want to export. Chose your Folder Path. Click Submit.
NOTE ON FOURTH STEP: If you want your number to skip the header row add a +1 to line 32.
This would mean if you typed "2" in the row box it actually exports row 3. I took this out because it can get confusing at times.
NOTE: Line 71 you can edit the word "Templates" to whatever folder you saved your Template into.
NOTE: Line 36 you can edit to change what comes up in the name of the file that is created. To do this just edit the column letter in the following piece: "+Sheet.getRange('E'+row).getValue()+"
You can then delete any other columns you do not want by deleteing the section of code that looks like the following: '+Sheet.getRange('D'+row).getValue()+'
Feel free to edit this code as you wish and for your needs. That is what I did with the original code.
So there is no reason I should restrict what others do with this code.
Bug Fix Log:
* changed row: 32 to remove the +1 6/18/2014
* changed row: 40 to remov e the row-- 6/18/2014
* changed row: 68 to update to DriveApp because of Google API Update - 4/21/15
* changed row: 68 to update to getFoldersByName and getFilesByType to update to new Google API - 4/21/15
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function generateDocument(e) {
var template = DriveApp.getFileById(e.parameter.Templates);
Logger.log(template.getName());
var Sheet = SpreadsheetApp.getActiveSpreadsheet();
var row = Number(e.parameter.row) //+1; // Remove the // in this line next to the +1 to skip headers
Logger.log(row);
var currentFID = e.parameter.curFID;
Logger.log(currentFID);
var myDocID = template.makeCopy(Sheet.getRange('B' + row).getValue() + ' - ' + Sheet.getRange('E' + row).getValue() + ' - ' + Sheet.getRange('D' + row).getValue() + ' - ' + Sheet.getRange('X' + row).getValue()).getId();
var myDoc = DocumentApp.openById(myDocID);
var copyBody = myDoc.getActiveSection();
var Sheet = SpreadsheetApp.getActiveSpreadsheet();
//row--; // decrement row number to be in concordance with real row numbers in sheet
var myRow = SpreadsheetApp.getActiveSpreadsheet().getRange(row + ":" + row);
for (var i = 1; i < Sheet.getLastColumn() + 1; i++) {
var myCell = myRow.getCell(1, i);
copyBody.replaceText("{" + myCell.getA1Notation().replace(row, "") + "}", myCell.getValue());
}
myDoc.saveAndClose();
var destFolder = DriveApp.getFolderById(currentFID);
Logger.log(myDocID);
var doc = DriveApp.getFileById(myDocID); // get the document again but using DriveApp this time...
doc.addToFolder(destFolder); // add it to the desired folder
doc.removeFromFolder(DriveApp.getRootFolder()); // I did it step by step to be more easy to follow
var pdf = DriveApp.getFileById(myDocID).getAs("application/pdf");
destFolder.createFile(pdf); // this will create the pdf file in your folder
var app = UiApp.getActiveApplication();
app.close();
return app;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function getTemplates() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
var app = UiApp.createApplication().setTitle('Generate from template');
// Create a grid with 3 text boxes and corresponding labels
var grid = app.createGrid(5, 2);
grid.setWidget(0, 0, app.createLabel('Template name:'));
var list = app.createListBox();
list.setName('Templates');
grid.setWidget(0, 1, list);
var docs = DriveApp.getFoldersByName("Templates").getFilesByType(documents); //Change the word "Templates" to whatever folder you saved your template into
/* OLD LOOP
for (var i = 0; i < docs.length; i++) {
list.addItem(docs[i].getName(),docs[i].getId());
}
*/
while (docs.hasNext()) {
var docs = docs.next();
list.addItem(docs[i].getName(), docs[i].getId());
}
grid.setWidget(1, 0, app.createLabel('Row:'));
var row = app.createTextBox().setName('row');
row.setValue(SpreadsheetApp.getActiveSpreadsheet().getActiveRange().getRow());
grid.setWidget(1, 1, row);
var curFN = app.createTextBox().setText('MyDrive/').setName('curFN').setId('curFN').setWidth('400');
var curFID = app.createTextBox().setText(DriveApp.getRootFolder().getId()).setName('curFID').setId('curFID').setVisible(false);
var listF = app.createListBox().setName('listF').setId('listF').addItem('Please Select Folder', 'x');
grid.setText(2, 0, 'Type Path:').setWidget(2, 1, curFN).setText(3, 0, 'OR').setText(4, 0, 'Choose Path:').setWidget(4, 1, listF).setWidget(3, 1, curFID);
var folders = DriveApp.getRootFolder().getFolders();
for (var i = 0; i < folders.length; i++) {
listF.addItem(folders[i].getName(), folders[i].getId())
}
var handlerF = app.createServerHandler('folderSelect').addCallbackElement(grid);
listF.addChangeHandler(handlerF);
var panel = app.createVerticalPanel();
panel.add(grid);
var button = app.createButton('Submit');
var handler = app.createServerClickHandler('generateDocument');
handler.addCallbackElement(grid);
button.addClickHandler(handler);
// Add the button to the panel and the panel to the application, then display the application app in the Spreadsheet doc
panel.add(button);
app.add(panel);
doc.show(app);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function folderSelect(e) {
var app = UiApp.getActiveApplication();
var currentFN = e.parameter.curFN;
var currentFID = e.parameter.listF;
Logger.log(currentFID);
var listF = app.getElementById('listF');
var curFN = app.getElementById('curFN');
var curFID = app.getElementById('curFID');
if (currentFID == 'x') {
currentFID = DriveApp.getRootFolder().getId();
curFN.setText('MyDrive/')
};
var startFolder = DriveApp.getFolderById(currentFID);
var folders = startFolder.getFolders();
listF.clear().addItem('No More Sub Folders!', 'x').addItem('Go back to Root', 'x');
if (folders.length > 0) {
listF.clear();
listF.addItem('Select Sub Folder', 'x')
};
for (var i = 0; i < folders.length; i++) {
listF.addItem(folders[i].getName(), folders[i].getId())
}
curFN.setText(currentFN + DriveApp.getFolderById(currentFID).getName() + '/');
if (currentFID == DriveApp.getRootFolder().getId()) {
curFN.setText('MyDrive/')
};
curFID.setText(currentFID);
return app;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [{
name: "Export Row to Document",
functionName: "getTemplates"
}];
ss.addMenu("Generate Documents Here!", menuEntries);
}
You need two while loops:
var folders = DriveApp.getFoldersByName("Templates");
while (folders.hasNext()) {
var folder = folders.next();
Logger.log(folder.getName());
var allMyFilesByType = folder.getFilesByType(mimeType)
};
while (allMyFilesByType.hasNext()) {
var file = allMyFilesByType.next();
Logger.log(file.getName());
};
For MIME Types, see:
Google Documentation - MIME Types
So I have an app script gadget embedded in a google site. What the app script does is get objects from scriptdb and display it on the screen. There also is an add button clicking on which you get a form to enter information and add objects. What I am trying to do is that after an object is saved, I repopulate the object and display them so the newly created object can be seen without manually refreshing the page.
I have a function called update() that is called after an object is saved and this function takes care of the "auto refresh".
In the save() function, I call the update function with this syntax, update(). Here is the submit() function
function SaveAssignment(e){
var db = ScriptDb.getMyDb();
var app = UiApp.getActiveApplication();
var name = e.parameter.assignmentname;
var date = e.parameter.assignmentdate.toString();
var desc = e.parameter.assignmentdesc;
var category = e.parameter.assignmentcategory;
var totalscore = e.parameter.assignmenttotalscore;
var site = SitesApp.getActiveSite();
var assignment = { name: name,
date: date,
description: desc,
url: pageUrl + '?name='+name+'&date='+date+'&description='+desc+'&id='+sheetId,
sheetid: sheetId,
totalScore: totalscore,
Category: category
};
db.save(assignment);
update();
}
and here is my update() method
function update(){
var app = UiApp.createApplication();
var oldGrid = app.getElementById('grid');
app.remove(oldGrid);
var handler = app.createServerHandler('AddAssignment');
var addAssignmentButton = app.createButton('Add Assignment', handler);
var assignments = db.query({});
var i = 1;
var j = 1;
var grid;
if(assignments.getSize() < 1){
grid = app.createGrid(3, 5).setId('grid');
}
else{
grid = app.createGrid(assignments.getSize() + assignments.getSize() + assignments.getSize(), 5).setId('grid');
}
handler.addCallbackElement(grid);
grid.setWidget(0, 2, addAssignmentButton);
while(assignments.hasNext()){
var assignment = assignments.next();
var name = assignment.name;
var date = assignment.date;
var description = assignment.description;
var nameLabel = app.createLabel('Assignment ' + i + ' : ' + name).setVisible(true);
var dateLabel = app.createLabel('Date: ' + date).setVisible(true);
var idLabel = app.createLabel(assignment.getId()).setVisible(false);
var deletebutton = app.createButton('Delete Assignment');
var handler = app.createServerHandler('deleteAssignment');
handler.addCallbackElement(idLabel);
deletebutton.addClickHandler(handler);
grid.setWidget(j, 0, nameLabel);
j = j + 1;
grid.setWidget(j, 0, dateLabel);
grid.setWidget(j, 1, deletebutton);
grid.setWidget(j, 3, idLabel);
i++;
j = j + 2;
}
app.add(grid);
return app;
I made some little test on your code. you need to do some little changes:
You need to change "var app = UiApp.createApplication();" for "var app = UiApp.getActiveApplication()" (already saw that in comment).
You didn't declared "db" your script will systematically be in error if you don't correct that.
Bellow your code where the update function actually update the grid:
function doGet(){
var app = UiApp.createApplication();
var grid = app.createGrid(3, 3).setId("grid").setWidget(1, 2, app.createLabel("test"));
grid.addClickHandler(app.createServerHandler("update"));
app.add(grid);
return(app);
}
function update(){
var app = UiApp.getActiveApplication(); // getActiveApplication
var oldGrid = app.getElementById('grid');
app.remove(oldGrid);
var handler = app.createServerHandler('AddAssignment');
var addAssignmentButton = app.createButton('Add Assignment', handler);
var db = ScriptDb.getMyDb();
var assignments = db.query({}); // YOU DIDNT DECLARED db
var i = 1;
var j = 1;
var grid;
if(assignments.getSize() < 1){
grid = app.createGrid(3, 5).setId('grid');
}
else{
grid = app.createGrid(assignments.getSize() + assignments.getSize() + assignments.getSize(), 5).setId('grid'); // assignments.getSize()*3
}
handler.addCallbackElement(grid);
grid.setWidget(0, 2, addAssignmentButton);
while(assignments.hasNext()){
var assignment = assignments.next();
var name = assignment.name;
var date = assignment.date;
var description = assignment.description;
var nameLabel = app.createLabel('Assignment ' + i + ' : ' + name).setVisible(true);
var dateLabel = app.createLabel('Date: ' + date).setVisible(true);
var idLabel = app.createLabel(assignment.getId()).setVisible(false);
var deletebutton = app.createButton('Delete Assignment');
var handler = app.createServerHandler('deleteAssignment');
handler.addCallbackElement(idLabel);
deletebutton.addClickHandler(handler);
grid.setWidget(j, 0, nameLabel);
j = j + 1;
grid.setWidget(j, 0, dateLabel);
grid.setWidget(j, 1, deletebutton);
grid.setWidget(j, 3, idLabel);
i++;
j = j + 2;
}
app.add(grid);
return app;
}