Author: https://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.sdn.businesscard.SDNBusinessCard?u=a8fZzxbWgJE%3D
Submitted: 19 May 2009
Related Links:
- https://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/13313
- https://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/751
- help.sap.com
Introduction
Few days back I got a requirement to display a set of data in the form of a Bar Chart just below an ALV grid in an ABAP report. Now had it been old R/3 days then it would have been difficult to achieve this as all the GRAPH* function modules available in those days would only display these charts in a separate window with it's own controls. But now SAP has provided us special classes which allow us to display our charts or graphs on the same window. These classes ( CL_GUI_CHART_ENGINE ) are part of chart engine.It's very easy to use this class and they need input in the form of XML files. Now to create these XML files there are different options :
- Use Call Transformation command to create the XML files based on the contents of your internal table. Refer to following blog for more details about this method : https://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/13313
- Create the XML file using the Chart Designer and then use this XML in the ABAP program.
- Create the XML file directly in the abap program passing value of each node from an internal table.
We will look at the 3rd approach in detail. It is very simple to program and gives the required output:
Requirement:
We want to display the flight capacity and number of seats occupied for each flight number in the form of a bar chart. This need to be done for an online report.
Solution:
I have written below a simple code to cater this requirement. This report will fetch data from SFLIGHT table and display the required information in the form of Bar Chart.
Let's start by creating a demo program and declare the following data in it.
Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'REPORT zat_ce_demo. * Global Data Portion DATA: g_t_sflight TYPE STANDARD TABLE OF sflight. DATA: wa_sflight LIKE LINE OF g_t_sflight. DATA: g_graph_container TYPE REF TO cl_gui_custom_container. DATA: g_ce_viewer TYPE REF TO cl_gui_chart_engine. DATA: g_ixml TYPE REF TO if_ixml. DATA: g_ixml_sf TYPE REF TO if_ixml_stream_factory. DATA: okcode LIKE sy-ucomm. *---------------------------------------------------------------------* * Start Of Selection *---------------------------------------------------------------------* START-OF-SELECTION. * Get Data to be displayed on the Chart SELECT * FROM sflight INTO TABLE g_t_sflight. * create global objects g_ixml = cl_ixml=>create( ). g_ixml_sf = g_ixml->create_stream_factory( ). * Call the screen to display the chart CALL SCREEN '100'.
Don't forget to create a dynpro screen having a custom controller using the screen painter. The ID of this custom controller should be 'GRAPH_CONTAINER'. In the PBO of this screen write the code given below :
Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'*---------------------------------------------------------------------* * Module STATUS_0100 OUTPUT *---------------------------------------------------------------------* MODULE status_0100 OUTPUT. DATA: l_ixml_data_doc TYPE REF TO if_ixml_document, l_ixml_custom_doc TYPE REF TO if_ixml_document, l_ostream TYPE REF TO if_ixml_ostream, l_xstr TYPE xstring. SET PF-STATUS '100'. * For initial display of graph data. IF g_graph_container IS INITIAL. * Create the object for container. CREATE OBJECT g_graph_container EXPORTING container_name = 'GRAPH_CONTAINER'. * Bind the container to the object. CREATE OBJECT g_ce_viewer EXPORTING parent = g_graph_container. * Create XML data using data in internal table. PERFORM create_xml_data USING l_ixml_data_doc. l_ostream = g_ixml_sf->create_ostream_xstring( l_xstr ). * Render Chart Data CALL METHOD l_ixml_data_doc->render EXPORTING ostream = l_ostream. g_ce_viewer->set_data( xdata = l_xstr ). CLEAR l_xstr. * Create the customizing data for the chart PERFORM create_customizing_data USING l_ixml_custom_doc. l_ostream = g_ixml_sf->create_ostream_xstring( l_xstr ). * Render Customizing Data CALL METHOD l_ixml_custom_doc->render EXPORTING ostream = l_ostream. g_ce_viewer->set_customizing( xdata = l_xstr ). ENDIF. * Render the Graph Object. CALL METHOD g_ce_viewer->render. ENDMODULE. " STATUS_0100 OUTPUT *---------------------------------------------------------------------* * Form CREATE_XML_DATA *---------------------------------------------------------------------* * -->P_L_IXML_DOC text *----------------------------------------------------------------------* FORM create_xml_data USING p_ixml_doc TYPE REF TO if_ixml_document. DATA: l_simplechartdata TYPE REF TO if_ixml_element, l_categories TYPE REF TO if_ixml_element, l_series TYPE REF TO if_ixml_element, l_element TYPE REF TO if_ixml_element, l_encoding TYPE REF TO if_ixml_encoding, l_value TYPE string. p_ixml_doc = g_ixml->create_document( ). * Set encoding to UTF-8 l_encoding = g_ixml->create_encoding( byte_order = if_ixml_encoding=>co_little_endian character_set = 'utf-8' ). p_ixml_doc->set_encoding( l_encoding ). * Populate Chart Data l_simplechartdata = p_ixml_doc->create_simple_element( name = 'SimpleChartData' parent = p_ixml_doc ). * Populate X-Axis Values i.e. Categories and Series l_categories = p_ixml_doc->create_simple_element( name = 'Categories' parent = l_simplechartdata ). * Here you can populate the category labels. First you need * to create all the labels and only then you can populate * values for these labels. LOOP AT g_t_sflight INTO wa_sflight. l_element = p_ixml_doc->create_simple_element( name = 'C' parent = l_categories ). CONCATENATE wa_sflight-carrid wa_sflight-connid INTO l_value. * Populate the category value which you want to display here. * This will appear in the X-axis. l_element->if_ixml_node~set_value( l_value ). CLEAR l_value. ENDLOOP. * Create an element for Series and then populate it's values. l_series = p_ixml_doc->create_simple_element( name = 'Series' parent = l_simplechartdata ). * You can set your own label for X-Axis here e.g. Airline l_series->set_attribute( name = 'label' value = 'Price' ). LOOP AT g_t_sflight INTO wa_sflight. l_element = p_ixml_doc->create_simple_element( name = 'S' parent = l_series ). * Populate the Value for each category you want to display from * your internal table. l_value = wa_sflight-price. l_element->if_ixml_node~set_value( l_value ). CLEAR l_value. ENDLOOP. * Similarly you can have number of Categories and values for each category * based on your requirement l_series = p_ixml_doc->create_simple_element( name = 'Series' parent = l_simplechartdata ). l_series->set_attribute( name = 'label' value = 'Max Capacity' ). LOOP AT g_t_sflight INTO wa_sflight. l_element = p_ixml_doc->create_simple_element( name = 'S' parent = l_series ). * Populate value for another category here. l_value = wa_sflight-seatsmax. l_element->if_ixml_node~set_value( l_value ). CLEAR l_value. ENDLOOP. ENDFORM. " CREATE_XML_DATA
After setting up the data we need to pass the customizing data to the chart. Customizing data consists of various parameters which decide the look and feel of your chart. I have done in perform CREATE_CUSTOMIZING_DATA and the code for same is given below :
Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'*&---------------------------------------------------------------------* *& Form CREATE_CUSTOMIZING_DATA *&---------------------------------------------------------------------* * -->P_L_IXML_CUSTOM_DOC text *----------------------------------------------------------------------* FORM create_customizing_data USING p_ixml_doc TYPE REF TO if_ixml_document. DATA: l_root TYPE REF TO if_ixml_element, l_globalsettings TYPE REF TO if_ixml_element, l_default TYPE REF TO if_ixml_element, l_elements TYPE REF TO if_ixml_element, l_chartelements TYPE REF TO if_ixml_element, l_title TYPE REF TO if_ixml_element, l_element TYPE REF TO if_ixml_element, l_encoding TYPE REF TO if_ixml_encoding. p_ixml_doc = g_ixml->create_document( ). l_encoding = g_ixml->create_encoding( byte_order = if_ixml_encoding=>co_little_endian character_set = 'utf-8' ). p_ixml_doc->set_encoding( l_encoding ). l_root = p_ixml_doc->create_simple_element( name = 'SAPChartCustomizing' parent = p_ixml_doc ). l_root->set_attribute( name = 'version' value = '1.1' ). l_globalsettings = p_ixml_doc->create_simple_element( name = 'GlobalSettings' parent = l_root ). l_element = p_ixml_doc->create_simple_element( name = 'FileType' parent = l_globalsettings ). l_element->if_ixml_node~set_value( 'PNG' ). * Here you can give the Chart Type i.e. 2D, 3D etc l_element = p_ixml_doc->create_simple_element( name = 'Dimension' parent = l_globalsettings ). * For 2 Dimensional Graph write - PseudoTwo * For 2 Dimensional Graph write - PseudoThree l_element->if_ixml_node~set_value( 'PseudoThree' ). * Here you can give the chart type l_element = p_ixml_doc->create_simple_element( name = 'ChartType' parent = l_globalsettings ). * For Bar Char write - Columns * For Pie Chart write - Pie etc l_element->if_ixml_node~set_value( 'Speedometer' ). l_element = p_ixml_doc->create_simple_element( name = 'FontFamily' parent = l_default ). l_element->if_ixml_node~set_value( 'Arial' ). l_elements = p_ixml_doc->create_simple_element( name = 'Elements' parent = l_root ). l_chartelements = p_ixml_doc->create_simple_element( name = 'ChartElements' parent = l_elements ). l_title = p_ixml_doc->create_simple_element( name = 'Title' parent = l_chartelements ). * Give the desired caption for the chart here l_element = p_ixml_doc->create_simple_element( name = 'Caption' parent = l_title ). l_element->if_ixml_node~set_value( 'Airline Details' ). ENDFORM. " CREATE_CUSTOMIZING_DATA
You can use following Category base chart types : Lines, StackedLines, Profiles, StackedProfiles, Bars, StackedBars, Columns, StackedColumns,
Area, StackedArea, ProfileArea, StackedProfileArea, Pie,Doughnut, SplitPie, Polar,
Radar, StackedRadar, Speedometer.
Last but not the least we need to handle some buttons in our PAI.
*-------------------------------------------------------------------* * Module USER_COMMAND_0100 INPUT *-------------------------------------------------------------------* MODULE user_command_0100 INPUT. CASE okcode. WHEN 'EXIT'. LEAVE PROGRAM. WHEN 'BACK'. LEAVE PROGRAM. ENDCASE. ENDMODULE. " USER_COMMAND_0100 INPUT
No more coding is required and when we execute the report we will get the output as shown below :
In a similar way we can create different types of charts by changing the chart type in our source code. These types can be :
Conclusion:
Thus we have seen how easy it is to use the chart engine and to display your own set of data in the charts. feel free to use this approach and develop your own applications using various options available in Chart Engine.
4 Comments
Former Member
do you have the code to be able to print graphs?
David Hesse
to display the graph you need to define the CC "
GRAPH_CONTAINER
" in dynpro 0100.Thanks for the example!
Former Member
Hello,
great example
RUTUL TRIVEDI
Hello,
Great Example.
I used this example for my requirement but i wan to understand about Color Changes details.
Please help me .