Friday 15 June 2018

New ABAP Table Sum

Introduction


In this blog series, the goal is to focus on comparing older ABAP language features with a detailed explanation of the new ABAP syntax.

I recently wrote a program to explain older and newer ways to do a summary on an internal table. This blog will dissect that program. We will show the various ways to accomplish the same thing for a table summary, and how the ABAP language has evolved over the years. This blog will be useful for both new ABAPers, as well as experienced ABAPers trying to get familiar with the new ABAP.

Software Versions:

52 of SAP, SAPGUI Version 750.
Eclipse Version: Oxygen.1a Release (4.7.1a)

Program Overview


The program will have the following select options:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

The program will perform the following steps:

1. Take the “Number of Records” field from the selection screen and generate a table of sample records.
2. Process the table according to the selected Radio Button option.
3. Display the resulting summary table in ALV.

Newer ABAP supports method chaining, so to run the program, we simply do the following at START-OF-SELECTION:

START-OF-SELECTION.
  lcl_my_class=>main( )->execute( ).

Broken into parts:

◉ lcl_my_class=>main( ) – Instantiates a new instance of LCL_MY_CLASS. This is a static factory method, which simply returns an instance of itself.
◉ execute( ) – All of the main logic is contained in the EXECUTE method of LCL_MY_CLASS.


Radio button Options

1. Standard Table: With this option, we will show the old school method for performing a summary by sorting and collecting.

2. Sorted Table: With this option, we will do a read on a sorted table, then update the summary field using a field symbol.

3. New ABAP: With this option, we will utilize the new ABAP language features to update the records and increment the summary field.

All 3 options, above, will perform the same logic, described below, but with different table reads and updates.

Here is an overview of what the 3 methods will do:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

You may have guessed, this simply doubles the value in SUMMARY_FIELD, since the table was cloned from the original.

Example:

IT_TEST_TABLE, passed into the method (unsorted):

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

Resulting ALV (sorted by keys), after adding the temporary tables. Simply doubles the SumField (SUMMARY_FIELD):

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

When executing each of the 3 options, the results will be identical to the above.

Record Generator

All 3 of the above methods will use the following generated sample table. We will use the new ABAP features to create the random records with the following method lm_build_records:

*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* METHOD lm_build_records: Build a table with nn records...
*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  METHOD lm_build_records.
    DO p_recs TIMES.
      APPEND VALUE lty_struct( key1          = 900 + sy-index
                               key2          = sy-index
                               field1        = |A Text Field - { sy-index }|
                               a_date_field  = sy-datum + sy-index
                               summary_field = sy-index * 10 )
        TO et_test_table.
    ENDDO.
  ENDMETHOD. " lm_build_records

The parameter p_recs is the “Number of Records” field on the selection screen. To further explain the above new ABAP code, here is how the random records are generated…

We will loop and create P_RECS number of records.

For each loop pass, it will dynamically generate a new record of type LTY_STRUCT. No intermediate variables needed with the new ABAP.

VALUE lty_struct(…) – This tells the compiler to generate a new record of type LTY_STRUCT. This structure was declared in our private global section for our class:

  PRIVATE SECTION.
    TYPES: BEGIN OF lty_struct,
             key1          TYPE matnr,
             key2          TYPE rsrnumc10,
             field1        TYPE string,
             a_date_field  TYPE sydatum,
             summary_field TYPE i,
           END OF lty_struct,
           lty_tab  TYPE STANDARD TABLE OF lty_struct,
           lty_stab TYPE SORTED TABLE OF lty_struct WITH UNIQUE KEY key1 key2.

This will randomly generate the following values for the fields:

◈ KEY1 – Take 900 plus the current loop pass number contained in SY-INDEX (i.e. 901, 902, etc.)
◈ KEY2 – The current loop pass contained in SY-INDEX.
◈ FIELD1 – The text “A Text Field”, plus the current loop pass number in SY-INDEX. The new string templates in the new ABAP, generates the exact string contained within the Pipe (|) symbols (no more CONCATENATE statement needed!). Also, within your string, you can dynamically specify a variable within your string within curly braces {}. So, |A Text Field – { sy-index }| will be “A Text Field – 1” on the first loop pass.
◈ A_DATE_FIELD – Take today’s date and add the current loop pass number (SY-INDEX) in days.
◈ SUMMARY_FIELD – Take the current loop pass multiplied by 10.

