Skip to main content

Dynamic charts using Google Sheets as a data source

QuickChart can render chart images based on the latest data from your spreadsheet. This post describes how to integrate Google Sheets as a data source for dynamic chart images.

The charts are rendered as images, meaning they are embeddable in websites, emails, reports, and anyplace else. Latest data is pulled in automatically - you don't need to change your chart configuration in order to update chart data.

QuickChart pulls data from a spreadsheet and renders a chart image that is embeddable anywhere.
QuickChart pulls data from a spreadsheet and renders a chart image that is embeddable anywhere.

Step 1: Build the sheet

I am assuming basic familiarity with Chart.js and the QuickChart renderer. To learn more about how to get started, check out the Getting Started guide.

Let's suppose we have a spreadsheet table that looks like this:

NameUsage countPayment
Joe75150
John87174
Sam48
Kathy56112
Arnold612
Sarah52104
Timmy2550
Rachel98196
Jared52104
George2040
Dave86172
Jeffrey1224

We want to create a chart that shows Usage count and Payment bars for each Name.

Begin by creating a Google Sheet and copy the data into it. You can also upload Excel spreadsheets to Google. The above example has been transferred into Google Sheets here.

Next, configure the sharing setting so that outsiders can access to it. To do this, click the green "Share" button in the top right, then click "Change to anyone with the link". After setting this correctly, it will say "Anyone on the internet with this link can view".

Google sharing settings

Step 2: Build the chart

Have a look at the URL for your spreadsheet. It looks something like this:

https://docs.google.com/spreadsheets/d/1qBJlbi200GozsP8W4gBGZOxuwKSYmBiiTH8olwx26E8/edit#gid=0

The bolded part is called the document ID. Take note of this doc ID.

Next, we'll construct our Chart.js configuration and add a custom plugin called googleSheets. Here's an example:

{
type: 'bar',
options: {
plugins: {
googleSheets: {
docId: '121DpBzwABbNB7JO3--dXGTI3CE2LL1WwPHXKCYDdsKM',
sheet: 'Sheet1',
labelColumn: 'Name',
dataColumns: ['Usage count', 'Payment'],
}
},
legend: {
display: false
}
}
}

docId tells the plugin where to get data from. The rest of the attributes are optional. Use labelColumn or dataColumns to override values in your chart configuration.

As an alternative to docId, you may simply paste the full URL to the sheet as a sheetUrl attribute.

AttributeDescriptionExampleNotes
sheetUrlGoogle Sheets shareable URL"https://docs.google.com/spreadsheets/..."Required when docId is not set. Overrides docId and sheet
docIdGoogle sheet ID"121DpBzwABbNB7JO3–dXGTI3CE2LL1WwPHXKCYDdsKM"Required when sheetUrl is not set
sheetName of the sheet or the 0-based index of the sheet"Sheet1" or "0"Optional, defaults to first sheet
labelColumnColumn name that defines the labels for your data series"Name"Optional, defaults to labels in chart config
dataColumnsList of column names that defines the numeric data for each data series["Usage count", "Payment"]Optional, defaults to labels in chart config
rowsObject that defines row criteria{"limit": 20, "offset": 1}Optional
rows.limitNumber of rows to take from sheet20 for first 20 rows, -10 for last 10 rowsIf negative, will count from bottom. Defaults to unlimited
rows.offsetNumber of rows to shift the table by1 to omit the first row. -5 to omit the last 5 rowsIf positive, shift rows up. If negative, shift rows down. Defaults to 0
filter.labelPredicate for filtering data by labellabel => label !== 'Joe'Return true to keep the row, return false to remove it

Like any other QuickChart chart, we can pack this configuration into a JSON string and send it to the QuickChart endpoint at https://quickchart.io/chart:

https://quickchart.io/chart?c={type:'bar',options:{plugins:{googleSheets:{docId:'121DpBzwABbNB7JO3--dXGTI3CE2LL1WwPHXKCYDdsKM',sheet:'Sheet1',labelColumn:'Name',dataColumns:['Usage count','Payment']}},legend:{display:false}}}

When you render the above URL in an image tag, you'll see the image below:

<img src="https://quickchart.io/chart?c=..." />
Data for this image is pulled dynamically from the spreadsheet
Data for this image is pulled dynamically from the spreadsheet

This image can be directly embedded in on a website, email, PDF, etc. using a standard <img> tag. This image will update automatically as you update your spreadsheet. Note that updates can happen once every 30 seconds, and you must refresh the image to see changes.

tip

