Monday, July 8, 2013

OBIEE dual Y line chart / graph using Javascript

In the new 305 SampeApp VM (Virtual Machine) available here  there is a sample of Dual Y line chart in dashboard 3.2, page Dyal Y Axis.
I wanted to find out how it is done, since it seems safer than using external engine such as  Google, described here. (There is also a post named OBIEE dual Y bar using BI Publisher and you might want to see:OBIEE - Dual Y axis line and Dual axis Bar charts: the easy, unsupported and not recommended way).
I could see on the chart, those are highchart.com java scripts. I don't know the legal aspect, but just for the sake of testing I copied the scripts folder from the VM to my local installation.
In case you don't have AnalyticsRes set up on your BI Server, please do, as described here.
So I copied the SampleApp/scripts folder under AnalyticsRes on the VM to the equivalent on my computer (MWHOME\instances\instance1\bifoundation\OracleBIPresentationServicesComponent\coreapplication_obips1\analyticsRes\SampleApp\Scripts). It is ~1MB of scripts.

In OBIEE I created an Analysis based on Sample Sales Lite:

 and copied the Narrative definition from the SampleApp. I couldn't  see it in the results tab but in the "show results how it will look in the Dashboard" It looked interesting:
Off course the legend and the scale legend was all wrong and needed fixing.

This was the original Narrative:

Header:

<script type='text/javascript' src='/analyticsRes/SampleApp/Scripts/highcharts/JQuery/jquery-1.8.2.min.js'></script>
<script src='/analyticsRes/SampleApp/Scripts/highcharts/highcharts.js'></script>
<script src='/analyticsRes/SampleApp/Scripts/highcharts/modules/exporting.js'></script>

<script type='text/javascript'>
$(function() {

var options = {
           chart: { renderTo: 'container2', zoomType: 'xy' },
                                                title: { text: 'Evolution Three different scale on the same chart' },
                                                subtitle: { text: 'Source: OBIEE SampleApp' },
                                                xAxis: [{ categories: [] }],
                                                yAxis: [
                                                                { labels: { formatter: function() { return this.value +' USD'; }, style: { color: '#89A54E' } }, title: { text: 'Unit Price', style: { color: '#89A54E' } } },
                                                                { gridLineWidth: 0, title: { text: 'Process Time', style: { color: '#AA4643' } }, labels: { formatter: function() { return this.value +' days'; }, style: { color: '#AA4643' } }, opposite: true },
                                                                { labels: { formatter: function() { return this.value +''; }, style: { color: '#89A54E' } }, title: { text: '# of Orders', style: { color: '#89A54E' } } }
                                                ],
                                                tooltip: { formatter: function() {var unit = { 'Temperature': '°C', 'Sea-Level Pressure': 'mb','test':'' }[this.series.name]; return ''+this.x+':'+this.y ; } },
                                                legend: { layout: 'vertical', align: 'left', x: 120, verticalAlign: 'top', y: 80, floating: true, backgroundColor: '#FFFFFF'},
                                                series: [
                                                                {name: 'Unit Price', type: 'spline', color: '#AA4643', yAxis: 1, marker: { enabled: false }, dashStyle: 'shortdot', data : []},
                                                                {name: 'Process Time', color: '#89A54E', type: 'spline', data: [] },
                                                                {name: '# of Orders', color: '#3ADF00', type: 'spline', data: [],  yAxis: 2 } ]
                                                };


                                               
                                               
Body:

options.series[0].data.push(parseFloat("@2".replace(" ", "")));
options.series[1].data.push(parseFloat("@3".replace(" ", "")));
options.series[2].data.push(parseFloat("@4".replace(" ", "")));
options.xAxis[0].categories.push('@1');                                               



Postfix:

var chart = new Highcharts.Chart(options);
});
</script>
<div id='container2' style='min-width: 850px; height: 400px; margin: 0 auto'></div>



we can see the 3 Javascripts being used:
'/analyticsRes/SampleApp/Scripts/highcharts/JQuery/jquery-1.8.2.min.js'
'/analyticsRes/SampleApp/Scripts/highcharts/highcharts.js'
'/analyticsRes/SampleApp/Scripts/highcharts/modules/exporting.js'


 The last one "exporting.js", is optional. It is responsible for the print and export options on the right top.




So it seems all changes need to be done in the header.

I'm OK with the internal Left Axis, but I want to rename it to Revenue.
So it's
 { labels: { formatter: function() { return this.value +' USD'; }, style: { color: '#89A54E' } }, title: { text: 'Revenue', style: { color: '#89A54E' } } },
instead of:
{ labels: { formatter: function() { return this.value +' USD'; }, style: { color: '#89A54E' } }, title: { text: 'Unit Price', style: { color: '#89A54E' } } },

the Right Axis was described here:
{ gridLineWidth: 0, title: { text: 'Process Time', style: { color: '#AA4643' } }, labels: { formatter: function() { return this.value +' days'; }, style: { color: '#AA4643' } }, opposite: true },
And I changed it to 
{ gridLineWidth: 0, title: { text: 'Billed Quantity', style: { color: '#AA4643' } }, labels: { formatter: function() { return this.value +' Units'; }, style: { color: '#AA4643' } }, opposite: true }, 

