I have an HTML file where I am uploading a local CSV file and once it has been uploaded I want to use the Google Charts API to generate a chart from that data however I am currently get this error
script.js:29 Uncaught TypeError: Cannot read property 'arrayToDataTable' of undefined
this points to the line in the JavaScript file
var dataDraw = new google.visualization.arrayToDataTable(data);
This is the index.html
<html>
<head>
<meta charset="utf-8" />
<title>CSV to chart</title>
</head>
<body>
<div id="inputs" class="clearfix">
<input type="file" id="files" name="files[]" multiple />
</div>
<hr />
<output id="list">
</output>
<hr />
<table id="contents" style="width:100%; height:400px;" border>
</table>
<div id="chart"></div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="http://evanplaice.github.io/jquery-csv/src/jquery.csv.min.js"></script>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script src="script.js"></script>
</body>
</html>
This is the Javascript file
$(document).ready(function() {
$('#files').bind('change', handleFileSelect);
});
function handleFileSelect(evt) {
var files = evt.target.files;
var file = files[0];
printTable(file);
}
function printTable(file) {
var reader = new FileReader();
reader.readAsText(file);
reader.onload = function(event){
var csv = event.target.result;
var data = $.csv.toArrays(csv);
google.load("visualization", "1", {packages:["corechart"]});
var dataDraw = new google.visualization.arrayToDataTable(data);
var view = new google.visualization.DataView(dataDraw);
view.setColumns([0,1]);
var options = {
title: "CSV Chart",
hAxis: {title: data.getColumnLabel(0), minValue: data.getColumnRange(0).min, maxValue: data.getColumnRange(0).max},
vAxis: {title: data.getColumnLabel(1), minValue: data.getColumnRange(1).min, maxValue: data.getColumnRange(1).max},
legend: 'none'
};
var chart = new google.visualization.ScatterChart(document.getElementById('chart'));
chart.draw(view, options);
console.log("array of data " + data)
var html = '';
for(var row in data) {
html += '<tr>\r\n';
for(var item in data[row]) {
html += '<td>' + data[row][item] + '</td>\r\n';
}
html += '</tr>\r\n';
}
$('#contents').html(html);
};
reader.onerror = function(){ alert('Unable to read ' + file.fileName); };
}
This is the CSV I am uploading.
Temp,Number
69,1
23.5,2
2.3,3
I am having trouble generating a chart from a local CSV file that I am uploading to use with the Google Charts API. I am quite new to using Google Charts so can someone help me understand what I am doing wrong?
Thanks.
there are a couple issues here...
first, the following load statement is incorrect, it is for the old version of google charts.
google.load("visualization", "1", {packages:["corechart"]});
it should be replaced with...
google.charts.load('current', {packages: ['corechart']});
see update library loader code for more info...
next, you need to wait until the load statement has finished,
before using any google chart components,
there are a few ways...
1) you can use the promise the load statement returns.
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
// place chart code here
});
2) use the callback property of the load statement.
google.charts.load('current', {
packages: ['corechart'],
callback: function () {
// place chart code here
}
});
3) use the setOnLoadCallback callback method.
google.charts.load('current', {packages: ['corechart']});
google.charts.setOnLoadCallback(function () {
// place chart code here
});
obviously, you can replace any of the above anonymous functions with a named one of your own, e.g.
google.charts.load('current', {
packages: ['corechart'],
callback: drawChart
});
note: arrayToDataTable is a static method, the new keyword is not needed...
var dataDraw = google.visualization.arrayToDataTable(data);
EDIT
if you receive the error...
Data for column(s) axis #0 cannot be of type String
this means the values for the y-axis columns are formatted as strings and not numbers. (columns > 0)
to correct the issue, add a calculated column to the view,
and parse the value as float.
var view = new google.visualization.DataView(dataDraw);
view.setColumns([0, {
calc: function (dt, row) {
return parseFloat(dt.getValue(row, 1));
},
type: 'number',
label: dataDraw.getColumnLabel(1)
}]);
Related
So I have a working google chart that uses a CSV file, parses the CSV data as a string into an array, and uses the array as the datatable.
I actually asked a question and answered it myself Here.
That link will show you a full chunk of code that I used in my full working website.
I intended to just pull the script from the test file and drop it into my website, but now that I've moved it over and included the scripts I needed, I'm getting an error as:
Type Error: $.csv is undefined
Here is the code where $.csv is being utilized (var arrayData), this is a function for drawing the chart
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="jquery.csv.min.js"></script>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript"> // load the visualisation API
google.load('visualization', '1', { packages: ['corechart', 'controls'] });
</script>
<script type="text/javascript">
function drawVisualization() {
$.get("Thornton.M2.csv", function(csvString) {
// transform the CSV string into a 2-dimensional array
var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar});
// this new DataTable object holds all the data
var data = new google.visualization.arrayToDataTable(arrayData);
// CAPACITY - En-route ATFM delay - YY - CHART
var crt_ertdlyYY = new google.visualization.ChartWrapper({
chartType: 'LineChart',
containerId: 'crt_ertdlyYY',
dataTable: data,
options:{
width: 450, height: 160,
title: 'EU-wide en-route ATFM delays (year to date)',
titleTextStyle : {color: 'grey', fontSize: 11},
}
});
crt_ertdlyYY.draw();
});
}
google.setOnLoadCallback(drawVisualization)
</script>
</head>
<body>
<div id="crt_ertdlyYY"></div>
</body>
This example works fully as you can see from the link I had posted before hand, if you wanted to test it. But now that I pull it into my main site the .csv calls do not recognize. I also have 2 other google charts on this page that still work properly so it's isolated to this issue. I'm very new to google charts and pretty confused here!
Here is code for one Google chart that I inserted into a raw HTML Block in WordPress Visual Composer -- chart ID name is 'chart_div1' -- this works on my WP webpage.
#
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([ ['X','Y'], [8,12], [6.5,7] ]);
var options = { };
var chart = new google.visualization.ScatterChart(document.getElementById('chart_div1'));
chart.draw(data, options);
}
</script>
<div id="chart_div1"></div>
#
Trying to add a second chart with chart id 'chart_div2' on the same page. The second chart in another raw HTML block, but the chart does not show up, only chart_div1 above does.
#
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([ ['XX','YY'], [18,112], [16.5,17] ]);
var options = { };
var chart = new google.visualization.ScatterChart(document.getElementById('chart_div2'));
chart.draw(data, options);
}
</script>
<div id="chart_div2"></div>
#
Have tried several variations and can't get any to work. I have also tried putting this code in shortcodes, and same issue.
Any suggestions?
If you look at the browser console, then you will notice an error message:
loader.js:146 Uncaught Error: google.charts.load() cannot be called more than once with version 45 or earlier.
And that's because of this function function call:
google.charts.load('current', {'packages':['corechart']});
Also, since you've already got the script loaded from gstatic, then you really don't need this more than once either:
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
A simple solution would be to load those resources first, and then each subsequent block:
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script>
google.charts.load('current', {'packages':['corechart']});
</script>
<script type="text/javascript">
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([ ['X','Y'], [8,12], [6.5,7] ]);
var options = { };
var chart = new google.visualization.ScatterChart(document.getElementById('chart_div1'));
chart.draw(data, options);
}
</script>
<div id="chart_div1"></div>
<hr/>
<script type="text/javascript">
google.charts.setOnLoadCallback(drawChart2);
function drawChart2() {
var data2 = google.visualization.arrayToDataTable([ ['XX','YY'], [18,112], [16.5,17] ]);
var options2 = { };
var chart2 = new google.visualization.ScatterChart(document.getElementById('chart_div2'));
chart2.draw(data2, options2);
}
</script>
<div id="chart_div2"></div>
But you may notice an efficiency/reusability conundrum arises. Do you really want to be loading those resources on every page, whether it has a chart or not? No. Do you want to keep track of whether you've already loaded the resources before adding an HTML block? No.
So to resolve this, you want to conditionally include those resources if they don't already exist. This way each HTML block is self-contained and ready for use anywhere without conflict with its peers.
To accomplish this, one way is to simply check if the google.charts object is defined, and only if not, then write to the document the script needed to include the resource.
If you're not using any other google objects, then you could just check google.
window.google || document.write('<script> ... </script>')
But that's unlikely because google has a lot of cool stuff. So to be more specific, you'll need to check if window.google.charts is defined, but you may notice that the above approach will throw a TypeError if you try to access a nested undefined object. So there's a slick workaround
(window.google || {}).charts || document.write('<script> ... </script>')
So when you put it all together, escaping tag slashes and newlines for readability, you get a nice contained reusable block like this:
<script>
(window.google || {}).charts || document.write('\
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"><\/script>\
<script> google.charts.load("current", {"packages":["corechart"]});<\/script>')
</script>
<script type="text/javascript">
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([ ['X','Y'], [8,12], [6.5,7] ]);
var options = { };
var chart = new google.visualization.ScatterChart(document.getElementById('chart_div1'));
chart.draw(data, options);
}
</script>
<div id="chart_div1"></div>
Which can happily coexist with other blocks on the same page. In any event, the first block loads the resources, and then each other block skips that and goes straight to rendering your data.
<script>
(window.google || {}).charts || document.write('\
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"><\/script>\
<script> google.charts.load("current", {"packages":["corechart"]});<\/script>')
</script>
<script type="text/javascript">
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([ ['X','Y'], [8,12], [6.5,7] ]);
var options = { };
var chart = new google.visualization.ScatterChart(document.getElementById('chart_div1'));
chart.draw(data, options);
}
</script>
<div id="chart_div1"></div>
<hr/>
<script>
(window.google || {}).charts || document.write('\
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"><\/script>\
<script> google.charts.load("current", {"packages":["corechart"]});<\/script>')
</script>
<script type="text/javascript">
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([ ['XX','YY'], [18,112], [16.5,17] ]);
var options = { };
var chart = new google.visualization.ScatterChart(document.getElementById('chart_div2'));
chart.draw(data, options);
}
</script>
<div id="chart_div2"></div>
You can try this:
google.charts.load('45', {packages: ['corechart']});
write "45" instead of "current", because "current" is still version "44". This worked for me.
i have this code and i want to change the static data with data from csv
the csv is look like:
GPA,Total Distance,id
3.27,22.0,20032202
2,64.0,20038107
2.81,10.0,20051566
2.33,66.5,20060382
i want to add the GPA in y axis
and total distance in the X axis
when i try to add code from d3 library it does not works
<html>
<head>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {
packages: ['corechart', 'line']
});
google.charts.setOnLoadCallback(drawBasic);
function drawBasic() {
var data = new google.visualization.DataTable();
data.addColumn('number', 'X');
data.addColumn('number', 'GPA');
data.addRows([
[0, 0],
[1, 10],
[2, 23],
[3, 17],
[4, 18],
]);
var options = {
hAxis: {
title: 'Total Distance'
},
vAxis: {
title: 'GPA'
}
};
var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));
chart.draw(data, options);
}
</script>
</head>
<body>
<div id="curve_chart" style="width: 900px; height: 500px"></div>
</body>
</html>
Here is the best answer I can come up with to help you.
In your question, you have to tackle different topics in javascript
get content of a local file in javascript
parse this content as a csv file (and make it a multidimensional array)
prepare the values to put in the chart
First, add the following two libraries : jQuery for the simplified ajax calls to the file and jquery-csv for an also simplified way to parse the content.
<script type="text/javascript" src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-csv/0.71/jquery.csv-0.71.min.js"></script>
Then, you have to re-route the charts callback : you have to point to a function that get asynchronously the file content (getFileContent in the example below).
Only in case of success, you can format the csv data into array.
And only then, you can serve the data to the chart by passing your formatted and sorted array to your drawbasic method.
Finally, you end up with that script
<script type="text/javascript">
google.charts.load('current', {
packages: ['corechart', 'line']
});
google.charts.setOnLoadCallback(getFileContent);
function getFileContent() {
var filePath = 'file:///path/to/file.csv';
// 1. Get local file content asynchronously
$.get(filePath, {}, function (data) {
console.log(arguments);
var lines = $.csv.toArrays(data); // 2. Parse the csv as a multidimensional array
var header = lines.shift(); // 3. Remove the header of the file
// 4. Sort the lines by the second column
lines.sort(function (a, b) {
if (a[1] === b[1]) {
return 0;
}
else {
return (a[1] < b[1]) ? -1 : 1;
}
});
// 5. Pass your lines to the draw method
drawBasic(lines);
}, 'text')
.fail(function () {
console.log(arguments);
})
;
}
function drawBasic(lines) {
var data = new google.visualization.DataTable();
data.addColumn('number', 'X');
data.addColumn('number', 'GPA');
for (i = 0; i < lines.length; i++) {
// 6. Don't forget to parse as float the numbers in the array, they are strings at this point
// You'll get a 'Type mismatch. Value 3,27 does not match type number' error if you don't
var xValue = parseFloat(lines[i][1]);
var yValue = parseFloat(lines[i][0]);
data.addRow([xValue, yValue]);
}
var options = {
hAxis: {
title: 'Total Distance'
},
vAxis: {
title: 'GPA'
}
};
var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));
chart.draw(data, options);
}
</script>
Don't forget to change the filepath in getFileContent, preceded by file://
I give credit to the answers in SO that helped me create this answer:
Javascript - read local text file
How to sort 2 dimensional array by column value?
Side note
In different conditions, it's much more common if you get csv (or, better with Javascript, JSON) via an HTTP call when working with Javascript to display data.
Local file reading may be reserved for server-side processing, that make this content available through HTTP.
I am in a trouble that the stacked chart in the left side runs well with JSFiddle. However, that code did not run with my ASP.NET. Here are the error and code. Please let me know how to address this problem.
You called the draw() method with the wrong type of data rather than a DataTable or DataView×
JSFIDDLE: http://jsfiddle.net/huydq91/pu5wbgpv/3/
<div id="div_id"></div>
<script type='text/javascript' src='https://www.google.com/jsapi?ext.js'>
</script><script type=text/javascript>
google.load('visualization', '1.1', {packages:['bar']});
google.setOnLoadCallback(drawChart);
function drawChart(){
var data = google.visualization.arrayToDataTable([['Month','Target Shipment','Actual Shipment'],['JAN',1053355,482899],['FEB',322087,468206],]);
var view = new google.visualization.DataView(data);
var options = { };
var chart = new google.charts.Bar(document.getElementById('div_id'));
chart.draw(view, google.charts.Bar.convertOptions(options));
}
</script>
Here is my code to create google chart from csv data. ANd also no error. But even chart does not appear.
Here is the documentation for which works: http://economistry.com/2013/07/easy-data-visualization-with-google-charts-and-a-csv/
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" type="text/javascript"></script>
<script src="http://jquery-csv.googlecode.com/files/jquery.csv-0.71.js"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
// grab the CSV
$.get("Chart1-data.csv", function(csvString) {
// transform the CSV string into a 2-dimensional array
var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar});
alert(arrayData);
// this new DataTable object holds all the data
var data = new google.visualization.arrayToDataTable(arrayData);
// this view can select a subset of the data at a time
var view = new google.visualization.DataView(data);
view.setColumns([0,1]);
// set chart options
var options = {
title: "A Chart from a CSV!",
hAxis: {title: data.getColumnLabel(0), minValue: data.getColumnRange(0).min, maxValue: data.getColumnRange(0).max},
vAxis: {title: data.getColumnLabel(1), minValue: data.getColumnRange(1).min, maxValue: data.getColumnRange(1).max},
legend: 'none'
};
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
});
}
</script>
</head>
<body>
<div id="piechart" style="width: 900px; height: 500px;"></div>
</body>
</html>
Chart1-data.csv
Category,
A,34
B,23
C,14
D,57
E,18
Other,5
Do I missing anything in the code?
Good news: Your Code is fine! Your CSV file is the bottleneck.
Column names can't be null, means Category, => Category,''
No additional line breaks between data rows, means
A,34
B,23
=>
A,34
B,23
Result:
Category,''
A,34
B,23
C,14
D,57
E,18
Other,5
That is all! :)
There doesn't seem any kind of problem with this Google chart code snippet.
Though in browser console there are some Uncaught JavaScript errors.
Most importantly there is
" Uncaught null "error which is in reference to blank space after "Category" so Category, ' ' should work fine