Skip to Content
Author's profile photo Jeroen van der A

Setting up a SDK bar chart

I will assume you have taken the steps in the developer manual here : http://help.sap.com/businessobject/product_guides/AAD12/en/ds12_dev_guide_en.pdf

To create a new SDK extension. The steps are described in paragraph 3.2.

The following code will result in this graph :

/wp-content/uploads/2013/12/barchartexample_picture1_343459.jpg

1 Create CSS :

Add the following line to contribution.xml

<cssInclude>res/css/component.css</cssInclude>

Add the following CSS code to res/css/component.css

.axis text {

  font: 10px sans-serif;

}

.axis path,

.axis line {

  fill: none;

  stroke: #000;

  shape-rendering: crispEdges;

}

.x.axis path {

  display: none;

}

benchmarkbar_label {

  position: absolute;

  top: 10px;

  right: 10px;

}

.benchmarkbar_benchmark {

  fill: steelblue;

  fill-opacity: .9;

}

.benchmarkbar_other {

  fill: steelblue;

fill-opacity: .6;

}

2 Create the component

Make sure that the following line is in the contribution.xml file
<jsInclude>res/js/component.js</jsInclude>

Add the following code to res/js/component.js

       var BENCHMARKBAR = “benchmarkbar_benchmark”;

       var OTHERBAR = “benchmarkbar_other”;

     

     

       var that = this;

     

       this.init = function() {

             this.jqGraph = $(“<SVG CLASS = ‘InterdobsBenchMark’> </SVG>”);

             this.$().append(this.jqGraph);

             this.$().click(function() {

                    that.fireEvent(“onclick”); });   

       };

       var benchmarkcompany = null;

     

       this.benchmark = function(value) {

             if (value === undefined) {

                    return benchmarkcompany;

             } else {

                    benchmarkcompany = value;

                    return this;

             }

       };

       this.afterUpdate = function() {

             this.jqGraph.empty();

             var data = [

                         {letter: “A”, frequency: .18167},

                         {letter: “B”, frequency: .03492},

                         {letter: “C”, frequency: .02780},

                         {letter: “D”, frequency: .04253},

                         {letter: “E”, frequency: .12702},

                         {letter: “F”, frequency: .22288}

                       ];

       var margin = {top: 10, right: 5, bottom: 30, left: 40};

              width = that.$().width() – margin.left – margin.right,

              height = that.$().height() – margin.top – margin.bottom;

       var formatPercent = d3.format(“.0%”);

       var x = d3.scale.ordinal()

           .rangeRoundBands([20, width], .1, 1);

       var y = d3.scale.linear()

           .range([height, 0]);

       var xAxis = d3.svg.axis()

           .scale(x)

           .orient(“bottom”);

       var yAxis = d3.svg.axis()

           .scale(y)

           .ticks(5)

           .orient(“left”)

           .tickFormat(formatPercent);

     

        if(typeof svg === ‘undefined’){

                    var svg = d3.select(“.InterdobsBenchMark”)

              .attr(“width”, width + margin.left + margin.right)

              .attr(“height”, height + margin.top + margin.bottom)

                    .append(“g”)

                    .attr(“transform”, “translate(“ + margin.left + “,” + margin.top + “)”);

              };

     

           

             data.sort(function(a, b) {

                return  b.frequency – a.frequency;

             });

             data.forEach(function(d) {

                 d.frequency = +d.frequency;

               });

               x.domain(data.map(function(d) { return d.letter; }));

               y.domain([0, d3.max(data, function(d) { return d.frequency; })]);

               svg.append(“g”)

                   .attr(“class”, “x axis”)

                   .attr(“transform”, “translate(0,” + height + “)”)

                   .call(xAxis);

               svg.append(“g”)

                   .attr(“class”, “y axis”)

                   .call(yAxis)

                 .append(“text”)

                   .attr(“transform”, “rotate(-90)”)

                   .attr(“y”, 6)

                   .attr(“dy”, “.61em”)

                   .style(“text-anchor”, “end”)

                   .text(“marktpercentage”);

               svg.selectAll(“.bar”)

                   .data(data)

                 .enter()

                 .append(“rect”)

                   .attr(“class”, function(d) { if (benchmarkcompany == d.letter) {return BENCHMARKBAR;} else {return OTHERBAR;}})

                   .attr(“x”, function(d) { return x(d.letter); })

                   .attr(“width”, x.rangeBand())

                   .attr(“y”, function(d) { return y(d.frequency); })

                   .attr(“height”, function(d) { return height – y(d.frequency); })

                 

                      .append(“text”)

                        .attr(“x”, function(d) { return x(d) – 3; })

                        .attr(“y”, function(d) { return y(d.frequency); })

                        .attr(“dy”, “.35em”)

                        .text(   function(d) { return d.letter; });

             };



3 add the methods

