How to create chart in google sheets with javascript? - javascript

I am using javascript to create Google-sheets-document with user data. The document is saved on the user's Drive.
I can't figure out how to make a graph from the data i have inserted. I am using vanilla javascript with the Google sheets API.
It would probably look something like this:
function createGraph() {
gapi.client.sheets.graph
.create({
properties: {
type(?): 'Pie'
spreadsheetid: //some id
range: 'A1:A10'
},
})
}
EDIT: To specify, i want to insert the graph to the sheets-document that i have created, not to the website.

If you want to add the chart to your spreadsheet, you can use Sheets API's AddChartRequest, as part of the spreadsheets.batchUpdate method.
Code snippet:
On broad terms, your request would look like this (check the reference below in order to build the request body in detail):
const payload = {
"requests": [
{
"addChart": {
"chart": {
"spec": { // Chart type, range source, etc.
"pieChart": { // Pie chart specification
// object (PieChartSpec)
}
// rest of ChartSpec properties
},
"position": { // Where the chart will be located
// object (EmbeddedObjectPosition)
}
}
}
}
]
}
const params = {
spreadsheetId = "YOUR-SPREADSHEET-ID",
body = payload
}
gapi.client.sheets.spreadsheets.batchUpdate(params);
Render chart in browsers and mobile devices:
In case you just wanted to render the chart in a browser, but not add it to your spreadsheet, you would use Google Charts (see Visualization: Pie Chart, for example).
Reference:
Sheets API > Charts
EmbeddedChart
ChartSpec
EmbeddedObjectPosition
PieChartSpec

Refer this example
<html>
<head>
<!--Load the AJAX API-->
<script
type="text/javascript"
src="https://www.gstatic.com/charts/loader.js"
></script>
<script type="text/javascript">
var data;
var chart;
// Load the Visualization API and the piechart package.
google.charts.load("current", { packages: ["corechart"] });
// Set a callback to run when the Google Visualization API is loaded.
google.charts.setOnLoadCallback(drawChart);
// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
function drawChart() {
// Create our data table.
data = new google.visualization.DataTable();
data.addColumn("string", "Topping");
data.addColumn("number", "Slices");
data.addRows([
["Mushrooms", 3],
["Onions", 1],
["Olives", 1],
["Zucchini", 1],
["Pepperoni", 2]
]);
// Set chart options
var options = {
title: "How Much Pizza I Ate Last Night",
width: 400,
height: 300
};
// Instantiate and draw our chart, passing in some options.
chart = new google.visualization.PieChart(
document.getElementById("chart_div")
);
chart.draw(data, options);
}
</script>
</head>
<body>
<!--Div that will hold the pie chart-->
<div id="chart_div" style="width: 400; height: 300;"></div>
</body>
</html>
Referred from
https://developers.google.com/chart/interactive/docs/drawing_charts

I solved it. Thanks for the help! This worked for me.
function createGraphv2(spreadsheetIdGraph, endIndex) {
var params = {
// The spreadsheet to apply the updates to.
spreadsheetId: spreadsheetIdGraph, // TODO: Update placeholder value.
};
var batchUpdateSpreadsheetRequestBody = {
// A list of updates to apply to the spreadsheet.
// Requests will be applied in the order they are specified.
// If any request is not valid, no requests will be applied.
requests: [
{
addChart: {
chart: {
spec: {
title: 'Rapport',
basicChart: {
chartType: 'COLUMN',
legendPosition: 'BOTTOM_LEGEND',
axis: [
//X-AXIS
{
position: "BOTTOM_AXIS",
title: "FORBRUK"
},
//Y-AXIS
{
position: "LEFT_AXIS",
title: "TID"
}
],
series: [
{
series: {
sourceRange: {
sources: [
{
sheetId: 0,
startRowIndex: 0,
endRowIndex: endIndex,
startColumnIndex: 5,
endColumnIndex: 6,
},
],
},
},
targetAxis: "LEFT_AXIS"
}
]
}
},
position : {
newSheet : 'True'
}
},
}
}
],
// TODO: Add desired properties to the request body.
};
var request = gapi.client.sheets.spreadsheets.batchUpdate(
params,
batchUpdateSpreadsheetRequestBody
);
request.then(
function (response) {
// TODO: Change code below to process the `response` object:
console.log(response.result);
},
function (reason) {
console.error("error: " + reason.result.error.message);
}
);
}

