Skip to Content
Author's profile photo Steve Rumsby

UI5 charts in Personas – a business example

In my first blog about Using SAPUI5 charts in Personas Flavours the example I gave was the Personas 2 migration tool, just because I’d been using that a lot recently. Here’s a business example, visualising credit exposure vs credit limit when creating a sales order in VA01. First here’s how it works:

Once the mandatory fields are completed – sold-to party and PO number – you get a chart showing the customer’s credit exposure (outstanding orders & invoices) against their credit limit. As I enter line items you’ll see the current order value added to the credit exposure column, in a contrasting colour. If the current order value + credit exposure exceeds the credit limit, first you get the standard warning from SAPgui, but also notice that the chart colour changes to give a visual indication.

The basic process here is the same as before – first collect the data, then build it into a suitable data model and finally build a chart on that data. The chart this time is a StackedColumn chart.

Collecting the data is easy this time – there are no tables to grab it from. The current order value is right at the top of VA01 main screen and the credit limit/exposure data comes from the screen you get to via the menu path “Environment->Partner->Display credit account”.

// Value of current order
var orderValue = parseFloat(session.findById("wnd[0]/usr/subSUBSCREEN_HEADER:SAPMV45A:4021/txtVBAK-NETWR").text.replace(",", ""));

// Credit account details
session.findById("wnd[0]/mbar/menu[4]/menu[0]/menu[6]").select();

var creditLimit = parseFloat(session.findById("wnd[0]/usr/txtKNKK-KLIMK").text.replace(",", ""));
var creditExposure = parseFloat(session.findById("wnd[0]/usr/txtRF02L-OBLIG").text.replace(",", ""));

session.findById("wnd[0]/tbar[0]/btn[3]").press();

Now to put these numbers in an array suitable for sending to the chart:

var contents = [
     { "Type": "Credit Limit", "Source": "Existing",   "Value": creditLimit },
     { "Type": "Credit Exposure",     "Source": "Existing",   "Value": creditExposure},
     { "Type": "Credit Exposure",     "Source": "This order", "Value": orderValue}
];

And now start writing the HTML, with the usual boilerplate header and code to build the data model. This is pretty much the same as my previous example.

var chartHTML = '<html> <head>';
chartHTML += '
<script src="/ui5/1/resources/sap-ui-core.js"\
 type="text/javascript"\
 data-sap-ui-libs="sap.ui.core,sap.ui.commons,sap.viz" \
 data-sap-ui-theme="sap_goldreflection"></script>';
chartHTML += '<script>';

chartHTML += 'var oModel = new sap.ui.model.json.JSONModel({businessData:' + JSON.stringify(contents) + '});';

// Need a sorter to get the chart columns in the right order
chartHTML += ' var oSorter = new sap.ui.model.Sorter("Source", true);'
    
// A Dataset defines how the model data is mapped to the chart
chartHTML += 'var oDataset = new sap.viz.ui5.data.FlattenedDataset({\
     dimensions : [ \
          {\
               axis : 1, \
               name : "Type", \
               value : "{Type}"\
          }, \
          {\
               axis: 2, \
               name: "Source", \
               value: "{Source}"\
          }\
     ],\
     measures : [ \
          {\
               name : "Value",  \
               value : "{Value}"    \
          }\
     ],\
     data : {\
          path : "/businessData", \
          sorter: oSorter \
     }\
});';

Finally build the chart. Again, this is pretty much the same as the previous example, with a small tweak to change the column colours where appropriate:

// Set the colour for the "this order" column based on exposure + order value
if(creditExposure + orderValue < creditLimit ) {
     thisOrderColour = "#9a9a08";
} else {
     thisOrderColour = "#b4153a";
}

// create a StackedColumn chart
chartHTML += 'var oBarChart = new sap.viz.ui5.StackedColumn({\
          width : "100%",\
          height : "100px",\
          plotArea : {colorPalette: ["' + thisOrderColour + '", "#5698d2"]} , \
          title : { visible : false },\
          legend: { visible: true },\
          toolTip: { visible: false }, \
          dataset : oDataset\
     });';

And of course we need to finish off with the usual boilerplate HTML

// attach the model to the chart and display it
chartHTML += '     oBarChart.setModel(oModel);\
          oBarChart.placeAt("content"); ';

chartHTML += '</script>';
chartHTML += '</head>';
chartHTML += '<body class="sapUiBody" supportedthemes="sap_corbu" role="application">';
chartHTML += '<div id="content"></div>'
chartHTML += '</body></html>';

