sorting some column of an internal table that meet a condition

51 Views Asked by At

I have an internal table

standard internal table

and i want to display it like this:

like this.

note that only a1's date is sorted descending. so im wondering if theres a method to only sort dates belong to a1 while leaving the others untouched.

I am a beginner so id appreciate if the answer is easy to understand

2

There are 2 best solutions below

0
Xavier Salomone On BEST ANSWER

You can use the LOOP/GROUP approach to sort the table before sending it to the ALV (sample code only):

    LOOP AT itab ASSIGNING FIELD-SYMBOL(<line>)
                     GROUP BY ( key1 = <line>-cust_id key2 = <line>-prod_id ) ASCENDINGdd
                     ASSIGNING FIELD-SYMBOL(<grp1>).

          LOOP AT GROUP <grp1> ASSIGNING FIELD-SYMBOL(<member>).
            members = VALUE #( BASE members ( <member> ) ).
          ENDLOOP.

          IF <grp1>-prod_id = 'A1'.
            SORT members BY sale_date DESCENDING.
          ELSE.
            SORT members BY sale_date ASCENDING.
          ENDIF.

        APPEND LINES OF members TO it_final.
    ENDLOOP.
  • First loop: sort ascending by cust_id/prod_id.
  • Second loop: obtain all members of group and sorting as you like, then append to final table.

Reference: https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abaploop_at_itab_group_by.htm

0
Herr Berthm On

There is no "simple" way of doing that. There is no statement like sort (tab) by (fields) where (cond).

One way I can come up with is to use the sort statement to get the cust_id and prod_id in order and then manually implement a bubble sort for the rest. Here is my testdata declaration:

types: begin of t_data,
        cust_id   type char1,
        prod_id   type char2,
        sale_date type dats,
        qty       type i,
      end of t_data.
data: lt_data type table of t_data.


lt_data = value #(
             ( cust_id = '1' prod_id = 'A1' sale_date = '20020318' qty = 10 )
             ( cust_id = '1' prod_id = 'A1' sale_date = '20020319' qty = 100 )
             ( cust_id = '1' prod_id = 'A1' sale_date = '20020329' qty = 50 )
             ( cust_id = '1' prod_id = 'A2' sale_date = '20020318' qty = 50 )
             ( cust_id = '1' prod_id = 'A2' sale_date = '20020329' qty = 200 )
             ( cust_id = '2' prod_id = 'A1' sale_date = '20020318' qty = 60 )
             ( cust_id = '2' prod_id = 'A1' sale_date = '20020329' qty = 80 )
             ( cust_id = '3' prod_id = 'X1' sale_date = '20020321' qty = 90 )
  ).

And this is how I implemented the sort logic:

data: lv_swapped type c.
data: ls_data type t_data.
field-symbols: <ls_curr> type t_data.
field-symbols: <ls_next> type t_data.

* Sort by general rules first:
sort lt_data by cust_id prod_id.

* Bubble sort the list partially, where the prod_id is 'A1' and the cust_id is the same:
do.
  clear lv_swapped.
  loop at lt_data assigning <ls_curr> where prod_id = 'A1'.
*    Read the next entry in the list that we can compare the current entry too.
*    The "where" condition should have all fields that the inital sort had too.
    loop at lt_data assigning <ls_next> from sy-tabix + 1
                                       where cust_id = <ls_curr>-cust_id
                                         and prod_id = <ls_curr>-prod_id.
      exit.
    endloop.
    if sy-subrc = 0.
      if <ls_curr>-sale_date < <ls_next>-sale_date.
*        Sort descending -> if the next entry is bigger then the current entry...
*        Swap entries
        ls_data = <ls_next>.
        <ls_next> = <ls_curr>.
        <ls_curr> = ls_data.
        lv_swapped = 'X'.
      endif.
    endif.
  endloop.
  if lv_swapped = space.
*    When nothing was swapped the list is sorted
    exit.
  endif.
enddo.

To explain a bit: The bubble sort algorithm goes through a list element by element and compares the current element to the next one. If the order is incorrect, the two elements are swapped. When we reach the end of the list we start over, until we haven't swapped any elements.

In my implementation I've simply added conditions:

  1. Which elements of the list do we want to sort in the first place? -> first loop condition
  2. Which elements can we compare the current element to? -> second loop condition

The second loop could be replaced by a read table, but we have to look ahead in the table. Since the "from" keyword in a loop can set a starting index, I thought it would be simpler to use a loop with an immediate exit.

I know the implementation is pretty static and could be improved to work dynamically, but I'll leave that for another day.