2025 Oct 19 1:19 PM
I get this syntax error (the message is different depending on the ABAP version - NB: the message ID is MESSAGEGAC in table TRMSG):
It happens in the line 6 (DELETE itab) of this code, used to delete the lines which are not of type 'E':
DATA(itab) = VALUE bapirettab( ( type = 'S' ) ( type = 'S' ) ( type = 'E' ) ).
LOOP AT itab REFERENCE INTO DATA(line)
GROUP BY line->type.
IF line->type <> 'E'.
LOOP AT GROUP line TRANSPORTING NO FIELDS.
DELETE itab INDEX sy-tabix.
ENDLOOP.
ENDIF.
ENDLOOP.NB: of course, this code may be reduced to one line, its only goal is to support the question, my original code is much more complex.
Thanks.
Sandra
For information, I did other tests with other statements to change the internal table:
MODIFY itab FROM VALUE #( ) is used instead of DELETE: "The implicit variants "DELETE itab." and "MODIFY itab FROM wa." cannot be used in a "LOOP AT itab ... USING KEY keyname ..." (message MESSAGEGJI in the table TRMSG).MODIFY itab FROM VALUE #( ) INDEX idx.2025 Oct 19 1:21 PM - edited 2025 Oct 19 6:32 PM
The syntax error is because "The internal table itab cannot be modified in the group loop [...]" (LOOP AT itab, GROUP BY | ABAP Keyword Documentation).
NB: the sentence is completed with "unless the addition WITHOUT MEMBERS is specified", because in that case the group keys are determined before the loop starts (grouping phase), then the loop starts on the group keys (Group Loop phase), so any modification to itab is valid because internally it's no more a loop on the itab lines (it was one only during the grouping phase), it's a loop on the group keys.
Now, the solution is simply to delay the modifications after the loop. There are two solutions:
Solution 1
During the loop, you need to save what is to be done to the internal table in a journal.
NB: it's important to delete from the end otherwise you would delete the wrong lines because the table indexes of the lines after the deleted line are changed.
DATA(itab) = VALUE bapirettab( ( type = 'S' ) ( type = 'S' ) ( type = 'E' ) ).
DATA itab_tabix TYPE TABLE OF sytabix. "<====== add
LOOP AT itab REFERENCE INTO DATA(line)
GROUP BY line->type.
IF line->type <> 'E'.
LOOP AT GROUP line TRANSPORTING NO FIELDS.
INSERT sy-tabix INTO TABLE itab_tabix. "<====== add
ENDLOOP.
ENDIF.
ENDLOOP.
SORT itab_tabix BY table_line DESCENDING. "<====== add these 4 lines
LOOP AT itab_tabix INTO DATA(tabix).
DELETE itab INDEX tabix.
ENDLOOP.EDIT enhanced solution proposed by @wridgeu : SORT not needed if using STEP -1, instead of the 4 last lines:
LOOP AT itab_tabix INTO DATA(tabix) STEP -1.
DELETE itab INDEX tabix.
ENDLOOP.Solution 2
If the internal table is small you may duplicate the internal table, do the changes immediately to the duplicated, and after the loop transfer back the values to the original internal table.
DATA(itab) = VALUE bapirettab( ( type = 'S' ) ( type = 'S' ) ( type = 'E' ) ).
DATA(itab_duplicate) = itab. "<====== add
LOOP AT itab REFERENCE INTO DATA(line)
GROUP BY line->type.
IF line->type <> 'E'.
LOOP AT GROUP line TRANSPORTING NO FIELDS.
DELETE itab_duplicate INDEX sy-tabix. "<====== add
ENDLOOP.
ENDIF.
ENDLOOP.
itab = itab_duplicate. "<====== add
2025 Oct 19 1:21 PM - edited 2025 Oct 19 6:32 PM
The syntax error is because "The internal table itab cannot be modified in the group loop [...]" (LOOP AT itab, GROUP BY | ABAP Keyword Documentation).
NB: the sentence is completed with "unless the addition WITHOUT MEMBERS is specified", because in that case the group keys are determined before the loop starts (grouping phase), then the loop starts on the group keys (Group Loop phase), so any modification to itab is valid because internally it's no more a loop on the itab lines (it was one only during the grouping phase), it's a loop on the group keys.
Now, the solution is simply to delay the modifications after the loop. There are two solutions:
Solution 1
During the loop, you need to save what is to be done to the internal table in a journal.
NB: it's important to delete from the end otherwise you would delete the wrong lines because the table indexes of the lines after the deleted line are changed.
DATA(itab) = VALUE bapirettab( ( type = 'S' ) ( type = 'S' ) ( type = 'E' ) ).
DATA itab_tabix TYPE TABLE OF sytabix. "<====== add
LOOP AT itab REFERENCE INTO DATA(line)
GROUP BY line->type.
IF line->type <> 'E'.
LOOP AT GROUP line TRANSPORTING NO FIELDS.
INSERT sy-tabix INTO TABLE itab_tabix. "<====== add
ENDLOOP.
ENDIF.
ENDLOOP.
SORT itab_tabix BY table_line DESCENDING. "<====== add these 4 lines
LOOP AT itab_tabix INTO DATA(tabix).
DELETE itab INDEX tabix.
ENDLOOP.EDIT enhanced solution proposed by @wridgeu : SORT not needed if using STEP -1, instead of the 4 last lines:
LOOP AT itab_tabix INTO DATA(tabix) STEP -1.
DELETE itab INDEX tabix.
ENDLOOP.Solution 2
If the internal table is small you may duplicate the internal table, do the changes immediately to the duplicated, and after the loop transfer back the values to the original internal table.
DATA(itab) = VALUE bapirettab( ( type = 'S' ) ( type = 'S' ) ( type = 'E' ) ).
DATA(itab_duplicate) = itab. "<====== add
LOOP AT itab REFERENCE INTO DATA(line)
GROUP BY line->type.
IF line->type <> 'E'.
LOOP AT GROUP line TRANSPORTING NO FIELDS.
DELETE itab_duplicate INDEX sy-tabix. "<====== add
ENDLOOP.
ENDIF.
ENDLOOP.
itab = itab_duplicate. "<====== add
2025 Oct 19 4:11 PM
Hi Sandra, one small addition to the first solution could be the use of STEP -1 (reverse LOOP) instead of sorting (finally, a use-case ^^).