threeheadsonapike

Salesforce frustrations? Ask one of our heads on a pike !

Category Archives: Google Visualization

Visualforce Charts and Google Visualization

Visualforce Charting – great feature but unusable as of now
Many customers would like to expose their data to specific clients using nice charts. One of the upcoming features of Salesforce is Visualforce charting.

These features would allow any developer to write either direct functions or remoting functions to load data into the charts. However as of now there are two main drawbacks to this feature:

  1. Salesforce will initially release this feature for the sandbox only. The official release is planned for Winter 2013 so if you are planning to develop charting and release them during the summer, you will be disappointed.
  2. Visualforce charts look great and do an easy job to create charts however; its current functionality is very limited. For example, for a bar chart there is no way to control the individual colors of the bars nor can you group a set of bars together having a single title on the y-axis and do this for each title (having a set of statuses per country for example).

Obviously there are hacks around this. Using jQuery you can manipulate the charts directly, coloring each individual bar, but after a mouse hover the colors will revert back to its original default coloring meaning you will require extra re-color functions. You can imagine this is not scalable and turns your page into a mess of Javascript horror.

That said, Salesforce is on the right path with Visualforce charts, being able to expose the data and having the innate power of Salesforce charts used on pages. Until the time we can actually use it on a production environment and being able to customize it, I would like to point to the great Google Visualization library and show you an example how this allows for customization.

Google Visualization
Let’s do an example with Google visualization and Javascript remoting. Google visualization allows for a rich set of charts, completely customizable and free to use. To see the possibilities, check out their gallery.

To begin, first load the library directly from Google in the head of your page, and we also a placeholder for a bar chart on the page:

<apex:page controller="DataController">

<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<div id="barChart"></div>
</apex:page>

This will load the Google library however now we need to fetch some data from Salesforce to actually show a bar chart and a pie chart. First let’s create our controller and add a container class that we can use to store our result and return it as a JSON object. We will call this GraphData.


global with sharing class DataController {

	global class GraphData {

		public String label { get; set; }
   		public List points { get; set;}

    		public GraphData(String label){
      			this.label = label;
      			this.points = new List();

    		}
         }
}

Our ChartData class will store a label for the point(s) and a list called points of type Double to store any number of points. Next – let us write a Javascript remoting function that can be accessed from our page to fetch the data. Notice:This is a fake query and will not work, it is simply used for example purposes.

Extending our Data Controller:


global with sharing class DataController {

	@RemoteAction
	global static List loadData(){

		List lGraphData = new List();

		List lCustomData = [ Select Country__c, Revenue1__c, Revenue2__c From CountryData__c ];

		for(CustomObjectData oData : lCustomData){
			GraphData oDataPoint = new GraphData(oData.Country__c);
			oDataPoint.points.add(oData.Revenue1__c);
			oDataPoint.points.add(oData.Revenue2__c);

			lGraphData.add(oDataPoint);
		}

		return lGraphData;
	}

	global class GraphData {

		public String label { get; set; }
   		public List points { get; set;}

    		public GraphData(String label){
      			this.label = label;
      			this.points = new List();

    		}
	}

}

Notice two things:

  1. We add the @RemoteAction tag before the function loadData to allow this function to become visible on the page using Javascript. Returning the list of data will automatically convert this object into JSON.
  2. Currently we add two custom fields in this example, Revenue1 and Revenue2. Using a list of points we can return any number of points. The only thing we need to pay attention to is what each number means when showing the chart.

Now our controller is ready to go – let’s fetch the data on the page and create the bar chart. Please see the following html:

<apex:page controller="DataController">

<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">

		google.load('visualization', '1.0', {'packages':['corechart']});

	      	google.setOnLoadCallback(drawCharts);

	      	function drawCharts() {

			DataController.LoadData(
				function(result, event){

                     			var visualization = new google.visualization.BarChart(document.getElementById('barChart'));

                     			var data = new google.visualization.DataTable();

                     			data.addColumn('string', 'Country');
                     			data.addColumn('number', 'Revenue 1');
                     			data.addColumn('number', 'Revenue 2');

                     			for(var i =0; i<result.length;i++){
                    				var p = result[i];

                        			data.addRow(p.label, p.points[0], p.points[1]);
                      			}

                     			var options = {
			          		title: 'Revenue 1 versus Revenue 2 per Country',
			          		chartArea:{ width: '90%', height: '90%' }

			        	};

                    			visualization.draw(data, options);
              		}, {escape:true});

		}


<div id="barChart"></div>

</apex:page>

Please note the following:

  1. We tell the Google library to load the ‘corechart’ capabilities: google.load(‘visualization’, ‘1.0’, {‘packages’:[‘corechart’]});
  2. Then we define a function that will be called after the packages are loaded, in our case ‘drawCharts’.
  3. Since we have three values, one for the label and two for the revenue values we have to create three columns, one string and two numbers:data.addColumn(‘string’, ‘Country’);
    data.addColumn(‘number’, ‘Revenue 1’);
    data.addColumn(‘number’, ‘Revenue 2’);
  4. Then we add rows to the data object, the first column will be the label of the result, and the second and third column will be result.points[0] and result.points[1] respectively.
  5. Finally we can draw the chart:  visualization.draw(data, options);

Hope this helps!