Add the following functions:

       /* Returns the current Benchmarkee of the benchmark */

       String getBenchmark() {*

             return this.benchmark;

       *}

       /* Sets the current Benchmarkee of the box */

       void setBenchmark(/* the new benchmark */ String newBenchmark) {*

             this.benchmark = newBenchmark;

       *}

}


There is a bug in Design studio (version 1.2), that the graph will only render in the web browser if another graph is in the application. When testing be sure to add another graph. This graph does not have to show any data.


Assigned Tags

      14 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member

      There is a bug in Design studio (version 1.2), that the graph will only render in the web browser if another graph is in the application. When testing be sure to add another graph. This graph does not have to show any data.

      If y want to use d3 you need to load library with stdInclude -> kind = d3

       

      If y add another chart  - another chart load this library...

      Thx for share this example;) 

       

       

      Author's profile photo Mike Howles
      Mike Howles

      Same for cvom as well.

      Author's profile photo Dirk Raschke
      Dirk Raschke

      Hi Michael, Hi Jeroen,

      did you try it, like Dimitry said?

      "stdInclude -> kind = d3"

      Br,

      Dirk

      Author's profile photo Mike Howles
      Mike Howles

      Not sure where you guys are getting that syntax...  The syntax to apply d3 in contribution.xml would be:

      <stdInclude kind="d3" />
      Author's profile photo Dirk Raschke
      Dirk Raschke

      yes, your syntax should be fine.  <stdInclude kind="d3" />

      and it doesn't work?

      For my sample I used <jsInclude>res/js/d3.v3.min.js</jsInclude>... and put it in a folder, but I know, its not the right way.

      Author's profile photo Mike Howles
      Mike Howles

      No, it should work.  I only commented to say that d3 and cvom are valid stdInclude kinds.

      Author's profile photo Mike Howles
      Mike Howles

      Jeroen,

      Mind if I run with your d3 example and post a follow-up blog on how to make this databound?

      Author's profile photo Jeroen van der A
      Jeroen van der A
      Blog Post Author

      hi Michael,

      no problem, good luck!

      Jeroen

      Author's profile photo Former Member
      Former Member

      Hi Michael,

      How to refer to D3 Library in component.js File ?? Or is it available by default for use.

      And where should I include the last 2 methods for getting and setting the benchmark.

      Author's profile photo Jeroen van der A
      Jeroen van der A
      Blog Post Author

      Hi Srikanth,

      you refer to the D3 library in the contribution.xml

      by adding the line  :

      <stdInclude kind="d3"/> within the component definition

      your  base D3 reference in the component.js is then :

      var container = this.$()[0];
      chart = d3.select(container).append("svg:svg").attr("width", "100%").attr("height", "100%")
      Author's profile photo Former Member
      Former Member

      Thanks Jeroen for the reply. I got above piece of code successfully imported to my Design Studio as a Component. Couple of questions -

      1. None of the Bars have a different color as expected, Even when I called the setbenchmark() method ??

      2. When the graph first loads do we expect one of the letters to be benchmarked in the Graph ??

      3.

      1. var benchmarkcompany = null
      2.   this.benchmark = function(value) { 
      3.   if (value === undefined) { 
      4.   return benchmarkcompany; 
      5.   } else
      6.   benchmarkcompany = value; 
      7.   return this
      8.   } 
      9.   }; 

      How and when the above code gets executed ?? this.benchmark has never been initialized before and let's say once I set the benchmark code, Do I need to call a function that redraws the Benchmark Graph ???

      Hoping you could reply ..Thanks once again

      Author's profile photo Jeroen van der A
      Jeroen van der A
      Blog Post Author

      Hi Srikanth,

      this part is a getter/setter to interact with the properties that you can define in the contribution.xml There should be a propery "benchmark" defined.

      If you look in DS you should see the property in the property panel when you select the component. Additionally you have the script option setBenchmark to change the value when you run the application.

      a getter/setter is code that if someone passes a new value it will pick that up and assign it internally (the benchmarkcompany variale). If someone calls the function without the parameter it returns the current value.

      By the way: this graph represents my babysteps in SDK development, so take everything with a grain of salt 😉

      Jeroen

      Author's profile photo Former Member
      Former Member

      Hi,

       

      i´m adding this code to simple table. Simple Table was a sample of the SDK.

      There are no errors while compiling it, but when i start the Design Studio and put the custom component in the field to view i only see the table?

       

      What is to do to see the table and the chart?

       

      sap.designstudio.sdk.Component.subclass("com.sap.sample.simpletable.SimpleTable", function() {
      
      	var CSS_CLASS_DIV = "sapzencrosstab-TableDiv";
      	var CSS_CLASS_TABLE = "sapzencrosstab-Crosstab";
      	var CSS_CLASS_TR_HEADER = 'sapzencrosstab-HeaderRow sapzencrosstab-DimensionHeaderArea';
      	var CSS_CLASS_TD_HEADER = "sapzencrosstab-HeaderCellFirstInRow sapzencrosstab-HeaderCellDefault";
      	var CSS_CLASS_TD_DEFAULT = "sapzencrosstab-DataCellDefault";
      
      	var column1_data = null;
      	var column2_data = null;
      	var column3_data = null;
      	var columnDif = null;
      	var meta_data = null;
      	
          var BENCHMARKBAR = "benchmarkbar_benchmark";
      
          var OTHERBAR = "benchmarkbar_other";
      
          var that = this;
          
          this.init = function() {
      
              this.jqGraph = $("<SVG CLASS = 'InterdobsBenchMark'> </SVG>");
      
              this.$().append(this.jqGraph);
      
              this.$().click(function() {
      
                     that.fireEvent("onclick"); });   
      
        };
      
        var benchmarkcompany = null;
      
      
      
        this.benchmark = function(value) {
      
              if (value === undefined) {
      
                     return benchmarkcompany;
      
              } else {
      
                     benchmarkcompany = value;
      
                     return this;
      
              }
      
        };
      
        this.afterUpdate = function() {
      
              this.jqGraph.empty();
      
              var data = [
      
                          {letter: "A", frequency: .18167},
      
                          {letter: "B", frequency: .03492},
      
                          {letter: "C", frequency: .02780},
      
                          {letter: "D", frequency: .04253},
      
                          {letter: "E", frequency: .12702},
      
                          {letter: "F", frequency: .22288}
      
                        ];
      
        var margin = {top: 10, right: 5, bottom: 30, left: 40};
      
               width = that.$().width() - margin.left - margin.right,
      
               height = that.$().height() - margin.top - margin.bottom;
      
        var formatPercent = d3.format(".0%");
      
        var x = d3.scale.ordinal()
      
            .rangeRoundBands([20, width], .1, 1);
      
        var y = d3.scale.linear()
      
            .range([height, 0]);
      
        var xAxis = d3.svg.axis()
      
            .scale(x)
      
            .orient("bottom");
      
        var yAxis = d3.svg.axis()
      
            .scale(y)
      
            .ticks(5)
      
            .orient("left")
      
            .tickFormat(formatPercent);
      
      
      
         if(typeof svg === 'undefined'){
      
                     var svg = d3.select(".InterdobsBenchMark")
      
               .attr("width", width + margin.left + margin.right)
      
               .attr("height", height + margin.top + margin.bottom)
      
                     .append("g")
      
                     .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
      
               };
      
      
      
            
      
              data.sort(function(a, b) {
      
                 return  b.frequency - a.frequency;
      
              });
      
              data.forEach(function(d) {
      
                  d.frequency = +d.frequency;
      
                });
      
                x.domain(data.map(function(d) { return d.letter; }));
      
                y.domain([0, d3.max(data, function(d) { return d.frequency; })]);
      
                svg.append("g")
      
                    .attr("class", "x axis")
      
                    .attr("transform", "translate(0," + height + ")")
      
                    .call(xAxis);
      
                svg.append("g")
      
                    .attr("class", "y axis")
      
                    .call(yAxis)
      
                  .append("text")
      
                    .attr("transform", "rotate(-90)")
      
                    .attr("y", 6)
      
                    .attr("dy", ".61em")
      
                    .style("text-anchor", "end")
      
                    .text("marktpercentage");
      
                svg.selectAll(".bar")
      
                    .data(data)
      
                  .enter()
      
                  .append("rect")
      
                    .attr("class", function(d) { if (benchmarkcompany == d.letter) {return BENCHMARKBAR;} else {return OTHERBAR;}})
      
                    .attr("x", function(d) { return x(d.letter); })
      
                    .attr("width", x.rangeBand())
      
                    .attr("y", function(d) { return y(d.frequency); })
      
                    .attr("height", function(d) { return height - y(d.frequency); })
      
                  
      
                       .append("text")
      
                         .attr("x", function(d) { return x(d) - 3; })
      
                         .attr("y", function(d) { return y(d.frequency); })
      
                         .attr("dy", ".35em")
      
                         .text(   function(d) { return d.letter; });
      
              };
      
      
      
      	this.init = function() {
      		this.$().addClass(CSS_CLASS_DIV);
      		this.$().css("overflow-y", "scroll");
      		this.jqTable = $("<table class=\"" + CSS_CLASS_TABLE + "\"/>");
      		this.$().append(this.jqTable);
      	};
      
      	this.afterUpdate = function() {
      		this.jqTable.empty();
      		var column_data = getAnySetColumn_Data();
      		if (column_data) {
      			var jqHeader = $("<thead/>").appendTo(this.jqTable);
      			var jqHeaderRow = $("<tr class=\"" + CSS_CLASS_TR_HEADER + "\"/>").appendTo(jqHeader);
      			jqHeaderRow.append($("<td class=\"" + CSS_CLASS_TD_HEADER + "\"/>"));
      			appendColumnHeaderCell(jqHeaderRow, column1_data);
      			appendColumnHeaderCell(jqHeaderRow, column2_data);
      			appendColumnHeaderCell(jqHeaderRow, column3_data);
      			$("<td class=\"" + CSS_CLASS_TD_HEADER + "\">Differenz</td>").appendTo(jqHeaderRow);
      
      			for (var i = 0; i < column_data.formattedData.length; i++) {
      				var jqRow = $("<tr/>");
      				this.jqTable.append(jqRow);
      				appendRowHeaderCell(jqRow, i);
      				appendCell(jqRow, column1_data, i);
      				appendCell(jqRow, column2_data, i);
      				appendCell(jqRow, column3_data, i);
      				calculateDiff(jqRow,column1_data, column2_data, i);
      			}
      		}
      	};
      	
      	function calculateDiff(jqRow, column1_data, column2_data, i) {		
      		var data1 = split(column1_data, i);
      		var data2 = split(column2_data, i);
      		var dif = data1 - data2;
      		console.log(dif);
      		jqRow.append($("<td class=\"" + CSS_CLASS_TD_DEFAULT + "\">" + Math.round(dif*100)/100 + "</td>"));
      		
      		
      	}
      	
      	function split(column_data, i){
      		var res = column_data.formattedData[i].split(" ");
      		var num = res[1].split(".");
      		var jessi = "";
      		for (var i = 0; i < num.length; i++) {
      			jessi = jessi + num[i];
      		}
      		var filip = jessi.replace(",",".");
      		var intNum = parseFloat(filip);
      		return intNum;
      	}
      	
      	function appendColumnHeaderCell(jqHeaderRow, column_data) {
      		if (column_data && column_data.formattedData) {
      			var headerText = "";
      			for (var i = 0; i < column_data.selection.length; i++) {
      				var selectionIndex = column_data.selection[i];
      				if (selectionIndex != -1) {
      					headerText += " " + meta_data.dimensions[i].members[selectionIndex].text;
      				}
      			}
      			$("<td class=\"" + CSS_CLASS_TD_HEADER + "\">" + headerText + "</td>").appendTo(jqHeaderRow);
      		}
      	}
      
      	function appendCell(jqRow, column_data, i) {
      		if (column_data && column_data.formattedData && (i < column_data.formattedData.length)) {
      			var cellText = column_data.formattedData[i];
      			jqRow.append($("<td class=\"" + CSS_CLASS_TD_DEFAULT + "\">" + cellText + "</td>"));
      		}
      	}
      
      	function appendRowHeaderCell(jqRow, i) {
      		var column_data = getAnySetColumn_Data();
      		if (meta_data && column_data && column_data.formattedData && (i < column_data.tuples.length)) {
      			var tuple = column_data.tuples[i];
      			var headerText = "";
      			for (var j = 0; j < tuple.length; j++) {
      				if (column_data.selection[j] == -1) {
      					headerText += " " + meta_data.dimensions[j].members[tuple[j]].text;
      				}
      			}
      			headerText = headerText.replace("|", " "); // Delimiter used for multiple presentations
      			jqRow.append($("<td class=\"" + CSS_CLASS_TD_HEADER + "\">" + headerText + "</td>"));
      		}
      	}
      
      	function getAnySetColumn_Data() {
      		if (column1_data && column1_data.formattedData) {
      			return column1_data;
      		} else if (column2_data && column2_data.formattedData) {
      			return column2_data; 
      		} else if (column3_data && column3_data.formattedData) {
      			return column3_data;
      		}
      		return null;
      	}
      
      	// called from Additional Properties Sheet JavaScript file
      
      	this.getMetadataAsString = function() {
      		return JSON.stringify(this.metadata());
      	};
      
      	// property setter/getter functions	
      	this.column1 = function(value) {
      		if (value === undefined) {
      			return column1_data;
      		} else {
      			column1_data = value;
      			return this;
      		}
      	};
      
      	this.column2 = function(value) {
      		if (value === undefined) {
      			return column2_data;
      		} else {
      			column2_data = value;
      			return this;
      		}
      	};
      
      	this.column3 = function(value) {
      		if (value === undefined) {
      			return column3_data;
      		} else {
      			column3_data = value;
      			return this;
      		}
      	};
      	
      	this.metadata = function(value) {
      		if (value === undefined) {
      			return meta_data;
      		} else {
      			meta_data = value;
      			return this;
      		}
      	};
      });
      

       

      Author's profile photo Former Member
      Former Member

      I only see this. I want to show the Difference of the table in the barchart but it doesn´t work to just show the chart. Please help me