Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
4,101
In many requirement graphical charts are required by the clients since a graph is much more appealing to the user. As graphs enables a better analysis of data to the user. It is however quite simple to provide the same functionality for building graphical charts in your ABAP report itself by using CL_IGS_CHART_ENGINE.

Recently I had the requirement of printing Charts on Smart forms. In Smart forms we can print the image if the image is already uploaded to the Form Graphics (SE78). I search through the SCN but doesn't find the solution of printing the charts on Smart forms. Then I had an idea of uploading the graphical image generated by CL_IGS_CHART_ENGINE dynamically to Form Graphics (SE78).  I have used the same functionality as used in Form Graphics (SE78) import to upload the image dynamically in Form Graphics.

Solution:

Create a Sample smart-Form to display the Graphical Chart generated by the custom function module.



TD_NAME is the name of the graphical chart generated dynamically by the custom function module YTESTCHART.



 

Delete the graphics after printing.


 

Print Preview of the Smart Form


 
FUNCTION ytestchart.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" REFERENCE(IM_TDNAME) TYPE STXBITMAPS-TDNAME
*" EXPORTING
*" VALUE(EX_STXBITMAPS) TYPE STXBITMAPS
*"----------------------------------------------------------------------

" IM_TDNAME Image name to be printed on smartforms
" EX_STXBITMAPS Image reference data generated dynamically

" Call This FM in the smartforms to generate image

DATA: xt_sflight TYPE flighttab,
g_ixml TYPE REF TO if_ixml,

x_ixml_data_doc TYPE REF TO if_ixml_document,
x_ixml_custom_doc TYPE REF TO if_ixml_document,
x_cl_igs_chart_engine TYPE REF TO cl_igs_chart_engine,
x_image_mime TYPE w3mimetabtype,
x_image_size TYPE w3param-cont_len,
x_image_type TYPE w3param-cont_type,

width_tw LIKE stxbitmaps-widthtw,
height_tw LIKE stxbitmaps-heighttw,
width_pix LIKE stxbitmaps-widthpix,
height_pix LIKE stxbitmaps-heightpix,
dpi LIKE stxbitmaps-resolution,
bds_bytecount TYPE i,
bitmap_file_bds TYPE sbdst_content,

lo_bds_object TYPE REF TO cl_bds_document_set,
xt_bds_components TYPE sbdst_components,
x_bds_components TYPE bapicompon,
xt_bds_signature TYPE sbdst_signature,
x_bds_signature TYPE bapisignat,
xt_bds_properties TYPE sbdst_properties,
x_bds_properties TYPE bapiproper,
x_stxbitmaps TYPE stxbitmaps,
x_object_key TYPE sbdst_object_key.



" Get Sample Data For the Chart/Graph

SELECT * FROM sflight INTO TABLE xt_sflight.

g_ixml = cl_ixml=>create( ).

" Generate XML for the chart

PERFORM create_data_demo USING x_ixml_data_doc xt_sflight
CHANGING g_ixml.

PERFORM create_custom_demo USING x_ixml_custom_doc
CHANGING g_ixml.

" Generate Image Using CL_IGS_CHART_ENGINE

x_cl_igs_chart_engine = NEW #( ).

CALL METHOD x_cl_igs_chart_engine->set_data
EXPORTING
data_doc = x_ixml_data_doc.
CALL METHOD x_cl_igs_chart_engine->set_customizing
EXPORTING
custom_doc = x_ixml_custom_doc.

CALL METHOD x_cl_igs_chart_engine->execute
EXCEPTIONS
OTHERS = 1.

IF sy-subrc IS INITIAL.

" Get Image to upload to SE78



CALL METHOD x_cl_igs_chart_engine->get_image
IMPORTING
image = x_image_mime
image_size = x_image_size
image_type = x_image_type.

CALL FUNCTION 'SAPSCRIPT_CONVERT_BITMAP_BDS'
EXPORTING
color = 'X'
format = 'BMP'
resident = ' '
bitmap_bytecount = x_image_size
compress_bitmap = ' '
IMPORTING
width_tw = width_tw
height_tw = height_tw
width_pix = width_pix
height_pix = height_pix
dpi = dpi
bds_bytecount = bds_bytecount
TABLES
bitmap_file = x_image_mime
bitmap_file_bds = bitmap_file_bds
EXCEPTIONS
format_not_supported = 1
no_bmp_file = 2
bmperr_invalid_format = 3
bmperr_no_colortable = 4
bmperr_unsup_compression = 5
bmperr_corrupt_rle_data = 6
OTHERS = 7.



* Save bitmap in BDS
lo_bds_object = NEW #( ).

x_bds_components-doc_count = '1'.
x_bds_components-comp_count = '1'.
x_bds_components-mimetype = 'application/octet-stream'.
x_bds_components-comp_size = bds_bytecount.
APPEND x_bds_components TO xt_bds_components.

x_bds_signature-doc_count = '1'.
APPEND x_bds_signature TO xt_bds_signature.