After this record is generated, it is appended to ET_TEST_TABLE, an export table parameter for the method.

Now, on to the table code…

Table Processing Options


Standard Table

The COLLECT statement was one original ABAP statement for adding numeric fields together in an internal table. If summarizing a standard table with no keys, it will compare all non-numeric fields, and will sum the numeric field. In our case, we have the following structure:

    TYPES: BEGIN OF lty_struct,
             key1          TYPE matnr,
             key2          TYPE rsrnumc10,
             field1        TYPE string,
             a_date_field  TYPE sydatum,
             summary_field TYPE i,
           END OF lty_struct,

Because SUMMARY_FIELD is our only numeric field, it will sum those values.

Example:

Table 1:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

Table 2:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

If adding the above 2 identical tables together with the COLLECT statement, it will give the following:

Summary Table:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

Logic for the above results:

*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* METHOD lm_process_standard_table: Pre-740 Method to process a
* standard table.
*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  METHOD lm_process_standard_table.
    DATA: lt_temp_table TYPE lty_tab,
          lt_sum_table  TYPE lty_tab,
          lw_rec        TYPE lty_struct.
    lt_temp_table[] = it_test_table[].
    lt_sum_table[] = it_test_table[].
    SORT lt_temp_table BY key1 key2.
    SORT lt_sum_table BY key1 key2.

    "This will double the summary_field entries...
    LOOP AT lt_temp_table INTO lw_rec.
      COLLECT lw_rec INTO lt_sum_table.
    ENDLOOP.
    lm_display( CHANGING ct_report = lt_sum_table ).
  ENDMETHOD. " lm_process_standard_table

The above code for a Standard Table was a classical way of performing a summary, and should work in most older SAP versions. Of course, what if you have 2 numeric fields, but you only want to add up one of them? Let’s say we add an additional numeric field at the end, that we do not want to summarize. For example, let’s add a field named DO_NOT_ADD, which is also an integer:

Table 1:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

Table 2:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

Summary Table:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

If we only wanted to add together the field SUMMARY_FIELD, then this would require a read and update of that record, and the COLLECT statement would not work. In this case, a Sorted Table or Hashed Table would be a good candidate to handle a fast read and update of existing records in an internal table.

Sorted Table

In this example, we will update a specific field, and summarize it by reading the record from a Sorted Table.

The code for a Sorted Table summary, to achieve the same results as the Standard Table example:

*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* METHOD lm_process_sorted_table: Pre-740 Logic to process a
* sorted table.
*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  METHOD lm_process_sorted_table.
    DATA: lt_temp_table TYPE lty_stab,
          lt_sum_table  TYPE lty_stab,
          lt_pass_table TYPE lty_tab,
          lw_rec        TYPE lty_struct.
    FIELD-SYMBOLS: <lw_rec> TYPE lty_struct.

    LOOP AT it_test_table INTO lw_rec.
      INSERT lw_rec INTO TABLE lt_temp_table.
      INSERT lw_rec INTO TABLE lt_sum_table.
    ENDLOOP.

    "This will double the summary_field entries...
    CLEAR lw_rec.
    LOOP AT lt_temp_table INTO lw_rec.
      UNASSIGN <lw_rec>.
      READ TABLE lt_sum_table ASSIGNING <lw_rec>
                              WITH TABLE KEY key1 = lw_rec-key1
                                             key2 = lw_rec-key2.
      IF <lw_rec> IS ASSIGNED.
        "Add the summary_field...
        <lw_rec>-summary_field = <lw_rec>-summary_field + lw_rec-summary_field.
      ENDIF.
    ENDLOOP.
    lt_pass_table[] = lt_sum_table[].
    lm_display( CHANGING ct_report = lt_pass_table ).
  ENDMETHOD. " lm_process_sorted_table

The above code uses a read on the sorted table using the keys and into a field symbol to update the SUMMARY_FIELD.

New ABAP

Finally, let’s look at the new ABAP way of achieving the same results. With 740, table indexes have been added with the bracket notation []. For example, to retrieve record #5 into a work area, you could specify:

data(lw_record5) = lt_sum_table[ 5 ].

For this table:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

For Record 5, it would retrieve the following:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

You can also specify values for your key fields to lookup a record.

Let’s try this:

data(lw_record5) = lt_sum_table[ key1 = '905' key2 = '5' ].

Ooops, that gives us a short dump saying “This line is not contained in the table”:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

