Skip to Content

Creating Excel the Java way

Hi all,

I would like to share with you a some code development .

There is a constant request to generate Excel report from SAP .

As far as I know there is no built in support to do that from ABAP.

There is also the requirement to run the whole show in back ground job .

The regular “solution” is create html files, CSV files etc.

There is ABAP project http://wiki.scn.sap.com/wiki/display/ABAP/abap2xlsx but not every
organization would like to go this way.

Since I use Java as a hobby I thought I will try and use java to do the job .

The code supplied here is supplied as is. Try it and see if it is good for you.

Steps

  • Create XML using ABAP .
    The XML will contain meta data and instructions to the java program.
  • Write the XML to a file .
  • Call Java as external command .
  • The Java program will parse the XML file and generate the Excel file.

Open source projects used

Apache POI – http://poi.apache.org/ – the Java API for Microsoft Documents
This is main work horse… it will be used to generate the Excel files .
At the time of writing I did not utilize the full potential of this project. It is full of goodies that
are worth exploring…(I plan to try and use the “Formula Support” ).

Apache Commons CLI – http://commons.apache.org/proper/commons-cli
parsing command line options .

Apache Commons Lang – http://commons.apache.org/proper/commons-lang/
StopWatch.

Required jars from the projects (Already included in XmlFileToExcel.jar )

commons-cli-1.2.jar
commons-lang3-3.1.jar
dom4j-1.6.1.jar
poi-3.9-20121203.jar
poi-ooxml-3.9-20121203.jar
poi-ooxml-schemas-3.9-20121203.jar
xmlbeans-2.3.0.jar

The environment
Java Editor – Eclipse –  http://www.eclipse.org/

The Java code is located here: https://drive.google.com/folderview?id=0B6Cb7sgVnODWNV9DS29kQXdPblE&usp=sharing

The reason for putting the code here is because of the file types involved.

(If someone can point me to a place within scn.sap.com I will be grateful…)

XmlFileToExcel.zip – The whole set of source code is in a this zip file this way the directory structure of the Java project is preserved.

XmlFileToExcel.jar – This is the “.exe” equivalent of Java .
                     This file contain all the required jars from the projects .
                     The jar was created by eclipse using the “Runnable JAR File Exporter”
                     Class main.Main is the start class for this program.
                     This file is actually a zip file with extension of “jar”.

Y_R_EITAN_TEST_40_02.xml  – Sample XML created from SAP .

Y_R_EITAN_TEST_40_02.xlsx – Sample Excel generated by the java program .

            

Java Setup

  • Create in some shared folder accessible from sap the following:
    • A folder with the name “jre” this will contain the “Java Runtime Environment”.
    • – Install java jre on your PC .
        http://www.oracle.com/technetwork/java/javase/downloads/jre7-downloads-1880261.html
      – Note the folder where you install the jre (Usually C:\Program Files\Java\jre7 )
      – Copy folder “jre7” to folder “jre” .
    • Create a batch file named Y_JAVA_1.bat
      The content of the file:(note the “\bin”)

      path \\<path to jre>\bin
      java.exe -jar %1 %2 %3 %4 %5 %6 %7 %8 %9

    • Download XmlFileToExcel.jar and put it next to Y_JAVA_1.bat .

The folder will look like this:

/wp-content/uploads/2013/12/capture_20131212_110900_342126.png

SAP setup (Simple….)

program:( Y_R_EITAN_TEST_40_02 source included)

Upload the source to SAP and activate .

The program use table sbook as input (On our site it contain 100000 records)
The program read the selected records (FORM get_data_1) .
The program generate and write XML file (FORM write_1_to_xml) .
The program Execute an External Command and call java (FORM write_2_to_excel) .

External command

Use Transaction SM69 and add “Y_JAVA_1” as external command.

Y_JAVA_1 will call the batch file Y_JAVA_1.bat with the required parameters.

/wp-content/uploads/2013/12/capture_20131212_094913_342127.png

When you run the program you will be prompted for “My folder” this also needs to be a shared folder accessible from SAP .

All the paths needs to to be in \\host\directoryname structure (Universal Naming Convention) .

Thats all for now. have fun….

