L’instruction LOOP AT est l’une des structures de contrôle les plus importantes en ABAP pour le traitement des tables internes. Elle permet de parcourir toutes ou des lignes sélectionnées d’une table interne de manière séquentielle et d’accéder à chaque ligne individuelle pour la lire, la modifier ou la supprimer.
Syntaxe
La syntaxe de base de l’instruction LOOP AT offre différentes variantes pour accéder aux lignes de la table :
1. LOOP avec zone de travail (INTO)
LOOP AT <interne_tabelle> INTO <arbeitsbereich> [WHERE <bedingung>] [FROM <index1>] [TO <index2>]. " Anweisungsblock " <arbeitsbereich> enthält eine Kopie der aktuellen ZeileENDLOOP.2. LOOP avec symbole de champ (ASSIGNING)
LOOP AT <interne_tabelle> ASSIGNING <feldsymbol> [WHERE <bedingung>] [FROM <index1>] [TO <index2>]. " Anweisungsblock " <feldsymbol> zeigt direkt auf die aktuelle Zeile (kein Kopieren)ENDLOOP.3. LOOP avec référence de données (REFERENCE INTO)
LOOP AT <interne_tabelle> REFERENCE INTO <datenreferenz> [WHERE <bedingung>] [FROM <index1>] [TO <index2>]. " Anweisungsblock " <datenreferenz> enthält einen Zeiger auf die aktuelle ZeileENDLOOP.4. LOOP sans accès aux lignes (seulement comptage)
LOOP AT <interne_tabelle> TRANSPORTING NO FIELDS [WHERE <bedingung>]. " Anweisungsblock (z.B. nur sy-tabix nutzen)ENDLOOP.Composants
<interne_tabelle>: La table dont les lignes doivent être parcourues.INTO <arbeitsbereich>: Le contenu de la ligne actuelle est copié dans la zone de travail. Les modifications de la zone de travail n’affectent pas automatiquement la table.ASSIGNING <feldsymbol>: Le symbole de champ pointe directement sur la ligne actuelle dans la table. Les modifications du symbole de champ modifient immédiatement la ligne de la table.REFERENCE INTO <datenreferenz>: Une référence de données qui pointe sur la ligne actuelle. Accès via déréférencement (->*).WHERE <bedingung>: Filtre les lignes à parcourir. Seules les lignes qui remplissent la condition sont traitées.FROM <index1>: Démarre la boucle à partir de la position d’index spécifiée (uniquement pour les tables d’index).TO <index2>: Termine la boucle à la position d’index spécifiée (uniquement pour les tables d’index).TRANSPORTING NO FIELDS: Aucun contenu de champ n’est transporté. Utile pour compter ou lorsque seulsy-tabixest nécessaire.
Champs système pendant la boucle
Dans un LOOP AT, des champs système importants sont définis :
sy-tabix: Contient l’index de ligne actuel de la ligne en cours de traitement (pour les tables standard et triées). Pour les tables de hachage,sy-tabixn’est pas défini (valeur 0).sy-subrc: Après leENDLOOP,sy-subrc = 0si au moins une ligne a été traitée.sy-subrc = 4si aucune ligne ne remplissait les conditions (table vide ou WHERE sans résultat).
Fonctionnement
- L’instruction
LOOP ATcommence avec la première ligne (ou la première ligne correspondante avecWHERE/FROM). - À chaque itération, la ligne actuelle est fournie via le mécanisme d’accès choisi (
INTO,ASSIGNING,REFERENCE INTO). - Le bloc d’instructions entre
LOOP ATetENDLOOPest exécuté une fois pour chaque ligne correspondante. - Après la dernière ligne (ou lorsqu’aucune ligne ne correspond plus), la boucle se termine et le programme continue après
ENDLOOP.
Variantes et ajouts
Condition WHERE
Avec WHERE, les lignes peuvent être filtrées pour que seules certaines lignes soient parcourues :
LOOP AT lt_orders INTO ls_order WHERE status = 'OPEN'. " Nur offene Bestellungen verarbeitenENDLOOP.La condition WHERE supporte :
- Opérateurs de comparaison :
=,<>,<,>,<=,>= - Liaisons logiques :
AND,OR,NOT - Tests de plage :
BETWEEN,IN(pour Ranges) - Pattern-Matching :
CP,NP(pour chaînes de caractères)
FROM et TO (basé sur l’index)
Pour les tables standard et triées, la plage peut être restreinte :
" Nur Zeilen 5 bis 10 verarbeitenLOOP AT lt_data INTO ls_data FROM 5 TO 10. " ...ENDLOOP.
" Ab Zeile 100 bis zum EndeLOOP AT lt_data INTO ls_data FROM 100. " ...ENDLOOP.GROUP BY (Regroupement)
À partir d’ABAP 7.40, les lignes peuvent être regroupées pendant la boucle :
LOOP AT lt_orders INTO ls_order GROUP BY ( customer = ls_order-customer_id size = GROUP SIZE ) INTO DATA(group). " Gruppenverarbeitung LOOP AT GROUP group INTO DATA(member). " Einzelne Mitglieder der Gruppe ENDLOOP.ENDLOOP.INTO vs. ASSIGNING vs. REFERENCE INTO
Le choix du mécanisme d’accès influence la performance et la fonctionnalité :
| Variante | Copie ? | Modifications | Performance | Cas d’usage |
|---|---|---|---|---|
INTO | Oui | Nécessite MODIFY | Plus lent | Lecture seule, pas de modifications |
ASSIGNING | Non | Direct | Plus rapide | Lecture et/ou modification |
REFERENCE INTO | Non | Via ->* | Plus rapide | Lorsqu’une référence est nécessaire |
Recommandation
- Lecture seule sans modification :
ASSIGNING(plus performant queINTO) - Lecture et modification :
ASSIGNING(les modifications sont immédiates) - Transmettre une référence :
REFERENCE INTO - Copie explicitement souhaitée :
INTO
Exemples
1. LOOP simple avec INTO
TYPES: BEGIN OF ty_material, matnr TYPE matnr, maktx TYPE maktx, menge TYPE i, END OF ty_material.
DATA: lt_materials TYPE STANDARD TABLE OF ty_material, ls_material TYPE ty_material.
" Tabelle füllen (Beispieldaten)lt_materials = VALUE #( ( matnr = 'MAT001' maktx = 'Schraube M6' menge = 100 ) ( matnr = 'MAT002' maktx = 'Mutter M6' menge = 200 ) ( matnr = 'MAT003' maktx = 'Scheibe M6' menge = 150 )).
" Alle Materialien ausgebenLOOP AT lt_materials INTO ls_material. WRITE: / sy-tabix, ':', ls_material-matnr, ls_material-maktx.ENDLOOP.2. LOOP avec ASSIGNING et modification de valeur
FIELD-SYMBOLS: <fs_material> TYPE ty_material.
" Alle Mengen um 10% erhöhenLOOP AT lt_materials ASSIGNING <fs_material>. <fs_material>-menge = <fs_material>-menge * '1.1'.ENDLOOP.
" Änderungen sind sofort in lt_materials wirksam!3. LOOP avec condition WHERE
DATA: lv_total TYPE i VALUE 0.
" Nur Materialien mit Menge > 100 summierenLOOP AT lt_materials INTO ls_material WHERE menge > 100. lv_total = lv_total + ls_material-menge.ENDLOOP.
WRITE: / 'Gesamtmenge (>100):', lv_total.
IF sy-subrc <> 0. WRITE: / 'Keine Materialien mit Menge > 100 gefunden.'.ENDIF.4. LOOP avec REFERENCE INTO
DATA: lr_material TYPE REF TO ty_material.
LOOP AT lt_materials REFERENCE INTO lr_material. " Zugriff über Dereferenzierung lr_material->menge = lr_material->menge + 50.ENDLOOP.5. Supprimer des lignes dans LOOP
" Zeilen mit Menge = 0 entfernenLOOP AT lt_materials ASSIGNING <fs_material>. IF <fs_material>-menge = 0. DELETE lt_materials. ENDIF.ENDLOOP.Remarque : La suppression de lignes dans un LOOP est autorisée. La boucle continue correctement avec la ligne suivante. Voir aussi DELETE pour d’autres variantes.
6. LOOP avec FROM/TO pour pagination
CONSTANTS: lc_page_size TYPE i VALUE 10.DATA: lv_page TYPE i VALUE 2, lv_from TYPE i, lv_to TYPE i.
lv_from = ( lv_page - 1 ) * lc_page_size + 1.lv_to = lv_page * lc_page_size.
LOOP AT lt_materials INTO ls_material FROM lv_from TO lv_to. " Zeilen 11-20 verarbeiten (Seite 2) WRITE: / ls_material-matnr.ENDLOOP.7. TRANSPORTING NO FIELDS pour compter
DATA: lv_count TYPE i VALUE 0.
LOOP AT lt_materials TRANSPORTING NO FIELDS WHERE menge > 100. lv_count = lv_count + 1.ENDLOOP.
WRITE: / 'Anzahl Materialien mit Menge > 100:', lv_count.Astuce : Pour le comptage pur, la fonction REDUCE ou lines() avec FILTER est souvent plus élégante :
DATA(lv_count) = REDUCE i( INIT count = 0 FOR wa IN lt_materials WHERE ( menge > 100 ) NEXT count = count + 1 ).Différenciation avec d’autres instructions
LOOP vs. READ TABLE
LOOP AT: Parcourt plusieurs/toutes les lignes de manière séquentielle.READ TABLE: Lit une seule ligne spécifique (par clé ou index).
Pour l’accès à une seule ligne, READ TABLE est plus performant :
" Einzelne Zeile per SchlüsselREAD TABLE lt_materials INTO ls_material WITH KEY matnr = 'MAT001'.
" Einzelne Zeile per IndexREAD TABLE lt_materials INTO ls_material INDEX 1.LOOP vs. Expression FOR
À partir d’ABAP 7.40, il existe l’expression FOR pour les itérations en ligne :
" Neue Tabelle mit gefilterten Daten erstellenDATA(lt_filtered) = VALUE ty_materials( FOR wa IN lt_materials WHERE ( menge > 100 ) ( wa )).LOOP AT reste le choix préféré pour une logique de traitement complexe avec plusieurs instructions.
Contrôle de boucle
Dans un LOOP AT, les instructions suivantes peuvent contrôler la boucle :
CONTINUE: Passe à l’itération suivante (saute le reste du passage actuel).EXIT: Termine immédiatement la boucle et continue aprèsENDLOOP.CHECK: Termine l’itération actuelle si la condition est fausse (commeIF NOT ... CONTINUE).
LOOP AT lt_materials ASSIGNING <fs_material>. " Materialien ohne Text überspringen CHECK <fs_material>-maktx IS NOT INITIAL.
" Bei speziellem Material abbrechen IF <fs_material>-matnr = 'STOP'. EXIT. ENDIF.
" Verarbeitung...ENDLOOP.Conseils de performance
-
ASSIGNINGau lieu deINTO: Évite la copie de données et est nettement plus rapide pour les grandes structures. -
Utiliser la condition WHERE : Filtre les lignes à traiter et réduit le nombre d’itérations.
-
Clé secondaire : Pour les requêtes WHERE fréquentes sur certains champs, une clé secondaire peut améliorer les performances. Voir aussi
SORTpour la préparation de recherches binaires. -
PARALLEL CURSOR : Lors du traitement de deux tables triées avec relation entre elles, la technique de curseur parallèle peut améliorer drastiquement les performances :
DATA: lv_tabix TYPE sy-tabix VALUE 1.
LOOP AT lt_header INTO ls_header. LOOP AT lt_items INTO ls_item FROM lv_tabix. IF ls_item-header_id <> ls_header-id. lv_tabix = sy-tabix. EXIT. ENDIF. " Item verarbeiten... ENDLOOP.ENDLOOP.- Éviter les LOOPs imbriqués sans index : Deux boucles imbriquées sur de grandes tables sans optimisation conduisent à une complexité O(n²).
Remarques importantes / Bonnes pratiques
LOOP ATest fondamental pour travailler avec les tables internes en ABAP. Chargez d’abord les données avecSELECTdepuis la base de données.- Préférez
ASSIGNINGpour de meilleures performances et un accès direct en écriture. - Utilisez les conditions
WHEREpour ne traiter que les lignes pertinentes. - N’oubliez jamais le
ENDLOOPfinal. - Vérifiez
sy-subrcaprès la boucle si vous devez savoir si des lignes ont été traitées. - Pour les tables de hachage,
sy-tabixn’est pas disponible – utilisez plutôt vos propres compteurs si nécessaire. - Pour le développement ABAP moderne (à partir de 7.40), vérifiez si les expressions
FORouREDUCEsont plus appropriées pour votre cas d’usage.