Related

Inserting Vanilla JS into VueJS framework

With the concept of VueJS is a kind of framework of JS, then it should have no problem inserting the vanilla JS into it. The following is the attempt to insert the pure JS code into vue-cli project(webpack structure).
[Before Start] I tried the example code as the following link(official document)
URL: https://codepen.io/Tobyliao/pen/ZEWNvwE?editable=true%3Dhttps%3A%2F%2Fdocs.bokeh.org%2F
it works.
[Question] As I tried to imlement into Vue project. It fails. picture1 is the directory structure.
I tried to place the src url include into ./public/html's tag as following:
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-2.2.1.min.js"></script>
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.2.1.min.js"></script>
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.2.1.min.js"></script>
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-api-2.2.1.min.js"></script>
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-api-2.2.1.min.js"></script>
Create a componet in './src/components/BokehPlot.vue'
inside the code, I insert
<template>
<h1>Measurement Plotting</h1>
</template>
<script src='./main.js'>
export default {
}
</script>
Then finally place all the Bokeh code into './src/component/main.js'. It is the pure JS code I want to import into the structure.
[Result]
I can see the plot in the background, but it kept on showing the error message like picture2.
You have many options here, I went ahead and simply made a mixin to utilize the component lifecycle that Vue provides. source
Here are the relevant parts:
BokehPlot.vue
<template>
<h1>治具量測</h1>
</template>
<script>
import Chart from "#/mixins/Chart";
export default {
mixins: [Chart],
};
</script>
Chart.js
export default {
data() {
return {
plot: null,
xdr: null,
ydr: null
};
},
beforeMount() {
// create some ranges for the plot
this.xdr = new Bokeh.Range1d({ start: -1, end: 100 });
this.ydr = new Bokeh.Range1d({ start: -0.5, end: 20.5 });
// make the plot
this.plot = new Bokeh.Plot({
title: "BokehJS Plot",
x_range: this.xdr,
y_range: this.ydr,
plot_width: 400,
plot_height: 400,
background_fill_color: "#F2F2F7"
});
},
mounted() {
this.loadData();
},
methods: {
loadData() {
// create some data and a ColumnDataSource
let x = Bokeh.LinAlg.linspace(-0.5, 20.5, 10);
let y = x.map(function (v) {
return v * 0.5 + 3.0;
});
let source = new Bokeh.ColumnDataSource({ data: { x: x, y: y } });
// add axes to the plot
let xaxis = new Bokeh.LinearAxis({ axis_line_color: null });
let yaxis = new Bokeh.LinearAxis({ axis_line_color: null });
this.plot.add_layout(xaxis, "below");
this.plot.add_layout(yaxis, "left");
// add grids to the plot
let xgrid = new Bokeh.Grid({ ticker: xaxis.ticker, dimension: 0 });
let ygrid = new Bokeh.Grid({ ticker: yaxis.ticker, dimension: 1 });
this.plot.add_layout(xgrid);
this.plot.add_layout(ygrid);
// add a Line glyph
let line = new Bokeh.Line({
x: { field: "x" },
y: { field: "y" },
line_color: "#666699",
line_width: 2
});
this.plot.add_glyph(line, source);
Bokeh.Plotting.show(this.plot);
}
}
};
Many decisions to still make, but hopefully that will get you pointed down the right path.
See working example:
https://codesandbox.io/s/bokehjs-forked-4w20k?fontsize=14&hidenavigation=1&theme=dark

Chart js old chart data not clearing