2 Comments
You must be Logged on to comment or reply to a post.
    • Hi,

      Sorry about that.

      I am retired now .

      For the java code you can find a lot of samples usage at poi site.

      Program Y_R_EITAN_TEST_40_02:

      REPORT y_r_eitan_test_40_02.

      TYPE-POOLS: abap .

      TYPE-POOLS: rsds .

      DATA: st_sbook TYPE sbook .

      CONSTANTS: c_java_call TYPE sxpgcolist-name VALUE 'Y_JAVA_1' .

      *----------------------------------------------------------------------*
      *----------------------------------------------------------------------*

      SELECTION-SCREEN BEGIN OF BLOCK block02 WITH FRAME.

      SELECT-OPTIONS: s_carrid FOR st_sbook-carrid .
      SELECT-OPTIONS: s_connid FOR st_sbook-connid .
      SELECT-OPTIONS: s_fldate FOR st_sbook-fldate .
      SELECT-OPTIONS: s_bookid FOR st_sbook-bookid .

      SELECTION-SCREEN SKIP .

      PARAMETERS: p_rows TYPE numrows DEFAULT 25000 .

      SELECTION-SCREEN END OF BLOCK block02.

      SELECTION-SCREEN BEGIN OF BLOCK block04 WITH FRAME.
      SELECTION-SCREEN COMMENT /32(79) fldr_c_1 .
      SELECTION-SCREEN COMMENT /32(79) fldr_c_2 .
      PARAMETERS: p_file_f TYPE localfile OBLIGATORY .
      SELECTION-SCREEN SKIP .
      PARAMETERS: p_file_s TYPE localfile MODIF ID mni .
      PARAMETERS: p_file_t TYPE localfile MODIF ID mni .
      SELECTION-SCREEN END OF BLOCK block04.

      *----------------------------------------------------------------------*
      *----------------------------------------------------------------------*

      INITIALIZATION.
      PERFORM at_initialization .

      AT SELECTION-SCREEN OUTPUT .
      PERFORM at_selection_screen_output .

      AT SELECTION-SCREEN .
      PERFORM at_selection_screen_input .

      *----------------------------------------------------------------------*
      *----------------------------------------------------------------------*
      FORM at_initialization .

      fldr_c_1 = 'The folder needs to be a shared folder (e.g. \\server\my_folder\). ' .
      fldr_c_2 = 'It needs to be accessible from SAP application server. ' .

      DATA: it_seltexts TYPE TABLE OF rsseltexts .
      DATA: st_seltexts LIKE LINE OF it_seltexts .

      st_seltexts-name = 'P_FILE_F' .
      st_seltexts-kind = 'P' .
      st_seltexts-text = 'My folder ' .
      APPEND st_seltexts TO it_seltexts .

      st_seltexts-name = 'P_FILE_S' .
      st_seltexts-kind = 'P' .
      st_seltexts-text = 'XML file name ' .
      APPEND st_seltexts TO it_seltexts .

      st_seltexts-name = 'P_FILE_T' .
      st_seltexts-kind = 'P' .
      st_seltexts-text = 'Excel file name ' .
      APPEND st_seltexts TO it_seltexts .

      CALL FUNCTION 'SELECTION_TEXTS_MODIFY'
      EXPORTING
      program = sy-cprog
      TABLES
      seltexts = it_seltexts
      EXCEPTIONS
      program_not_found = 1
      program_cannot_be_generated = 2
      OTHERS = 3.

      IF sy-subrc NE 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
      WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
      ENDIF.

      PERFORM set_file_names .

      ENDFORM. "at_initialization
      *----------------------------------------------------------------------*
      FORM at_selection_screen_output .

      LOOP AT SCREEN .

      CASE screen-group1 .
      WHEN 'MNI' ."No input
      screen-input = '0' .
      ENDCASE .

      MODIFY SCREEN .

      ENDLOOP.

      ENDFORM . "at_selection_screen_output
      *----------------------------------------------------------------------*
      FORM set_file_names .

      CONCATENATE sy-cprog '.xml' INTO p_file_s .
      CONCATENATE sy-cprog '.xlsx' INTO p_file_t .

      ENDFORM. "set_file_names
      *----------------------------------------------------------------------*
      FORM at_selection_screen_input .

      PERFORM set_file_names .

      CHECK sy-ucomm EQ 'ONLI' OR sy-ucomm EQ 'PRIN' .

      DATA: it_sbook TYPE ty_bookings .

      PERFORM get_data_1
      CHANGING
      it_sbook .

      IF it_sbook[] IS INITIAL .
      MESSAGE e668(vl).
      ENDIF .

      DATA: st_bal_s_log TYPE bal_s_log .

      st_bal_s_log-extnumber = sy-title .
      st_bal_s_log-aluser = sy-uname.
      st_bal_s_log-alprog = sy-repid.

      CALL FUNCTION 'BAL_LOG_CREATE'
      EXPORTING
      i_s_log = st_bal_s_log
      EXCEPTIONS
      OTHERS = 1.

      IF sy-subrc NE 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
      WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
      ENDIF.

      PERFORM write_1_to_xml
      USING
      it_sbook .

      PERFORM write_2_to_excel .

      DATA: st_display_profile TYPE bal_s_prof.

      * get a prepared profile
      CALL FUNCTION 'BAL_DSP_PROFILE_POPUP_GET'
      IMPORTING
      e_s_display_profile = st_display_profile
      EXCEPTIONS
      OTHERS = 1.

      st_display_profile-use_grid = abap_true .

      CALL FUNCTION 'BAL_DSP_LOG_DISPLAY'
      EXPORTING
      i_s_display_profile = st_display_profile
      i_amodal = abap_true
      EXCEPTIONS
      OTHERS = 1.
      IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE 'S' NUMBER sy-msgno
      WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
      ENDIF.

      ENDFORM . "at_selection_screen_input
      *----------------------------------------------------------------------*
      FORM get_random_color
      CHANGING
      color TYPE string .

      STATICS: it_color TYPE TABLE OF string .
      STATICS: lines TYPE i .
      STATICS: ob_abap_random_1 TYPE REF TO cl_abap_random_int .

      IF it_color[] IS INITIAL .

      APPEND 'AQUA ' TO it_color .
      APPEND 'BLACK ' TO it_color .
      APPEND 'BLUE ' TO it_color .
      APPEND 'BLUE_GREY ' TO it_color .
      APPEND 'BRIGHT_GREEN ' TO it_color .
      APPEND 'BROWN ' TO it_color .
      APPEND 'CORAL ' TO it_color .
      APPEND 'CORNFLOWER_BLUE ' TO it_color .
      APPEND 'DARK_BLUE ' TO it_color .
      APPEND 'DARK_GREEN ' TO it_color .
      APPEND 'DARK_RED ' TO it_color .
      APPEND 'DARK_TEAL ' TO it_color .
      APPEND 'DARK_YELLOW ' TO it_color .
      APPEND 'GOLD ' TO it_color .
      APPEND 'GREEN ' TO it_color .
      APPEND 'GREY_25_PERCENT ' TO it_color .
      APPEND 'GREY_40_PERCENT ' TO it_color .
      APPEND 'GREY_50_PERCENT ' TO it_color .
      APPEND 'GREY_80_PERCENT ' TO it_color .
      APPEND 'INDIGO ' TO it_color .
      APPEND 'LAVENDER ' TO it_color .
      APPEND 'LEMON_CHIFFON ' TO it_color .
      APPEND 'LIGHT_BLUE ' TO it_color .
      APPEND 'LIGHT_CORNFLOWER_BLUE ' TO it_color .
      APPEND 'LIGHT_GREEN ' TO it_color .
      APPEND 'LIGHT_ORANGE ' TO it_color .
      APPEND 'LIGHT_TURQUOISE ' TO it_color .
      APPEND 'LIGHT_YELLOW ' TO it_color .
      APPEND 'LIME ' TO it_color .
      APPEND 'MAROON ' TO it_color .
      APPEND 'OLIVE_GREEN ' TO it_color .
      APPEND 'ORANGE ' TO it_color .
      APPEND 'ORCHID ' TO it_color .
      APPEND 'PALE_BLUE ' TO it_color .
      APPEND 'PINK ' TO it_color .
      APPEND 'PLUM ' TO it_color .
      APPEND 'RED ' TO it_color .
      APPEND 'ROSE ' TO it_color .
      APPEND 'ROYAL_BLUE ' TO it_color .
      APPEND 'SEA_GREEN ' TO it_color .
      APPEND 'SKY_BLUE ' TO it_color .
      APPEND 'TAN ' TO it_color .
      APPEND 'TEAL ' TO it_color .
      APPEND 'TURQUOISE ' TO it_color .
      APPEND 'VIOLET ' TO it_color .
      APPEND 'WHITE ' TO it_color .
      APPEND 'YELLOW ' TO it_color .

      lines = LINES( it_color ) .

      ob_abap_random_1 = cl_abap_random_int=>create( min = 1 max = lines ) .

      ENDIF .

      DATA: tabix_1 TYPE sytabix .

      tabix_1 = ob_abap_random_1->get_next( ) .

      READ TABLE it_color INTO color INDEX tabix_1 .

      ENDFORM . "get_random_color
      *----------------------------------------------------------------------*
      FORM get_data_1
      USING
      it_sbook TYPE ty_bookings .

      SELECT * INTO TABLE it_sbook
      FROM sbook
      UP TO p_rows ROWS
      WHERE
      carrid IN s_carrid AND
      connid IN s_connid AND
      fldate IN s_fldate AND
      bookid IN s_bookid .

      ENDFORM . "GET_DATA_1
      *----------------------------------------------------------------------*
      FORM write_1_to_xml
      USING
      it_data TYPE table .

      DATA: message TYPE bapiret2-message .

      MESSAGE s001(00) WITH 'Start the XML phase' INTO message .
      PERFORM add_message .

      * Converting table it_data to XML DOM using cl_ixml .

      IF LINES( it_data ) EQ 0 .
      MESSAGE s560(oc).
      RETURN .
      ENDIF .

      DATA: it_ddfields TYPE ddfields .
      FIELD-SYMBOLS: <st_ddfields> LIKE LINE OF it_ddfields .

      * Get DDIC Information
      CALL METHOD cl_salv_ddic=>get_by_data
      EXPORTING
      data = it_data
      RECEIVING
      t_dfies = it_ddfields.

      DELETE it_ddfields WHERE fieldname EQ 'MANDT' .

      * Take care of invalid names (name space etc.).
      LOOP AT it_ddfields ASSIGNING <st_ddfields> .
      IF <st_ddfields>-lfieldname+0(1) = '/' .
      SHIFT <st_ddfields>-lfieldname LEFT BY 1 PLACES .
      TRANSLATE <st_ddfields>-lfieldname USING '/_' .
      ENDIF .
      ENDLOOP .

      FIELD-SYMBOLS: <st_data> TYPE ANY .
      FIELD-SYMBOLS: <component> TYPE ANY .

      DATA: dref TYPE REF TO data .

      CREATE DATA dref LIKE LINE OF it_data .

      ASSIGN dref->* TO <st_data> .

      DATA: buffer TYPE char64 .

      DATA: ob_ixml TYPE REF TO if_ixml .
      DATA: ob_ixml_document TYPE REF TO if_ixml_document ,
      ob_ixml_encoding TYPE REF TO if_ixml_encoding .

      ob_ixml = cl_ixml=>create( ).

      ob_ixml_document = ob_ixml->create_document( ).

      ob_ixml_encoding = ob_ixml->create_encoding(
      byte_order = if_ixml_encoding=>co_little_endian
      character_set = 'utf-8' ) .

      ob_ixml_document->set_encoding( ob_ixml_encoding ) .

      DATA: ob_root TYPE REF TO if_ixml_element .
      DATA: ob_sheet TYPE REF TO if_ixml_element .
      DATA: ob_rowx TYPE REF TO if_ixml_element .
      DATA: ob_colx TYPE REF TO if_ixml_element .
      DATA: string TYPE string .

      ob_root = ob_ixml_document->create_simple_element(
      name = 'root' parent = ob_ixml_document ) .

      WRITE sy-datum TO buffer .
      WRITE sy-uzeit TO buffer+12 .
      string = buffer .
      ob_root->set_attribute( name = 'Time' value = string ) .

      ob_sheet = ob_ixml_document->create_simple_element(
      name = 'sheet' parent = ob_root ) .

      * Freeze pane directive.
      ob_sheet->set_attribute( name = 'rowSplit' value = '1' ) .
      ob_sheet->set_attribute( name = 'colSplit' value = '5' ) .

      * Create the header row - Headings,metadata etc.
      ob_rowx = ob_ixml_document->create_simple_element(
      name = 'header' parent = ob_root ) .

      LOOP AT it_ddfields ASSIGNING <st_ddfields> .

      string = 'headerCell' .

      ob_colx = ob_ixml_document->create_simple_element(
      name = string parent = ob_rowx ) .

      string = <st_ddfields>-fieldname .
      ob_colx->set_attribute( name = 'NAME' value = string ) .

      string = <st_ddfields>-reptext .
      ob_colx->set_attribute( name = 'REPTEXT' value = string ) .

      string = <st_ddfields>-scrtext_m .
      ob_colx->set_attribute( name = 'SCRTEXT_M' value = string ) .

      string = <st_ddfields>-inttype .
      ob_colx->set_attribute( name = 'INTTYPE' value = string ) .

      string = <st_ddfields>-datatype .
      ob_colx->set_attribute( name = 'DATATYPE' value = string ) .

      ob_colx->set_attribute( name = 'Boldweight' value = 'BOLDWEIGHT_BOLD' ) .

      ob_colx->set_attribute( name = 'ForegroundColor' value = 'BLACK' ) .

      ob_colx->set_attribute( name = 'FontColor' value = 'GOLD' ) .

      ob_colx->set_attribute( name = 'Alignment' value = 'ALIGN_CENTER' ) .

      ENDLOOP .

      * Create the details rows
      LOOP AT it_data ASSIGNING <st_data> .

      string = sy-tabix .

      ob_rowx = ob_ixml_document->create_simple_element(
      name = 'detail'
      parent = ob_root ) .

      ob_rowx->set_attribute( name = 'line' value = string ) .

      LOOP AT it_ddfields ASSIGNING <st_ddfields> .

      string = 'detailCell' .

      ob_colx = ob_ixml_document->create_simple_element(
      name = string
      parent = ob_rowx ) .

      string = <st_ddfields>-fieldname .
      ob_colx->set_attribute( name = 'NAME' value = string ) .

      PERFORM get_random_color
      CHANGING
      string .

      ob_colx->set_attribute( name = 'ForegroundColor' value = string ) .

      PERFORM get_random_color
      CHANGING
      string .

      ob_colx->set_attribute( name = 'FontColor' value = string ) .

      ASSIGN COMPONENT <st_ddfields>-fieldname OF STRUCTURE <st_data> TO <component> .

      CASE <st_ddfields>-inttype .
      WHEN 'P' OR 'I' OR 'S' OR 'N' .
      WRITE <component> TO buffer . CONDENSE buffer .
      string = buffer .
      WHEN 'D' .
      WRITE <component>+0(4) TO buffer .
      WRITE '-' TO buffer+4(1) .
      WRITE <component>+4(2) TO buffer+5(2) .
      WRITE '-' TO buffer+7(1) .
      WRITE <component>+6(2) TO buffer+8(2) .
      WRITE <component> TO buffer .
      * buffer = <component> .
      CONDENSE buffer .
      string = buffer .
      WHEN OTHERS.
      buffer = <component> .
      string = buffer .
      CALL METHOD cl_http_utility=>if_http_utility~escape_html
      EXPORTING
      unescaped = string
      RECEIVING
      escaped = string.
      ENDCASE.

      ob_colx->if_ixml_node~set_value( string ).

      * ob_colx->set_attribute( name = 'VALUE' value = string ) .

      ENDLOOP .

      ENDLOOP.

      DATA: ob_ixml_stream_factory TYPE REF TO if_ixml_stream_factory.
      DATA: ob_ostream TYPE REF TO if_ixml_ostream .
      DATA: xstring TYPE xstring.

      ob_ixml_stream_factory = ob_ixml->create_stream_factory( ).
      ob_ostream = ob_ixml_stream_factory->create_ostream_xstring( xstring ).
      ob_ixml_document->render( ostream = ob_ostream ) .

      DATA: debug TYPE string.

      * For debug purpose only
      ob_ixml_stream_factory = ob_ixml->create_stream_factory( ).
      ob_ostream = ob_ixml_stream_factory->create_ostream_cstring( debug ).
      ob_ixml_document->render( ostream = ob_ostream ) .

      DATA: filesize TYPE i.

      filesize = XSTRLEN( xstring ).

      DATA: file_name TYPE string .

      CONCATENATE p_file_f p_file_s INTO file_name .

      DATA: mess TYPE string .

      OPEN DATASET file_name FOR OUTPUT IN BINARY MODE MESSAGE mess .

      IF sy-subrc NE 0.

      MESSAGE e306(f7) WITH file_name .

      RETURN .

      ENDIF.

      TRANSFER xstring TO file_name .

      CLOSE DATASET file_name .

      MESSAGE s838(5z) WITH file_name INTO message .
      PERFORM add_message .

      ENDFORM. "write_1_to_xml
      *----------------------------------------------------------------------*
      FORM write_2_to_excel .

      DATA: message TYPE bapiret2-message .

      MESSAGE s001(00) WITH 'Start the Excel phase' INTO message .
      PERFORM add_message .

      * Use Transaction SM69 Maintain External OS Commands.
      * Use Java program via external command .

      DATA: status TYPE extcmdexex-status ,
      exitcode TYPE extcmdexex-exitcode .
      DATA: it_exec_protocol TYPE TABLE OF btcxpm .

      DATA: additional_parameters TYPE sxpgcolist-parameters .

      DATA: file_name TYPE string .

      CONCATENATE p_file_f 'XmlFileToExcel.jar main.Main' INTO additional_parameters .

      CONCATENATE p_file_f p_file_s INTO file_name .
      CONCATENATE additional_parameters '-s' file_name INTO additional_parameters SEPARATED BY space .

      CONCATENATE p_file_f p_file_t INTO file_name .
      CONCATENATE additional_parameters '-t' file_name INTO additional_parameters SEPARATED BY space .

      CALL FUNCTION 'SXPG_COMMAND_EXECUTE'
      EXPORTING
      commandname = c_java_call
      additional_parameters = additional_parameters
      IMPORTING
      status = status
      exitcode = exitcode
      TABLES
      exec_protocol = it_exec_protocol
      EXCEPTIONS
      no_permission = 1
      command_not_found = 2
      parameters_too_long = 3
      security_risk = 4
      wrong_check_call_interface = 5
      program_start_error = 6
      program_termination_error = 7
      x_error = 8
      parameter_expected = 9
      too_many_parameters = 10
      illegal_command = 11
      wrong_asynchronous_parameters = 12
      cant_enq_tbtco_entry = 13
      jobcount_generation_error = 14
      OTHERS = 15.

      IF sy-subrc NE 0 .
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
      WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 .
      ENDIF .

      DATA: BEGIN OF st_ms .
      DATA: msgv1 TYPE symsgv ,
      msgv2 TYPE symsgv ,
      msgv3 TYPE symsgv ,
      msgv4 TYPE symsgv .
      DATA: END OF st_ms .

      FIELD-SYMBOLS: <st_exec_protocol> LIKE LINE OF it_exec_protocol .

      LOOP AT it_exec_protocol ASSIGNING <st_exec_protocol>.
      st_ms = <st_exec_protocol>-message .
      MESSAGE s001(00) WITH st_ms-msgv1 st_ms-msgv2 st_ms-msgv3 st_ms-msgv4 INTO message .
      PERFORM add_message .
      ENDLOOP.

      ENDFORM. "write_2_to_Excel_file
      *----------------------------------------------------------------------*
      FORM add_message .

      DATA: st_bal_s_msg TYPE bal_s_msg.

      st_bal_s_msg-msgty = sy-msgty.
      st_bal_s_msg-msgid = sy-msgid.
      st_bal_s_msg-msgno = sy-msgno.
      st_bal_s_msg-msgv1 = sy-msgv1.
      st_bal_s_msg-msgv2 = sy-msgv2.
      st_bal_s_msg-msgv3 = sy-msgv3.
      st_bal_s_msg-msgv4 = sy-msgv4.

      CALL FUNCTION 'BAL_LOG_MSG_ADD'
      EXPORTING
      i_s_msg = st_bal_s_msg
      EXCEPTIONS
      log_not_found = 0
      OTHERS = 1.

      IF sy-subrc NE 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
      WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
      ENDIF.

      ENDFORM . "add_message

      *Selection texts
      *----------------------------------------------------------
      * P_FILE D .
      * P_ROWS D .
      * P_TABLE D .
      * S_BOOKID D .
      * S_CARRID D .
      * S_CONNID D .
      * S_FLDATE D .

      *Messages
      *----------------------------------------------------------
      *
      * Message class: 00
      *001 &1&2&3&4&5&6&7&8
      *
      * Message class: 5Z
      *838 XML file created successfully: &
      *
      * Message class: F7
      *306 File & could not be opened
      *
      * Message class: OC
      *560 Download cancelled - no data found
      *
      * Message class: VL
      *668 No entry found for selection

      ----------------------------------------------------------------------------------
      Extracted by Mass Download version 1.5.2 - E.G.Mellodew. 1998-2018. Sap Release 701