CALL METHOD lo_bds_object->create_with_table
EXPORTING
classname = 'DEVC_STXD_BITMAP'
classtype = 'OT'
components = xt_bds_components
content = bitmap_file_bds
CHANGING
signature = xt_bds_signature
object_key = x_object_key
EXCEPTIONS
OTHERS = 1.

* Save bitmap header in Database Table STXBITPMAPS
x_stxbitmaps-tdname = im_tdname.
x_stxbitmaps-tdobject = 'GRAPHICS'.
x_stxbitmaps-tdid = 'BMAP'.
x_stxbitmaps-tdbtype = 'BCOL'.
x_stxbitmaps-docid = xt_bds_signature[ 1 ]-doc_id.
x_stxbitmaps-widthpix = width_pix. " Width and hights can be changed
x_stxbitmaps-heightpix = height_pix.
x_stxbitmaps-widthtw = width_tw.
x_stxbitmaps-heighttw = height_tw.
x_stxbitmaps-resolution = '075'.
* x_stxbitmaps-resident = 'X'.
x_stxbitmaps-autoheight = 'X'.
* x_stxbitmaps-bmcomp = 'X'.
INSERT INTO stxbitmaps VALUES x_stxbitmaps.
IF sy-subrc <> 0.
UPDATE stxbitmaps FROM x_stxbitmaps.
ENDIF.

ex_stxbitmaps = x_stxbitmaps.

x_bds_properties-prop_name = 'DESCRIPTION'.
x_bds_properties-prop_value = 'Charts'.
APPEND x_bds_properties TO xt_bds_properties.

CALL METHOD lo_bds_object->change_properties
EXPORTING
classname = 'DEVC_STXD_BITMAP'
classtype = 'OT'
object_key = x_object_key
doc_id = xt_bds_signature[ 1 ]-doc_id
doc_ver_no = '1'
doc_var_id = '1'
CHANGING
properties = xt_bds_properties
EXCEPTIONS
OTHERS = 1.

ENDIF.

ENDFUNCTION.

**----------------------------------------------------------------------*
****INCLUDE LYTESTCHARTF01.
**----------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form CREATE_DATA_DEMO
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_X_IXML_DATA_DOC text
* -->P_XT_SFLIGHT text
* <--P_G_IXML text
*----------------------------------------------------------------------*
FORM create_data_demo USING p_ixml_doc TYPE REF TO if_ixml_document
pt_sflight TYPE flighttab
CHANGING p_ixml TYPE REF TO if_ixml.

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 = p_ixml->create_document( ).
* Set encoding to UTF-8
l_encoding = p_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 pt_sflight ASSIGNING FIELD-SYMBOL(<sflight>).
l_element = p_ixml_doc->create_simple_element(
name = 'C' parent = l_categories ).
CONCATENATE <sflight>-carrid <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 pt_sflight ASSIGNING <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 = <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 pt_sflight ASSIGNING <sflight>.
l_element = p_ixml_doc->create_simple_element(
name = 'S' parent = l_series ).
* Populate value for another category here.
l_value = <sflight>-seatsmax.
l_element->if_ixml_node~set_value( l_value ).
CLEAR l_value.
ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form CREATE_CUSTOM_DEMO
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_L_IXML_CUSTOM_DOC text
*----------------------------------------------------------------------*
FORM create_custom_demo USING p_ixml_doc TYPE REF TO if_ixml_document
CHANGING p_ixml TYPE REF TO if_ixml.
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_text TYPE REF TO if_ixml_element,
l_element TYPE REF TO if_ixml_element,
l_chartaxes TYPE REF TO if_ixml_element,
l_categoryaxis TYPE REF TO if_ixml_element,
l_line TYPE REF TO if_ixml_element,
l_encoding TYPE REF TO if_ixml_encoding.

p_ixml_doc = p_ixml->create_document( ).
l_encoding = p_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( 'BMP' ).
* 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('Columns'). "( '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.

 

Conclusion: -

Now we can print any type of charts using CL_IGS_CHART_ENGINE on smart-forms dynamically. we just need to change the XML for changing the chart.

I hope that makes drawing graphs/charts with ABAP complete and easily achievable.

Thanks for reading this blog post. I would like to see your comments and would like to answer questions which u can post at Q&A tag area: https://answers.sap.com/tags/66233466-fcd6-45d2-a9ae-2cba38c72e19

 
6 Comments
Florian
Active Contributor
 

Hi Yogesh,

First question which come to my mind... you link to a S/4 space and writing about smartforms... so what's the reason for that.

There is this brandnew.. errm new.. ermm in 2006 presented technology called IFbA which make such requirements a little easier to solve..

So, everyone who wants to print today anything out of SAP.. expecially in the context of S/4 I recommend to have a look  what IFbA can do for you and why it's the recommended way to print anything. But if you want to use smartforms or Sapscript you can.. but should you?!

Next to that, examples with form-routines developed in 2021.. don't add anything here.