the opposite:true is a good hint, where it is located.

There are actually 2 Axis on the left so the leftmost of them was changed from:
{ labels: { formatter: function() { return this.value +''; }, style: { color: '#89A54E' } }, title: { text: '# of Orders', style: { color: '#89A54E' } } } 
to: 
{ labels: { formatter: function() { return this.value +'USD'; }, style: { color: '#89A54E' } }, title: { text: 'Discount', style: { color: '#89A54E' } } } 

Now comes the harder part, the tooltip:
tooltip: { formatter: function() {var unit = { 'Temperature': '°C', 'Sea-Level Pressure': 'mb','test':'' }[this.series.name]; return ''+this.x+':'+this.y ; } },
I have no idea what the Temperature part does, on the other hand I'm happy with the result, so Ill leave it unchanged.

What is left is to change the labels to fit our series (the floating window on the left).
From:
legend: { layout: 'vertical', align: 'left', x: 120, verticalAlign: 'top', y: 80, floating: true, backgroundColor: '#FFFFFF'},
 series: [ 

{name: 'Unit Price', type: 'spline', color: '#AA4643', yAxis: 1, marker: { enabled: false }, dashStyle: 'shortdot', data : []},
{name: 'Process Time', color: '#89A54E', type: 'spline', data: [] },
{name: '# of Orders', color: '#3ADF00', type: 'spline', data: [],  yAxis: 2 } ]


 I prefer the legend location on the top and a bit to the left.
To:
legend: { layout: 'vertical', align: 'left', x: 60, verticalAlign: 'top', y: 1, floating: true, backgroundColor: '#FFFFFF'},
series: [ {name: 'Revenue', type: 'spline', color: '#AA4643', yAxis: 1, marker: { enabled: false }, dashStyle: 'shortdot', data : []},
{name: 'Billed Quantity', color: '#89A54E', type: 'spline', data: [] },
{name: 'Disscount Amount', color: '#3ADF00', type: 'spline', data: [],  yAxis: 2 }]


So the result is:

The complete Narrative is now (of course remember to check the "Contains HTML Markup"):

Header:

<script type='text/javascript' src='/analyticsRes/SampleApp/Scripts/highcharts/JQuery/jquery-1.8.2.min.js'></script>
<script src='/analyticsRes/SampleApp/Scripts/highcharts/highcharts.js'></script>
<script src='/analyticsRes/SampleApp/Scripts/highcharts/modules/exporting.js'></script>
<script type='text/javascript'>
$(function() {
var options = {
           chart: { renderTo: 'container2', zoomType: 'xy' },
                    title: { text: 'Sample of Three different scale on the same chart' },
                                                subtitle: { text: 'My Sample' },
                                                xAxis: [{ categories: [] }],
                                                yAxis: [
              { labels: { formatter: function() { return this.value +' USD'; }, style: { color: '#89A54E' } }, title: { text: 'Revenue', style: { color: '#89A54E' } } },
              { gridLineWidth: 0, title: { text: 'Billed Quantity', style: { color: '#AA4643' } }, labels: { formatter: function() { return this.value +' Units'; }, style: { color: '#AA4643' } }, opposite: true },
              { labels: { formatter: function() { return this.value +'USD'; }, style: { color: '#89A54E' } }, title: { text: 'Discount', style: { color: '#89A54E' } } }
                                                ],
               tooltip: { formatter: function() {var unit = { 'Temperature': '°C', 'Sea-Level Pressure': 'mb','test':'' }[this.series.name]; return ''+this.x+':'+this.y ; } },
                 legend: { layout: 'vertical', align: 'left', x: 60, verticalAlign: 'top', y: 1, floating: true, backgroundColor: '#FFFFFF'},
                           series: [
                                {name: 'Revenue', type: 'spline', color: '#AA4643', yAxis: 1, marker: { enabled: false }, dashStyle: 'shortdot', data : []},
                                {name: 'Billed Quantity', color: '#89A54E', type: 'spline', data: [] },
                               {name: 'Disscount Amount', color: '#3ADF00', type: 'spline', data: [],  yAxis: 2 } ]
                           };


Body:

options.series[0].data.push(parseFloat("@2".replace(" ", "")));
options.series[1].data.push(parseFloat("@3".replace(" ", "")));
options.series[2].data.push(parseFloat("@4".replace(" ", "")));
options.xAxis[0].categories.push('@1');                                               



Postfix:

var chart = new Highcharts.Chart(options);
});
</script>
<div id='container2' style='min-width: 850px; height: 400px; margin: 0 auto'></div>




Looks better, but there is some work to be done.




So since stealing java scripts from Oracle VM is not easy (And not the best policy); I wanted to be sure I can download the relevant scripts myself.

So I downloaded:
1. A newer version of jQwuery from jquery.com, specifically, Download the compressed, production jQuery 1.10.2.
2. Downloaded Highcharts 3.0.2 from http://www.highcharts.com/download
 extracted HighCharts.
Replaced the files at analyticsRes, had to do some minor modifications to the Narrative (jquery file is 1.10.2 now and not 1.8.2. Slightly different File Name).

And .... All is working fine. 



 


1 comment:

  1. Very good! I am test more no look in show results, only box

    ReplyDelete