Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
basarozgur_kahraman
Contributor
4,798

In my previous blog post, we created a mobile application to show ALV data. Now we will visualize data with Highcharts .

Before begin, i recommend you to read previous posts.

Part 1 - Create RESTful service

Part 2 - Create JQueryMobile Web Application with Datatables plugin

Pre-requisites:

  1. Check over Highcharts documentation

Steps:

  1. Modify index.html for charting
  2. Create charting rule selections dynamicly based on ALV Metadata
  3. Create chart data according to rule selections
  4. Initialize highcharts

index.html

<!DOCTYPE html>

<html>

    <!--<html manifest="app.appcache">-->

    <head>

    <title></title>

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">   

    <meta name="apple-mobile-web-app-capable" content="yes"/>

    <meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />

    <link rel="shortcut icon" href="images/mysapreport.jpg" />

    <link rel="stylesheet" href="css/jqm/jquery.mobile-1.1.1.min.css" />

    <!-- DataTables CSS     -->

    <link rel="stylesheet" type="text/css" href="css/datatables/jquery.dataTables.css"/>  

    <link rel="stylesheet" type="text/css" href="css/datatables/ColVisAlt.css"/>

    <script src="js/jqm/jquery-1.7.2.min.js"></script>

    <script src="js/jqm/jquery.mobile-1.1.1.min.js"></script>

    <!-- DataTables -->

    <script type="text/javascript" src="js/datatables/jquery.dataTables.min.js"></script>              

    <script type="text/javascript" src="js/datatables/ColVis.min.js"></script>    

    <script type="text/javascript" src="js/datatables/TableTools.min.js"></script>    

    <script type="text/javascript" src="js/settings.js"></script>

    <script type="text/javascript" src="js/table.js"></script>

    <script type="text/javascript" src="js/chart.js"></script>   

    <script>

        $.support.cors = true;

        jQuery.support.cors = true;                 

    </script>

</head>

<body>

<div data-role="page" id="alv" data-theme="e">

    <div data-role="header" data-position="fixed">

        <h1>MySapReport</h1>

        <a href="#settings"  data-role="button" data-icon="gear" data-theme="b">Settings</a>

    </div>

    <div data-role="content" >

        <div data-role="fieldcontain">

            <label for="transaction">Transaction:</label>

            <input type="text" name="transaction" id="transaction" value="" />      

        </div>

        <div data-role="fieldcontain">

            <label for="variant">Variant:</label>

            <input type="text" name="variant" id="variant" value="" />

        </div>

        <a href="javascript:getALV()"  data-role="button" data-icon="grid" data-theme="b">Call Report</a>

        <a href="javascript:getDemoData()"  data-role="button" data-icon="grid" data-theme="b">Demo</a>      

        <br>

    </div>

</div>

<div data-role="dialog" id="settings">

    <div data-role="content" >

        <label for="connectUrl">Connect to:</label>

        <input type="url" name="connectUrl" id="connectUrl" value="" data-mini="true" />

        <label for="username">Username:</label>

        <input type="text" name="username" id="username" value="" data-mini="true" />

        <label for="password">Password:</label>

        <input type="password" name="password" id="password" value="" data-mini="true" />

        <br>

        <a href="javascript:exitSettings()" data-role="button" data-icon="delete">Exit</a>

        <a href="javascript:saveSettings()" data-role="button" data-icon="check" data-theme="b">Save</a>               

    </div>

</div>

<div data-role="page" id="showDatatable" data-theme="e" data-add-back-btn="true" data-dom-cache="true">

    <div data-role="header" data-position="fixed">

        <h1 id="datatableHeader">ALV</h1>

        <div class="ui-btn-right">          

            <a href="#chartRules" data-role="button" data-icon="star" data-theme="e" data-back="true">Chart</a>          

        </div>

    </div>

    <div data-role="content">

        <div id="dynamicDatatableDIV" >          

            <!--<table id="dynamicDatatable" class="tbl_basket_style"></table>-->

        </div>

    </div>

</div>

