Skip to Content

Hello World !

For my first post on SDN I have chosen a simple topic.

Throughout the years I have often heard from co-workers that one cannot trust the AT NEW/END statements to create sub-totals in ABAP reports. I have come across many programs where the developer coded the AT NEW/END statements on his own using multiple variables just because it “did not work”.

One condition for correct results is to sort the driving internal table by the fields used to create the sub-totals. That is done in most of the cases but still the results are wrong. Let’s check the following example:

  data: begin of t_test occurs 0,

    field1(10) type c,

    field2(10) type c,

    field3(10) type c.

  data: end of t_test.

 

  t_test-field1 = ‘ABAP’.

  t_test-field2 = ‘Programming’.

  t_test-field3 = ‘Language’.

  append t_test.

 

  t_test-field1 = ‘C’.

  t_test-field2 = ‘Programming’.

  t_test-field3 = ‘Language’.

  append t_test.

 

  sort t_test by field3.

 

  loop at t_test.

    at new field3.

      write:/ ‘Field 3 – new value: ‘, t_test-field3.

    endat.

  endloop.

 

This is the output:

 

Field 3 – new value:  Language

Field 3 – new value:  Language

 

Although there is no new occurrence in field field3, the AT NEW statement is triggered. What went wrong ? See the following slightly modified example:

 

  data: begin of t_test2 occurs 0,

    field3(10) type c,

    field2(10) type c,

    field1(10) type c.

  data: end of t_test2.

 

  t_test2-field1 = ‘ABAP’.

  t_test2-field2 = ‘Programming’.

  t_test2-field3 = ‘Language’.

  append t_test2.

 

  t_test2-field1 = ‘C’.

  t_test2-field2 = ‘Programming’.

  t_test2-field3 = ‘Language’.

  append t_test2.

  sort t_test2 by field3.

  loop at t_test2.

    at new field3.

      write:/ ‘Field 3 – new value: ‘, t_test2-field3.

    endat.

  endloop.

 

This is the output:

Field 3 – new value:  Language

This time the results are correct. Since there is only one value in field field3, the code inside the AT NEW structure is triggered only once. The difference is the order of the fields in the internal table. They should be declared in the same sequence of the desired subtotals. Summarizing: the correct functioning of AT NEW/AT END depends on:

–         Sorting the internal table by the fields to be totalized;

–         Declare the internal table with those fields at the beginning and in the order of the subtotals.

Sometimes you want to let the end-user choose the fields to be totalized. For that the best option is the ALV Grid. Still, you can achieve that by using a large string field in the beginning of the internal table, which you fill by concatenating the fields in the order chosen by the user.

To report this post you need to login first.

7 Comments

You must be Logged on to comment or reply to a post.

  1. Michelle Crapo
    Our guidelines state always use OO ALV grid.  Why?  Because it does things like this for you.

    Second example you probably should add a sort.  You probably just missed it.  Loop at itab assigning should be used or into. 

    In spite of all of this good first post.  It got me thinking about some of my older code.  Anything that makes me think in the morning is a good post.  

    I rarely use At new/end statements.  Just for the reasons stated.  (Also I usually need more fields than the “at new” field.  Entire lines. (hide – I know about that one.)  And yes I’m sure there is a way to get it using at new.)

    There are 1000 ways to do something.  Which is the right one?   I have fun running things like this thru SE30 just to see what is faster.

    BR,

    Michelle

    Maybe think about adding this to the code gallery  WIKI. 

    http://wiki.sdn.sap.com/wiki/display/Snippets/Home?bc=true

    (0) 
    1. Wagner Oliveira Post author
      Thanks for the comments.
      1) ALV is the choice for online applications; AT NEW/END will have their chance in batch processing or any logic that does not depend on user interaction. You can break using multiple fields, as long as they appear in the right order and the table is sorted:

      Loop at materials.
      at new werks.
      endat.

      at new matnr.
      endat.
      endloop.

      2) I added the missing sort. I did not use ASSIGNING or work areas just to put more focus on the AT NEW/END behaviour. A post about field-symbols/work areas is on my plans.

      (0) 
  2. Kumud Singh
    In short, AT NEW statement is triggered either when the specified field changes or any field to the left of specified field changes.

    Regards,
    Kumud

    (0) 
  3. Sandra Rossi
    We could also talk about the LOOP AT … WHERE … mixed with AT, behavior is undefined according to SAP help 🙂 (next blog?)

    Analyzing break on left fields only of the internal table is really a big drawback I think. What a pity that AT does not support that (even at 7.02, despite the introduction of secondary table keys).

    Here is a possible solution template using ABAP Objects, I let you imagine the code inside the class… 😀
      SORT itab BY planetype carrid.
      CREATE OBJECT lo_at EXPORTING itab = itab sorting_fields = ‘PLANETYPE,CARRID’.
      LOOP AT itab INTO wa.
        lo_at->check_breaks( ). “based on SY-TABIX
        IF lo_at->at_new( 2 ) = abap_true.
          WRITE : / ‘First line for couple plane type/carrier’, wa-planetype, wa-carrid.
        ENDIF.
        IF lo_at->at_end_of( 2 ) = abap_true.
          WRITE : / ‘Last line for couple plane type/carrier’, wa-planetype, wa-carrid.
        ENDIF.
      ENDLOOP.

    sandra

    (0) 
  4. Poul Bundgaard
    I often use AT END OF, because it reads one row ahead and therefore catches the last break – and by that saves you the trouble of handling the last break after the loop has finished.

    But, as stated before, you have to make sure your colums are in the correct order.

    Another trap: Between AT… and ENDAT, the char fields to the right of the control field are filled with ‘*********’ in your work structure.
    Example:

      data: begin of t_test occurs 0,
        field1(10) type c,
        field2(10) type c.
      data: end of t_test.
      data: wa_test like line of t_test.

      t_test-field1 = ‘ABAP’.
      t_test-field2 = ‘Programming’.
      append t_test.

      t_test-field1 = ‘C’.
      t_test-field2 = ‘Programming’.
      append t_test.

      sort t_test by field1.

      loop at t_test into wa_test.
        at new field1.
          write:/ wa_test-field1, wa_test-field2.
        endat.
      endloop.

    This will output:
    ABAP      **********
    C         **********

    The easiest way to avoid this is by using ASSIGNING instead of INTO.

    (0) 

Leave a Reply