You are on page 1of 17

Create a nice looking chart with CL_GUI_CHART_ENGINE - Part 1 - Chart Designer

At the beginning of my work with SAP I was disappointed with the charts that was available in
standard transactions. In fact I am still :) But when I have to create own program with nice
looking chart then it's no longer a problem as we can use CL_GUI_CHART_ENGINE together
with chart designer provided by SAP. Chart designer is a tool which allows you to create a
customizing for your chart and save it in XML file which can be used in ABAP after.

So first of all we need to download chart designer from SDN so you can google "sap chart
designer" to get it. After you'll have it just run one of the versions available there (640 or 700)
depending on your GUI version. All files which you'll find in the package are shown below, XML
Format.pdf file will tell you how to prepare chart data depending on chart type.

When you run ChartDesigner you'll se that there is a lot of chart types available for your use,
surely you'll find the one you need here.
Step 1) For my article purpose I will use Pie2.5D type
Step 2) Let's setup title, subtitle, number of series and categories. In title I will use
string TITLE_REPLACE and for subtitle SUBTITLE_REPLACE to be able to easily replace it to
dynamic texts during creation of chart in ABAP. I'll set up 1 series and 3 categories for our
demo.
Step 3) Here we can customize the colors for our categories and if we want to display labels or
not. I will use text labels here.
Step 4) Here we can customize background, plot area, title, subtitle and legend styles:

For Background we can make it visible or not, set colors and gradients.

Same settings are available for Plot Area


For Title we can set up font size, font family, font color , font style and position.

Same we can do for Subtitle.


For Legend we can set if we want to have it on chart or not, its alignment and position.

Step 5) (Yeah I know it's on the screen-shot as 6 ) Just the info that we finished.
Step 6) At the end we receive all customization in one place so we can adjust something if
needed or jus save the XML using "File" menu.
Create a nice looking chart with CL_GUI_CHART_ENGINE - Part 2 - Customization

In part one for this tutorial I quickly shown you how to create a chart customizing using Chart
Designer, in this part I will show how I store and use such customizing. For the beginning I'll tell
you that there are many ways to store the customizing, you can keep it in GOS, or in APP
server or load it directly from PC, but my favorite one is to keep the customizing in standard
texts (SO10) and read it from there. It's easy to do changes there and it can be restricted in
authorizations who can do changes for such text.
So I'll go to SO10 and create new text for customization there:

Then I'll paste the XML content here and save:

After it's done I can prepare a module to read the text, replace title and subtitle and to create
an xstring from it. I will use this xstring in next part of tutorial to render the chart.

Importing parameters:

I_TEXTNAME TYPE RSSCE-TDNAME -> text name


I_TITLE TYPE CSEQUENCE -> our titile
I_SUBTITLE TYPE CSEQUENCE ->our subtitle

Returning parameters:

VALUE( C_XSTRING ) TYPE XSTRING -> I'll use that in next part

Implementation:
method chart_customizing.
*This is the code from http://abapblog.com.
data: ft_raw255 type solix_tab.
data: fs_raw255 type solix.
data: f_tablenght type i.
data: f_string type string.
data: f_xstring type xstring.
data: fo_ixml type ref to if_ixml.
data: fo_streamfactory type ref to if_ixml_stream_factory.
data: fo_istream type ref to if_ixml_istream.
data: fo_document type ref to if_ixml_document. "<=== here is IF_IXML_DOCUMENT
data: fo_parser type ref to if_ixml_parser.
data: f_ostream type ref to if_ixml_ostream.
data: f_subtitle type string.
data: f_title type string.
data: ft_itf_text type table of tline.
field-symbols: <itf> type tline.

f_subtitle = i_subtitle.
f_title = i_title.

call function 'READ_TEXT'


exporting
id = 'ST'
language = 'E'
name = i_textname
object = 'TEXT'
tables
lines = ft_itf_text
exceptions
id =1
language = 2
name = 3
not_found = 4
object = 5
others = 8.
if sy-subrc <> 0.
* raise error_reading_standard_text.
else.
loop at ft_itf_text assigning <itf>.
concatenate f_string <itf>-tdline into f_string.
endloop.
endif.

