Friday, July 13, 2012

Google Image Chart API - Compare data by Line chart

This API is very useful to generate graphs/charts without any API libraries or JavaScript. It provides the chart as images just by creating a URL. Using any language such as PHP, Java, .Net, Ruby, JavaScript, Apex, Visual force, Sales force, etc.. we can generate dynamic charts. 

For example:


The corresponding URL :

[http://chart.apis.google.com/chart?chds=0,50&chd=t:33,44,24,8,38,27,23,29,32,35,16,36,33,30,27,17,12,8,36,17,20,24,18,22,13,22,31,26,36,27,18%7C17,35,47,36,31,38,16,10,34,33,37,25,16,11,8,20,32,23,32,19,18,22,29,35,22,39,26,15,18,18,_&chxs=0,000000,12,0,lt,000000%7C1,000000,12,0,lt,000000&chxt=x,y&chco=9BCE32,0098FF&chls=2%7C2.5&chg=23.33,20.00&chxr=0,01,31,7%7C1,0,50,10&chxl=0:%7C1-Apr+%28Mar%29%7C8-Apr+%28Mar%29%7C15-Apr+%28Mar%29%7C22-Apr+%28Mar%29%7C29-Apr+%28Mar%29&chm=d,9BCE32,0,-1,9.0%7Cd,0098FF,1,-1,9.0&chma=9,9,9,9&chs=500x270&cht=lc&]

         I have generated this chart for comparing two months Google analytic data. I have integrated this chart to Sales force CRM using Apex language and Visual force UI along with the Google Analyics API.


Set the chart properties

   Chart size : chs=<width>x<height> Eg: chs=500x270
   Chart type : cht=<type>    Eg:cht=lc    (for line chart)

Set the chart data

   "chd" is the parameter used to send the chart data with the following format. The data series are separated by pipe character: "|" . The null values or empty values are represented by "_".

   chd=t:val,val,val|val,val,val...

Eg:- chd=t:33,44,24,8,38,27,23,29,32,35,16,36,33,30,27,17,12,8,36,17,20,24,18,22,13,22,31,26,36,27,18|

 17,35,47,36,31,38,16,10,34,33,37,25,16,11,8,20,32,23,32,19,18,22,29,35,22,39,26,15,18,18,_

Set the chart axis properties

   Visible Axes : chxt= <axis_1>,...,<axis_n> Eg: chxt=x,y
   Axis Range   : chxr= <axis_index>,<start_val>,<end_val>,<opt_step> |...| <axis_index>,<start_val>,<end_val>,<opt_step>
                         Eg: chxr=0,01,31,7|1,0,50,10
   Axis Labels  : chxl=<axis_index>:|<label_1>|...|<label_n>    |...|  <axis_index>:|<label_1>|...|<label_n>
                     Eg: chxl=0:|1-Apr+%28Mar%29|8-Apr+%28Mar%29|15-Apr+%28Mar%29|22-Apr+%28Mar%29|29-Apr+%28Mar%29


   Axis Label Styles : chxs= <axis_index><opt_format_string>,<opt_label_color>,<opt_font_size>,<opt_alignment>,<opt_axis_or_tick>,<opt_tick_color>,<opt_axis_color>
                             |...|
                             <axis_index><opt_format_string>,<opt_label_color>,<opt_font_size>,<opt_alignment>,<opt_axis_or_tick>,<opt_tick_color>,<opt_axis_color>
                           Eg: 0,000000,12,0,lt,000000|1,000000,12,0,lt,000000

Dynamic axis label position

     For x-axis, the default labels positions are 0 to 100. In my chart, need to show the days of a month. I have to show only 7 days apart.  so I set

       chxr=0,01,31,7 (0:x-axis, 01:fist_day, 31:last_day, 7: steps).

    For y-axis,  the default labels positions are 0 to 100. But we have to plot dynamic values. So I have find the y-min & y-max from both set of data and used a fixed step 10
    ie chxr=1,0,50,10 (1:y-axis, 0:y-min, 31:y-max, 10: steps)

  Combining both chxr=0,01,31,7|1,0,50,10

 
Dynamic axis scaling

    The y-axis data may vary dynamically. We have y-axis based on the plotted value, so use y-min & y-max from both set of data.
    ie, chds=0,50 (y-min, y-max)

Dynamic grid line position
 
   we have to position the grid lines on the axis labels that we are labelled dynamically. For both x & y axis, there are default 100 grid line step sizes. Then we can to set the grid positions using the parameter "chg".

   chg= <x_axis_step_size>,<y_axis_step_size>,<opt_dash_length>,<opt_space_length>,<opt_x_offset>,<opt_y_offset>

  so we have to calculate the x_axis_step_size & y_axis_step_size dynamically.

  We can use the (100 * axis_steps) / (axis_ max_value - axis_ min_value) to find out the gidline step size.

  Hence for x-axis & y -axis ,
     x_axis_step_size =(100 * x_steps) / (x_max - x_min) = (100 * 7) / (31 - 1) = 23.33
     y_axis_step_size = (100 * y_steps) / (y_max - y_min) = (100 * 10) / (50 - 0) = 20

  ie, chg=23.33, 20


Apex code to set up chart axis

Integer yMax, yMin, yDiv = 10;
decimal ySteps, xSteps;        
if(math.mod(maxValue,yDiv) != 0){
    yMax = ((maxValue/yDiv)+1)*yDiv;
}else{
    yMax = maxValue;
}

if(math.mod(minValue,yDiv)!= 0){
    yMin = ((minValue/yDiv))*yDiv;
}else{
    yMin = minValue;
}       
string str = '0,01,'+monthEnd+',7%7C1,'+yMin+','+yMax+','+yDiv; //0,01,31,7|1,0,20,5
chartObj.changeParam('cht' ,'lc');
chartObj.changeParam('chxr',str);
xSteps = decimal.valueOf(100*7)/decimal.valueOf(monthEnd-1); // 100*7/(31-1) = 23.33
if(yMax <= 0){
    yMax = 10;
}
ySteps = (decimal.valueOf(1000)/(decimal.valueOf(yMax) - decimal.valueOf(yMin)));
str = xSteps.setScale(2)+','+ySteps.setScale(2);
chartObj.changeParam('chds',yMin+','+yMax);
chartObj.changeParam('chg',str);
chartObj.changeParam('chxl','0:%7C1-'+currMonthName+'+%28'+prevMonthName+'%29'+'%7C8-'+currMonthName+'+%28'+prevMonthName+'%29'+'%7C15-'+currMonthName+'+%28'+prevMonthName+'%29'+'%7C22-'+currMonthName+'+%28'+prevMonthName+'%29'+'%7C29-'+currMonthName+'+%28'+prevMonthName+'%29');// 0:|01|08|15|22|29|31st

References:
https://developers.google.com/chart/image/docs/chart_params#gcharts_grid_lines/docs/chart_params#gcharts_grid_lines

NB: These posts are for my future references