Because we are attempting to use a record that could not be found and assign it to the work area lw_record5, we get a short dump. To handle this, SAP added the “line_exists” function in order to verify that the line actually exists, before trying to use it. So, we must always do this:

    if line_exists( lt_sum_table[ key1 = '905' key2 = '5' ] ).
      data(lw_record5) = lt_sum_table[ key1 = '905' key2 = '5' ].
    endif.

We can now avoid a short dump.

But wait, why doesn’t it exist? As you guessed, if we look at the data type for key1 and key2, it is of type MATNR and RSRNUMC10:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

If I copy the variable exactly as it appears in the Eclipse Debugger, I get:

KEY1 (MATNR) as:

“                                    905”

KEY2 is “0000000005”.

So, if we try the following, we can find the record:

    if line_exists( lt_sum_table[ key1 = '                                    905' key2 = '0000000005' ] ).
      data(lw_record5) = lt_sum_table[ key1 = '                                    905' key2 = '0000000005' ].
    endif.

So, the keys must match exactly, with leading zeros, spaces, etc.

Alternatively, you could do the following, and compare it to record 5 in our duplicate table:

data(lw_record5) = lt_sum_table[ key1 = lt_temp_table[ 5 ]-key1 key2 = lt_temp_table[ 5 ]-key2 ].

…enough on that, here is the method for new ABAP:

*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* METHOD lm_process_new_abap: Use New ABAP Features to process a table.
*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  METHOD lm_process_new_abap.
    DATA: lt_temp_table TYPE lty_stab,
          lt_sum_table  TYPE lty_stab,
          lt_pass_table TYPE lty_tab.

    LOOP AT it_test_table INTO DATA(lw_rec).
      INSERT lw_rec INTO TABLE lt_temp_table.
      INSERT lw_rec INTO TABLE lt_sum_table.
    ENDLOOP.

    "This will double the summary_field entries...
    "The bracket notation [] finds the record with that key, then we can update it...
    CLEAR lw_rec.
    LOOP AT lt_temp_table INTO lw_rec.
      IF line_exists( lt_sum_table[ key1 = lw_rec-key1 key2 = lw_rec-key2 ] ).
        lt_sum_table[ key1 = lw_rec-key1 key2 = lw_rec-key2 ]-summary_field =
        lt_sum_table[ key1 = lw_rec-key1 key2 = lw_rec-key2 ]-summary_field + lw_rec-summary_field.
      ENDIF.
    ENDLOOP.
    lt_pass_table[] = lt_sum_table[].
    lm_display( CHANGING ct_report = lt_pass_table ).
  ENDMETHOD. " lm_process_new_abap

Performance


As I was looking at the following code, I became curious about performance:

      IF line_exists( lt_sum_table[ key1 = lw_rec-key1 key2 = lw_rec-key2 ] ).
        lt_sum_table[ key1 = lw_rec-key1 key2 = lw_rec-key2 ]-summary_field =
        lt_sum_table[ key1 = lw_rec-key1 key2 = lw_rec-key2 ]-summary_field + lw_rec-summary_field.
      ENDIF.

Is the bracket notation, for the above, doing 3 reads on the same record, 3 different times? Perhaps we could eliminate these by assigning it to a field-symbol, then updating the summary_field. I don’t know the answer to this, does it matter? To answer that question, let’s just do a very un-scientific runtime analysis and see if there is a difference in runtimes. Also, I would like to see which of the 3 methods – Standard, Sorted and the new ABAP technique has a performance difference, if any.

Since we have the “Number of Records” parameter on the selection screen, let’s crank it up to a number that is large, but acceptable enough to run multiple times. 40,000 records seems like a bearable number to test.

Execute the SAP transaction “SAT” and enter the program name:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

Click on the “Execute” button, and it will take you to the selection screen:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

Enter 40,000 for number of records (or more or less, depending on your system).

Execute the transaction, to get the results:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

Click on the Exit button twice, to get back to the SAT measurement screen:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

Note the call to our “LM_PROCESS_STANDARD_TABLE” method took 24,927,504 microseconds:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

Perform these same steps with the other 2 options for Sorted Table and New ABAP. We get the following runtimes:

Sorted Table:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

New ABAP:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

So, overall, we have:

Standard Table: 24,927,504

Sorted Table: 1,137,987

New ABAP: 1,200,210

