Skip to main content

Creating Charts in Visualforce PDFs using Apex

This post describes how to use Apex components to display chart images in SalesForce. These chart images can be embedded in SalesForce or exported to other formats such as PDF.

Visualforce supports some charting, but these charts depend on client-side rendering using Javascript. If you're building PDFs or other reports in Visualforce, you'll have to use a static method for rendering chart images.

This means that you'll have to define the chart and its data in a controller and then render it as an Apex image on a page.

Code example

To get started, we'll define the controller on our Visualforce page:

<apex:page controller="ChartController" renderAs="pdf">
<apex:image url="{!dynamicUrl}"/>
</apex:page>

Then, we'll create a custom controller in Apex:

public class ChartController {
public String dynamicUrl {get;set;}
public ChartController() {
// Insert your chart config here. You can replace the data with dynamic values.
String config = '{'
+ ' type: "bar",'
+ ' data: {'
+ ' labels: ["Q1", "Q2", "Q3", "Q4"],'
+ ' datasets: [{'
+ ' label: "Users",'
+ ' data: [50, 60, 70, 180]'
+ ' }]'
+ ' }'
+ '}';

// Construct the URL
String encodedConfig = EncodingUtil.urlEncode(config);
dynamicUrl = 'https://quickchart.io/chart?c=' + encodedConfig;
}
}

Next, add https://quickchart.io as a Remote Site in Remote Site Settings.

The dynamic URL in the example above will display the following chart:

Chart image rendered in Salesforce via Apex component
Chart image rendered in Salesforce via Apex component

Dynamic data

Chances are you'll want to use a variable to fill the chart data. The config variable is just a string, so you can concatenate values from a variable as you would any other string.

For example, below we run a query and create a list of integers representing the data we wish to graph. Then, we use String.join() to convert the list into a comma-separated string:

public class ChartController {
public String dynamicUrl {get;set;}

public ChartController() {
// Query the Account data
List<Account> accounts = [SELECT Name, Spend__c FROM Account LIMIT 4];

// Create lists to store the account names and spend data
List<String> accountNames = new List<String>();
List<String> accountSpends = new List<String>();
for (Account acc : accounts) {
accountNames.add(acc.Name);
accountSpends.add(String.valueOf(acc.Spend__c));
}

// Set up chart config and replace the data with dynamic values.
String config = '{'
+ ' type: "bar",'
+ ' data: {'
+ ' labels: [' + String.join(accountNames, '","') + '],'
+ ' datasets: [{'
+ ' label: "Spend",'
+ ' data: [' + String.join(accountSpends, ',') + ']'
+ ' }]'
+ ' },'
+ ' options: {'
+ ' scales: {'
+ ' yAxes: [{'
+ ' ticks: {'
+ ' beginAtZero: true'
+ ' }'
+ ' }]'
+ ' }'
+ ' }'
+ '}';

// Construct the URL
String encodedConfig = EncodingUtil.urlEncode(config);
dynamicUrl = 'https://quickchart.io/chart?c=' + encodedConfig;
}
}

This example creates a chart with Account Names on the X-axis and Account Spend on the Y-axis.

Chart image rendered using Apex with dynamic queried data
Chart image rendered using Apex with dynamic queried data

Customization

Note that you can further customize your chart by setting other API parameters.

The chart itself is very customizable - you can render any Chart.js configuration. Have a look at our chart gallery to get ideas, or get started with the developer documentation.

Embedding elsewhere

The QuickChart API returns PNG images by default. The <apex:image> tag will allow you to embed the image in your VisualForce page. You can then render the Visualforce page as a PDF file (see example).


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