Charting is the graphical representation of data.

Visualforce charting is a collection of components that provide a simple and intuitive way to create charts on Visualforce pages and custom components.

Visualforce charting gives:

  • An easy way to create customized business charts, based on data sets you can create directly from SOQL queries or by building the data set in your own Apex code.
  • By combining and configuring individual data series, you can compose charts that display your data in ways meaningful to your organization.
  • Visualforce charts are rendered client-side using JavaScript.
  • This allows charts to be animated and visually exciting and chart data can load and reload asynchronously which can make the page feel more responsive.

Used when:

  • The standard Salesforce charts and dashboards are insufficient.
  • Creating custom pages that combine charts and data tables in ways that are more specific to our requirement.

Features:

  • Visualforce charting is designed to be flexible and also easy to use.
  • It offers variations on bar, line, area, pie charts ,radar, gauge, and scatter charts
  • For different chart types, greater page interactivity and customization we can use JavaScript charting library by:
    • Integrating Visualforce and Google Charts
    • Using JavaScript in Visualforce Pages

Salesforce has already provided us with Reports and Dashboard that gives us the functionality to create charts, then why should we use Visualforce charting?

Some basic differences are listed below:

 

SALESFORCE CHARTS

VISUALFORCE CHARTS

I

     Salesforce charts 

Charts are nearly static or with minimal animations for which we  will have to check certain checkboxes while creating the chart.

Visualforce Chart
 Outstanding animations which are auto-generated as we create a chart  on a Visualforce page (pie wedges with movement as well as data value)

II

 

 

3

 Combinational charts cannot be created.

4

Combinational charts can be created.

III

 Integration with Google charts is not possible

 Integration with Google charts is possible

IV Customization according to business requirement is minimal. Charts can be highly customized according to business requirement of the organization

 

Creating a Simple Chart using Visualforce :

Here is a pie chart representing the percentage of estimated World population by continent.

Visualforce Page:
  1.       <apex:page controller=”PieChartController” title=”Pie Chart” sidebar=”false” showHeader=”false”>
  2.          <apex:sectionHeader subtitle=”Percentage of estimated World population by continent”/>
  3.             <apex:chart height=”450″ width=”550″ data=”{!pieData}”> 
  4.                         <apex:pieSeries dataField=”data” labelField=”name”/> 
  5.                         <apex:legend position=”right”/> 
  6.             </apex:chart> 
  7. </apex:page>

 

<apex:pieSeries> is a data series to be rendered as wedges in a Visualforce pie chart. At a minimum we must specify the fields in the data collection to use as label and value pairs for each pie wedge.

Note: This component must be enclosed within an <apex:chart> component and also we can only have one <apex:pieSeries> in a chart.

The visualforce page alone is not sufficient to display the chart according to our requirement. It needs to be paired with a controller that can supply the pie chart data. Here we pair it with PieChartController class. Normally we perform a SOQL query to calculate the pie wedge data from our application, but to keep this simple let’s give some rough data:

Apex class:
  1.       public class PieChartController {
  2.                 //For Pie Chart 
  3.                public List<PieWedgeData> getPieData()  {
  4.                            List<PieWedgeData> data = new List<PieWedgeData>();
  5.                            data.add(new PieWedgeData(‘Africa’, 14));
  6.                            data.add(new PieWedgeData(‘Antartica’,1 ));
  7.                            data.add(new PieWedgeData(‘Asia’, 60));
  8.                            data.add(new PieWedgeData(‘Australia’, 2));
  9.                            data.add(new PieWedgeData(‘Europe’, 10)); 
  10.                        data.add(new PieWedgeData(‘North America’, 8)); 
  11.                        data.add(new PieWedgeData(‘South America’, 5)); 
  12.                       return data; 
  13.            }
  14.            // Wrapper class for Pie Chart 
  15.            public class PieWedgeData   {
  16.                       public String name { get; set; } 
  17.                        public Integer data { get; set; } 
  18.    
  19.                        public PieWedgeData(String name, Integer data) { 
  20.                                    this.name = name; 
  21.                                    this.data = data; 
  22.                        } 
  23.           }
  24.  }

 

This is how the simple pie chart looks like after implementing the above code.

simple pie chart

 

Figure: Pie Chart representing the percentage of estimated World population by continent

Creating a Pie Chart on a Custom Object:

 

We can also create charts on custom objects of our app according to our business requirements.

The sample below gives an idea about creating a pie chart in Visualforce on a custom object i.e., Position (Position__c) which is a part of the Recruitment app. The ultimate aim of this sample illustration is to represent the Count of Positions in each Functional Area on a pie chart.

 