Because the New ABAP technique and the Sorted Table option both use sorted tables, this just tells us that the New ABAP is about the same speed as the other sorted technique. A standard table is slow, simply because it’s doing a sequential read. Now, let’s change the code, and compare the “3 reads” we brought up earlier, to see if using a field-symbol makes a difference.

Here is our current code for the New ABAP option, which got us the above results:

    LOOP AT lt_temp_table INTO lw_rec.
      IF line_exists( lt_sum_table[ key1 = lw_rec-key1 key2 = lw_rec-key2 ] ).
        lt_sum_table[ key1 = lw_rec-key1 key2 = lw_rec-key2 ]-summary_field =
        lt_sum_table[ key1 = lw_rec-key1 key2 = lw_rec-key2 ]-summary_field + lw_rec-summary_field.
      ENDIF.
    ENDLOOP.

We could change it to a single read, as follows:

    FIELD-SYMBOLS: <lfs_sum> TYPE lty_struct.
    LOOP AT lt_temp_table INTO lw_rec.
      UNASSIGN <lfs_sum>.
      ASSIGN lt_sum_table[ key1 = lw_rec-key1 key2 = lw_rec-key2 ] TO <lfs_sum>.
      IF <lfs_sum> IS ASSIGNED.
        <lfs_sum>-summary_field = <lfs_sum>-summary_field + lw_rec-summary_field.
      ENDIF.
    ENDLOOP.

When doing the same runtime analysis in SAT for 40K records, we get runtimes of:

Run1:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

Run2:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

Run3:

ABAP Development, ABAP Testing and Analysis, SAP ABAP Study Materials

So, when running 3 times, each one was slightly faster by using the field symbol.

Complete Program


Here is the complete program:

REPORT zjctest_tables.

SELECTION-SCREEN BEGIN OF BLOCK b1.
PARAMETERS: rb_std  RADIOBUTTON GROUP g1,
            rb_sort RADIOBUTTON GROUP g1,
            rb_new  RADIOBUTTON GROUP g1,
            p_recs  TYPE syindex DEFAULT '20000'.
SELECTION-SCREEN END OF BLOCK b1.

CLASS lcl_my_class DEFINITION CREATE PRIVATE FINAL.
  PUBLIC SECTION.
    CLASS-METHODS:
      main
        RETURNING VALUE(r_obj) TYPE REF TO lcl_my_class.
    METHODS:
      execute.

  PRIVATE SECTION.
    TYPES: BEGIN OF lty_struct,
             key1          TYPE matnr,
             key2          TYPE rsrnumc10,
             field1        TYPE string,
             a_date_field  TYPE sydatum,
             summary_field TYPE i,
           END OF lty_struct,
           lty_tab  TYPE STANDARD TABLE OF lty_struct,
           lty_stab TYPE SORTED TABLE OF lty_struct WITH UNIQUE KEY key1 key2.
    METHODS:
      constructor,
      lm_process_standard_table
        IMPORTING it_test_table TYPE lty_tab,
      lm_process_sorted_table
        IMPORTING it_test_table TYPE lty_tab,
      lm_process_new_abap
        IMPORTING it_test_table TYPE lty_tab,
      lm_display
        CHANGING ct_report TYPE table,
      lm_build_alv_table
        CHANGING  ct_report     TYPE table
        RETURNING VALUE(rt_alv) TYPE REF TO cl_salv_table,
      lm_build_records
        EXPORTING et_test_table TYPE lty_tab.
ENDCLASS.

CLASS lcl_my_class IMPLEMENTATION.
*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* METHOD constructor: Initialize my object.
*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  METHOD constructor.

  ENDMETHOD. " constructor

*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* METHOD main: Instantiate the object
*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  METHOD main.
    CREATE OBJECT r_obj.
  ENDMETHOD.                    "MAIN

*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* METHOD lm_process_standard_table: Pre-740 Method to process a
* standard table.
*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  METHOD lm_process_standard_table.
    DATA: lt_temp_table TYPE lty_tab,
          lt_sum_table  TYPE lty_tab,
          lw_rec        TYPE lty_struct.
    lt_temp_table[] = it_test_table[].
    lt_sum_table[] = it_test_table[].
    SORT lt_temp_table BY key1 key2.
    SORT lt_sum_table BY key1 key2.

    "This will double the summary_field entries...
    LOOP AT lt_temp_table INTO lw_rec.
      COLLECT lw_rec INTO lt_sum_table.
    ENDLOOP.
    lm_display( CHANGING ct_report = lt_sum_table ).
  ENDMETHOD. " lm_process_standard_table