<div id="chartRules" data-role="dialog">

    <div data-role="header">

        <h1>Chart Rules</h1>

    </div>

    <section data-role="content">

        <div data-role="fieldcontain">

            <label for="select-choice-ctype" class="select">Chart Type</label>          

            <select name="select-choice-ctype" id="select-choice-ctype" data-native-menu="false">                              

                <option value="line">Basic Line</option>                    

                <option value="area">Basic Area</option>              

                <option value="bar">Basic Bar</option>              

                <option value="column">Basic Column</option>             

                <option value="pie">Pie chart</option>              

            </select>

            <label for="select-choice-x" class="select">X-Axis</label>          

            <select name="select-choice-x" id="select-choice-x" data-native-menu="false"></select>

            <label for="select-choice-y" class="select">Y-Axis</label>

            <select name="select-choice-y" id="select-choice-y" data-native-menu="false"></select>

            <label for="select-choice-b" class="select">Series</label>

            <select name="select-choice-b" id="select-choice-b" data-native-menu="false"></select>

            <label for="select-choice-f" class="select">Series Filter</label>

            <select name="select-choice-f" id="select-choice-f" multiple="multiple" data-native-menu="false"></select>

        </div>

        <a href="#pageChart" data-role="button" data-icon="grid" data-theme="e" data-back="true">Show Chart</a>                                       

    </section>

</div>

<div id="pageChart" data-role="page" data-add-back-btn="true" data-theme="b">

    <header data-role="header" data-position="fixed">

        <h1>Chart</h1>

    </header>

    <section data-role="content">

        <div id="chartContainer" style="width: 100%; min-width: 400px; height: 100%; margin: 0 auto"></div>

        <div id="myChart" ></div>      

    </section>

</div>

<script type="text/javascript" src="js/highcharts/highcharts.js"></script>

<script type="text/javascript" src="js/highcharts/modules/exporting.js"></script>

<script type="text/javascript" src="js/highcharts/themes/gray.js"></script>

</body>

</html>

Create charting rule selections

function fillChartingRules(){

    var outputx = [];

    var outputy = [];

    var outputb = [];

    if (!$('#select-choice-x').is(':empty')){

        return;

    }

    outputx.push('<option>X-Axis</option>');      

    outputy.push('<option>Y-Axis</option>');      

    outputb.push('<option>Base</option>');      

    for(i=0;i<alvMetadata.length;i++){

        if (alvMetadata[i].inttype === 'P' || alvMetadata[i].inttype === 'I' ||

            alvMetadata[i].inttype === 'F' || alvMetadata[i].inttype === 'b' ||

            alvMetadata[i].inttype === 's'){             

            outputy.push('<option value="' + alvMetadata[i].fieldname.toLowerCase() + '">' + alvMetadata[i].coltext + '</option>');  

        }else{                          

            outputx.push('<option value="' + alvMetadata[i].fieldname.toLowerCase() + '">' + alvMetadata[i].coltext + '</option>');      

            outputb.push('<option value="' + alvMetadata[i].fieldname.toLowerCase() + '">' + alvMetadata[i].coltext + '</option>');          

        }

    }     

    $('#select-choice-x').empty();

    $('#select-choice-y').empty();

    $('#select-choice-b').empty();   

    $('#select-choice-f').empty();

    $('#select-choice-x').append(outputx.join(''));

    $('#select-choice-y').append(outputy.join(''));

    $('#select-choice-b').append(outputb.join(''));

    try{

        $('#select-choice-x').selectmenu("refresh");

        $('#select-choice-y').selectmenu("refresh");

        $('#select-choice-b').selectmenu("refresh");

        $('#select-choice-f').selectmenu("refresh");

    }catch(err){ }

}

function fillSeriesFilterData(){

    var outputf = [];

    var optionf;                

    outputf.push('<option>Base Filter</option>');       

    for(i=0;i<alvData.length;i++){

        optionf = '<option value="' + alvData[i][$("#select-choice-b").val()] + '">' + alvData[i][$("#select-choice-b").val()] + '</option>';

        if (jQuery.inArray(optionf, outputf) === -1)

            outputf.push(optionf);              

    }

    outputf.sort(function(a,b) {

        return (a > b) ? 1 : ((b > a) ? -1 : 0);

    } );       

    $('#select-choice-f').empty();

    $('#select-choice-f').append(outputf.join(''));  

    $('#select-choice-f').selectmenu('refresh', true);

}

Create chart data