Visualforce Page:
  1.       <apex:page controller=”PositionCountController” title=”Pie Chart” >
  2.        <apex:sectionHeader subtitle=”Pie Chart – Count of positions by functional area”/>
  3.             <apex:chart height=”450″ width=”700″ data=”{!positionCountData}” >
  4.                 <apex:pieSeries dataField=”posCount” labelField=”Functional_Area”/> 
  5.                  <apex:legend position=”right”/> 
  6.             </apex:chart> 
  7. </apex:page>

 

We know that the visualforce page itself is not sufficient to display the chart according to our requirement. So, let us pair it with a PositionCountController class that can supply the data. Here we are performing a SOQL query to retrieve the pie wedge data from the application.

Apex class:
  1.       public class PositionCountController {
  2.                   public List<PositionData> getPositionCountData ()  {   
  3.       // SOQL query to get the count of positions by its functional area
  4.                                List<AggregateResult> countdata = [select count(Name) cnt,Functional_Area__c
  5.                                                                                            from position__c
  6.                                                                                           group by functional_area__c
  7.                                                                                           order by Functional_Area__c asc];
  8.                                list<SelectOption> options = new list<SelectOption>();
  9.       // PickListController is used to get values from picklist since Functional area has datatype as picklist
  10.                           options = PickListController.getPicklistValues(new Position__c(),’Functional_Area__c’);
  11.   // Position data is stored in a list    
  12.                            List<PositionData> posList = new List<PositionData>();
  13.                            PositionData pos;
  14.                            Integer j=0;
  15.                            for (Integer i=0; i<options.size(); i++) {
  16.                                   pos = new PositionData();
  17.                                   String FAList = ”;
  18.                                   String FAPickList = null;
  19.                                   if(i!=0) {
  20.                                                  FAPickList = options[i-1].getLabel();
  21.                                    }
  22.                                   if(j < countdata.size()){
  23.                                         FAList = String.valueOf(countdata[j].get(‘Functional_Area__c’));
  24.                                   }
  25.                                   if(FAPickList == FAList) {
  26.                                          pos.posCount = Double.valueOf(countdata[j].get(‘cnt’));
  27.                                         pos.Functional_Area = String.valueOf(countdata[j].get(‘Functional_Area__c’));
  28.                                          pos.Functional_Area = FAPickList;
  29.                                          j++;
  30.                                   }
  31.                                  else{
  32.                                         pos.posCount = 0;
  33.                                          pos.Functional_Area = FAPickList;
  34.                                   } 
  35.                            posList.add(pos);
  36.   // In case there are positions without any specific functional area they are grouped under “Others”
  37.                           if(i==0) {
  38.                                pos.Functional_Area = ‘Others’;
  39.                            } 
  40.                    }
  41.                 return posList; 
  42.            } 
  43.   // Wrapper class for Pie Chart 
  44.        public class PositionData { 
  45.                      public Double posCount; 
  46.                      public String Functional_Area;
  47.         }
  48.  }

 

When you click on save save  you will see an error on your screen similar to the one shown below:

error

This is because we have used a PickListController class and have not created it yet.

Here, I have used a PickListController class as the Functional Area field is of the data type picklist. By using this class we can retrieve all the values in the picklist as a list. This class can be re-used in any apex class to retrieve values from a picklist by just calling it in your code.

Create an apex class using the code below:

 

Apex class:
  1.       global without sharing class PickListController {
  2.       // Get a list of picklist values from an existing object field.
  3.                 global static list<SelectOption> getPicklistValues(SObject obj, String fld) {
  4.                             list<SelectOption> options = new list<SelectOption>();
  5.       // Get the object type of the SObject.
  6.                                         Schema.sObjectType objType = obj.getSObjectType();
  7.       // Describe the SObject using its object type.
  8.                                       Schema.DescribeSObjectResult objDescribe = objType.getDescribe();      
  9.       // Get a map of fields for the SObject
  10.                                   map<String, Schema.SObjectField> fieldMap = objDescribe.fields.getMap();
  11.   // Get the list of picklist values for this field.
  12.                                   list<Schema.PicklistEntry> values = fieldMap.get(fld).getDescribe().getPickListValues();
  13.   // Add these values to the selectoption list.
  14.                                   for (Schema.PicklistEntry a : values) {
  15.                              options.add(new SelectOption(a.getLabel(), a.getValue()));
  16.                                    }
  17.             return options;
  18.         }
  19. }

 

Save save this class and then execute the previous code.

You are expected to get an output which will look somewhat similar to the one below:

5

 Figure: Pie Chart representing the count of positions in each functional area 

When you hover the mouse across each pie wedge, you can see the wedge moving outwards and simultaneously displaying the data that represents the position count, which is contained within it.

Thereby, we have created an interactive and responsive chart representing the Count of Positions in each Functional Area in the Recruitment app.

 

Creating a Combinational Chart on a Custom Object:

In Salesforce we could not combine different charts to meet business requirements. Visualforce charting facilitates the use of combinational charts.

The sample below gives an idea about creating a combinational chart combining a bar chart and line chart in Visualforce once again on the Position (Position__c) custom object which is the part of Recruitment app.

Here :

1. Bar chart represents the Count of Positions in each Functional Area and

2. Line chart represents the Count of Open Positions in each Functional Area

The ultimate aim of this sample illustration is to compare the Count of Positions and Count of Open Positions in each Functional Area on a single combinational chart.

 

Visualforce Page:
  1.       <apex:page controller=”CombinationalChartController”>
  2.          <apex:sectionHeader subtitle=”Combinational Chart”/>
  3.             <apex:chart height=”500″ width=”700″ data=”{!combinationalChartControllerData}”>
  4.                  <apex:axis type=”Numeric” position=”left” fields=” posCount1″ title=”Position Count”
  5.                     grid=”true”/>
  6.                  <apex:axis type=”Category” position=”bottom” fields=”Functional_Area”
  7.                     title=”Functional Area”/>   
  8.                  <apex:lineSeries title=”Open positions by functional area” axis=”left”  fill=”true”
  9.                    fillColor=”#00FF00″ xField=”Functional_Area” yField=” posCount2″ markerType=”cross”                  
  10.                 markerSize=”4″ markerFill=”#FF0000″/>
  11.              <apex:barSeries title=”Count of positions by functional area” orientation=”vertical” axis=”left”
  12.                 colorSet=”#82CAFF” xField=”Functional_Area” yField=”posCount1″/>
  13.         </apex:chart> 
  14.   </apex:page>

 

<apex:axis> defines an axis for a chart. This is used to set the units, scale, labeling, and other visual options for the axis. We can define up to four axes for a single chart, one for each edge.

<apex:lineSeries> is a data series to be rendered as connected points in a linear Visualforce chart. At a minimum we must specify the fields in the data collection to use as X and Y values for each point, as well as the X and Y axes to scale against.

<apex:barSeries> is a data series to be rendered as bars in a Visualforce chart. At a minimum we must specify the fields in the data collection to use as X and Y values for each bar, as well as the X and Y axes to scale against.

Note: This components must be enclosed within an <apex:chart> component. We can have multiple <apex:barSeries> and <apex:lineSeries> components in a single chart.

We pair the visualforce page with CombinationalChartController class to retrieve the data required for the combinational chart. Here we are performing two SOQL queries to retrieve data for:

1. Bar chart – showing the Position count

2. Line chart – showing the count of Position which are New & Open-Approved

 

Apex class:
  1.       public class CombinationalChartController{
  2.          public List<PositionData> getCombinationalChartControllerData()  {
  3.       // SOQL query to get the count of positions in each functional area   
  4.               List<AggregateResult> dataList1 = [select count(Name) cnt1,Functional_Area__c
  5.                                                                        from Position__c
  6.                                                                        group by Functional_Area__c
  7.                                                                        order by Functional_Area__c asc];
  8.       // SOQL query to get the count of Open positions in each functional area                                          
  9.               List<AggregateResult> dataList2 = [select count(Name) cnt2, Functional_Area__c
  10.                                                                    from Position__c
  11.                                                                    where Status__c in ('New Position','Open - Approved')
  12.                                                                    group by Functional_Area__c
  13.                                                                    order by Functional_Area__c asc];
  14.            list<SelectOption> options = new list<SelectOption>();
  15.   // PickListController is used to get values from Functional area picklist
  16.           options = PickListController.getPicklistValues(new Position__c(),’Functional_Area__c’);
  17.           List<PositionData> posList = new List<PositionData>();
  18.           PositionData pos;
  19.           Integer j=0,k=0;
  20.           for (Integer i=0; i<options.size(); i++){
  21.                  pos = new PositionData();
  22.                  String FAList1 = ”;
  23.                  String FAList2 = ”;
  24.                  String FAPickList = null;
  25.              if(i!=0){
  26.                   FAPickList = options[i-1].getLabel();
  27.               }
  28.               if(j < dataList1.size()){
  29.                  FAList1 = String.valueOf(dataList1[j].get(‘Functional_Area__c’));
  30.               }
  31.               if(k < dataList2.size()){
  32.                   FAList2 = String.valueOf(dataList2[k].get(‘Functional_Area__c’));
  33.               }
  34.               if(FAPickList == FAList1 && FAPickList == FAList2){
  35.                   pos.posCount1= Double.valueOf(dataList1[j].get(‘cnt1′));
  36.                   pos.posCount2= Double.valueOf(dataList2[k].get(‘cnt2′));
  37.                   pos.Functional_Area = FAPickList;
  38.                   j++;
  39.                   k++;
  40.               }
  41.               else if(FAPickList == FAList1 && FAPickList!= FAList2){
  42.                     pos.posCount1= Double.valueOf(dataList1[j].get(‘cnt1′));
  43.                     pos.posCount2= 0;
  44.                     pos.Functional_Area = FAPickList ;
  45.                     j++;
  46.               }
  47.               else{
  48.                   pos.posCount1= 0;
  49.                   pos.posCount2= 0;
  50.                   pos.Functional_Area = FAPickList ;
  51.               }
  52.               if(i==0){
  53.                   pos.Functional_Area = ‘Others’;
  54.               } 
  55.               posList.add(pos);
  56.           }
  57.           return posList; 
  58.       }  
  59.   // Wrapper class for Pie Chart 
  60.        public class PositionData{ 
  61.           public Double posCount1{get; set;}
  62.           public Double posCount2{get; set;}
  63.           public String Functional_Area {get; set;}
  64.       }
  65. }

 