This question has been asked many times and I went through most of them but non of them helped me finding a solution.
I am generating couple of bar charts using a for loop as a part of reporting functionality.
I am using node.js with Express Handlebars.
My page looks like:
<div class="row report-charts">
<div class="col-md-12">
{{#buildings}}
<div class="col-md-6">
<h4>{{Name}}</h4>
<canvas id="{{idBuildings}}" width="200" height="80"></canvas>
</div>
{{/buildings}}
</div>
</div>
My js code looks like:
$('.case-report-btn').click(function(){
$.ajax({
type: 'post',
url: '/reports/cases/filter',
data : {
StartDate : $('.start-ms-time-hidden').val(),
EndDate : $('.end-ms-time-hidden').val(),
ReportKey : $('.cases-filter-type').val()
},
dataType: 'json',
success: function(res) {
$('.report-charts').show();
for(key in res) {
var innerObj = res[key]; //gives the inner obj
var ctx = document.getElementById(key); //the idBuildings
var labels = [];
var data = [];
var buildingName = innerObj.Name;
for(innerKey in innerObj) {
if(innerKey != 'Name' && innerKey != 'Total') {
labels.push(innerKey);
data.push(innerObj[innerKey]);
}
}
var options = {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: buildingName,
data: data,
backgroundColor: 'rgba(255, 99, 132, 0.2)',
borderColor: 'rgba(255,99,132,1)',
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true,
fixedStepSize: 1
}
}]
}
}
}
var myChart = new Chart(ctx, options);
}
$('#pleaseWaitDialog').modal('hide');
},
error: function(err) {
$('#pleaseWaitDialog').modal('hide');
bootbox.alert('Error: ' + err);
}
});
});
So basically, I am using for loop to generate multiple charts on the page. Inside the loop I declared the chart variable, every time I change the report parameters and hit the button, the new chart is generated. But when I hover over it, the old one still shows up.
Now I am not sure where I should be putting the myChart.destroy() or myChart.clear() methods. I also tried moving the myChart declaration outside the for loop but it didn't help either.
Any suggestions on how to handle this?
I think there are a few ways to do it. You can update your chart data if the chart already exist. Here two functions you can use:
function removeData(chart) {
chart.data.labels.pop();
chart.data.datasets.forEach((dataset) => {
dataset.data.pop();
});
chart.update();
}
function addData(chart, label, data) {
chart.data.labels.push(label);
chart.data.datasets.forEach((dataset) => {
dataset.data.push(data);
});
chart.update();
}
First you have to remove all your data and then add the new data.
If you want to destroy the chart and create it again you have to save your variable as global. To do this you have yo declare your variable like window.myChart and then before create the new chart, something like this:
if (window.myChart) window.myChart.destroy();
window.myChart = new Chart(ctx, options);
Another way you can try is removing your canvas and creating another one. Something like this:
$('#your_canvas').remove();
$('#your_canvas_father').append('<canvas id="your_canvas"></canvas>');

Error While Inserting json data into Google SpreadSheet

