cannot read property "0" of undefined error - for-loop

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.

Related

How do i get this code to copy only the rows that match my object matching criteria? currently if copies every row

Currently this code copies every row and not the ones that match my criteria
I had some issues getting it to loop. Hence the loggers.
I'm quite new to this.
function searchAnotherSheetAndReturnRows(){
Logger.clear()
var tss = SpreadsheetApp.openById('1dX5MMLXGsG_S_KzRhOcquOp00VhzRBSlTCkyw'); // tss = target spreadsheet
var ts = tss.getSheetByName('Sheet1'); // ts = target sheet
var sss = SpreadsheetApp.openById('1ImDswr6ADS7t4HKIFHpntykN2LS7Mmd-cls34'); // sss = source spreadsheet
var ss = sss.getSheetByName('Page1'); // ss = source sheet
var tslast_row = ts.getLastRow();
var i=0;
Logger.log(i)
for (var i = 1; i < tslast_row; i++) {
Logger.log(i)
Logger.log(tslast_row);
var ssSearch1 = ss.getRange(2,1).getValue();
Logger.log(ssSearch1);
var tsSearch1 = ts.getRange(i,1).getValue();
Logger.log(tsSearch1);
if (ssSearch1 == tsSearch1); {
var tsSearch1Range = ts.getRange(i,1,1,7);
Logger.log(tsSearch1Range);
var range2Copy = tsSearch1Range.getValues();// Copies data from root sheet
Logger.log(range2Copy);
var last_row = ss.getLastRow();
Logger.log(last_row);
var last_row = last_row+1;
Logger.log(last_row);
ss.getRange(last_row,1,1,7).setValues(range2Copy);// Adds root sheet data to target
}
}
}
It's really hard to figure out what you're trying to do. So here's an example that will hopefully help you a little. The job of this function is to copy rows in the AlaskanWilderness that contain GOLD to MyPocket. (Names of Sheets)
function moveGoldFromAlaskanWildernessToMyPocket() {
var tss=SpreadsheetApp.openById('id');
var ts=tss.getSheetByName('MyPocket');
var sss=SpreadsheetApp.openById('id');
var ss=sss.getSheetByName('AlaskanWildernes');
var sr=ss.getDataRange()
var sd=sr.getValues();
var criteria='GOLD';
for (var i=1;i<sd.length;i++) {//skip header
for(var j=0;j<sd[i].length;i++) {
if (sd[i][j]=='GOLD'); {
ss.appendRow(sd[i]);
}
}
}
}
sheet.appendRow
range.getValues

Enhancing Performance in Student Info App