It's best practice to URL encode the chart JSON parameter. Nearly every programming language has a built-in function to do this. URL encoding your JSON will avoid problems with more complex chart specifications.

Another usage example

You don't always have to override labels or use every data column in your spreadsheet.

Take this example chart configuration, which uses the same underlying spreadsheet as the previous example:

{
type: 'bar',
data: {
labels: ['Person 1', 'Person 2', 'Person 3', 'Person 4', 'Person 5'],
datasets: [
{ label: 'Total payments' }
],
},
options: {
plugins: {
googleSheets: {
sheetUrl: 'https://docs.google.com/spreadsheets/d/121DpBzwABbNB7JO3--dXGTI3CE2LL1WwPHXKCYDdsKM/edit#gid=0',
dataColumns: ['Payment'],
rows: {
limit: -5
},
},
datalabels: {
color: '#fff',
font: {
weight: 'bold',
},
},
},
}
}

In this configuration, we've chosen to anonymize the chart by omitting the labels from the Name column. We've also limited it to the last 5 data series. Note that the chart won't show data without an associated label (if you want to show data with no label, use an empty string).

Also, we purposely left out the Usage count column so that we show just a single Payment dataset. This dataset is labeled Total payments in the chart legend.

Finally, we've enabled the datalabels plugin. It's just one of many potential customizations we can introduce.

The end result looks like this:

Data for this image is pulled dynamically from the spreadsheet
Data for this image is pulled dynamically from the spreadsheet

Just as in the previous example, this image will automatically reflect the latest data in your spreadsheet when it is loaded.

Customizing chart series

In this example, we use a new "Temperature vs. Precipitation" dataset and split the datasets onto multiple axis, representing one with a bar and one with a line.

The spreadsheet looks like this (this data is on the "Weather" tab of the example Google Sheet we used above):

LabelsTemperaturePrecipitation
Jan33.371.59
Feb28.756.47
Mar47.583.52
Apr54.4815.32
Mar74.4915.92
Jun86.2919.69
Jul83.111.2
Aug88.2919.88
Sep66.064.08
Oct57.796.18
Nov54.5610.7
Dec45.0512.73

We set the chart config like so:

{
type: 'bar',
data: {
datasets: [
{
label: 'Temperature (F)',
order: 2,
},
{
type: 'line',
label: 'Precipitation (inches)',
yAxisID: 'y2',
order: 1,
fill: false,
}
]
},
options: {
plugins: {
googleSheets: {
docId: '121DpBzwABbNB7JO3--dXGTI3CE2LL1WwPHXKCYDdsKM',
sheet: 'Weather',
labelColumn: 'Labels',
dataColumns: ['Temperature', 'Precipitation'],
}
},
scales: {
yAxes: [{
id: 'y1',
}, {
id: 'y2',
position: 'right',
gridLines: {
drawOnChartArea: false,
},
}]
}
}
}

We are rewarded with the following graph:

Data for this image is pulled from the Google Sheet and then graphed across multiple Y axes
Data for this image is pulled from the Google Sheet and then graphed across multiple Y axes

Filtering data

QuickChart supports dynamic filtering using the filter property.

For example, this configuration will display specific labels according to custom Javascript logic:

{
// ...
plugins: {
googleSheets: {
sheetUrl:
'https://docs.google.com/spreadsheets/d/121DpBzwABbNB7JO3--dXGTI3CE2LL1WwPHXKCYDdsKM/edit#gid=0',
labelColumn: 'Name',
dataColumns: ['Usage count', 'Payment'],
filter: {
// Exclude Joe's column
label: (labelName) => labelName !== 'Joe',
},
},
},
}

Limitations

As noted above, charts will update at most once every 30 seconds.

The user must refresh the page or reload the image in order to see the latest spreadsheet data. Some clients cache images (for example, GMail caches images for about 48 hours on email open). In such cases, the chart may not update after caching has taken place.

Further reading

The look and feel of the chart is completely customizable using the Chart.js documentation. You should also see the QuickChart documentation for more information on shortcuts and plugins.

For starters, try replacing bar with line in the above examples to get a line graph instead of a bar chart!

If you're looking for shorter URLs, check out the URL shortener documentation.

QuickChart is open source for individuals and organizations that wish to self-host. Or, you can sign up for QuickChart in order to generate charts on our infrastructure. Feel free to reach out with any questions!


Ian Webster

About the author

Ian Webster is a software engineer and former Googler based in San Mateo, California. He has helped Google, NASA, and governments around the world improve their data pipelines and visualizations. In 2018, Ian created QuickChart, a collection of open-source APIs that support data visualization efforts.

Email · LinkedIn · Twitter