*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* METHOD lm_process_sorted_table: Pre-740 Logic to process a
* sorted table.
*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  METHOD lm_process_sorted_table.
    DATA: lt_temp_table TYPE lty_stab,
          lt_sum_table  TYPE lty_stab,
          lt_pass_table TYPE lty_tab,
          lw_rec        TYPE lty_struct.
    FIELD-SYMBOLS: <lw_rec> TYPE lty_struct.

    LOOP AT it_test_table INTO lw_rec.
      INSERT lw_rec INTO TABLE lt_temp_table.
      INSERT lw_rec INTO TABLE lt_sum_table.
    ENDLOOP.

    "This will double the summary_field entries...
    CLEAR lw_rec.
    LOOP AT lt_temp_table INTO lw_rec.
      UNASSIGN <lw_rec>.
      READ TABLE lt_sum_table ASSIGNING <lw_rec>
                              WITH TABLE KEY key1 = lw_rec-key1
                                             key2 = lw_rec-key2.
      IF <lw_rec> IS ASSIGNED.
        "Add the summary_field...
        <lw_rec>-summary_field = <lw_rec>-summary_field + lw_rec-summary_field.
      ENDIF.
    ENDLOOP.
    lt_pass_table[] = lt_sum_table[].
    lm_display( CHANGING ct_report = lt_pass_table ).
  ENDMETHOD. " lm_process_sorted_table

*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* METHOD lm_process_new_abap: Use New ABAP Features to process a table.
*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  METHOD lm_process_new_abap.
    DATA: lt_temp_table TYPE lty_stab,
          lt_sum_table  TYPE lty_stab,
          lt_pass_table TYPE lty_tab.
    FIELD-SYMBOLS: <lfs_sum> TYPE lty_struct.

    LOOP AT it_test_table INTO DATA(lw_rec).
      INSERT lw_rec INTO TABLE lt_temp_table.
      INSERT lw_rec INTO TABLE lt_sum_table.
    ENDLOOP.

    "This will double the summary_field entries...
    "The bracket notation [] finds the record with that key, then we can update it...
    CLEAR lw_rec.
    LOOP AT lt_temp_table INTO lw_rec.
      UNASSIGN <lfs_sum>.
      ASSIGN lt_sum_table[ key1 = lw_rec-key1 key2 = lw_rec-key2 ] TO <lfs_sum>.
      IF <lfs_sum> IS ASSIGNED.
        <lfs_sum>-summary_field = <lfs_sum>-summary_field + lw_rec-summary_field.
      ENDIF.
    ENDLOOP.
    lt_pass_table[] = lt_sum_table[].

    lm_display( CHANGING ct_report = lt_pass_table ).
  ENDMETHOD. " lm_process_new_abap

*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* METHOD lm_build_records: Build a table with nn records...
*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  METHOD lm_build_records.
    DO p_recs TIMES.
      APPEND VALUE lty_struct( key1          = 900 + sy-index
                               key2          = sy-index
                               field1        = |A Text Field - { sy-index }|
                               a_date_field  = sy-datum + sy-index
                               summary_field = sy-index * 10 )
        TO et_test_table.
    ENDDO.
  ENDMETHOD. " lm_build_records

*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* METHOD execute: Execute the work for my object.
*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  METHOD execute.
    DATA: lt_report TYPE lty_tab.
    "Create records...
    lm_build_records( IMPORTING et_test_table = lt_report ).
    "Mess up the sorting, so that we can process and test, below...
    SORT lt_report DESCENDING.

    IF rb_std = abap_true.
      lm_process_standard_table( lt_report ).
    ELSEIF rb_sort = abap_true.
      lm_process_sorted_table( lt_report ).
    ELSEIF rb_new = abap_true.
      lm_process_new_abap( lt_report ).
    ENDIF.
  ENDMETHOD.                    "execute

*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* METHOD lm_display: Show the report...
*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  METHOD lm_display.
    lm_build_alv_table( CHANGING ct_report = ct_report )->display( ).
  ENDMETHOD.                    "display

