I have an area chart and on the vAxis I'd like the labels to read # hrs. For the data below, the Total Time Spent column is an integer of total minutes. I'd like the vAxis label to show as # hrs. So for example, the first row would read 31.3 hrs. I'm not finding a way to create a custom formatter for that where I can convert the minutes into decimal hours and append the "hrs" suffix. Any ideas? Thanks.
var data = google.visualization.arrayToDataTable([
['Date', 'Deals Processed', 'Total Time Spent'],
[ '12/17/2020', 4, 1878],
[ '12/18/2020', 3, 290],
[ '12/21/2020', 8, 2772],
[ '12/22/2020', 6, 1084],
[ '12/23/2020', 4, 1175]
]);
we can customize the y-axis labels by providing our own ticks.
for each tick, we can use object notation, and provide the value (v:) and formatted value (f:)
{v: 1878, f: '31.3 hrs'}
we can also customize the tooltip when hovering the point by using the same approach,
in the data table.
['12/17/2020', 4, {v: 1878, f: '31.3 hrs'}],
or we can set the formatted value after the data table has been created.
data.setFormattedValue(0, 2, (1878 / 60).toFixed(1) + ' hrs');
to build the ticks, we can use data table method --> getColumnRange(columnIndex)
this will return an object with properties for min & max
which we can use to build our ticks array.
// build y-axis labels
var range = data.getColumnRange(2);
var max = Math.ceil(range.max / 100) * 100;
var ticks = [];
for (var i = 0; i <= max + 600; i = i + 600) {
ticks.push({
v: i,
f: (i / 60).toFixed(0) + ' hrs'
});
}
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['Date', 'Deals Processed', 'Total Time Spent'],
[ '12/17/2020', 4, 1878],
[ '12/18/2020', 3, 290],
[ '12/21/2020', 8, 2772],
[ '12/22/2020', 6, 1084],
[ '12/23/2020', 4, 1175]
]);
// format tooltip
for (var i = 0; i < data.getNumberOfRows(); i++) {
var minutes = data.getValue(i, 2);
data.setFormattedValue(i, 2, (minutes / 60).toFixed(1) + ' hrs');
}
// build y-axis labels
var range = data.getColumnRange(2);
var max = Math.ceil(range.max / 100) * 100;
var ticks = [];
for (var i = 0; i <= max + 600; i = i + 600) {
ticks.push({
v: i,
f: (i / 60).toFixed(0) + ' hrs'
});
}
var options = {
height: 400,
vAxis: {
ticks: ticks
}
};
var chart = new google.visualization.AreaChart(document.getElementById('chart_div'));
chart.draw(data, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
Related
I have two different list values i want get the corresponding one list between value to other list between values. Please look at the list below. Here i have 1st list value of 11 and 15 here i need to find the between values of 12, 13 and 15.
11 value =22
15 value =30
List<double> list1 =[11, 15];
List<double> list2 =[22, 30];
If I understand correct you need the interpolation function to generate values between 2 points:
List<double> interpolate(double start, double end, int count) {
if (count < 2) {
throw Exception("interpolate: illegal count!");
}
final array = List.generate(count + 1, (index) => 0.0);
for (int i = 0; i <= count; ++i) {
array[i] = start + i * (end - start) / count;
}
return array;
}
Usage:
void main() {
final input = [1.0, 15.0];
print(interpolate(input.first, input.last, 4));
}
Result:
[1.0, 4.5, 8.0, 11.5, 15.0]
I keep track of trading data in a private spreadsheet and, once a trade is closed, I push a button to run some AppsScript to copy the data across to a publicly visible spreadsheet. It all works well except the following point. I put the dates and times a trade is opened in two different columns and the same with the dates and times trades are closed. When I copy the dates across to the target spreadsheet, instead of "10 Jul 2022" it is showing as "10/07/2022 02:00:00". When I sort the spreadsheet on these date and time columns, this can often produce unwated results. What I want is for the date column to just display as "10 Jul 2022" and for that data to recognized as a date for sorting purposes. Is that possible?
function updatePublicSheet(){
var coinBought;
var dateBought;
var timeBought;
var priceBought;
var dateSold;
var timeSold;
var priceSold;
var sLrIndex;
var tLrIndex;
var sss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1cBGpD0nUqCGtQqq78svw4fxA4ZgwBqV2yzIbgY1tY2o/edit#gid=1107419239");
var sSheet = sss.getSheetByName('SS Open Trades');
var sRng = sSheet.getRange("H3:J").getValues();
// Find last entry in columns H, I or J in the Open Trades sheet
for (var i = sRng.length-1;i>=0;i--){
var sLrIndex = i;
if (!sRng[i].every(function(c){return c == "";})){
break;
}
}
Logger.log("Last source row is %s", sLrIndex + 3);
// Check that the closed information has been added to all columns
// index 8 = 8th column = H = dateSold
// index 9 = 9th column = I = timeSold
// index 10 = 10th column = J = priceSold
if ((sSheet.getRange((sLrIndex + 3),8).getValue().length) == 0 ||
(sSheet.getRange((sLrIndex + 3),9).getValue().length) == 0 ||
(sSheet.getRange((sLrIndex + 3),10).getValue().length) == 0){
SpreadsheetApp.getUi().alert("You cannot process partially completed entries");
return;
}
// If there is a complete closed entry, copy the values to the variables
if (sLrIndex > 0)
{
coinBought = sSheet.getRange((sLrIndex + 3),2).getValue();
dateBought = toUtcString(sSheet.getRange((sLrIndex + 3),4).getValue());
timeBought = sSheet.getRange((sLrIndex + 3),5).getValue();
priceBought = sSheet.getRange((sLrIndex + 3),6).getValue();
dateSold = toUtcString(sSheet.getRange((sLrIndex + 3),8).getValue());
timeSold = sSheet.getRange((sLrIndex + 3),9).getValue();
priceSold = sSheet.getRange((sLrIndex + 3),10).getValue();
//Logger.log(priceSold);
}
else
{
SpreadsheetApp.getUi().alert("There are no completed entries to process");
return;
}
var tss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1umkTCr95FZUrZzv0e_ZDD9QZYiiYuH1fJohPYQzNE9Q/edit#gid=1644116137");
var tSheet = tss.getSheetByName('Trade Tracker');
var tRng = tSheet.getRange("B3:J").getValues();
// Create a new row at Row 5 on the Trades Tracker Sheet
tSheet.insertRows(5, 1);//shift all rows down by one from row 5
// Copy values from row 4 to row 5, including the formulae
var tRange = tSheet.getRange(4, 1, 1, 26);
tRange.copyTo(tSheet.getRange(5, 1, 1, 26), {contentsOnly:false});
// Populate row 4, first 7 table columns, from the variables
//Logger.log(coinBought);
tSheet.getRange(4,2).setValue(coinBought);
tSheet.getRange(4,3).setValue(dateBought);
tSheet.getRange(4,4).setValue(timeBought);
tSheet.getRange(4,5).setValue(priceBought);
tSheet.getRange(4,6).setValue(dateSold);
tSheet.getRange(4,7).setValue(timeSold);
tSheet.getRange(4,8).setValue(priceSold);
// Format the cells with dates and times
tSheet.getRange(4,3).setNumberFormat("dd MMM yyyy"); // Short Date
tSheet.getRange(4,4).setNumberFormat("HH:mm"); // Short Time
tSheet.getRange(4,6).setNumberFormat("dd MMM yyyy"); // Short Date
tSheet.getRange(4,7).setNumberFormat("HH:mm"); // Short Time
// Sort the sheet by date/time closed
// Find last entry in Trade Tracker sheet
for (var i = tRng.length-1;i>=0;i--){
var tLrIndex = i;
if (!tRng[i].every(function(c){return c == "";})){
break;
}
}
Logger.log("Last target row is %s", tLrIndex + 4);
var tRange = tSheet.getRange(4, 2, tLrIndex + 4, 8)
tRange.sort([{column: 6, ascending: false}, {column: 7, ascending: false}]);
// On the source sheet, delete the row just copied and add another blank row at the bottom of the table
sSheet.deleteRows(sLrIndex + 3, 1);
var rowLast = sSheet.getLastRow();
sSheet.insertRowAfter(rowLast - 1);
// Copy values from the new last row to the new previous to last row, including the formulae
var sRange = sSheet.getRange(rowLast + 1, 1, 1, 10);
sRange.copyTo(sSheet.getRange(rowLast - 1, 1, 1, 10), {contentsOnly:false});
SpreadsheetApp.getUi().alert("One completed entry processed");
}
How make a possible to display 2 values in 1 column (split red and yellow columns in one)?
I have plan of sold and value of sold ordered by months.
For ex:
Jan -
plan:100, sold:80
Feb -
plan:150, sold:150
So i want to see 2(4 columns in mind, second value should overlap first value) columns:
100 80
150 150
first column will be colored in two colors because sold value less then plan (100/80 )
second column will be colored in one color(yellow), because second column overlap first value 150/150
isStacked: true doesn't overlay first column
Thanks for advise.
Code that i use JsFiddle and what I need
google.load('visualization', '1', {packages: ['corechart', 'bar']});
google.setOnLoadCallback(drawStacked);
function drawStacked() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Date');
data.addColumn('number', 'Plan');
data.addColumn('number', 'Sold');
data.addRows([
['Jan, 2015', 100, 80],
['Feb, 2015', 150, 150],
]);
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
chart.draw(data, {
colors: ['red', 'yellow'],
width: 600,
height: 175,
title: 'Total',
legend: 'none',
});
}
I was just doing a pie sample so I set up a diff bar sample with your data. It has our PDF print code in it but shows what I think you want (except the color):
http://jsfiddle.net/1og99wL1/
function drawChart() {
var oldData = new google.visualization.DataTable();
oldData.addColumn('string', 'Date');
oldData.addColumn('number', 'Plan');
oldData.addRows([
['Jan, 2015', 100],
['Feb, 2015', 150],
]);
var newData = new google.visualization.DataTable();
newData.addColumn('string', 'Date');
newData.addColumn('number', 'Sold');
newData.addRows([
['Jan, 2015', 80],
['Feb, 2015', 150],
]);
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
var data = chart.computeDiff(oldData, newData);
var options = {
colors: ['yellow'],
diff: {
oldData: { opacity: 1, color: '#ff0000' },
newData: { opacity: 1, widthFactor: 1 }
},
legend: 'none',
width: 600
};
<!-- For the PDF print -->
google.visualization.events.addListener(chart, 'ready', AddNamespace);
chart.draw(data, options);
}
Result:
Comments:
You must use "oldData" and "newData" as the names for the datasets. You cannot just choose arbitrary names. If you do, the chart will draw but the "diff" option will not work (crazy, must be burned into the code). The color must be set like below with one color set in "colors" option and the other set in "diff" option.
I have the below code for drawing a JQPlot bar chart. Now I want all the bars to be at the same height and display the colors in percentages. Couldn't seem to find an example. Please help!!
Current graph
Expected result
var s3 = [11, 28, 22, 47, 11, 11];
var s1 = [0, 6, 3, 0, 0, 0];
var s2 = [1, 0, 3, 0, 0, 0];
var dataArray = [s3, s1, s2];
var ticks = ['John', 'Tumm', 'Wen', 'Ken', 'Dolly'];
var options = {
title: 'Title ',
stackSeries: true,
seriesColors: ["#eb4b3d", "#ffc800", "#009149"],
seriesDefaults: {
renderer: $.jqplot.BarRenderer,
pointLabels: {
show: true
},
rendererOptions: {
barWidth: 25,
varyBarColor: true,
},
},
axes: {
xaxis: {
// renderer: $.jqplot.CategoryAxisRenderer,
//
renderer: $.jqplot.CategoryAxisRenderer,
ticks: ticks,
},
yaxis: {
//autoscale: true,
//label: 'Application Count',
min: 0,
tickInterval: 5,
max: 50
}
},
axesDefaults: {
tickRenderer: $.jqplot.CanvasAxisTickRenderer,
tickOptions: {
angle: -30,
fontSize: '10pt'
}
}
};
var plot = $.jqplot('chartDivId', dataArray, options);
I resolved this issue recently and thought I would share a description of how I solved the problem. I managed to produce a "normalized" stacked bar chart; a chart where all the bars are the same size with data of different scales. Excel of course produces this easily. Turns out, so does jqPlot; there just are no good examples.
The solution is to structure the chart data so that each of the inner-most elements contain three items (i.e. [1, 2, 3]) rather than the usual 2 ([1, 2]). The 1st item is the series number, the 2nd item is the plot point, which jqPlot assumes will also be the label for the plot point. However, this behavior is over ridden by the third item, a label which can be different from the data. So in my case the structure is: ([series], [bar percent], [data]).
For example, if my first bar has two stacks, the 1st stack is 97% and the 2nd stack is 3%, yet the data displayed can be 12 and 456 (12 + 456 = 468 >>> 12/468 = 2.56% and 456/468 = 97.43% [you could also just subtract the first from 100%])
The jqPlot documentation does hint at this but it's not very explicit and I spent an entire day trying to figure this out myself. Read carefully example #2: http://www.jqplot.com/tests/point-labels.php. That's what cracked it for me. :)
Cheers,
Rich
The problem is resolved now!! Its all about supplying the data though arrays(S1,S2,S3) in percentages!!
I am using the following function to add all of my line totals together. Each of the totals will be a decimal number such as 23.45 . When the user enters any qty into any of text input boxes it should fire the function, but all I'm getting at the moment in grandtotal is NaN, who's nan is it and why is she messing with my script?
By the way, each of the linetotals is a span, which is filled with the line total calculation once a quantity is entered into the qty text box.
So basically, user comes along, selects a price from the line one drop down, so lets say 20.00 , they then enter the quantity into the text box qty, let's say 2, jQuery then multiplies qty by priceeach and output into the span with the id linetotal1. What I want to do is add all of the linetotals together for a grand total, but lets say if they don't enter anything into line 2, linetotal2, 3, 4, 5 will them be empty.
<script>
$(document).ready(function () {
$('input').on('keyup', function () {
linetotal1 = $('#linetotal1').text(),
linetotal2 = $('#linetotal2').text(),
linetotal3 = $('#linetotal3').text(),
linetotal4 = $('#linetotal4').text(),
linetotal5 = $('#linetotal5').text(),
grandtotal = parseFloat(linetotal1) + parseFloat(linetotal2) + parseFloat(linetotal3) + parseFloat(linetotal4) + parseFloat(linetotal5);
$('#grandtotal').text(grandtotal);
}); });
</script>
You could just loop from 1-5, and have the value default to 0 if it's a blank string:
var rawValue, grandtotal = 0;
for(var i=1; i<6; i++)
{
rawValue = $.trim($('#linetotal' + i).text());
if(rawValue == '') rawValue = 0;
grandtotal += parseFloat(rawValue);
}
$('#grandtotal').text(grandtotal);
jsFiddle Demo
If you wanted to do something a bit fancier with jQuery you could select each of the spans based on the ID starting with linetotal. This would work if you added more spans, where as with the for loop, you'd have to update the count. It would be better if the spans all had a common class, which you could use to easily select them.
var rawValue, grandtotal = 0;
$('span[id^="linetotal"]').each(function(i, elem){
rawValue = $.trim($(this).text());
if(rawValue == '') rawValue = 0;
grandtotal += parseFloat(rawValue);
});
$('#grandtotal').text(grandtotal);
jsFiddle Demo
You should do this by loop, i have done this before for my client check if my code helps you
var disValue = new Array();
var this_size = document.getElementsByName("myVal").length;
sum = 0;
for (i=0; i<this_size; i++)
{
disValue[i] = document.getElementsByName("myVal")[i].value;
}
for (i=0; i<this_size; i++)
{
sum = parseFloat(sum)+ parseFloat(disValue[i]);
}
if (sum != 0) {
document.getElementById("disc_test").innerHTML="<?php echo $this->__('You are saving') ?> "+sum +" <?php echo $this->__('on this order') ?>!";
}
ignore php tags :)