AT FIRST triggers at the first loop iteration whereas AT LAST triggers at the last loop iteration. We can’t mention any particular field here as we can do in AT NEW or AT END OF. The main purpose of this control break is to write some header or footer information. We can write some header info by using AT FIRST statement and similarly some footer info by using AT LAST statement.
REPORT zctrlbrk_at_first_last NO STANDARD PAGE HEADING.
TYPES: BEGIN OF ty_tab,
werks TYPE mard-werks,
matnr TYPE mard-matnr,
lgort TYPE mard-lgort,
END OF ty_tab.
DATA: wtab TYPE ty_tab,
itab TYPE TABLE OF ty_tab.
START-OF-SELECTION.
SELECT matnr werks lgort
UP TO 25 ROWS FROM mard
INTO CORRESPONDING FIELDS OF TABLE itab.
IF sy-subrc = 0.
SORT itab BY werks.
WRITE: / 'Material', 20 'Plant', 27 'Storage Location'.
ULINE.
LOOP AT itab INTO wtab.
WRITE: / wtab-matnr, 20 wtab-werks, 27 wtab-lgort.
AT FIRST.
WRITE: '===AT FIRST will trigger here'.
ENDAT.
AT LAST.
WRITE: '===AT LAST will trigger here'.
ENDAT.
ENDLOOP.
ENDIF.
TYPES: BEGIN OF ty_tab,
werks TYPE mard-werks,
matnr TYPE mard-matnr,
lgort TYPE mard-lgort,
END OF ty_tab.
DATA: wtab TYPE ty_tab,
itab TYPE TABLE OF ty_tab.
START-OF-SELECTION.
SELECT matnr werks lgort
UP TO 25 ROWS FROM mard
INTO CORRESPONDING FIELDS OF TABLE itab.
IF sy-subrc = 0.
SORT itab BY werks.
WRITE: / 'Material', 20 'Plant', 27 'Storage Location'.
ULINE.
LOOP AT itab INTO wtab.
WRITE: / wtab-matnr, 20 wtab-werks, 27 wtab-lgort.
AT FIRST.
WRITE: '===AT FIRST will trigger here'.
ENDAT.
AT LAST.
WRITE: '===AT LAST will trigger here'.
ENDAT.
ENDLOOP.
ENDIF.
Now at the debugger level we see the following results. AT FIRST triggers at 1st loop iteration when SY-TABIX = 1. Here all fields of work area are ***.
After that the system triggers AT LAST statement at the last loop iteration when SY-TABIX = 25. Previously the values of work area are also ***.
The output is as follows.