highchart - average value of serie for shown period - average

Using Highstock, I've a serie timestamp / value
with different rangeselectors (hour, day, week, month,...) or zoomX
I want to display the average value for the displayed time period.
Now, I can compute the average of the overall series data:
for (i = 0; i < chart.series[0].yData.length; i++) {
total += chart.series[0].yData[i];
}
seriesAvg = (total / chart.series[0].yData.length).toFixed(4); // fix decimal to 4 places
$('#report1').html('<b>Average:</b>: '+ seriesAvg);
How to compute the average only on the displayed datapoints ? And to refresh automatically after zoom ?
Thank you

Use series.processedYData or series.points.

I implemented the same but I notice that processedYdata is loading also one data more than the one showed at the screen.
for that reason i added one additional command to remove the first processedYData:
processedYData.splice(0, 1);
below is the final result of the function
function showStat(objHighStockchart) {
for (j = 0; j < (json_data.length); j++) {
var seriesAvg = 0,
processedYData = objHighStockchart.series[j].processedYData;
processedYData.splice(0, 1);
var seriesMin = Math.min.apply(null, processedYData);
var seriesMax = Math.max.apply(null, processedYData);
var i = 0
var total = 0;
console.log(processedYData);
for (i = 1; i < processedYData.length; i++) {
total += processedYData[i];
}
seriesAvg = (total / processedYData.length).toFixed(2); // fix decimal to 4 places
$('#container_stat' + j).html(
'<br>Statistics for ' + objHighStockchart.series[j].name + '<br>' +
'Total: ' + total + ' logs<br>' +
'Min: ' + seriesMin + ' logs<br>' +
'Avg: ' + seriesAvg + ' logs<br>' +
'Max: ' + seriesMax + ' logs<br>'
+ '---' + processedYData
);
}
};

Related

send email reminders based on date of expiry and a status in another column

A bit new at this I hope someone can help me :)
I have a list of properties in Col 24 and a "room status" in Col 35 and a contract expiry date in Col 37.
I need to send email reminder to myself 30 days before expiry to send email to the person and 27 days before expiry a reminder email to myself to follow up if I have response. I have this script ready but need it to trigger only if the status is "NO RENEW" in Col 35.
Below is the script I have:
function emailAlert(){
// 27 days from now
var twoWeeksFromToday = new Date();
twoWeeksFromToday.setDate(twoWeeksFromToday.getDate() + 27);
var twoWeeksMonth = twoWeeksFromToday.getMonth() + 1;
var twoWeeksDay = twoWeeksFromToday.getDate();
var twoWeeksYear = twoWeeksFromToday.getFullYear();
// 1 month from now
var newToday = new Date()
var oneMonthFromToday = new Date(newToday.setMonth(newToday.getMonth()+1));
var oneMonthMonth = oneMonthFromToday.getMonth() + 1;
var oneMonthDay = oneMonthFromToday.getDate();
var oneMonthYear = oneMonthFromToday.getFullYear();
// getting data from spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("dash");
var startRow = 3; // First row of data to process
var numRows = 4; // Number of rows to process
var dataRange = sheet.getRange(startRow, 24, numRows, 41);
var data = dataRange.getValues();
//looping through all of the rows
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var expireDateFormat = Utilities.formatDate(
new Date(row[13]),
'ET',
'dd/MM/yyyy'
);
//expiration date information
var expireDateMonth = new Date(row[13]).getMonth() + 1;
var expireDateDay = new Date(row[13]).getDate();
var expireDateYear = new Date(row[13]).getFullYear();
//checking for expiry date 27 days from now
Logger.log('2 weeks month, expire month' + twoWeeksMonth + expireDateMonth);
if (
expireDateMonth === twoWeeksMonth &&
expireDateDay === twoWeeksDay &&
expireDateYear === twoWeeksYear
) {
var subject =
row[11] + // Status
'\n' +
' - ' +
'\n' +
row[0] + // Address
'\n' +
' - ' +
'\n' +
'Did we get a response ? ';
MailApp.sendEmail('hello#gmail.com', subject, message);
Logger.log('2 weeks from now');
}
//checking for expiry date 1 month from now
if (
expireDateMonth === oneMonthMonth &&
expireDateDay === oneMonthDay &&
expireDateYear === oneMonthYear
) {
var subject =
row[11] + // Status
'\n' +
' - ' +
'\n' +
row[0] + // Address
'\n' +
' - ' +
'\n' +
'CONTRACT ENDING ';
MailApp.sendEmail('hello#gmail.com', subject, message);
Logger.log('1 month from now');
}
}
}