function setXaxisCategories(pOptions){

    alvData.sort(function(a,b) {

        return (a[$("#select-choice-x").val()] > b[$("#select-choice-x").val()]) ? 1 : ((b[$("#select-choice-x").val()] > a[$("#select-choice-x").val()]) ? -1 : 0);

    } );

    for(i=0;i<alvData.length;i++){

        if (jQuery.inArray(alvData[i][$("#select-choice-x").val()], pOptions.xAxis.categories) === -1)

            pOptions.xAxis.categories.push(alvData[i][$("#select-choice-x").val()]);       

    }

}

function setSeries(pOptions){

    var seriesData = [];

    var seriesFilter = $("#select-choice-f").val() || [];

    var hasFilter = false;

    var _series = {

        name:"",

        data:[]

    };

    //initialize data array for each category

    var _initData = [];

    for(i=0;i<pOptions.xAxis.categories.length;i++){

        _initData.push(0);

    }       

    if (seriesFilter.length < 1){

        _series.name = "";

        _series.data = _initData.slice();

        seriesData.push(_series);

    }else{

        hasFilter = true;

        for(i=0;i<seriesFilter.length;i++){       

            var _seriesF = {

                name:"",

                data:[]

            };

            _seriesF.name = seriesFilter[i];

            _seriesF.data = _initData.slice();

            seriesData.push(_seriesF);

        }

    }

    var xValue;

    var yValue;

    var _index;

    var _seriesindex;

    var _filter;

    for(i=0;i<alvData.length;i++){

        xValue = alvData[i][$("#select-choice-x").val()];

        yValue = alvData[i][$("#select-choice-y").val()];

        _index = jQuery.inArray(xValue, pOptions.xAxis.categories);

        _seriesindex = 0;

        if (hasFilter) {

            _filter = alvData[i][$("#select-choice-b").val()];

            if (jQuery.inArray(_filter, seriesFilter) !== -1){

                for(j=0;j<seriesData.length;j++){

                    if (_filter === seriesData[j].name){

                        _seriesindex = j;

                        break;

                    }                                              

                }     

            }else{

                continue;

            }

        }

        if (isNaN(seriesData[_seriesindex].data[_index]))

            seriesData[_seriesindex].data[_index] = parseFloat(yValue); 

        else

            seriesData[_seriesindex].data[_index] = seriesData[_seriesindex].data[_index] + parseFloat(yValue);

        //set 2 decimal point

        seriesData[_seriesindex].data[_index] = parseFloat(seriesData[_seriesindex].data[_index].toFixed(2));

    }

    pOptions.series = seriesData;

}

Initialize Highcharts

function basicChart(){

    var options = {

        chart: {

            renderTo: 'chartContainer',

            defaultSeriesType: $("#select-choice-ctype").val()//pie, column, bar, line          

        },

        title: {

            text: reportDescription          

        },

        subtitle: {

            text: $('#select-choice-x option:selected').text() + ' / ' + $('#select-choice-y option:selected').text()          

        },

        legend: {

            layout: 'vertical',

            align: 'right',

            verticalAlign: 'top',

            x: -10,

            y: 100,

            borderWidth: 0

        },

        xAxis: {

            categories: [],

            labels: {

                rotation: -45,

                align: 'right',

                style: {

                    fontSize: '13px',

                    fontFamily: 'Verdana, sans-serif'

                }

            },

            title: {

                text: $('#select-choice-x option:selected').text()

            }

        },

        yAxis: {

            title: {

                text: $('#select-choice-y option:selected').text()

            }

        },

        series: []

    };

    setXaxisCategories(options);

    setSeries(options);

    // Create chart

    var chart = new Highcharts.Chart(options);                   

}

Test

You may use MySapReport for testing.

Rule definions of chart;

  1. Chart Type (Mandatory): There are 5 kind of charts predefined (Line, Area, Bar, Column, Pie).
  2. X-Axis       (Mandatory): Used as category axis. Only non-numerical alv columns can be chosen.
  3. Y-Axis       (Mandatory): Used as value type axis. Only numeric alv columns can be chosen.
  4. Series          (Optional): Used as collection of datapoints in category axis.
  5. Series Filter (Optional): Used as filter for series, filled by selection event of Series and values are derived dynamicly from alv data.

You can find all sources codes on https://github.com/basarozgur/MySapReport

Screen Shots:

    Chart rule definition

   Basic Line


   Basic Area

    Basic Bar

    Basic Column

    Pie



1 Comment
Labels in this area