if f_string is not initial. "if you have other special html characters in titles or variables in
configurations then add it here
replace all occurrences of '&' in f_subtitle with '&amp;'.
replace all occurrences of '&' in f_title with '&amp;'.
replace all occurrences of '<' in f_subtitle with '&lt;'.
replace all occurrences of '<' in f_title with '&lt;'.
replace all occurrences of '>' in f_subtitle with '&gt;'.
replace all occurrences of '>' in f_title with '&gt;'.
replace all occurrences of 'SUBTITLE_REPLACE' in f_string with f_subtitle.
replace all occurrences of 'TITLE_REPLACE' in f_string with f_title.
clear f_xstring.

call function 'SCMS_STRING_TO_XSTRING'


exporting
text = f_string
* MIMETYPE =''
* ENCODING = ENCODING
importing
buffer = f_xstring
exceptions
failed =1
others =2
.
if sy-subrc eq 0.
call function 'SCMS_XSTRING_TO_BINARY'
exporting
buffer = f_xstring
* APPEND_TO_TABLE =''
importing
output_length = f_tablenght
tables
binary_tab = ft_raw255
.
endif.

check ft_raw255[] is not initial.

fo_ixml = cl_ixml=>create( ).
fo_streamfactory = fo_ixml->create_stream_factory( ).
fo_document = fo_ixml->create_document( ).
fo_istream = fo_streamfactory->create_istream_itable(
size = f_tablenght
table = ft_raw255 ).
fo_parser = fo_ixml->create_parser( stream_factory = fo_streamfactory
istream = fo_istream
document = fo_document ).
fo_parser->parse( ).
clear c_xstring.
f_ostream = fo_streamfactory->create_ostream_xstring( c_xstring ).
call method fo_document->render
exporting
ostream = f_ostream.

endif.

endmethod.
Create a nice looking chart with CL_GUI_CHART_ENGINE - Part 3 - Chart Data and render

We know already how to use chart designer and we're able to save/read it's result to/from
standard texts. So let's go for most interesting part - rendering the chart. Of course we will
need some data but I will use dummy one just to show you how to create the chart, you can
replace this part with loop on your internal table or even better change it in the way that you'll
pass internal table.
In the method provided bellow I firstly create custom container object
(cl_gui_custom_container) to place the chart in it, then I create chart engine
(cl_gui_chart_engine), then using if_xml I create an xml data container which in fact can be
written using simple concatenate statement but it's not nice to change and easy to mess.

So after we receive an xml with data then I will pass it to chart engine, then I will run the
method prepared in previous part (Create a nice looking chart with CL_GUI_CHART_ENGINE -
Part 2 - Customization ) to read the customization of the chart and I will pass it also to engine.
Finally I will render the chart.
Importing:

I_CONTAINER_NAME TYPE CSEQUENCE -> custom container's name

Changing:

CO_CHART_ENGINE TYPE REF TO CL_GUI_CHART_ENGINE


CO_CONTAINER TYPE REF TO CL_GUI_CUSTOM_CONTAINER

Implementation:

method create_and_init_chart.
*This is the code from http://abapblog.com.
data: f_lenght type i.
data: f_xstring type xstring.
data: fo_ixml_mf type ref to if_ixml.
data: fo_ixml_sf type ref to if_ixml_stream_factory.
data: f_ixml_data_doc type ref to if_ixml_document.
data: f_ostream type ref to if_ixml_ostream.
data: f_encoding type ref to if_ixml_encoding.
* chart data elements:
data: f_chartdata type ref to if_ixml_element,
f_categories type ref to if_ixml_element,
f_category type ref to if_ixml_element,
f_series type ref to if_ixml_element,
f_point type ref to if_ixml_element,
f_value type ref to if_ixml_element.

if co_container is initial.
"create container
create object co_container
exporting
container_name = i_container_name.
"create an engine assigned to our container
create object co_chart_engine
exporting
parent = co_container.
endif.

* processing data
fo_ixml_mf = cl_ixml=>create( ).
fo_ixml_sf = fo_ixml_mf->create_stream_factory( ).
* create an empty document and set encoding
f_ixml_data_doc = fo_ixml_mf->create_document( ).
f_encoding = fo_ixml_mf->create_encoding(
byte_order = if_ixml_encoding=>co_little_endian
character_set = 'utf-8' ).
f_ixml_data_doc->set_encoding( f_encoding ).

* Now build a DOM, representing an XML document with chart data


