----EDIT the question was to long and to hard to understand------
Here is a working exemple : http://codepen.io/anon/pen/Mwapgb
WARNING : This will make firefox CRASH ! , if you dare, click around 500 time on any div (i suggest to use a tool to simulate it. Rip mouse)
But This http://codepen.io/anon/pen/eNNqde
Wont make firefox crash
What is the difference :
function GetDateFromDatetimePython(stringdate){ // IT CRASH
var partieDate = stringdate.split(' ');
var ymd = partieDate[0].split('-');
var hms = partieDate[1].split(':');
return new Date(Date.UTC(ymd[0],ymd[1]-1,ymd[2],hms[0],hms[1],hms[2],0));
}
function GetDateFromDatetimePython(stringdate){ // IT DON'T
var partieDate = stringdate.split(' ');
var tmp = partieDate[0]; // add this
var tmp2 = partieDate[1]; // add this
var ymd = tmp.split('-'); // change this
var hms = tmp2.split(':'); // change this
return new Date(Date.UTC(ymd[0],ymd[1]-1,ymd[2],hms[0],hms[1],hms[2],0));
}
I'm going crazy. What is wrong with the first practice ?
Ok , it's stupid to make 3 split, i could combined in 1 . Whenever. WHY does this blow up firefox , Why aren't Chrome nor IE affect ?
May be you are trapped into some infinite loop or a process is instantiated which involves heavy processing which drains all the memory available with your browser.
Related
I've been trying for hours to make the following Google Apps Script work. What it needs to do, is send emails (from an html-template) to anyone that:
has a complete Event Schedule (which is completed if they have been
assigned to at least 4 events, which is counted in column Q);
has NOT been sent an email earlier (which is kept track of in column
R);
The script keeps track of errors in column S, i.e. if there's no email address provided.
It appears it only works:
if I comment out
data = data.filter(function(r){ return r[17] == true & r[16] > 3});
or if I comment out
ws.getRange("S3:S" + ws.getLastRow()).setValues(errors);
ws.getRange("R3:R" + ws.getLastRow()).setValues(mailSucces);
How can I get this script to work properly?
A copy of the Google Sheet I'm referring to is this one:
https://docs.google.com/spreadsheets/d/1sbOlvLVVfiQMWxNZmtCLuizci2cQB9Kfd8tYz64gjP0/edit?usp=sharing
This is my code so far:
function SendEmail(){
var voornaam = 3;
var achternaam = 4;
var email = 5;
var event1 = 9;
var event2 = 10;
var event3 = 11;
var event4 = 12;
var event5 = 13;
var event6 = 14;
var event7 = 15;
var emailTemp = HtmlService.createTemplateFromFile("email");
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Events Day 1");
var datum = ws.getRange(1,3).getValue();
var spreker = ws.getRange(1,6).getValue();
var data = ws.getRange("A3:R" + ws.getLastRow()).getValues();
data = data.filter(function(r){ return r[17] == false && r[16] > 3}); //Either this needs to be commented out...
let errors = [];
let mailSucces = [];
data.forEach(function(row){
try{
emailTemp.voornaam = row[voornaam];
emailTemp.email = row[email];
emailTemp.datum = datum;
emailTemp.spreker = spreker;
emailTemp.event1 = row[event1];
emailTemp.event2 = row[event2];
emailTemp.event3 = row[event3];
emailTemp.event4 = row[event4];
emailTemp.event5 = row[event5];
emailTemp.event6 = row[event6];
emailTemp.event7 = row[event7];
var htmlMessage = emailTemp.evaluate().getContent();
GmailApp.sendEmail(
row[email],
"Here you go! Your personal schedule for the event of " + datum,
"Your emailprogramm doesn't support html.",
{
name: "Event Organisation Team", htmlBody: htmlMessage, replyTo: "info#fakeemail.com"
});
errors.push([""]);
mailSucces.push(["TRUE"]);
}
catch(err){
errors.push(["Error: no message sent."]);
mailSucces.push(["False"]);
}
}); //close forEach
ws.getRange("S3:S" + ws.getLastRow()).setValues(errors); //or this and the next line need to be commented out.
ws.getRange("R3:R" + ws.getLastRow()).setValues(mailSucces);
}
Edit I have been trying and thinking en trying... but still haven't found out how to make it work. But I also got understanding of why it's not working; I just don't know how to get it fixed.
Let me elaborate on the problem a bit more:
The problem is, that within the forEach loop the range is a filtered variant of the data, pulled from the spreadsheet with getValues. Therefore, writing data back with ws.getRange("R3:R" + ws.getLastRow()).setValues(mailSucces); results in mismatched checkmarks in te spreadsheet.
So, somehow I need to put the range of the previous used filter data = data.filter(function(r){ return r[17] == false & r[16] > 3}); in a variable...? I guess?
Furthermore, I don't think it's wise to use setValue within the loop, because (from what I understand from my searching on the topic) this results in a slow script, because every loop the script makes an API call to write in the spreadsheet. Hence the errors.push and mailSucces.push, and my attempt to do a setValue at the end, after the loop is finished.
Can someone help me to finish this problem?
The problem is different size of the range you write to and data you are writing in.
Try replacing:
ws.getRange("S3:S" + ws.getLastRow()).setValues(errors);
ws.getRange("R3:R" + ws.getLastRow()).setValues(mailSucces);
With:
ws.getRange(3, 19, errors.length, 1).setValues(errors);
ws.getRange(3, 18, mailSucces.length, 1).setValues(mailSucces);
You should use this variation of getRange
https://developers.google.com/apps-script/reference/spreadsheet/sheet#getrangerow,-column,-numrows,-numcolumns
Your data has non-fixed number of rows and fixed number of columns (1). In general case your data will be matrix of X rows and Y columns. For that purpose you can make it completely dynamic:
sheet.getRange(startRow, startColumn, data.length, data[0].length)
Just make sure data.length is > 0 before you do this, otherwise data[0].length will break.
Edit:
I started writing a comment but it got too long. There are couple of things that may go wrong with sending emails. First thing I noticed is that you use & in filter, but in AppsScript/JavaScript/C-like-languages, you should use && for logical AND. Now the email: you only detect the code break with the catch block. At this point you don't know why the code breaks it could be anything. With GmailApp I recommend you to use createDraft while developing, then when all ok replace it with sendEmail for the final version, both functions have the exact same parameters, thank you Google devs ;-).
To find out the exact problem you should get the error message on break and display it. err.stack should tell you pretty much everything:
catch(err){
Logger.log(err.stack); // Added
errors.push(["Error: no message sent."]);
mailSucces.push(["False"]);
}
Run the sendEmail function from the code editor and you should see the Log for each catch(err) pass.
Is it possible to get the time that is needed to read a specific message ? I would like to use the SpeechSynthesisUtterance Web API and it only has to work in google chrome.
Would it be recommendet to use a third party libary ? Is it viable to messure the time in the background ?
For a workaround (using SpeechSynthesisUtterance) I meassure the time with the help of the onend event. This is not feasible for all situations, since it will take some time to meassure and is not very precise. You could increase the speed (up to 10) but it will get very unprecise.
var speed = 2;
var text = "Test";
var speech = new SpeechSynthesisUtterance(text);
var speakDuration;
speech.volume = 0;
speech.rate = speed;
speech.onend = function (event) {
speakDuration = event.elapsedTime / speed;
console.log(speakDuration)
};
window.speechSynthesis.speak(speech);
So, I never ever programmed JavaScript and never did anything with Google Script before either. I have a fairly good understanding of Visual Basic and macros in Excel and Word. Trying to make a fairly basic program: Plow through a list of variables in a spreadsheet, make a new sheet for each value, insert a formula in this new sheet, cell (1,1).
Debug accepts my program, no issues - however, nothing at all is happening when I run the program:
function kraft() {
var rightHere =
SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange("A1:A131");
var loopy;
var goshDarn = "";
for (loopy = 1; loopy < 132; loopy++) {
celly = rightHere.getCell(loopy,1);
vaerdi = celly.getValue();
fed = celly.getTextStyle();
console.log(vaerdi & " - " & fed);
if (vaerdi != "" && fed.isBold == false) {
SpreadsheetApp.getActiveSpreadsheet().insertSheet(vaerdi);
var thisOne = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(vaerdi);
thisOne.deleteRows(500,500);
thisOne.deleteColumns(5, 23);
thisOne.getRange(1,1).setFormula("=ArrayFormula(FILTER('Individuelle varer'!A16:D30015,'Individuelle varer'!A16:A30015=" & Char(34) & vaerdi & Char(34) & ")))");
}
}
}
activeSheet could be called by name, so could activeSpreadsheet, I guess. But range A1:A131 has a ton of variables - some times there are empty lines and new headers (new headers are bold). But basically I want around 120 new sheets to appear in my spreadsheet, named like the lines here. But nothing happens. I tried to throw in a log thingy, but I cannot read those values anywhere.
I must be missing the most total basic thing of how to get script connected to a spreadsheet, I assume...
EDIT: I have tried to update code according to tips from here and other places, and it still does a wonderful nothing, but now looks like this:
function kraft() {
var rightHere = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange("A1:A131");
var loopy;
var goshDarn = "";
for (loopy = 1; loopy < 132; loopy++) {
celly = rightHere.getCell(loopy,1);
vaerdi = celly.getValue();
fed = celly.getFontWeight();
console.log(vaerdi & " - " & fed);
if (vaerdi != "" && fed.isBold == false) {
SpreadsheetApp.getActiveSpreadsheet().insertSheet(vaerdi);
var thisOne = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(vaerdi);
thisOne.deleteRows(500,500);
thisOne.deleteColumns(5, 23);
thisOne.getRange(1,1).setFormula("=ArrayFormula(FILTER('Individuelle varer'!A16:D30015,'Individuelle varer'!A16:A30015=" + "\"" + vaerdi + "\"" + ")))");
}
}
}
EDIT2: Thanks to exactly the advice I needed, the problem is now solved, with this code:
function kraft() {
var rightHere = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange("A1:A131");
var loopy;
for (loopy = 1; loopy < 132; loopy++) {
celly = rightHere.getCell(loopy,1);
vaerdi = celly.getValue();
fed = celly.getFontWeight()
console.log(vaerdi & " - " & fed);
if (vaerdi != "" && fed != "bold") {
SpreadsheetApp.getActiveSpreadsheet().insertSheet(vaerdi);
var thisOne = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(vaerdi);
thisOne.deleteRows(500,499);
thisOne.deleteColumns(5, 20);
thisOne.getRange(1,1).setFormula("=ArrayFormula(FILTER('Individuelle varer'!A16:D30015;'Individuelle varer'!A16:A30015=" + "\"" + vaerdi + "\"" + "))");
}
}
}
There are multiple issues with your script, but the main one is that you never actually call the isBold() function in your 'if' statement.
if (value && format.isBold() == false) {
//do something
}
Because you omitted the parentheses in 'fed.isBold', the expression never evaluates to 'true'. 'isBold' (without the parentheses) is of type Object as it's a function.
There are other issues that prevent the script from running properly:
Not using the 'var' keyword to declare variables and polluting the global scope. As a result, all variables you declare within your 'for' loop are not private to your function. Instead, they are attached to the global object and are accessible outside the function. https://prntscr.com/kjd8s5
Not using the built-in debugger. Running the function is not debugging. You should set the breakpoints and click the debug button to execute your function step-by-step and examine all values as it's being executed.
Deleting the non-existent columns. When you create the new sheet, you call the deleteColums(). There are 26 columns in total. The 1st parameter is the starting column while the 2nd one specifies how many columns must be deleted. Starting from column 5 and telling the script to remove 23 columns will throw an exception. Always refer to the documentation to avoid such errors.
console.log doesn't exist within the context of the Script Editor. You are NOT executing the scripts inside your browser, so Browser object model is not available. Use Logger.log(). Again, this is detailed in the documentation.
Your formula is not formatted properly.
JS is a dynamically typed language that's not easy to get used to. If you don't do at least some research prior to writing code, you'll be in for a lot of pain.
I would like to evaluate the execution time of the processes contained in a javascript function, so I created a simple code that can evaluate this.
I would like your opinion as experts and know if I can use the code to evaluate the execution time of much more complex processes.
I tried it on IE, FF and Chrome, and Chrome processes were faster.
LINK TO THE EXPERIMENT
This is my Javascript:
/* Global Vars */
var inputSearch = document.getElementById('texto');
var buscando = document.getElementById('buscando');
/* TIME PERFORMANCE > Catching */
var timer = document.getElementById('timer');
var maxtimer = document.getElementById('maxtimer');
var qmaxtimer = document.getElementById('querymaxtimer');
/* Adding Event */
if(window.addEventListener)
{inputSearch.addEventListener('keyup',searching,false);}
else
{if(window.attachEvent){inputSearch.attachEvent('keyup',searching);}}
/* Test Function */
function searching(event,callback)
{
/* TIME PERFORMANCE */
/* >> Timer Ini */
var i = performance.now();
/* Do something........ */
var query = this.value;
buscando.textContent = query;
/* Finish something ......... */
/* TIME PERFORMANCE */
/* >> Timer End */
var f = performance.now();
/* >> TotalTime */
var totalTime = f - i;
var t;
if(totalTime < 1){
if(totalTime<=0.0001){t= ' Nanoseconds?';}
else{t= ' Microseconds';}
}else{t = ' Miliseconds'};
/* >> Max Time */
var mt = parseFloat(maxtimer.textContent);
if(totalTime > mt){
maxtimer.textContent = totalTime.toFixed(15) + t;
qmaxtimer.textContent=query;
}
/* >> Current Time */
timer.textContent = totalTime.toFixed(15) + t;
}
Thank you.
P.D.: Sorry for my bad english :-)
These kind of measurements can never be truly achieved via editing the code. First of all, it might be too difficult to just edit each and every method in your code to add those timing calls, secondly, you might be breaking stuff in the process.
I would suggest you to use the Performance tools present in both Firefox and Chrome, via these, you can measure time spent in various parts of your code along with the bottlenecks etc.
You can also see where your UI froze, and what code was super efficient.
Firefox : https://developer.mozilla.org/en-US/docs/Tools/Profiler
Chrome : https://developer.chrome.com/devtools/docs/timeline
I have the following function in javascript. It works in every browser except firefox. There seems to be some problems with the substring keyword in this browser.
function EvalMonthYear() {
var RawMonth = $.trim( $('#MonthList').val() );
var SpacePosition = RawMonth.lastIndexOf(' ') + 1;
var TheYear = $.trim(RawMonth.substring(SpacePosition, RawMonth.lenght));
var TheMonth = IndexOfMonth($.trim(RawMonth.substring(0, SpacePosition)));
};
MonthList contains a month/year string such as January 2011 or May 2009. The goal is to fill the variables TheYear and TheMonth so that it works in every browser.
If you've run into this problem and can think of a good solution this would be helpful.
Thanks.
Maybe you want to rewrite
RawMonth.lenght
as
RawMonth.length
Your original code works in Firefox 4b11 for me, so it might be an issue with 3.6. I'm guessing that your typo works in most browsers because RawMonth.lenght is undefined, which is similar to not passing in the argument. (It's a little different, if you inspect the arguments array.)
Try this:
function EvalMonthYear() {
var RawMonth = $.trim( $('#MonthList').val() );
var MonthYear = RawMonth.split(" ");
var TheYear = MonthYear[1];
var TheMonth = MonthYear[0];
};