*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* METHOD lm_build_alv_table: Build the ALV Table...
*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  METHOD lm_build_alv_table.
    DATA: lv_functions TYPE REF TO cl_salv_functions_list,
          lv_columns   TYPE REF TO cl_salv_columns_table,
          lv_display   TYPE REF TO cl_salv_display_settings,
          lv_col_tab   TYPE salv_t_column_ref,
          lv_key       TYPE salv_s_layout_key,
          lv_layout    TYPE REF TO cl_salv_layout,
          lv_oref      TYPE REF TO cx_root,
          lv_text      TYPE bapi_msg,
          lv_ltext     TYPE scrtext_l,
          lv_mtext     TYPE scrtext_m,
          lv_stext     TYPE scrtext_s,
          lv_select    TYPE REF TO cl_salv_selections.
    FIELD-SYMBOLS: <lfs_w_col> TYPE salv_s_column_ref.

    CLEAR lv_text.
    TRY.
        cl_salv_table=>factory(
          IMPORTING
            r_salv_table = rt_alv
          CHANGING
            t_table      = ct_report ).
      CATCH cx_salv_msg INTO lv_oref.
        lv_text = lv_oref->get_text( ).
        RETURN.
    ENDTRY.

    lv_functions = rt_alv->get_functions( ).
    lv_functions->set_all( ).
    lv_columns = rt_alv->get_columns( ).
    lv_columns->set_optimize( if_salv_c_bool_sap=>true ).
    lv_col_tab = lv_columns->get( ).

    LOOP AT lv_col_tab ASSIGNING <lfs_w_col>.
      CASE <lfs_w_col>-columnname.
        WHEN 'KEY1'.
          <lfs_w_col>-r_column->set_short_text( 'Key1' ).
          <lfs_w_col>-r_column->set_medium_text( 'Key Field #1' ).
          <lfs_w_col>-r_column->set_long_text( 'Key Field #1' ).
        WHEN 'KEY2'.
          <lfs_w_col>-r_column->set_short_text( 'Key2' ).
          <lfs_w_col>-r_column->set_medium_text( 'Key Field #2' ).
          <lfs_w_col>-r_column->set_long_text( 'Key Field #2' ).
        WHEN 'FIELD1'.
          <lfs_w_col>-r_column->set_short_text( 'Field1' ).
          <lfs_w_col>-r_column->set_medium_text( 'Text Field1' ).
          <lfs_w_col>-r_column->set_long_text( 'Text Field1' ).
        WHEN 'A_DATE_FIELD'.
          <lfs_w_col>-r_column->set_short_text( 'DateField' ).
          <lfs_w_col>-r_column->set_medium_text( 'A Date Field' ).
          <lfs_w_col>-r_column->set_long_text( 'The First Date Field' ).
        WHEN 'SUMMARY_FIELD'.
          <lfs_w_col>-r_column->set_short_text( 'SumField' ).
          <lfs_w_col>-r_column->set_medium_text( 'Summary Field' ).
          <lfs_w_col>-r_column->set_long_text( 'Summary Field' ).
      ENDCASE.
    ENDLOOP.
    lv_display = rt_alv->get_display_settings( ).
    lv_display->set_striped_pattern( if_salv_c_bool_sap=>true ).
    lv_layout = rt_alv->get_layout( ).
    lv_key-report = sy-repid.
    lv_layout->set_key( lv_key ).
    lv_layout->set_default( abap_true ).
    lv_layout->set_save_restriction( if_salv_c_layout=>restrict_none ).
    lv_select = rt_alv->get_selections( ).
    lv_select->set_selection_mode( if_salv_c_selection_mode=>multiple ).
  ENDMETHOD.                    "lm_build_alv_table
ENDCLASS.

*---------------------------------------------------------------------*
*                  I N I T I A L I Z A T I O N                        *
*---------------------------------------------------------------------*
INITIALIZATION.
  %_rb_std_%_app_%-text  = 'Standard Table'.
  %_rb_sort_%_app_%-text = 'Sorted Table'.
  %_rb_new_%_app_%-text  = 'New ABAP'.
  %_p_recs_%_app_%-text  = 'Number of Records'.

*---------------------------------------------------------------------*
*               S T A R T   O F   S E L E C T I O N
*---------------------------------------------------------------------*
START-OF-SELECTION.
  lcl_my_class=>main( )->execute( ).

*---------------------------------------------------------------------*
*               E N D   O F   S E L E C T I O N
*---------------------------------------------------------------------*
END-OF-SELECTION.

No comments:

Post a Comment