I've built a simple Student Information platform using Google Sheets. It allows the user to query, update and create new student info on a user interface. Please refer to this sheet to see how it works.
The functions to Refresh/Update/Save are inside the Actions button on a menu bar. Everything seems to work well however when the number of records increases, say above 100 records, all the functions slow down and it gets extremely slow with 200+ records.
Appreciate if anyone could help to take a look at the scripts as I suspect they need to be optimized.
Many thanks in advance!
function UpdateDataIntoMaster() { //This script is used in the SAVE button in UPDATE sheet)
/*Get data from UPDATE Sheet*/
var ss = SpreadsheetApp.openById("11Djp9UmXbtWv7VitZFfo0X4Ctet3O8Amh4xADNKOZgY");
var sheet = ss.getSheetByName('UPDATE');
var range = sheet.getRange("D30:AE30"); //All data transposed into this line. MUST be updated if more fields are added into the Data sheet
var values = range.getValues();
var rangeForKey = sheet.getRange("D30") //Student Name is used as the
key identifier
var keyValue = rangeForKey.getValue();
/*Pass in keyValue(identifier = Student Name)
and all data in the function below in order
to update master data sheet*/
updDbase(keyValue,values);
function updDbase(keyValue,values) {
var ss = SpreadsheetApp.openById("11Djp9UmXbtWv7VitZFfo0X4Ctet3O8Amh4xADNKOZgY")
var sheet = ss.getSheetByName('Data');
var data = sheet.getDataRange().getValues();
var noOfRow = values.length
var noOfCol = values[0].length
for (var i=0; i < data.length; i++) { // going through all the rows in Data sheet
var keyData = ss.getSheetByName("Data").getRange(i+1,1).getValue(); //Get the Student Name from Data sheet
if (keyData == keyValue) {
// for (var j=0; j < data[i].length; j++) { // this is going through all the cell of a row
var row = Number(i)+1;
var sh = SpreadsheetApp.getUi();
var response = sh.alert("Update Information","Are you sure you want to update the student information?", sh.ButtonSet.YES_NO);
if (response == sh.Button.YES)
{
var sheets = ss.getSheetByName("Data").getRange(row,1,noOfRow,noOfCol).setValues(values);
}//If response == YES
}
}
}
}
function CreateNew() {
/*Get data from Inquiry Sheet*/
var ss = SpreadsheetApp.openById("11Djp9UmXbtWv7VitZFfo0X4Ctet3O8Amh4xADNKOZgY");
var sheetNew = ss.getSheetByName('Create New');
var range = sheetNew.getRange("D30:AZE30"); //All data transposed into
this line
var values = range.getValues();
var rangeForKey = sheetNew.getRange("E30") //Using Student ID as key identifier
var keyValue = rangeForKey.getValue();
var noOfRow = values.length
var noOfCol = values[0].length
var sheetData = ss.getSheetByName('Data');
var lastRow = sheetData.getLastRow();
var data = sheetData.getDataRange().getValues();
for (var i=0; i < data.length; i++) { // going through all the rows in Data sheet
var keyData = sheetData.getRange(i+1,2).getValue(); //Get the Student ID from Data sheet
if (keyData == keyValue) {
AlertBox();//If Student ID is found, to prompt Student ID already
exist
return;
} //If
} //For
/*Confirming with user whether to proceed to create new entry*/
var sh = SpreadsheetApp.getUi();
var response = sh.alert("Create New Record","Are you sure you want to
create new student information?", sh.ButtonSet.YES_NO);
if (response == sh.Button.YES){
if (keyValue == ""){
var response = sh.alert("Create New Record","Unable to proceed
because Student ID is empty", sh.ButtonSet.OK);
return;}
else {
//var response = sh.alert("Create New Record","Unable to
proceed because Student ID is empty", sh.ButtonSet.OK);
var sheets =
sheetData.getRange(lastRow+1,1,1,noOfCol).setValues(values)
}
}//If
}
function EditStudentInfo() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Inquiry");
//var ss = SpreadsheetApp.getActive();
var protections = ss.getProtections(SpreadsheetApp.ProtectionType.RANGE);
for (var i = 0; i < protections.length; i++) {
var protection = protections[i];
if (protection.canEdit()) {
protection.remove();
}
}
}
function EditContent() {
var s = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Update");
var rangeContentCol1 = s.getRange("E3:E23");
var CopyContentCol1 = s.getRange("E3:E23").getValues();
var rangeContentCol2 = s.getRange("I3:I23");
var CopyContentCol2 = s.getRange("I3:I23").getValues();
rangeContentCol1.clearContent();
rangeContentCol2.clearContent();
var PasteContentCol1 =
s.getRange("E3:E23").setValues(CopyContentCol1);
var PasteContentCol2 = s.getRange("I3:I23").setValues(CopyContentCol2);
}
A common performance mistake people with Apps Script is doing the .getRange().getValues() within their for loops. Performance-wise these get and set calls are quite expensive.
Lucky the fix for this is quite easy - get all the data at once first, then loops through it. You actually do this already, sort of. In your script you get the whole data range, but then only use a part of the data and instead do another getValues call. I've updated the two areas in your script that had getRange() calls in a for loop --> var keyData = data[i][0];
function UpdateDataIntoMaster() { //This script is used in the SAVE button in UPDATE sheet)
/*Get data from UPDATE Sheet*/
var ss = SpreadsheetApp.openById("11Djp9UmXbtWv7VitZFfo0X4Ctet3O8Amh4xADNKOZgY");
var sheet = ss.getSheetByName('UPDATE');
var range = sheet.getRange("D30:AE30"); //All data transposed into this line. MUST be updated if more fields are added into the Data sheet
var values = range.getValues();
var rangeForKey = sheet.getRange("D30") //Student Name is used as the
key identifier
var keyValue = rangeForKey.getValue();
/*Pass in keyValue(identifier = Student Name)
and all data in the function below in order
to update master data sheet*/
updDbase(keyValue,values);
function updDbase(keyValue,values) {
var ss = SpreadsheetApp.openById("11Djp9UmXbtWv7VitZFfo0X4Ctet3O8Amh4xADNKOZgY")
var sheet = ss.getSheetByName('Data');
var data = sheet.getDataRange().getValues();
var noOfRow = values.length
var noOfCol = values[0].length
for (var i=0; i < data.length; i++) { // going through all the rows in Data sheet
var keyData = data[i][0]; //Use the data that is already loaded.
if (keyData == keyValue) {
// for (var j=0; j < data[i].length; j++) { // this is going through all the cell of a row
var row = Number(i)+1;
var sh = SpreadsheetApp.getUi();
var response = sh.alert("Update Information","Are you sure you want to update the student information?", sh.ButtonSet.YES_NO);
if (response == sh.Button.YES)
{
var sheets = ss.getSheetByName("Data").getRange(row,1,noOfRow,noOfCol).setValues(values);
}//If response == YES
}
}
}
}
function CreateNew() {
/*Get data from Inquiry Sheet*/
var ss = SpreadsheetApp.openById("11Djp9UmXbtWv7VitZFfo0X4Ctet3O8Amh4xADNKOZgY");
var sheetNew = ss.getSheetByName('Create New');
var range = sheetNew.getRange("D30:AZE30"); //All data transposed into
this line
var values = range.getValues();
var rangeForKey = sheetNew.getRange("E30") //Using Student ID as key identifier
var keyValue = rangeForKey.getValue();
var noOfRow = values.length
var noOfCol = values[0].length
var sheetData = ss.getSheetByName('Data');
var lastRow = sheetData.getLastRow();
var data = sheetData.getDataRange().getValues();
for (var i=0; i < data.length; i++) { // going through all the rows in Data sheet
var keyData = data[i][0]; //Use the data that is already loaded.
if (keyData == keyValue) {
AlertBox();//If Student ID is found, to prompt Student ID already
exist
return;
} //If
} //For
/*Confirming with user whether to proceed to create new entry*/
var sh = SpreadsheetApp.getUi();
var response = sh.alert("Create New Record","Are you sure you want to
create new student information?", sh.ButtonSet.YES_NO);
if (response == sh.Button.YES){
if (keyValue == ""){
var response = sh.alert("Create New Record","Unable to proceed
because Student ID is empty", sh.ButtonSet.OK);
return;}
else {
//var response = sh.alert("Create New Record","Unable to
proceed because Student ID is empty", sh.ButtonSet.OK);
var sheets =
sheetData.getRange(lastRow+1,1,1,noOfCol).setValues(values)
}
}//If
}
function EditStudentInfo() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Inquiry");
//var ss = SpreadsheetApp.getActive();
var protections = ss.getProtections(SpreadsheetApp.ProtectionType.RANGE);
for (var i = 0; i < protections.length; i++) {
var protection = protections[i];
if (protection.canEdit()) {
protection.remove();
}
}
}
function EditContent() {
var s = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Update");
var rangeContentCol1 = s.getRange("E3:E23");
var CopyContentCol1 = s.getRange("E3:E23").getValues();
var rangeContentCol2 = s.getRange("I3:I23");
var CopyContentCol2 = s.getRange("I3:I23").getValues();
rangeContentCol1.clearContent();
rangeContentCol2.clearContent();
var PasteContentCol1 =
s.getRange("E3:E23").setValues(CopyContentCol1);
var PasteContentCol2 = s.getRange("I3:I23").setValues(CopyContentCol2);
}
Give this a test and let me know if it helps!

Using IPersistFile::Load multiple times with IPropertyStore

I am iterating through a bunch of .lnk files and getting information on them.
For each file I do this, this is js-ctypes but is a winapi question. I removed the error checking and simplified the code:
var hr_CoInitializeEx = ostypes.API('CoInitializeEx')(null, ostypes.CONST.COINIT_APARTMENTTHREADED);
var shellLinkPtr = ostypes.TYPE.IShellLinkW.ptr();
var hr_CoCreateInstance = ostypes.API('CoCreateInstance')(ostypes.CONST.CLSID_ShellLink.address(), null, ostypes.CONST.CLSCTX_INPROC_SERVER, ostypes.CONST.IID_IShellLink.address(), shellLinkPtr.address());
shellLink = shellLinkPtr.contents.lpVtbl.contents;
var persistFilePtr = ostypes.TYPE.IPersistFile.ptr();
var hr_shellLinkQI = shellLink.QueryInterface(ostypes.CONST.IID_IPersistFile.address(), persistFilePtr.address());
persistFile = persistFilePtr.contents.lpVtbl.contents;
var propertyStorePtr = ostypes.TYPE.IPropertyStore.ptr();
var hr_shellLinkQI2 = shellLink.QueryInterface(ostypes.CONST.IID_IPropertyStore.address(), propertyStorePtr.address());
propertyStore = propertyStorePtr.contents.lpVtbl.contents;
for (var i = 0; i < arrOSPath.length; i++) {
var hr_Load = persistFile.Load(persistFilePtr, arrOSPath[i], 0);
var ppropvar = ostypes.TYPE.PROPVARIANT();
var hr_GetValue = propertyStore.GetValue(ostypes.CONST.PKEY_AppUserModel_ID.address(), ppropvar.address());
console.log(ppropvar.pwszVal); ////// <<<<< this is fishy
var rez_PropVariantClear = ostypes.API('PropVariantClear')(ppropvar.address());
}
// cleanup
persistFile.Release(persistFilePtr);
propertyStore.Release(propertyStorePtr);
shellLink.Release(shellLinkPtr);
ostypes.API('CoUninitialize')();
However ppropvar.pwszVal is coming out to be the SystemAppUserModelID of the first file I IPersitFile::Loaded, is this expected? Do I have to CoUninitialize and CoInitialize each loop or something to fix this?
Thanks

Updating Panel with new values in GAS UI

I have a huge spreadsheet matrix, from which I create a long list of check boxes. The users then select different abilities, press search. The code the cross-checks with the database spreadsheet, returning names of the persons who has those abilities.
I need to update the "rightPanel" with the results of my search. But i simple can't figure out how to - if at all posible - update a panel in my UI..
var dataSSkey = 'sheetID'; //datasheet ID
var dataSheet = SpreadsheetApp.openById(dataSSkey).getSheetByName('Ansatte');
var groupsArray = [[],[],[],[]];
var lastRow = dataSheet.getLastRow();
var lastColumn = dataSheet.getLastColumn();
var dataArray = dataSheet.getRange(1,1,lastRow,lastColumn).getValues();
var numberGroups
var app = UiApp.createApplication().setTitle('Find Consultant');
var panel = app.createVerticalPanel();
var leftPanel = app.createVerticalPanel().setWidth(450);
var rightPanel = app.createVerticalPanel().setWidth(450);
var grid = app.createGrid(1, 2).setId('myGrid')
var outputArray = []; //to store output from search
var positiveList = [[],[]]; //array to store name and folder-ID of consultants matching
var numberPositive = 0; //number of consultants matching
function doGet() {
buildGroupsArray()
addCheckBoxesToUI()
var scrollPanel = app.createScrollPanel().setHeight(460);
//Search button
var searchButton = app.createButton('Search');
var clickHandler = app.createServerClickHandler("respondToSearch");
searchButton.addClickHandler(clickHandler);
clickHandler.addCallbackElement(panel);
var spacerImage = app.createImage("http://www.bi..ge.jpg").setHeight(3);
scrollPanel.add(panel);
rightPanel.add(app.createLabel('resultat her'));
leftPanel.add(scrollPanel);
leftPanel.add(spacerImage);
leftPanel.add(searchButton);
grid.setWidget(0, 0, leftPanel)
grid.setWidget(0, 1, rightPanel);
app.add(grid);
return app;
}
function respondToSearch(e){
var numberLogged = 0;
//define firstEmpty
var firstEmpty = "A"+lastRow;
if(lastRow !== 1){
firstEmpty = "A"+(lastRow+1);
};
//find selected competencies --> store in array + count competencies
for(i = 1; i <= lastRow; i++){
if (e.parameter["Checkbox"+i] == "true") {
var value = e.parameter["CheckboxValue"+i];
outputArray[numberLogged] = value;
numberLogged++;
}
}
for(i = 2; i <= lastColumn; i++){
var numberCorrect = 0;
//Run through rows according to content of output from selection
for(j in outputArray){
//Check if consultant own selected competency
if(dataArray[outputArray[j]][i] == "x"){
numberCorrect++; //if consultant owns selected competency then count
}
}
//if consultant owns all competencies, then add name and folder-id to array
if(numberCorrect == numberLogged){
positiveList[0][numberPositive] = dataArray[1][i]; //Add consultant name
positiveList[1][numberPositive] = dataArray[2][i]; //Add consultant-folder ID
numberPositive++ //count the number of consultants that own all competencies
}
}
for(j in positiveList[0]){
var name = positiveList[0][j];
var id = positiveList[1][j];
Logger.log(name);
Logger.log(id)
var anchor = app.createAnchor(name,'https://ww......folderviewid='+id);
rightPanel.add(anchor)
}
return app;
}
I don't really understand the problem you have...
In your handler function you only have to use app=UiApp.getActiveApplication() and from there populate the panel exactly the same way you did it in the doGet() function, ending with a return app; that will actually update the current Ui.
There are dozens of examples all around... did I misunderstand something in your question ?
Edit : following your comment.
I suppose you defined your variables outside of the doGet function hoping they will become global and so available to all the functions in your script but this is not going to work. Global variables in Google Apps script can't be updated by functions.
I would strongly recommend that you create app and panels in the doGet function and give them an ID so that you can get them back and update their values (or content) from the handler functions.
Here is a re-written version of your code (didn't test)
: (some parts are not reproduced (see //...)
var dataSSkey = 'sheetID'; //datasheet ID
var dataSheet = SpreadsheetApp.openById(dataSSkey).getSheetByName('Ansatte');
var groupsArray = [[],[],[],[]];
var lastRow = dataSheet.getLastRow();
var lastColumn = dataSheet.getLastColumn();
var dataArray = dataSheet.getRange(1,1,lastRow,lastColumn).getValues();
var numberGroups
var outputArray = []; //to store output from search
var positiveList = [[],[]]; //array to store name and folder-ID of consultants matching
var numberPositive = 0; //number of consultants matching
function doGet() {
var app = UiApp.createApplication().setTitle('Find Consultant');
var panel = app.createVerticalPanel();
var leftPanel = app.createVerticalPanel().setWidth(450).setId('leftPanel');
var rightPanel = app.createVerticalPanel().setWidth(450).setId('rightPanel');;
var grid = app.createGrid(1, 2).setId('myGrid')
buildGroupsArray(app); // in this function get app as parameter or use UiApp.getActiveApplication();
addCheckBoxesToUI(app);// in this function get app as parameter or use UiApp.getActiveApplication();
var scrollPanel = app.createScrollPanel().setHeight(460);
//...
//...
return app;
}
function respondToSearch(e){
//...
//...
var app = UiApp.getActiveApplication();
var rightPanel = app.getElementById('rightPanel');
for(j in positiveList[0]){
var name = positiveList[0][j];
var id = positiveList[1][j];
Logger.log(name);
Logger.log(id)
var anchor = app.createAnchor(name,'https://ww......folderviewid='+id);
rightPanel.add(anchor)
}
return app;
}

How do I fix charset problems in .gs script?

I have a problem with charsets.
I parsed a csv file in google-app-engine and I'm posting to an uiapp table.
But I checked special characters like áéíóú and those are not well displayed (?square symbol).
When I was setting up my code I played writing the string imported to a google docs document and it worked the same.
some advice please?
I search for:
a global charset definition to the code. or
string var transformation that makes the chars appear like I want to. (avoiding html &number definitions.
Is this related to the blob object?
The thing is important i come from spain and we need such characters.
app that get's a csv ';' delimited file and shows it's content
I post all my code, it's barely as the tutorial that is given.
function arreglaUrl(cadena){
var texto = cadena[cadena.length - 2]
if (texto == ''){
cadena[cadena.length - 2] = 'Sin enlace';
}
else{
cadena[cadena.length - 2] = '<center>Link.</center>' ;
};
}
function parsedCSV(){
var listaArchivos = DocsList.getFolderById('XXXXX').getFiles()
for (var i = 0; i < listaArchivos.length; i++) {
if (listaArchivos[i].getName() == 'baul.csv'){
var origen = listaArchivos[i];
};
}
var texto = origen.getContentAsString();
var arra = Utilities.parseCsv(texto,";");
return(arra);
}
function doGet() {
var datos = parsedCSV()
var baul = Charts.newDataTable()
for (i = 0; i < datos[0].length; i++){
baul.addColumn(Charts.ColumnType.STRING, datos[0][i])
}
for (i = 1; i < datos.length; i++){
arreglaUrl(datos[i]) // this only makes some html i need to post some links
baul.addRow(datos[i])
}
baul.build();
var sectorFilter = Charts.newCategoryFilter()
.setFilterColumnLabel("sector")
.build();
var tipoFilter = Charts.newCategoryFilter()
.setFilterColumnLabel("tipo")
.build();
var searchFilter = Charts.newStringFilter()
.setFilterColumnLabel("Titulo")
.build();
var searchDesc = Charts.newStringFilter()
.setFilterColumnLabel("descripcion")
.build();
var tableChart = Charts.newTableChart().setOption('allowHtml', true).setDimensions(0,0)
.build();
var dashboard = Charts.newDashboardPanel()
.setDataTable(baul)
.bind([sectorFilter, tipoFilter, searchFilter, searchDesc], [tableChart])
.build();
var uiApp = UiApp.createApplication().setTitle('Baul de Recursos');
var anchoTotal = '100%';
dashboard.add(uiApp.createVerticalPanel()
.add(uiApp.createHorizontalPanel()
.add(sectorFilter)
.add(tipoFilter)
.setSpacing(15)
)
.add(uiApp.createHorizontalPanel()
.add(searchFilter)
.add(searchDesc)
.setSpacing(15)
)
.add(uiApp.createHorizontalPanel()
.add(tableChart).setBorderWidth(1).setHorizontalAlignment(UiApp.HorizontalAlignment.CENTER).setWidth(anchoTotal)
)
);
uiApp.add(dashboard);
return uiApp;
}
I found it, we need to get the content of the file first with a Blob object.
This function is the one I use to parse some csv info into an array:
function parsedCSV(){
//searching the file. This gets only one file in var origen
var listaArchivos = DocsList.getFolderById('XXXXXXX').getFiles()
for (var i = 0; i < listaArchivos.length; i++) {
if (listaArchivos[i].getName() == 'baul.csv'){
var origen = listaArchivos[i];
};
}
// HERE IS THE GOOD DEFINITION OF CHAR:
var texto2= origen.getBlob().getDataAsString('ISO-8859-1');
// I put all the corrected text in an array
var arra = Utilities.parseCsv(texto2,";");
return(arra);
}
This is the solved thing: https://script.google.com/macros/s/AKfycbyHa-bLWBHBr3qifbvzxecqGgGUYX8mhyo-TKoyfGvy/exec
The trick:
var textVariableName = fileObjectVariableName.getBlob().getDataAsString('ISO-8859-1');

Resources