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.
How can I set the min/max after the datetimepicker has been created?
With the datepicker I can do something like this:
var start = $("#start").kendoDatePicker();
start.max(endDate);
However, the datetimepicker won't allow that.
I get the error as
"Uncaught TypeError: start.max is not a function"
Do it like kendo doc here does, just like this i limit min to yesterday and max to tomorrow :
var datepicker = $("#datepicker").data("kendoDatePicker");
var $today = new Date();
var $yesterday = new Date($today);
$yesterday.setDate($today.getDate() - 1);
var $tomorrow = new Date($today);
$tomorrow.setDate($today.getDate() + 1);
var min = datepicker.min($yesterday);
var max = datepicker.max($tomorrow);
Here is the kendo dojo as working example
Here I have tis function that is querying data and returning it to me and im putting that data in to html elements to make a post.my if statement at the bottom is where im having a bit of problem i trying to only apply my comment window once to the new clones once they have been pushed over to the new div called story board, i believe im telling my if statement that if the class already exists in that new clone then do nothing else apply it there.. to seee what i am talking about...here is my test domain...http://subdomain.jason-c.com/
sign in is "kio" pass is the same and when you hit publish on the stories, everytime a nw one hits it will apply comment box to a post in the storyboard window that already has a comment text area. what am i doing wrong.
function publishWindowHandler(){
var query = new Parse.Query('Post');
console.log(currentUser);
query.equalTo("User", currentUser);
query.include("User");
query.descending("createdAt")
console.log(user.get('username'));
query.find({
success:function(results){
document.getElementById("publishCenter").textContent = "";
for(var i =0; i < results.length; i++){
var userPost = results[i];
//console.log(userPost.get("User") + " / " + userPost.get("Author") + " / " + userPost.get("Story") + " / " + userPost.get("objectId"));
var authorTitle = document.createElement("p");
var newPost = document.createElement("P");
var title = document.createElement("P");
var userLabel = document.createElement("p");
var postId = userPost.id;
var postBtn = document.createElement("INPUT");
postBtn.className ="publishBtn";
postBtn.id ="publishBtn";
postBtn.setAttribute("Type", "button");
postBtn.setAttribute("value", "Publish");
title.textContent = "Story: " + userPost.get("Title");
authorTitle.textContent = "Author: " + userPost.get("Author");
newPost.textContent = userPost.get("Story");
userLabel.textContent = "Published by: " +userPost.get("User").get ("username");
var postWrapper = document.createElement("DIV");
postWrapper.className = "postWrapper";
postWrapper.id = postId;
document.getElementById("publishCenter").appendChild(postWrapper);
postWrapper.appendChild(title);
postWrapper.appendChild(authorTitle);
postWrapper.appendChild(newPost);
postWrapper.appendChild(userLabel);
postWrapper.appendChild(postBtn);
postBtn.addEventListener("click", publicViewHandler);
function publicViewHandler(){
$(this).parent(".postWrapper").clone().appendTo(".storyBoard");
function testWindow(){
if($(publicBoard).children().hasClass(".commentWindow")){
}
else
{
$(".storyBoard").children().append(commentWindow);
}
}
testWindow();
}
}
}
})
}
According to the documentation, jquery hasClass doesn't need '.' prefixing the passed in class name.
https://api.jquery.com/hasclass/
Try removing that and see if that get's you anywhere.
Also, where is the variable commentWindow defined? Is it global?
var myClone = $(this).parent().clone(true);
myClone.appendTo(".storyBoard");
console.log(publicBoard);
console.log("hello",$(this));
console.log($(publicBoard).find('.postWrapper').find("commentWindow"));
myClone.append($(commentWindow).clone());
this is what i ended up doing to solve my issue took me a while and a little help from a friend.
My first post and I must admit that I'm bad at explaining stuffs. let me try.
I have this java code in spreadsheet which adds a UI, have certain checkboxes & a chart attached to UI.
When the first (EDC) checkbox is clicked range(C2) goes as true/false, changes the chart values in data.
Since the chart doesnt automatically update, I decided to remove the existing chart and add a new one. When the code is runned for first time...the UI is visible along with Populate charts, when I click checkbox the existing chart gets delete but the populate_chart function does not. Can any one help me??? Almost my first code (such big).
function Show_chart() {
var ss = SpreadsheetApp.getActive();
var calc = ss.getSheetByName("Calculations");
var data = calc.getRange(6, 19, 22, 2)
// var values = data.getValues()
// for (var row in values) {
// for (var col in values[row]) {
// Logger.log(values[row][col]);
// }
// }
var app = UiApp.createApplication().setHeight(600).setWidth(1200).setTitle("Attrition Report");
var mygrid = app.createGrid(7, 2)
var label1 = mygrid.setWidget(0, 0, app.createLabel("EDC Project"));
var label2 = mygrid.setWidget(1, 0, app.createLabel("Customer Project"));
var label3 = mygrid.setWidget(2, 0, app.createLabel("Support"));
var checkbox1 = mygrid.setWidget(0, 1, app.createCheckBox().setName("EDC"));
var checkbox2 = mygrid.setWidget(1, 1, app.createCheckBox().setName("CP"));
var checkbox3 = mygrid.setWidget(2, 1, app.createCheckBox().setName("Support"));
checkbox1.addClickHandler(app.createServerHandler("myClickHandler"));
var panel = app.createVerticalPanel();
panel.add(mygrid);
app.add(panel);
populate_charts()
ss.show(app);
}
function populate_charts(){
var ss = SpreadsheetApp.getActive();
var app = UiApp.getActiveApplication();
var calc = ss.getSheetByName("Calculations");
var data = calc.getRange(6, 19, 22, 2);
//1200 300
var chart = Charts.newLineChart().setDimensions(300, 100)
.setDataTable(data)
.build();
var chartpanel = app.createHorizontalPanel().setId("tbd");
chartpanel.add(chart);
return app.add(chartpanel);
}
function myClickHandler(e) {
var ss = SpreadsheetApp.getActive();
var calc = ss.getSheetByName("Calculations");
var app = UiApp.getActiveApplication();
// var data = calc.getRange(6, 19, 22, 2)
var chvalue = e.parameter.EDC;
calc.getRange("C2").setValue(chvalue);
var del = app.getElementById("tbd");
return app.remove(del);
populate_charts()
}
Thanks...
You should call populate_charts(); before return app.remove(del); in your function myClickHandler.
Whatever you add after returnin your function simply doesn't happen.
Don't delete an UiElement and recreate a new element with the same Id - very bad things will happen in UiApp, or GWT which is the mechanics behind UiApp.
You could simplify populate_charts:
function populate_charts(app, sSheet){
var data = sSheet.getSheetByName("Calculations").getRange(6, 19, 22, 2);
var chart = Charts.newLineChart().setDimensions(300, 100)
.setDataTable(data).build();
return chart;
}
myClickHandler could be reduced as well:
function myClickHandler(e) {
var app = UiApp.getActiveApplication();
var chvalue = e.parameter.EDC;
var sSheet = SpreadsheetApp.getActive();
sSheet.getSheetByName("Calculations").getRange("C2").setValue(chvalue);
app.getElementById("chartContainer").clear().add(populate_charts(app, sSheet));
return app;
}
The last 7 lines of Show_chart changed to:
app.add(mygrid.setId('grid'));
app.add(app.createFlowPanel()
.setId('chartContainer').add(populate_charts(app, ss)));
checkbox1.addClickHandler(
app.createServerHandler('myClickHandler')
.addCallbackElement(app.getElementById('grid'))
.addCallbackElement(app.getElementById('chartContainer')));
return app;
}
Don't forget to add all missing semicolons ; .
SOLVED
Here's the result:
window.onload = function timeScroll()
{
var current_date = new Date();
hour_value = current_date.getHours();
var big_number = hour_value*833.3
$(window).scrollTop(big_number)
}
PREVIOUS QUESTION
I'm working on a page, that takes the time of day (hour) and uses that time to scroll to a particular point on the page. I multiply the getHour in order to get a variable I've called big_number. However, I can't seem to pass that variable into my scroll function.
This tells me that it's calculating the number correctly:
window.onload = function timeScroll()
{
var current_date = new Date();
hour_value = current_date.getHours();
var big_number = hour_value*833.3
window.alert(big_number);
}
I'm looking to do something like this:
window.onload = function timeScroll()
{
var current_date = new Date();
hour_value = current_date.getHours();
var big_number = hour_value*833.3
**scrollTo(x,big_number)**
}
Anything you've got helps. Also, here's the site live...
http://newmedia.emerson.edu/~caleb_ungewitter/weather/index.html