Skip to Content

I had been interested in trying out some new JavaScript libraries particularly related to the area of data visualization. I felt that some of these offered very promising complementary functionality to the standard BSP user interface building blocks. I plumped for D3.js as it seems to have gained some popularity and I liked what I saw. To test it out I decided to add a simple bar chart to a BSP application using D3.js.

For this purpose I created a small stateful BSP application. I then fetched some test data from into a static public table of the BSP application class YCL_TEST2=>DATA and created a main page set as initial BSP page containing a htmlb:tableView to display this data.  Finally, I set selectionMode to SINGLESELECT and saved the currently selected row number to YCL_TEST2=>SELECTEDROWINDEX so it is available to the window which will contain the d3 created bar chart and will be called via a window.open statement when the user clicks on a htmlb:button at the top of the page.

/wp-content/uploads/2014/04/image0_433686.png

The test data used for this demonstration in YCL_TEST2=>DATA takes the form of total cost of labour and subcontracted activities in warranty claims by customer and month. The concept of this demonstration BSP is that when the user selects a line and hits the button at the top of the page a popup with the a bar chart showing the total value claimed each month by the customer of the selected line.

To begin building the bar chart I downloaded the d3.js library and uploaded it to the BSP application. As this was done purely for research in a development environment, I used the non minified version of the library.

/wp-content/uploads/2014/04/image1_433687.png

/wp-content/uploads/2014/04/image2_433688.png

To be able to use the data in our table we need to convert it from the internal ABAP to a more JavaScript friendly format. I chose to convert our data to a json file format contained in a public string attribute of our application class. This was done in the OnInitialization event of the popup window with some ABAP code that once it has extracted the vendor of the line highlighted in the main window it then generates a JSON formatted string with the two attributes month and value containing the relevant information.

/wp-content/uploads/2014/04/image4_433690.png

And finally I created the layout of my BSP page which also contains in the head my JavaScript code using D3 that generates my bar chart as well some CSS formatting. To learn a bit about D3 and to guide me in creating I used a few resources but I should particularly credit http://bost.ocks.org/mike/bar/, https://www.dashingd3js.com/, https://gist.github.com/jasondavies/2300078/ and http://jsfiddle.net/robdodson/KWRxW/.

<!doctype html>
<html lang=
“en”>
<head>
<meta charset=
“utf-8”>
<title>Claims by
<%= parnr %> </title>

<style>
.chart {
background-color: #eee;
}

.chart rect {
stroke: white;
fill: steelblue;
}

.axis {
shape-rendering: crispEdges;
}

.x.axis line {
stroke: black;
}

.y.axis line {
stroke: black;
}

.axis text {
font-size: 12px;
}
</style>

<script type=“text/javascript” src=“d3.js”></script>
<script type=
“text/javascript”>

function load() {
var results,
data = [],
chart,
bars,
margin = 100,
w = 50,
h = 500,
x, y,
xAxis, yAxis;

var json = <%= ycl_test2=>json %>;
results = d3.map( json );
results.forEach( function( key, val ) {
var result = {};
result.month = new Date(2010, ( parseInt( val.Month.slice(4,6),
10 ) – 1 ), 15);
result.value = parseInt( val.Value.replace( /,/g,
), 10 );
data.push( result );
} );

chart = d3.select( ‘body’ ).append( ‘svg’ )
.attr(
‘class’, ‘chart’ )
.attr(
‘width’, 800 )
.attr(
‘height’, h )
.append(
‘g’);

d3.select(‘svg g’)
.attr(
‘transform’, ‘translate(50, 50)’);

x = d3.time.scale()
.domain( [new Date(2010, 0, 1), new Date(2010, 11, 31)] )
.range( [0, ( w * 12 )] );

y = d3.scale.linear()
.domain( [0, d3.max( data, function( d ) { return d.value; } )] )
.rangeRound( [0, h – margin] );

// Bars
bars = chart.append(‘g’)
.attr(
‘class’, ‘bars’);

bars.selectAll( ‘rect’ )
.data(
data )
.enter().append(
‘rect’ )
.attr(
‘x’, function( d, i ) { return x( d.month ) – 23; } )
.attr(
‘y’, function( d ) { return (h – margin) – y( d.value ) } )
.attr(
‘width’, w )
.attr(
‘height’, function( d ) { return y( d.value ) } )
.append(
‘g’);

// Axis
xAxis = d3.svg.axis()
.scale(x)
.ticks(d3.time.month)
.tickSize(6, 3, 1)
.tickPadding(10);

yAxis = d3.svg.axis()
.scale(d3.scale.linear().domain( [0, d3.max( data, function( d ) { return d.value; } )] ).rangeRound( [h – margin, 0] ))
.tickSize(6, 3, 1)
.orient(‘right’);

chart.append(‘g’)
.attr(
‘class’, ‘x axis’)
.attr(
‘transform’, ‘translate(0, ‘ + (h – margin) + ‘)’)
.call(xAxis);

chart.append(‘g’)
.attr(
‘class’, ‘y axis’)
.attr(
‘transform’, ‘translate(‘ + x.range()[1] + ‘)’)
.call(yAxis);

};
</script>
</head>
<body onload=“load()”>
</body>
</html>

And here’s the end result. As described above when the user selects a line from the main page they are shown a bar chart of the customers from that line’s claims over.

/wp-content/uploads/2014/04/image3_433703.png

So there we go. A little rough around the edges but good enough for a first attempt destined for a non production environment and there’s might be something in there that others could find useful.

I found this an interesting learning exercise and I’m still enthusiastic about the possibilities of enhancing the capabilities of BSP by incorporating open source JavaScript libraries. Specifically in respect to D3.js I really liked the easy with which SVG and other screen elements could be manipulated and the approach to binding to screen elements seems particularly well suited to creating visualization of data. On the downside I found the learning a bit steeper than expected (in fact I had originally planned to create various different type of graph for the same data set but ran out of time because it took me longer than I thought to get my code working) but this is obviously only an initial hurdle. I also felt that although I liked the flexibility of d3.js there were more steps than I would have expected for data visualisation library to such a standard task as creating a bar chart. I can see why this is but this draw back made me quite interested in the NVD3.js project which “to build re-usable charts and chart components for d3.js without taking away the power that d3.js gives you”. But that will have to wait for another time.

To report this post you need to login first.

4 Comments

You must be Logged on to comment or reply to a post.

  1. HariKrishna Malladi

    Hi Jamie MacCuish,

    I followed your blog, it’s very good explanation….. But my requirement is to display data in form of charts in CRM WebUI. I have a DB table & I want to show its data (not in tabular manner), but in graphical way through column charts.

    Could you please help me how can i proceed in my requirement.


    Thanks,

    HariKrishna.M

    (0) 
  2. Octav Onu

    Very nice Jamie .

    Have you any idea why my BSP cannot understand <svg> tag ? The same web page i can see it if i am placing it to my personal web server…in SAP HTML Container cannot see svg in action !

    (0) 
    1. Cody Deckard

      Octav,

      Try appending the SVG to an element other than the body tag. I was able to successfully do something similar, but I ran into the same issue as you and had to append it to a particular div for it to show up.

      d3.select(“body”)….

      should be something like the following. Unfortunately we just refreshed our sandbox and I can’t recall which div I actually attached it to, but you should be able to find one with your browser.

      d3.select(“div.main”)

      Cody

      (0) 

Leave a Reply