How can I extract data from a specific column in a table, then assign it to array of variables using loop?

I want to extract all the data from column B, then assign it to variables using for loop. I'm using this code, but it is looping wrong.
Ex:
Total row count = 10
Variable 1 to variable 10 are having the same data; then it will loop 10x. So the final values of array variables are all the same :(
for (int getAllAccts = 1; getAllAccts <= TotalRowCount.size(); getAllAccts++) {
try{
String[] accName = new String[TotalRowCount.size()]
for(int accNameCount=1; accNameCount < TotalRowCount.size(); accNameCount++){
accName[accNameCount] = driver.findElement(By.xpath("//*[#id='tbl-table1']/tbody/tr[" + (getAllAccts)+ "]/td[2]/a")).getText();
log.logWarning('Customer Name' + accNameCount + ' ' + accName[accNameCount])
}
}
catch(org.openqa.selenium.StaleElementReferenceException ex) {
String[] accName
for(int accNameCount=1; accNameCount < TotalRowCount.size(); accNameCount++){
accName[accNameCount] = driver.findElement(By.xpath("//*[#id='tbl-table1']/tbody/tr[" + (getAllAccts)+ "]/td[2]/a")).getText();
log.logWarning('Customer Name' + accNameCount + ' ' + accName[accNameCount])
}
}
}
The getAllAccts is always the same inside of the inner (nested) for loop. So all the accNames will have the same value.
Change
accName[accNameCount] = driver.findElement(By.xpath("//*[#id='tbl-table1']/tbody/tr[" + (getAllAccts)+ "]/td[2]/a")).getText();
to
accName[accNameCount] = driver.findElement(By.xpath("//*[#id='tbl-table1']/tbody/tr[" + (accNameCount)+ "]/td[2]/a")).getText();

Issues with naming ranges for charts within the Google Spreadsheet Script

I've been trying for days to create charts with an intelligent range, that differs when the data in the google spreadsheet is updated. However i succeeded doing so, i can't get the .setOption aspect to work. I want for example, a title, description etc with the chart. But this is not the main issue since i can insert there by hand.
More important however is the range name, because there isn't when i use the script. So, within the chart it is not possible to see what each column represents, and i really want to fix that. I tried to use the .setNamedRange() aspects, but that is not working.
Someone who can help me with that?
function check() {
var sheet = SpreadsheetApp.getActiveSheet();
var end = sheet.getLastRow();
var start = (end - 5);
var endnew = (end - 4);
var startnew = (end - 6);
if(sheet.getCharts().length == 0){
Logger.log("Er is geen grafiek");
var chartBuilder = sheet.newChart()
.asColumnChart().setStacked()
.addRange(sheet.getRange("A" + startnew + ":" + "A" + endnew)) // should have a name
.addRange(sheet.getRange("B" + startnew + ":" + "B" + endnew)) // should have a name
.addRange(sheet.getRange("E" + startnew + ":" + "E" + endnew)) //should have a name
.setOption('title', 'Effectief gebruik kantoorruimte') //not working
.setPosition(10, 10, 0, 0)
var chart = chartBuilder.build();
sheet.insertChart(chart);
}
else{
Logger.log("Er is wel een grafiek");
var charts = sheet.getCharts();
for (var i in charts) {
var chart = charts[i];
var ranges = chart.getRanges();
var builder = chart.modify();
for (var j in ranges) {
var range = ranges[j];
builder.removeRange(range);
builder
.addRange(sheet.getRange("A" + (start) + ":" + "A" + end)) //should have a name
.addRange(sheet.getRange("B" + (start) + ":" + "B" + end)) //should have a name
.addRange(sheet.getRange("E" + (start) + ":" + "E" + end)) // should have a name
.setOption('title', 'Effectief gebruik kantoorruimte')
.build();
sheet.updateChart(builder.build());
}
}
}
}
I'm assuming that this code is the issue?
builder
.addRange(sheet.getRange("A" + (start) + ":" + "A" + end))
Maybe try using the JavaScript toString() method to make sure that your text formula is working.
.addRange(sheet.getRange("A" + start.toString() + ":" + "A" + end.toString()))
There is a different format that you can use:
getRange(row, column, numRows, numColumns)
So, it would be:
getRange(start, 1, 1, numColumns)
That starts on row "start" in column A. It gets one row of data, and how ever many number of columns.

Dates (Duration) in Google Sheets Script

I have a Google Sheet with three columns:
- Date and time (timestamp)
- Duration
- Description
I have an script that when I write something in 'Description', inserts in 'Date' the date and time at this moment, and the 'Duration':
function onEdit(e) {
if(e.source.getActiveSheet().getName() == "Sheet2" ) {
var col = e.source.getActiveCell().getColumn();
if(col == 3 ) {
// I'm in column three
var cellTimeStamp = e.range.offset(0,-2); // First column of the same row
var cellTimeDiff = e.range.offset(0,-1); // Second column of the same row
var cellTimePrev = e.range.offset(-1,-2); // First column of the previous row
var timeTimeStamp = new Date();
var iniTime = cellTimePrev.getValue().getTime();
var finTime = timeTimeStamp.getTime() ;
var timeDiff = String(finTime - iniTime) ;
cellTimeStamp.setValue(timeTimeStamp);
cellTimeDiff.setValue(timeDiff); // [***]
}
}
}
When this executes (as an event) in the column of 'Duration' there is NOT something in the format of 'HH:mm:ss'.
But if I remove the last line in this script and adds this formulae in the sheet:
=A3-A2 (in row 3)
=A4-A3 (in row 4)
...
then it works ok.
I'd like to know how to meet the same result but with a script.
Thanks in advance.
timeDiff is the result of finTime - iniTime which are both native date object values, which means we have milliseconds .
converting that in hh:mm:ss is simple math... : 60 seconds in a minute and 60 minutes in an hour...
A simple code could be like this :
function msToTime(s) {
var ms = s % 1000;
s = (s - ms) / 1000;
var secs = s % 60;
s = (s - secs) / 60;
var mins = s % 60;
var hrs = (s - mins) / 60;
return hrs + ':' + mins + ':' + secs; // milliSecs are not shown but you can use ms if needed
}
If you prefer formating your string more conventionally (2 digits for each value) don't forget you can use Utilities.formatString() to do so.
example below :
return Utilities.formatString("%02d",hrs) + ':' + Utilities.formatString("%02d",mins) + ':' + Utilities.formatString("%02d",secs);
EDIT
Following your comment :
Spreadsheets are smarter than you think, you can try the code below and you will see that the result is actually a time value.(check by double clicking on it)
function test() {
var sh = SpreadsheetApp.getActiveSheet();
var t1 = sh.getRange('a1').getValue().getTime();
var t2 = sh.getRange('b1').getValue().getTime();
sh.getRange('c1').setValue(msToTime(t1-t2)).setNumberFormat('hh:mm:ss');
}
function msToTime(s) {
var ms = s % 1000;
s = (s - ms) / 1000;
var secs = s % 60;
s = (s - secs) / 60;
var mins = s % 60;
var hrs = (s - mins) / 60;
return hrs + ':' + mins + ':' + secs; // milliSecs are not shown but you can use ms if needed
}
note that setNumberFormat('hh:mm:ss') is optional, it's only there to force the spreadsheet to display hour:min:sec format but automatic mode works as well.

programming a range of data : Matlab

I have this program, something related with statistic.
maximo = max(muestra);
minimo = min(muestra);
rango = maximo - minimo;
num_intervalo = round(1 + 3.322*log(length(muestra)));
amplitud = rango/num_intervalo;
rango_intervalo = [];
for i=1 : num_intervalo + 1
if i == 1
rango_intervalo(i: num_intervalo + 1) = minimo;
else
rango_intervalo(i: num_intervalo + 1) = rango_tabulado(i) + amplitud;
end
if i == num_intervalo + 1
rango_intervalo(i: num_intervalo + 1) = maximo;
end
end
rango_intervalo = rango_intervalo';
the intention is to create nine (or k intervals) intervals, where each interval has it ranges:
[1.580 - 2.587]
[2.587 - 3.594]
.
.
[9.636 - 10.650]
With code that I've programmed, it is resulting in 10 data not nine as per the intention.
Any idea, the improve this code?
Thanks.
How about:
intervals = linspace(minimo, maximo, num_intervalo + 1 );
intervals = [ intervals(1:end-1); intervals(2:end) ]';