~Florian

 

~Florian
former_member301082
Discoverer
0 Kudos
Thanks for the post Yogesh.

We are utilizing Smartforms for our major number of print outs in our organization and also looking for similar provision for our analytical dashboards.

Please also let us know for analytical tools like time series (Laplace and fourier series) in case we are running our utilities solutions.

KK
former_member361443
Discoverer
0 Kudos
Hi,

Kindly can anyone suggest me how to generate data labels on the bars in the graphs.

Which XML tags to use with the interface -  IF_IXML_DOCUMENT to get the data labels.

Regards,

Satyendra Sahay

 

 

 

 

 

 
shais
Participant
0 Kudos
<Series>
<ShowLabel>true</ShowLabel>
<Format>$Label</Format>
</Series>

I would suggest you to use the (executable) SAP Chart Designer in order to experience with the different configuration options.
former_member361443
Discoverer
0 Kudos
Hi,

Kindly can you guide me how to use the above mentioned XML tags in the SAP ABAP code.

Regards,

Satyendra Sahay
Stepniake
Newcomer
0 Kudos

Great job 🙂

You solution works very good in SAP GUI, but when i try to show generated pdf in FIORI, i have a problem with generated chart.
As you can see, on FIORI caption works (1), gray area for chart is the same like on GUI, but i do not see pieces of pie 😉

smart_char_fiori.png

Difference between code for Fiori and GUI is bellow:

smart_char_gui.png

For GUI I am using just SSF_FUNCTION_MODULE_NAME and CALL FUNCTION for generated "fm_name". And it works.

For Fiori, i have to use additionaly:
- CALL FUNCTION 'SSF_GET_DEVICE_TYPE'
and later:
- CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME'
- CALL FUNCTION lv_fm_name
and then:
- CALL FUNCTION 'CONVERT_OTF'.

Full code You can see bellow.

CONVERT_OTF gives me value in lv_pdf_xstring, i can see all pdf but, as i said, without chart.

I think, that there is a problem when i am using convert_orf FM. Or am i wrong?

Anyone can suggest me some solution?



      lv_language = sy-langu.
      TRANSLATE lv_language TO UPPER CASE.
      ls_control_parameters-langu = lv_language.

* set control parameters to get the output text format (OTF) from Smart Forms
      ls_control_parameters-no_dialog = 'X'.
      ls_control_parameters-getotf   = 'X'.
      ls_control_parameters-preview = space. "no preview

* get device type from language

*call function 'ssf_get_device_type'
      CALL FUNCTION 'SSF_GET_DEVICE_TYPE'
        EXPORTING
          i_language             = lv_language
*         i_application          = ‘SAPDEFAULT’
        IMPORTING
          e_devtype              = lv_devtype
        EXCEPTIONS
          no_language            = 1
          language_not_installed = 2
          no_devtype_found       = 3
          system_error           = 4
          OTHERS                 = 5.

* set device type in output options
      ls_output_options-tdprinter = lv_devtype.

* Set relevant output options
      ls_output_options-tdnewid = 'X'. "print parameters,
      ls_output_options-tddelete = space. "print parameters
*      ls_output_options-XSF   = 'X'.

*call function 'ssf_function_module_name'
      CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME'
        EXPORTING
*         formname           = ‘sf_example_03’  "smartform name
          formname           = lv_formname "smartform name
        IMPORTING
          fm_name            = lv_fm_name
        EXCEPTIONS
          no_form            = 1
          no_function_module = 2
          OTHERS             = 3.


      IF sy-subrc <> 0.
* Implement suitable error handling here
      ENDIF.



* Call Smartform generated FM

      CALL FUNCTION lv_fm_name
        EXPORTING
          control_parameters = ls_control_parameters
          output_options     = ls_output_options
          user_settings      = space
*         customer           = ls_customer
*         bookings           = lt_bookings
*         connections        = lt_connections
          td_name            = lv_td_name
        IMPORTING
          job_output_info    = ls_output_data
        TABLES
          it_data            = it_data
        EXCEPTIONS
          formatting_error   = 1
          internal_error     = 2
          send_error         = 3
          user_canceled      = 4
          OTHERS             = 5.

      APPEND LINES OF ls_output_data-otfdata[] TO lt_tstotf[].

* Convert to OTF

*CALL FUNCTION 'convert_otf'
      CALL FUNCTION 'CONVERT_OTF'
        EXPORTING
          format                = 'PDF'
        IMPORTING
          bin_filesize          = lv_pdf_len
          bin_file              = lv_pdf_xstring " binary file
        TABLES
          otf                   = lt_tstotf
          lines                 = lt_lines
        EXCEPTIONS
          err_max_linewidth     = 1
          err_format            = 2
          err_conv_not_possible = 3
          err_bad_otf           = 4
          OTHERS                = 5.

      IF sy-subrc = 0.
        e_xstring = lv_pdf_xstring.
      ENDIF.

 

Labels in this area