session.findById("wnd[0]/usr/htmlViewerPersonas_1447866610072").content = chartHTML;

Don’t forget in the screen editor to add an HTMLViewer control to hold the HTML, and to update the last line above with the correct ObjectID. Finally, in the editor assign this script to the “onAfterRefresh” screen event and the chart will then refresh each time to make a change to the line item details.

Right at the top I mentioned that there are a couple of mandatory fields – sold-to party and PO number. If there is no data in those fields then you can’t navigate to the credit account screen and the above script will fail. The whole thing therefore need to be protected with a test for values in those fields:

var customer = session.findById("wnd[0]/usr/subSUBSCREEN_HEADER:SAPMV45A:4021/subPART-SUB:SAPMV45A:4701/ctxtKUAGV-KUNNR").text;
var PONumber = session.findById("wnd[0]/usr/subSUBSCREEN_HEADER:SAPMV45A:4021/txtVBKD-BSTKD").text;

var chartHTML;
if(!customer || !PONumber) {
     chartHTML = '';
} else {
     // The rest of the script from above...
}

This seems like a nice little addition to VA01 screen, providing easy to interpret visual feedback about credit data, and wasn’t too hard to build. I’m sure there must be many more examples of business transactions that would benefit from this sort of addition. Feel free to make suggestions in the comments!

[ PS. For some reason I couldn’t figure out how to use the “Type” values – “Credit Exposure” and “Credit Limit” – as labels for the two columns on the x axis. If anyone can help me with that, do please let me know how 🙂 ]