Am trying to Inserting JSON data's into Google Spreadsheet. This is My code ,
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script>
var read=(function(){
data1={
"jobstatus": [
{
"dateAndTime": "hi",
"jobId": "TCC_tfc",
"userId": "admin",
"status": "Completed",
"jobType": "Excel Upload"
}
]
};
var jobs = data1;
var datae = new google.visualization.DataTable();
datae.addRows(["datetime",jobs.jobstatus.dateAndTime],
['jobId', jobs.jobstatus.jobId],
['userId', jobs.jobstatus.userId],
['status', jobs.jobstatus.status],
['jobType', jobs.jobstatus.jobType]
);});
</script>
While am Executing this code am getting error as
TypeError: google.visualization is undefined
How can i solve that Error ? i searched solution for that in "SO" they said me to add this line :
google.load('visualization', '1.0', {'packages':['corechart'], 'callback': read});
By adding this also am getting that same error . Can someone help me out from this .
here are a few recommendations...
1) recommend using loader.js vs. the older library jsapi
<script src="https://www.gstatic.com/charts/loader.js"></script>
2) name the callback function, rather than assigning to a variable
google.charts.load('current', {
callback: read,
packages:['table']
});
function read(){...}
3) must add columns before addRows, several ways to do this, using arrayToDataTable is easy
var datae = google.visualization.arrayToDataTable([
['datetime', 'jobId', 'userId', 'status', 'jobType'],
]);
4) in data1, "jobstatus" is an array, so must use array element index to access value
jobs.jobstatus[0].dateAndTime // get first array element with [0]
--or--
if there is more than one jobstatus in the array, use a loop to add them all, using addRow
jobs.jobstatus.forEach(function (job) {
datae.addRow([
job.dateAndTime,
job.jobId,
job.userId,
job.status,
job.jobType
]);
});
see following working snippet...
google.charts.load('current', {
callback: read,
packages:['table']
});
function read(){
var data1={
"jobstatus": [{
"dateAndTime": "hi",
"jobId": "TCC_tfc",
"userId": "admin",
"status": "Completed",
"jobType": "Excel Upload"
}]
};
var jobs = data1;
var datae = google.visualization.arrayToDataTable([
['datetime', 'jobId', 'userId', 'status', 'jobType'],
]);
jobs.jobstatus.forEach(function (job) {
datae.addRow([
job.dateAndTime,
job.jobId,
job.userId,
job.status,
job.jobType
]);
});
var chart = new google.visualization.Table(document.getElementById('chart_div'));
chart.draw(datae);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

How do you make reusable/template charts in c3js

I'm trying to use C3.js(c3js.org) to make charts, but I want to specify everything but the data(and any other minor deviations unique to that chart) once then reuse that for all charts of that variation(a specific configuration of a chart).
All the documentation and all examples I've found for C3.js only deal with how you make a single chart. Applying that to multiple charts means a lot of repeated code and doesn't ensure consistency when making changes.
The only thing related to this that I've found is a concept on making reusable charts in D3.js(d3js.org), the underlying library used by C3.js, and an implementation inspired by that concept. That doesn't really help me because I want the higher-level abstraction that C3.js provides but these may give you an idea what I'm looking for.
I have found no info on this but one idea is to make a chart type that is based on an existing type but that also include the extra configuration(for example make a new chart type called 'horizontalbar' based on the existing 'bar' chart type).
Here is a chart I've made, bindto and columns are the unique parts of this chart, the rest should be part of a template, but I don't know how.
var chart = c3.generate({
bindto: '#chart',
data: {
columns: [
['data1', 125.2],
['data2', 282.7],
['data3', 3211.1],
['data4', 212.2],
['data5', 131.1],
['data6', 329.7]
],
type: 'pie',
order: null
},
pie: {
label: {
format: function (value, ratio, id) {
return d3.format('.1f')(ratio*100)+'%'; //percent with one decimal
}
}
},
tooltip: {
format: {
value: function (value, ratio, id, index) {
return value+'mkr ('+d3.format('.1f')(ratio*100)+'%)'; //example: 155.2mkr (3.3%)
}
}
},
legend: {
item: {
onclick: function () {} //disable clicking to hide/show parts of the chart
}
}
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.9/c3.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.9/c3.min.js"></script>
<div id="chart"></div>
I have this in my html:
<script src="../static/js/test.js"></script> <!-- this is the js file contains the drawChart function -->
<div class='chart'>
<div id='chart1'></div>
</div>
<script>drawChart('chart1','pathToCsvData',ture, 200);</script>
in my js code:
function drawChart(toChart,dataURL,showLegend,chartHeight)
{
var chart1 = c3.generate({
bindto: toChart,
data: {
url: dataURL,
labels: false
},
color: {pattern: ['green','black']},
zoom: {enabled: false},
size: {height: chartHeight},
transition: {duration: 0},
legend: {show: showLegend}
});
}
the js code serve as a template, and I can as many different template I want, put them in functions, with customized chart parameters, and the call the js function in html code.

reactive chart with chart.js in meteor

i am using chart.js to generate charts in a meteor app.
Here is my code
function drawChart(){
var data = [
{
value: Policies.find({'purchased_cover.trip_type': 'Single Trip'}).count(),
color:"#F38630"
},
{
value :Policies.find({'purchased_cover.trip_type': 'Annual Multi-Trip'}).count(),
color : "#E0E4CC"
},
{
value : Policies.find({'purchased_cover.trip_type': 'Backpacker'}).count(),
color : "#69D2E7"
},
{
value :Policies.find({'purchased_cover.trip_type': 'Golf Annual'}).count(),
color : "green"
},
{
value :Policies.find({'purchased_cover.trip_type': 'Golf'}).count(),
color : "red"
},
{
value :Policies.find({'purchased_cover.trip_type': 'Winter Sports Annual'}).count(),
color : "yellow"
}
]
var ctx = $("#pieChart").get(0).getContext("2d");
var myPieChart = new Chart(ctx);
new Chart(ctx).Pie(data);
}
Template.charts.rendered = function(){
drawChart();
};
i have few helpers to display the count in html templates and it works fine whenever the counts changes but the chart is not changing until i reload the page..i want the chart to be reactive to the changes in the collection.
You can use Tracker.autorun to rerun drawChart whenever reactive data sources it depends on change:
if (Meteor.isClient) {
function drawChart() {
...
}
Tracker.autorun(drawChart());
}

Categories