I'm attempting to pull data from Google Sheets and use it as a source for my Gantt chart. I've followed the example in the Google Charts documentation for pulling Sheets data for a columnchart, but not sure if more customization is necessary.
I'm not as familiar with Javascript, so not sure what is triggering the error. Here is the code in JSFiddle.
google.charts.load('current', {'packages':['gantt']});
google.charts.setOnLoadCallback(drawChart);
function daystoMilliseconds(days) {
return days * 24 * 60 * 60 * 1000;
}
function drawGID() {
var queryString = encodeURIComponent('SELECT A, B, C, D, E, F, G, H');
var query = new google.visualization.Query(
'https://docs.google.com/spreadsheets/d/1f0wxDrEfptRKCRY5pQPu6Dc_ue_tIX_ja5pQO3vXjOY/edit#gid=0&headers=1&tq=' + queryString);
query.send(handleSampleDataQueryResponse);
}
function handleSampleDataQueryResponse(response) {
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}}
function drawChart() {
var otherData = response.getDataTable();
var options = {
height: 275,
gantt: {
defaultStartDateMillis: new Date(2015, 3, 28)
}
};
var chart = new google.visualization.Gantt(document.getElementById('chart_div'));
chart.draw(otherData, options);
}
first, the callback should be --> drawGID
instead of --> drawChart
next, notice the data format for a Gantt chart
both the 'Start' and 'End' dates are required and cannot be blank,
as in the spreadsheet
see following working snippet...
a new data table is built, using the data from the spreadsheet (otherData),
using the 'Duration' column to fill in the the dates
google.charts.load('current', {
callback: drawGID,
packages: ['gantt']
});
function drawGID() {
var queryString = encodeURIComponent('SELECT A, B, C, D, E, F, G, H');
var query = new google.visualization.Query(
'https://docs.google.com/spreadsheets/d/1f0wxDrEfptRKCRY5pQPu6Dc_ue_tIX_ja5pQO3vXjOY/edit#gid=0&headers=1&tq=' + queryString);
query.send(handleSampleDataQueryResponse);
}
function handleSampleDataQueryResponse(response) {
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var otherData = response.getDataTable();
var ganttData = new google.visualization.DataTable({cols: [
{type: 'string', label: 'Task Id'},
{type: 'string', label: 'Task Name'},
{type: 'string', label: 'Resource'},
{type: 'date', label: 'Start'},
{type: 'date', label: 'End'},
{type: 'number', label: 'Duration'},
{type: 'number', label: '% Complete'},
{type: 'string', label: 'Dependencies'}
]});
var duration = 0;
var startDate = new Date(2016, 0, 1);
var endDate;
for (var i = 0; i < otherData.getNumberOfRows(); i++) {
startDate = new Date(startDate.getTime() + duration);
duration += otherData.getValue(i, 5);
endDate = new Date(startDate.getTime() + duration);
ganttData.addRow([
otherData.getValue(i, 0),
otherData.getValue(i, 1),
otherData.getValue(i, 2),
startDate,
endDate,
otherData.getValue(i, 5),
parseFloat(otherData.getValue(i, 6)),
otherData.getValue(i, 7)
]);
}
var options = {
height: 275,
gantt: {
defaultStartDateMillis: new Date(2015, 3, 28)
}
};
var chart = new google.visualization.Gantt(document.getElementById('chart_div'));
chart.draw(ganttData, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
The following Google project allows you to view a Google Spreadsheet as a Gantt Chart:
https://github.com/google/ezgantt
Related
I have created a web server on ESP8266 that uses Google gauge to display current temperature data and line graph to display previous data. The gauge and line graph will update as new data come in. Everything works well and when I call the IP the line graph will display and start to populate. The problem is that every IP call the line graph starts with no data and populates all over again because when dataTable is initialized it is returning a new empty data table. Can anyone make a suggestion on creating a line graph from the existing data array in the datatable when make IP call? Thanks.
Code to update line graph:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['corechart','gauge']});
google.charts.setOnLoadCallback(drawChart);
function drawChart(){
//Create opening gauges
var gaugeData = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Room 1', 0],
['Room 2', 0]
]);
var gaugeOptions = {
width: 800, height: 240,
redFrom: 90, redTo: 100,
yellowFrom:75, yellowTo: 90,
minorTicks: 5
};
var chart = new google.visualization.Gauge(document.getElementById('chart_div'));
chart.draw(gaugeData, gaugeOptions);
//Obtain new temperature data and update gauge and line graph
setInterval(updateValues, 3000);
function updateValues() {
//Obtain Room 1 temperature and update Google Gauge
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState === 4 && this.status === 200) {
Room1temp = parseFloat(this.responseText);
gaugeData.setValue(0, 1, Room1temp);
chart.draw(gaugeData, gaugeOptions);
}
};
xhttp.open("GET", "/Room1temp", true);
xhttp.send();
//Obtain Room 2 temperature and update Google Gauge
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState === 4 && this.status === 200) {
Room2temp = parseFloat(this.responseText);
gaugeData.setValue(1, 1, Room2temp);
chart.draw(gaugeData, gaugeOptions);
}
};
xhttp.open("GET", "/Room2temp", true);
xhttp.send();
};
//Update Google line chart with timestamp and Room 1 & 2 temperatures
var data = new google.visualization.DataTable();
data.addColumn('datetime', 'Time');
data.addColumn('number', 'Room 1');
data.addColumn('number', 'Room 2');
setInterval(updateGraph, 3000);
function updateGraph() {
//create timestamp
let date = new Date();
var Year = date.getFullYear();
var Month = date.getMonth();
var Day = date.getDate();
var Hour = date.getHours();
var Min = date.getMinutes();
var Sec = date.getSeconds();
//Update line graph
if(data.getNumberOfRows()<5){
data.addRows([
[new Date(Year,Month,Day,Hour,Min,Sec), parseFloat(Room1temp), parseFloat(Room2temp)]
]);
} else {
var view = new google.visualization.DataView(data);
data.addRows([
[new Date(Year,Month,Day,Hour,Min,Sec), parseFloat(Room1temp), parseFloat(Room2temp)]
]);
data.removeRow(0);
}
var options = {
title: 'Temperature Data',
pointSize: 8
};
var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));
chart.draw(data, options);
}; //End function updateGraph
} // End function drawChart
</script>
</head>
<body>
<div id="chart_div" style="width:600px;margin-left:auto;margin-right:auto"></div>
<div id="curve_chart" style="width:1400px;margin-left:auto;margin-right:auto"></div>
</body>
</html>
try making the IP calls in succession, waiting for each to complete,
before continuing to the next and updating the charts.
see following snippet...
google.charts.load('current', {
packages: ['corechart', 'gauge']
}).then(function () {
//Create opening gauges
var gaugeData = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Room 1', 0],
['Room 2', 0]
]);
var gaugeOptions = {
width: 800, height: 240,
redFrom: 90, redTo: 100,
yellowFrom:75, yellowTo: 90,
minorTicks: 5
};
var gaugeChart = new google.visualization.Gauge(document.getElementById('chart_div'));
gaugeChart.draw(gaugeData, gaugeOptions);
// line chart
var data = new google.visualization.DataTable();
data.addColumn('datetime', 'Time');
data.addColumn('number', 'Room 1');
data.addColumn('number', 'Room 2');
var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));
var options = {
title: 'Temperature Data',
pointSize: 8
};
//Obtain new temperature data and update gauge and line graph
setInterval(updateValues, 3000);
function updateValues() {
//Obtain Room 1 temperature and update Google Gauge
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState === 4 && this.status === 200) {
var Room1temp = parseFloat(this.responseText);
gaugeData.setValue(0, 1, Room1temp);
gaugeChart.draw(gaugeData, gaugeOptions);
//Obtain Room 2 temperature and update Google Gauge
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState === 4 && this.status === 200) {
var Room2temp = parseFloat(this.responseText);
gaugeData.setValue(1, 1, Room2temp);
gaugeChart.draw(gaugeData, gaugeOptions);
//Update line graph
if(data.getNumberOfRows()<5){
data.addRows([
[new Date(), parseFloat(Room1temp), parseFloat(Room2temp)]
]);
} else {
data.addRows([
[new Date(), parseFloat(Room1temp), parseFloat(Room2temp)]
]);
data.removeRow(0);
}
chart.draw(data, options);
}
};
xhttp.open("GET", "/Room2temp", true);
xhttp.send();
}
};
xhttp.open("GET", "/Room1temp", true);
xhttp.send();
};
});
I am generating html to pdf using jsPDF jsPDF-autotable, the header, and footer is being printed well. I have tried adding a logo to the header but it is failing to print it, when I console.log(base64Img) and convert it, it is the same logo.
This is the code to convert image to base64 string
imgToBase64 (url, callback) {
if (!window.FileReader) {
callback(null);
return;
}
const xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = function () {
const reader = new FileReader();
reader.onloadend = function () {
callback((reader.result as string).replace('text/xml', 'image/jpeg'));
};
reader.readAsDataURL(xhr.response);
};
xhr.open('GET', url);
xhr.send();
And this is the code to generate the pdf
generatePDF() {
let base64Img = null;
this.imgToBase64(this.imageURL, (base64) => {
base64Img = base64;
console.log('image in base 64', base64Img);
const doc = new jspdf('p', 'pt', 'a4');
const header = function(headerData: any) {
doc.setFontSize(20);
doc.setTextColor(0, 190, 208);
doc.setFontStyle('normal');
if (this.base64Img) {
doc.addImage(this.base64Img, 'JPEG', headerData.settings.margin.left, 15, 60, 10);
doc.setFontSize(20);
}
doc.text('Header Title', headerData.settings.margin.left, 60);
const currentdate = new Date();
const datetime = currentdate.getDate() + '/' + (currentdate.getMonth() + 1) + '/' + currentdate.getFullYear();
doc.text('Date: ' + datetime, headerData.settings.margin.left + 400, 60);
doc.setFontSize(5);
};
const totalPagesExp = '{total_pages_count_string}';
const footer = function(footerData) {
doc.setFontSize(10);
let str = 'Page ' + footerData.pageCount;
// Total page number plugin only available in jspdf v1.0+
if (typeof doc.putTotalPages === 'function') {
str = str + ' of ' + totalPagesExp;
console.log('test');
}
doc.text(str, footerData.settings.margin.left, doc.internal.pageSize.height - 10);
doc.text('https://wwww.example.com', footerData.settings.margin.left + 400, doc.internal.pageSize.height - 10);
};
const head = [['Name', 'Phone', 'Email', 'Gender', 'Location', 'Country']]
const options = {
beforePageContent: header,
afterPageContent: footer,
margin: {
top: 100
},
head: head,
columnStyles: {
0: {columnWidth: 100},
1: {columnWidth: 80},
2: {columnWidth: 80},
3: {columnWidth: 50},
}
};
const elem = document.getElementById('pdfContent');
const data = doc.autoTableHtmlToJson(elem);
doc.autoTable( data.columns, data.rows, options);
// Total page number plugin only available in jspdf v1.0+
if (typeof doc.putTotalPages === 'function') {
doc.putTotalPages(totalPagesExp);
}
doc.save('generated.pdf');
});
}
I thing i'm too late, but this will help others.
you can use like
var doc = new jsPDF('p', 'pt');
var header = function (data) {
doc.setFontSize(18);
doc.setTextColor(40);
doc.setFontStyle('normal');
doc.addImage(base64_source, 'JPEG', data.settings.margin.left, 20, 50, 50);
//doc.addImage(image base64_source, 'image format', logo_sizes.centered_x, _y, logo_sizes.w, logo_sizes.h);
//Image must be Base64 encoded
};
doc.autoTable(columns, rows, {margin: {top: 80}, beforePageContent: header});
doc.save("test.pdf");
Note: you have to use with your code variables this is only demo.
Ive been trying to load data from a SQL table thats generated daily via a SP, Table consists of 4 columns.
My Ajax call gets the data and puts into an array -
Array
Heres my code im using to draw the view and pass the array -
var chartData;
$(document).ready(function () {
$.ajax({
url: "/Reporting/LeaveList",
data: "",
dataType: "json",
type: "POST",
contentType: "application/json; chartset=utf-8",
success: function (data) {
//console.log(data);
console.log(typeof data);
chartData = data;
},
error: function () {
alert("Error loading data! Please try again.");
}
}).done(function () {
google.setOnLoadCallback(createTable);
});
});
function createTable() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Date');
data.addColumn('number', 'AnnualLeave');
data.addColumn('number', 'Sick');
data.addColumn('number', 'Total');
data.addRow(chartData[0])
// Create a dashboard.
var dash_container = document.getElementById('dashboard_div'),
myDashboard = new google.visualization.Dashboard(dash_container);
// Create a date range slider
var myDateSlider = new google.visualization.ControlWrapper({
'controlType': 'ChartRangeFilter',
'containerId': 'control_div',
'options': {
'filterColumnLabel': 'Date'
}
});
// Table visualization
var myTable = new google.visualization.ChartWrapper({
'chartType': 'Table',
'containerId': 'table_div'
});
// Bind myTable to the dashboard, and to the controls
// this will make sure our table is update when our date changes
myDashboard.bind(myDateSlider, myTable);
// Line chart visualization
var myLine = new google.visualization.ChartWrapper({
'chartType': 'LineChart',
'containerId': 'line_div',
});
// Bind myLine to the dashboard, and to the controls
myDashboard.bind(myDateSlider, myLine);
myDashboard.draw(data);
And heres some of the controller -
data = (
from u in db.StaffReportingDay
select new StaffReportingDayVM
{
Date = u.Date.ToString(),
AnnualLeave = u.AnnualLeave,
CompassionateLeave = u.CompassionateLeave,
Sick = u.Sick,
StudyLeave = u.StudyLeave,
Total = u.Total
}).ToList();
}
var ChartOne = new object[data.Count + 1];
ChartOne[0] = new object[]
{
"Date",
"Annual Leave",
"Sick Leave",
"Total on Leave"
};
int j = 0;
foreach(var i in data)
{
j++;
ChartOne[j] = new object[] {i.Date.ToString(), i.AnnualLeave, i.Sick, i.Total };
}
return Json(ChartOne, JsonRequestBehavior.AllowGet);
What i cant get is the array to pull into the view, i just get an error -
Uncaught Error: Type mismatch. Value Annual Leave does not match type number in column index 1
Ive tried many things but would like some pointers and other people to give their insight please.
Solved with
function drawVisualization() {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'AnnualLeave');
data.addColumn('number', 'CompassionateLeave');
data.addColumn('number', 'StudyLeave');
data.addColumn('number', 'Sick');
data.addColumn('number', 'Total');
$.each(chartData, function (i, row) {
data.addRow([
(new Date(row.Date)),
parseFloat(row.AnnualLeave),
parseFloat(row.CompassionateLeave),
parseFloat(row.StudyLeave),
parseFloat(row.Sick),
parseFloat(row.Total)
]);
});
I have this java script code that generate organizational chart from database
<script type="text/javascript">
google.load("visualization", "1", { packages: ["orgchart"] });
google.setOnLoadCallback(drawChart);
function drawChart() {
$.ajax({
type: "POST",
url: "add org unit.aspx/GetChartData",
data: '{}',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (r) {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Entity');
data.addColumn('string', 'ParentEntity');
data.addColumn('string', 'ToolTip');
for (var i = 0; i < r.d.length; i++) {
var employeeId = r.d[i][0].toString();
var employeeName = r.d[i][1];
var designation = r.d[i][2];
var reportingManager = r.d[i][3] != null ? r.d[
i][3].toString() : '';
data.addRows([[{
v: employeeId,
f: '<a target="_blank" href="edit emp cv.aspx?employeeId='+employeeId+'">' + employeeName + '</a>' + '<div><span>' + designation + '</div></span>',
}, reportingManager, designation]]);
}
var chart = new google.visualization.OrgChart($("#chart")[0]);
chart.draw(data, { allowHtml: true });
},
failure: function (r) {
alert(r.d);
},
error: function (r) {
alert(r.d);
}
});
}
</script>
and these web method in c# code behind
[WebMethod]
public static List<object> GetChartData()
{
DataLayer.StoreDBEntities dbEntities = new DataLayer.StoreDBEntities();
List<object> chartData = new List<object>();
List<DataLayer.org_unit> result = dbEntities.org_unit.ToList();
foreach (DataLayer.org_unit unit in result)
{
string name = unit.org_unit_type.alias + " " + unit.name;
string Details = "";
if (unit.emp_assignment.ToArray().Length != 0)
{
List<DataLayer.emp_assignment> empAssigns = unit.emp_assignment.ToList();
foreach (DataLayer.emp_assignment assign in empAssigns)
{
Details += assign.job_title.alias + ":" + assign.employee.name + "<br/>";
}
}
chartData.Add(new object[] { unit.id, name, Details, unit.upper_unit_id });
}
return chartData;
}
the chart is regenerated every postback and when page is load
although I did not call java script function at all
how to stop this ? i want to generate chart only whene butten click
First, you need to remove this google.setOnLoadCallback(drawChart); then you can use the jQuery click event like this:
$(function() {
$('#draw-chart').click(function(event) {
event.preventDefault();
drawChart();
});
});
Add a button to your HTML like this:
<button id="draw-chart">Draw Chart</button>
I want to create an organization chart which I want to populate using the values from a sharepoint list. I would like to retrieve items using REST and Javascript. Here is my code. It in partially working, but cannot create a chart. Please help someone.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", { packages: ["orgchart"] });
google.setOnLoadCallback(drawChart);
function drawChart() {
debugger;
$.ajax({
url: "http://myurl/_api/Web/Lists/GetByTitle('Employee Hierarchy')/items",
type: "GET",
headers: {
"accept": "application/json;odata=verbose",
},
success: function (r) {
debugger;
var items = r.d.results;
var data = new google.visualization.DataTable();
data.addColumn('string', 'Entity');
data.addColumn('string', 'ParentEntity');
data.addColumn('string', 'ToolTip');
for (var i = 0; i <items.length; i++) {
var employeeId = r.d[i][0].toString();
var employeeName = r.d[i][1];
var designation = r.d[i][2];
var reportingManager = r.d[i][3] != null ? r.d[i][3].toString() : '';
data.addRows([[{
v: employeeId,
f: employeeName + '<div>(<span>' + designation + '</span>)</div><img src = "Pictures/' + employeeId + '.jpg" />'
}, reportingManager, designation]]);
var chart = new google.visualization.OrgChart($("#chart")[0]);
chart.draw(data, { allowHtml: true });
},
failure: function (r) {
alert(r.d);
},
error: function (r) {
alert(r.d);
}
});
}
</script>
<div id="chart">
</div>
this is the structure of my sharepoint list
The following example demonstrates how to visualize SharePoint List data as organization chart via Google Visualization API
google.load("visualization", "1", { packages: ["orgchart"] });
google.setOnLoadCallback(displayChart);
function displayChart()
{
loadListItems('Employee Hierarchy')
.done(function(data){
var items = data.d.results;
drawChart(items);
})
.fail(function(error){
console.log(error);
});
}
function drawChart(items) {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Name');
data.addColumn('string', 'Manager');
data.addColumn('string', 'ToolTip');
for (var i = 0; i < items.length; i++) {
data.addRow([items[i]['Title'],items[i]['Manager']['Title'],'']);
}
var chart = new google.visualization.OrgChart(document.getElementById('chart_div'));
chart.draw(data, { allowHtml: true });
}
function loadListItems(listTitle){
return $.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/Web/Lists/GetByTitle('" + listTitle + "')/items?$select=Title,Manager/Title&$expand=Manager",
type: "GET",
headers: {
"accept": "application/json;odata=verbose",
}
});
}
Key points
In my example the list has the following schema:
Field Name Type
Title Text
Manager Lookup
Description Note
List view page
Resulting page