Assigned Tags

      10 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Yogendra Ahuja
      Yogendra Ahuja

      Hi @steve.rumsby

      I am little lost with HTML part. Could you please provide steps how to create HTML and assign to HTMLViewer .

       

      Thanks,

       

      Author's profile photo Steve Rumsby
      Steve Rumsby
      Blog Post Author

      The code is all up there in the blog post. Just to make it a little easier, the entire script is below. You'll need to change the object ID of your HTMLViewer control in the last line, and you'll need to fix the URL of the UI5 library - I've used a hardwired hostname here (which I've redacted), which you probably shouldn't. The object IDs of the standard SAP controls should be the same in your system, but check them anyway.

      Hope this makes it clearer. You can also read my previous blog where the process is explained in a little more detail.

      Anyway, the whole script:

      var customer = session.findById("wnd[0]/usr/subSUBSCREEN_HEADER:SAPMV45A:4021/subPART-SUB:SAPMV45A:4701/ctxtKUAGV-KUNNR").text;
      var PONumber = session.findById("wnd[0]/usr/subSUBSCREEN_HEADER:SAPMV45A:4021/txtVBKD-BSTKD").text;
      
      //debugger;
      
      var chartHTML;
      if(!customer || !PONumber) {
       chartHTML = '<html><head></head><body></body></html>';
      } else {
      
      session.findById("wnd[0]/mbar/menu[4]/menu[0]/menu[6]").select();
      
      var creditLimit = parseFloat(session.findById("wnd[0]/usr/txtKNKK-KLIMK").text.replace(",", ""));
      var creditExposure = parseFloat(session.findById("wnd[0]/usr/txtRF02L-OBLIG").text.replace(",", ""));
      
      session.findById("wnd[0]/tbar[0]/btn[3]").press();
       
      // Now get value from current order
      var orderValue = parseFloat(session.findById("wnd[0]/usr/subSUBSCREEN_HEADER:SAPMV45A:4021/txtVBAK-NETWR").text.replace(",", ""));
      
      var contents = [
       { "Type": "Credit Limit", "Source": "Existing", "Value": creditLimit },
       { "Type": "Credit Exposure", "Source": "Existing", "Value": creditExposure},
       { "Type": "Credit Exposure", "Source": "This order", "Value": orderValue}
       ];
       
      chartHTML = '<html><head>';
      chartHTML += '<script src="https://<hostname>/sap/public/bc/ui5_ui5/1/resources/sap-ui-cachebuster/sap-ui-core.js" id="sap-ui-bootstrap" data-sap-ui-libs="sap.ui.core,sap.ui.commons,sap.viz" data-sap-ui-theme="sap_goldreflection"></script>';
      chartHTML += '<script>';
      
      // Build a data model
      chartHTML += ' var oModel = new sap.ui.model.json.JSONModel({businessData:' + JSON.stringify(contents) + '});';
      
      chartHTML += ' var oSorter = new sap.ui.model.Sorter("Source", true);';
       
       // A Dataset defines how the model data is mapped to the chart 
       chartHTML += ' var oDataset = new sap.viz.ui5.data.FlattenedDataset({\
       dimensions : [ \
       {\
       axis : 1, \
       name : "Type", \
       value : "{Type}"\
       }, \
       {\
       axis: 2, \
       name: "Source", \
       value: "{Source}"\
       }\
       ],\
       measures : [ \
       {\
       name : "Value", \
       value : "{Value}" \
       }\
       ],\
       data : {\
       path : "/businessData", \
       sorter: oSorter \
       }\
       });';
      
      // Set the colour for the "this order" column based on exposure + order value
       if(creditExposure + orderValue < creditLimit ) {
       thisOrderColour = "#9a9a08";
       } else {
       thisOrderColour = "#b4153a";
       }
       // create a StackedColumn chart
       chartHTML += 'var oBarChart = new sap.viz.ui5.StackedColumn({\
       width : "100%",\
       height : "100px",\
       plotArea : {colorPalette: ["' + thisOrderColour + '", "#5698d2"]} , \
       title : { visible : false },\
       legend: { visible: true },\
       toolTip: { visible: false }, \
       dataset : oDataset\
       });';
      
      // attach the model to the chart and display it
       chartHTML += ' oBarChart.setModel(oModel);\
       oBarChart.placeAt("content"); ';
      
      chartHTML += '</script>';
       chartHTML += '</head>';
       chartHTML += '<body class="sapUiBody" supportedthemes="sap_corbu" role="application">';
       chartHTML += '<div id="content"></div>';
       chartHTML += '</body></html>';
      }
      
      session.findById("wnd[0]/usr/htmlViewerPersonas_1447950484571").content = chartHTML;

       

      Author's profile photo Harpreet Daphu
      Harpreet Daphu

      Hello Steve,

      I've configured it exactly as you mentioned, but it doesn't seem to be showing anything.

      What do you mean by - "you’ll need to fix the URL of the UI5 library"? When I create and HTML Viewer control, what URL should I be pointing to?

      I am pointing it to http://<host>:<port>/sap/public/bc/ui5_ui5/ but don't think that is correct.

      I have change the last line of the script to point to my HTML control and added the script to "onAfterRefresh" Screen event.

      What am I missing?

      Thanks!

      Harpreet

       

      Author's profile photo Steve Rumsby
      Steve Rumsby
      Blog Post Author

      There's a line near the top that starts:

      chartHTML += '<script src="https://<hostname>/sap/public/bc/ui5_ui5/1/resources/sap-ui-cachebuster/sap-ui-core.js"

      That URL needs to point to a UI5 library that you have access to. That should be as simple as replacing "<hostname>" with the hostname of your SAP instance and leaving the rest alone. Or more usefully with some JavaScript to generate the current hostname rather than hardwiring it!

      Author's profile photo Harpreet Daphu
      Harpreet Daphu

      Thanks Steve for your quick reply. So I tried with just replacing the host name and it did not work, then I provided the port and it worked. It is pointing to the below function, which I think is correct ??

      One of my other question is where should be HTML Viewer control target link be pointed at? I am currently pointing to the same link as in the script - http://<host>:<port>/sap/public/bc/ui5_ui5/1/resources/sap-ui-cachebuster/sap-ui-core.js Is that correct?

      The graph still doesn't show up, guess I need to get the right data, if technically everything is correct.

      Thanks a bunch Steve, you have been great help!

      Harpreet

      Author's profile photo Steve Rumsby
      Steve Rumsby
      Blog Post Author

      The link for the HTMLviewer determines what gets displayed until your script replaces the HTML with the dynamically generated code. I always use "about:blank", so that I can be sure the box displays nothing. Whatever you put there should be in the URL whitelist.

      Author's profile photo Harpreet Daphu
      Harpreet Daphu

      Thank you Steve.

       

      Author's profile photo Neil Ward
      Neil Ward

      Cool Blog Steve,

      I've managed to get this working on my system, but I notice the controls used here are now deprecated, have you tried to get this working with vizframe, i.e. sap.viz.ui5.controls.VizFrame ?

      cheers,

      Neil

      Author's profile photo Steve Rumsby
      Steve Rumsby
      Blog Post Author

      No, I haven't yet. It is on my todo list. I can't promise I'll get to it soon, though (it has been on that list for quite a while already, sadly). If you happen to get there first, do blog the details 🙂

      Author's profile photo Neil Ward
      Neil Ward

      no worries, thanks for replying!