f_chartdata = f_ixml_data_doc->create_simple_element(
name = 'ChartData'
parent = f_ixml_data_doc ).

* Categories (parent)
f_categories = f_ixml_data_doc->create_simple_element(
name = 'Categories'
parent = f_chartdata ).
* Categories (children)
f_category = f_ixml_data_doc->create_simple_element(
name = 'Category'
parent = f_categories ).
f_category->if_ixml_node~set_value( 'My first category' ).

f_category = f_ixml_data_doc->create_simple_element(
name = 'Category'
parent = f_categories ).
f_category->if_ixml_node~set_value( 'My second category' ).
f_category = f_ixml_data_doc->create_simple_element(
name = 'Category'
parent = f_categories ).
f_category->if_ixml_node~set_value( 'My third category' ).

* Build series (we need only 1)


f_series = f_ixml_data_doc->create_simple_element(
name = 'Series'
parent = f_chartdata ).
f_series->set_attribute( name = 'customizing'
value = 'Series1' ).

*1st category
f_point = f_ixml_data_doc->create_simple_element(
name = 'Point'
parent = f_series ).
f_point->set_attribute( name = 'customizing'
value = 'Category1' ).
f_point->set_attribute( name = 'label'
value = 'Best one' ).
f_value = f_ixml_data_doc->create_simple_element(
name = 'Value'
parent = f_point ).
f_value->if_ixml_node~set_value( '50' ).

*2nd category
f_point = f_ixml_data_doc->create_simple_element(
name = 'Point'
parent = f_series ).
f_point->set_attribute( name = 'customizing'
value = 'Category2' ).
f_point->set_attribute( name = 'label'
value = 'Not so bad' ).
f_value = f_ixml_data_doc->create_simple_element(
name = 'Value'
parent = f_point ).
f_value->if_ixml_node~set_value( '35' ).

*3rd category
f_point = f_ixml_data_doc->create_simple_element(
name = 'Point'
parent = f_series ).
f_point->set_attribute( name = 'customizing'
value = 'Category3' ).
f_point->set_attribute( name = 'label'
value = 'Worst one' ).
f_value = f_ixml_data_doc->create_simple_element(
name = 'Value'
parent = f_point ).
f_value->if_ixml_node~set_value( '15' ).

* create ostream (into string variable) and render document into stream
f_ostream = fo_ixml_sf->create_ostream_xstring( f_xstring ).
f_ixml_data_doc->render( f_ostream ). "here f_xstring is filled

"set data to chart


co_chart_engine->set_data( xdata = f_xstring ).

"get customizing from Standard text - method found here


f_xstring = chart_customizing(
i_textname = 'Z_MY_CHART_CUSTOMIZING'
i_title = 'My nice chart'
i_subtitle = 'http://abapblog.com').
"set customizing
co_chart_engine->set_customizing( xdata = f_xstring ).
"render chart
co_chart_engine->render( ).

endmethod.
Example of use:
To be able to use the method we should firstly create a screen with custom control and call
it CHART_SAMPLE. Remember about allowing of resizing of the control so the chart can change
it size together with window size change.

Add variable name for OK Code also to be able to handle PAI.

Add PBO and PAI modules, PBO I will use to render chart and PAI to exit from the screen.
At the end we would need also GUI Status, to simplify it I will only fill few buttons
with END command.

Example Code for program:

report zab_chart_pie.

data: g_okcode type sy-ucomm.


data: go_abapblog type ref to zcl_abapblog_com. "our class with chart methods
data: go_chart type ref to cl_gui_chart_engine.
data: go_container type ref to cl_gui_custom_container.

call screen 0100.

*----------------------------------------------------------------------*
* MODULE pbo OUTPUT
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
module pbo output.
set pf-status 'STATUS_0100'.

if go_abapblog is initial.
create object go_abapblog.

"render chart
go_abapblog->create_and_init_chart(
exporting
i_container_name = 'CHART_SAMPLE'
changing
co_chart_engine = go_chart
co_container = go_container
).
endif.
endmodule. "pbo OUTPUT

*----------------------------------------------------------------------*
* MODULE pai INPUT
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
module pai input.
if g_okcode eq 'END'.
leave to screen 0.
endif.
endmodule. "pai INPUT

Result of our work:

Enjoy!

You might also like