Click on save save  to execute the above code.

 

Expected Output:

 

6

                                  Figure: Combinational chart

The expected output will look somewhat similar to the figure above. It represents the bar chart and line chart of two different qureies on the same chart.

 

7

 

Figure: Highlighted Bar Chart representing the count of positions in each functional area represented on a Combinational chart

As you hover the mouse across each bar of the chart you can see the bar highlighted and simultaneously displaying the Count of Positions corresponding to each Functional Area.

 

8

     

Figure: Highlighted Line Chart representing the count of Open positions in each functional area represented on a Combinational chart

As you hover the mouse across each cross-point of the line chart you can see the line getting highlighted and simultaneously displaying the Count of Open Positions in each Functional Area.

Limitations and Considerations of Visualforce Charting:

  • Can be rendered only on browsers which support scalable vector graphics (SVG).
  • Cannot be used in email messages or email templates yet.
  • Sends errors and messages so it is advised to keep a JavaScript debugging tool like Firebug, active during development.
  • Dynamic (Apex-generated) charting components are not yet supported.
Sources/Reference:
http://www.salesforce.com/us/developer/docs/pages/Content/pages_charting.htm
Be Sociable, Share!
3
0



14 Responses to “Visualforce Charting”

  1. Neta

    Thank you very much for the very helpful post.
    One comment: Is it possible that in the apex class of “Creating a Pie Chart on a Custom Object” the line “for (Integer i=0; i<options.size(); i++) {" should be "for (Integer i=0; i<options.size()+1; i++) {" ? I think that the original code misses the last option in the picklist (only tried it on standard object but guess it's the same).

  2. Salesforce Learner

    Can we display percentage of the value which is being used by each wedge in the chart (same functionality which is displayed in Standard pie charts)?

  3. Harsha

    Hi I am trying develop a chart like if i click on the part of the chart it has to redirect to another page and it has to show those details on that page how can i achieve this.
    Thanks

    • Admin

      Hi Harsha,

      Could you please post the question on the forum where our expert members are active and you will get an early response. Thank You.

  4. mandava

    can i use list controller instead of apex(soql in apex controller)

  5. kd

    hi.. i have another requirment i wann to show bar series with lineseries . in which data set is grouped by week as well as group by another field called GEO .. Line show the geo Weekly Amount white Bar show total week amount . Can you Plz help me how i show data on chart which is group by two different fields?

    • Abhishek Sivasubramanian

      As mentioned in the combinationalChartController apex code, we have 2 SOQL queries. Modify the first SOQL query to group by Week and modify the second SOQL query to group by GEO. Make sure that the order by is mentioned in both the SOQL queries so that you know that the first item in the dataset of first SOQL and first item in the dataset of second SOQL are in correct sequence.

      Now, bind the two dataset to the two charts. This should hopefully solve the issue.

  6. Salesforce Learner

    This is really great…. Awesome is the word…. :) Im trying to display a similar kind of pie chart but instead of the picklist field ‘Functional_Area__c’ I want to use a formula type field. How can this be achieved?

    • Krishna

      Hi,

      Could you please post the question on the forum. I am sure one of our community member will post you the answer for your query.

    • Abhishek Sivasubramanian

      From a technical standpoint, you can use formula field in your chart controllers. You should make sure that the formula field values in records will be predictable. If the data being calculated in the formula field is not at all predictable, then the data set that you build based on this formula field might render the charts in an unexpected and awkward look.

  7. ezthde

    This one looks awesome and complicated to me (just kidding). Is it possible to design a visualforce chart and place it on salesforce dashboard ?

    • Celin Joseph

      Celin Joseph

      Hi Ezthde,
      Thank you for the compliment :)
      The answer to your question is yes, you can indeed design Visualforce pages containing charts which can be placed as dashboard components. A dashboard shows data from source reports as visual components which could be charts, gauges, tables or even Visualforce pages. Sounds amazing, isn’t?