Aller au contenu
  1. Documentation/

Instructions ITAB en ABAP

··41 mins· loading · loading · · ·
SAP ERP Back-End
Adrien D'acunto
Auteur
Adrien D’acunto
Sommaire

Instructions ITAB en ABAP
#

Is initial
#

Objectifs
#

  • Vérifier si une table interne est vide ou non
  • Comprendre l’usage des crochets []
  • Utiliser IS INITIAL ou IS NOT INITIAL pour tester le contenu d’une table interne
  • Savoir que IS INITIAL fonctionne aussi avec des variables simples

Définition
#

IF itab[] IS INITIAL.
  " La table est vide
ENDIF.

IF [NOT] itab[] IS [NOT] INITIAL.
  " La table contient au moins une ligne
ENDIF.

L’expression IS INITIAL vérifie si une donnée est vide ou non initialisée.
Pour les tables internes, les crochets [] signifient qu’on évalue le contenu complet de la table.

  • itab[] IS INITIAL → la table ne contient aucune ligne
  • itab[] IS NOT INITIAL → la table contient au moins une ligne

Analogie
#

Imagine une boîte :

  • Si la boîte ne contient aucun objet, elle est initiale (vide).
  • Si elle contient au moins un objet, elle n’est pas initiale.

De la même façon :

  • itab[] IS INITIAL → la boîte est vide.
  • NOT itab[] IS INITIAL → la boîte contient quelque chose.

Exemple complet
#

TYPES: BEGIN OF ty_citizen,
         country TYPE char3,
         name    TYPE char20,
         age     TYPE numc2,
       END OF ty_citizen.

DATA: lt_citizen TYPE STANDARD TABLE OF ty_citizen,
      ls_citizen TYPE ty_citizen.

" --- Vérification avant ajout ---
IF lt_citizen[] IS INITIAL.
  WRITE: / 'La table est vide au départ.'.
ENDIF.

" --- Ajout d'un enregistrement ---
ls_citizen-country = 'FR'.
ls_citizen-name    = 'Thierry'.
ls_citizen-age     = '24'.
APPEND ls_citizen TO lt_citizen.

" --- Vérification après ajout ---
IF NOT lt_citizen[] IS INITIAL.
  WRITE: / 'La table contient au moins un enregistrement.'.
ENDIF.
  • Avant le APPEND, la table est vide → IS INITIAL renvoie VRAI.
  • Après le APPEND, elle contient une ligne → IS NOT INITIAL renvoie VRAI.

Attention
#

  • Si vous oubliez les crochets [], vous testez la référence de la table, pas son contenu.
  • Une table peut être “non initiale” même si elle n’a plus de lignes si elle a été initialisée ailleurs.
    → Utilisez toujours itab[] IS INITIAL avec les crochets.

Bonnes pratiques
#

Bonne pratique Explication
Toujours tester avant traitement Évite les erreurs de boucle sur table vide
Utiliser IS INITIAL avec [] Spécifie clairement que le test concerne le contenu
Utiliser ... IS NOT INITIAL Vérifie qu’il y a au moins une ligne dans la table
Appliquer aussi à des variables Permet de contrôler l’initialisation d’une donnée
Préférer IS INITIAL à LINES( itab ) = 0 Plus lisible et plus rapide

Exemples résumé
#

1 – Table vide
#

DATA lt_data TYPE TABLE OF string.

IF lt_data[] IS INITIAL.
  WRITE: / 'La table est vide.'.
ENDIF.

2 – Table non vide
#

APPEND 'Hello' TO lt_data.

IF NOT lt_data[] IS INITIAL.
  WRITE: / 'La table contient au moins une valeur.'.
ENDIF.

Résumé
#

IS INITIAL permet de vérifier si une table interne ou une variable est vide.

  • itab[] IS INITIAL → table vide
  • itab[] IS NOT INITIAL → table non vide
  • Fonctionne aussi pour variables et structures simples

Bon réflexe : toujours vérifier avant de traiter ou boucler sur une table.

Tester si une boîte contient quelque chose avant d’essayer de prendre un objet à l’intérieur.

Clear table
#

Objectifs
#

  • Supprimer toutes les lignes d’une table interne avec CLEAR
  • Comprendre la syntaxe avec les crochets []
  • Savoir que CLEAR peut aussi être utilisé sur des variables simples
  • Différencier CLEAR itab[] et REFRESH itab
  • Vérifier le contenu d’une table avant et après effacement

Définition
#

CLEAR: itab[],
       var1.

L’instruction CLEAR permet de supprimer toutes les données d’une table interne ou de remettre à zéro des variables.

Imaginez un tableau blanc rempli d’informations.

  • CLEAR itab[] = effacer complètement le tableau (toutes les lignes).
  • CLEAR var1 = effacer le contenu d’une seule cellule du tableau.

Les crochets [] sont essentiels : sans eux, seule la structure est effacée, pas son contenu.

Exemples
#

1 – Clear sur une table interne
#

TYPES: BEGIN OF ty_citizen,
         country TYPE char3,
         name    TYPE char20,
         age     TYPE numc2,
       END OF ty_citizen.

DATA: lt_citizen TYPE STANDARD TABLE OF ty_citizen,
      ls_citizen TYPE ty_citizen,
      gv_count   TYPE i.

" REMPLISSAGE DE LA TABLE
ls_citizen-country = 'FR'.
ls_citizen-name    = 'Thierry'.
ls_citizen-age     = '24'.
APPEND ls_citizen TO lt_citizen.

ls_citizen-country = 'ES'.
ls_citizen-name    = 'Luis'.
ls_citizen-age     = '32'.
APPEND ls_citizen TO lt_citizen.

gv_count = lines( lt_citizen ). " Nombre de lignes avant CLEAR

WRITE:/ 'Lignes avant suppression :', gv_count.

CLEAR lt_citizen[]. " Supprime toutes les lignes de la table

gv_count = lines( lt_citizen ). " Recalcul du nombre de lignes
WRITE:/ 'Lignes apres CLEAR :', gv_count.
  • Avant CLEAR, la table contient 2 lignes.
  • Après CLEAR, la table est complètement vide.

Le CLEAR lt_citizen (sans []) n’efface pas les lignes, il ne fait que remettre la variable au statut initial (structure vide).

2 – Clear sur variable simple
#

DATA: gv_total TYPE i VALUE 125.

WRITE:/ 'Avant CLEAR :', gv_total.

CLEAR gv_total.

WRITE:/ 'Apres CLEAR :', gv_total.

Le CLEAR sur une variable simple remet sa valeur à zéro (ou initiale).
Par exemple

  • Numérique → 0
  • Caractère → vide
  • Booléen → ’ ’ (faux)

3 – Clear sur plusieurs objets en une seule fois
#

DATA: gv_counter TYPE i VALUE 10,
      gv_name    TYPE string VALUE 'Thierry',
      lt_data    TYPE STANDARD TABLE OF ty_citizen.

CLEAR: gv_counter, gv_name, lt_data[].

Il est possible d’effacer plusieurs éléments en une seule instruction.
Pratique pour remettre un environnement à zéro avant de relancer un traitement.

4 – Différence entre clear et refresh
#

DATA: lt_table TYPE STANDARD TABLE OF ty_citizen.

CLEAR lt_table[].  " Efface le contenu de la table
REFRESH lt_table.  " Efface aussi le contenu (comportement identique depuis ABAP 7.40)

Le CLEAR itab[] est préféré dans le code moderne.
Le REFRESH est conservé pour compatibilité avec les anciens programmes.

5 – Clear sur structure complète
#

DATA: ls_person TYPE ty_citizen.

ls_person-country = 'FR'.
ls_person-name    = 'Thierry'.
ls_person-age     = '24'.

WRITE:/ 'Avant CLEAR :', ls_person-country, ls_person-name, ls_person-age.

CLEAR ls_person.

WRITE:/ 'Apres CLEAR :', ls_person-country, ls_person-name, ls_person-age.

Le CLEAR sur une structure remet chaque champ à sa valeur initiale (vidée ou zéro).

6 – Clear dynamique avec field-symbol
#

FIELD-SYMBOLS: <lfs_tab> TYPE STANDARD TABLE.

ASSIGN lt_citizen TO <lfs_tab>.

IF <lfs_tab> IS ASSIGNED.
  CLEAR <lfs_tab>[].
ENDIF.

Très utile pour écrire des programmes dynamiques manipulant plusieurs tables internes sans les nommer directement.

Bonnes pratiques
#

Bonne pratique Explication
Toujours vérifier le nombre de lignes LINES( itab ) avant/après CLEAR permet de confirmer la suppression
Utiliser CLEAR avec [] Indique explicitement que toute la table est effacée
CLEAR peut combiner plusieurs variables Réduit le code et garde la logique claire
Préférer CLEAR à REFRESH dans le code Syntaxe plus moderne, même effet
Ne pas oublier les crochets [] Sans crochets, seule la variable est remise à zéro, pas le contenu
Eviter CLEAR sur des références non testées Toujours vérifier IS ASSIGNED avant CLEAR sur FIELD-SYMBOLS

Résumé
#

CLEAR est une instruction simple mais puissante

  • CLEAR itab[] : efface toutes les lignes d’une table interne
  • CLEAR var : remet une variable à sa valeur initiale
  • CLEAR structure : réinitialise tous les champs de la structure
  • CLEAR peut être combiné sur plusieurs objets
  • CLEAR avec [] est l’équivalent moderne de REFRESH

[!TIP] C’est comme appuyer sur “Réinitialiser” – on remet tout à zéro avant de recommencer proprement.

Sort
#

Objectifs
#

  • Comprendre le fonctionnement de l’instruction SORT pour les tables internes
  • Savoir trier selon la clé primaire ou des champs spécifiques
  • Identifier les options ASCENDING, DESCENDING, AS TEXT et STABLE
  • Savoir quand trier avant certaines opérations comme DELETE ADJACENT DUPLICATES

Définition
#

SORT itab [ASCENDING|DESCENDING] [AS TEXT] [STABLE]
            BY c1 [ASCENDING|DESCENDING] [AS TEXT]
              ...
                cn [ASCENDING|DESCENDING] [AS TEXT].

L’instruction SORT organise une table interne (itab) de type STANDARD ou HASHED selon

  • sa clé primaire si définie
  • ou une liste de champs c1 à cn

[!NOTE]

  • ASCENDING / DESCENDING : tri croissant ou décroissant
  • AS TEXT : tri des chaînes de caractères selon la langue locale définie par SET LOCALE LANGUAGE
  • STABLE : maintien de l’ordre relatif pour les valeurs égales

Imaginez un classeur de fiches

  • Vous pouvez trier par identifiant, nom ou plusieurs critères combinés (ex. nom puis âge)
  • L’option STABLE garantit que les fiches ayant le même critère restent dans le même ordre relatif
  • Les tables SORTED ne peuvent pas être triées avec SORT, car leur ordre est fixe
  • Le tri est obligatoire avant certaines opérations comme DELETE ADJACENT DUPLICATES pour STANDARD TABLE

Exemples
#

Tri simple
#

TYPES: BEGIN OF ty_citizen,
         country TYPE char3,
         name    TYPE char20,
         age     TYPE numc2,
       END OF ty_citizen.

DATA: lt_citizen TYPE STANDARD TABLE OF ty_citizen,
      ls_citizen TYPE ty_citizen.

" Ajout des données
ls_citizen-country = 'FR'.
ls_citizen-name    = 'Thierry'.
ls_citizen-age     = '24'.
APPEND ls_citizen TO lt_citizen.

ls_citizen-country = 'ES'.
ls_citizen-name    = 'Luis'.
ls_citizen-age     = '32'.
APPEND ls_citizen TO lt_citizen.

ls_citizen-country = 'BR'.
ls_citizen-name    = 'Renata'.
ls_citizen-age     = '27'.
APPEND ls_citizen TO lt_citizen.

ls_citizen-country = 'FR'.
ls_citizen-name    = 'Floriane'.
ls_citizen-age     = '32'.
APPEND ls_citizen TO lt_citizen.

Tri descendant sur toute la table
#

SORT lt_citizen DESCENDING.

Tri par champs spécifiques
#

SORT lt_citizen BY country ASCENDING age DESCENDING.
  • Si aucun BY n’est spécifié et qu’il n’existe pas de clé primaire, le tri peut être instable et aléatoire
  • STABLE garantit un résultat identique lors de tris multiples
  • Obligatoire avant DELETE ADJACENT DUPLICATES pour STANDARD TABLE

Bonnes pratiques
#

Bonne pratique Explication
Toujours préciser les champs pour BY Évite un tri aléatoire sur STANDARD TABLE
Utiliser ASCENDING ou DESCENDING Contrôle le sens du tri
Utiliser AS TEXT pour chaînes locales Respecte l’ordre linguistique
STABLE pour tris répétitifs Maintient l’ordre relatif des valeurs égales
Trier avant DELETE ADJACENT DUPLICATES Assure la suppression correcte des doublons

Résumé
#

SORT organise les lignes d’une table interne selon une clé primaire ou des champs spécifiques.

[!NOTE] Le ASCENDING, DESCENDING, AS TEXT, STABLE

[!TIP] trier un classeur selon un ou plusieurs critères tout en gardant l’ordre relatif des doublons si nécessaire

Insert into itab
#

Objectifs
#

  • Comprendre le fonctionnement de l’instruction INSERT pour les tables internes
  • Savoir insérer une structure, une ligne vide ou des lignes d’une autre table
  • Maîtriser l’insertion à un index précis dans la table cible
  • Simplifier le code en évitant des boucles manuelles pour ajouter plusieurs lignes

Définition
#

L’instruction INSERT permet d’ajouter des lignes dans une table interne (itab).
Elle peut provenir de différentes sources

  • Une structure (ls)
  • Une ligne vide (INITIAL LINE)
  • Une autre table interne (LINES OF jtab) avec possibilité de spécifier un intervalle (FROM idx1 TO idx2)

Imaginez un classeur de fiches

  • Ajouter une fiche complète (structure)
  • Glisser une page blanche (INITIAL LINE)
  • Copier certaines pages d’un autre classeur (LINES OF) à une position précise
  • L’option INDEX permet de contrôler l’ordre final des lignes.
  • Si aucun INDEX n’est spécifié, la ligne est ajoutée en fin de table.
  • Très pratique pour insérer plusieurs lignes d’un coup, sans boucle.

Déclaration et exemple
#

TYPES: BEGIN OF ty_citizen,
         country TYPE char3,
         name    TYPE char20,
         age     TYPE numc2,
       END OF ty_citizen.

DATA: lt_citizen1 TYPE TABLE OF ty_citizen,
      lt_citizen2 TYPE TABLE OF ty_citizen,
      ls_citizen  TYPE ty_citizen.

1️⃣ Insertion d’une structure dans la table
#

ls_citizen-country = 'FR'.
ls_citizen-name    = 'Thierry'.
ls_citizen-age     = '24'.
INSERT ls_citizen INTO TABLE lt_citizen1.

2️⃣ Création de plusieurs enregistrement dans une autre table
#

ls_citizen-country = 'ES'.
ls_citizen-name    = 'Luis'.
ls_citizen-age     = '32'.
INSERT ls_citizen INTO TABLE lt_citizen2.

ls_citizen-country = 'BR'.
ls_citizen-name    = 'Renata'.
ls_citizen-age     = '27'.
INSERT ls_citizen INTO TABLE lt_citizen2.

ls_citizen-country = 'FR'.
ls_citizen-name    = 'Floriane'.
ls_citizen-age     = '32'.
INSERT ls_citizen INTO TABLE lt_citizen2.

3️⃣ Insertion d’une ligne vide a un index précis
#

INSERT INITIAL LINE INTO lt_citizen1 INDEX 1.

4️⃣ Insertion de plusieurs lignes d’une autre table
#

INSERT LINES OF lt_citizen2 FROM 2 TO 3 INTO lt_citizen1 INDEX 1.
  • Une structure sert de modèle de ligne pour la table interne.
  • On peut insérer une ligne unique, une ligne vide ou plusieurs lignes d’une autre table.
  • L’ordre des lignes est contrôlé par INDEX.

Résultat final de lt_citizen1
#

COUNTRY NAME AGE
BR Renata 27
FR Floriane 32
FR Thierry 24

L’ordre final reflète la position des insertions et l’usage des INDEX.

Bonnes pratiques
#

Bonne pratique Explication
Définir clairement les structures Facilite la lecture et la maintenance
Préciser l’index si nécessaire Contrôle l’ordre final des enregistrements
Utiliser LINES OF pour copier des plages Évite les boucles manuelles et simplifie le code
Vérifier la présence de la table cible Prévenir les erreurs d’insertion

Exercices
#

1 – Créer et insérer des enregistrements
#

Déclarer une table interne lt_employees avec une structure ty_employee

  • id (CHAR5)
  • nom (CHAR20)
  • departement (CHAR10)

Insérer deux employés et afficher les données.

SOLUTION
TYPES: BEGIN OF ty_employee,
         id         TYPE char5,
         nom        TYPE char20,
         departement TYPE char10,
       END OF ty_employee.

DATA: lt_employees TYPE TABLE OF ty_employee,
      ls_employee  TYPE ty_employee.

ls_employee-id         = 'E001'.
ls_employee-nom        = 'Dupont'.
ls_employee-departement = 'RH'.
INSERT ls_employee INTO TABLE lt_employees.

ls_employee-id         = 'E002'.
ls_employee-nom        = 'Martin'.
ls_employee-departement = 'IT'.
INSERT ls_employee INTO TABLE lt_employees.

LOOP AT lt_employees INTO ls_employee.
  WRITE: / ls_employee-id, ls_employee-nom, ls_employee-departement.
ENDLOOP.

2 – Insérer une ligne vide
#

Ajouter une ligne vide à l’index 2 et afficher la table.

SOLUTION
INSERT INITIAL LINE INTO lt_employees INDEX 2.

LOOP AT lt_employees INTO ls_employee.
  WRITE: / ls_employee-id, ls_employee-nom, ls_employee-departement.
ENDLOOP.

3 – Copier des lignes d’une autre table
#

Créer lt_new_employees avec deux lignes et les insérer dans lt_employees à l’index 1.

SOLUTION
DATA: lt_new_employees TYPE TABLE OF ty_employee.

ls_employee-id         = 'E003'.
ls_employee-nom        = 'Renata'.
ls_employee-departement = 'FIN'.
INSERT ls_employee INTO TABLE lt_new_employees.

ls_employee-id         = 'E004'.
ls_employee-nom        = 'Luis'.
ls_employee-departement = 'LOG'.
INSERT ls_employee INTO TABLE lt_new_employees.

INSERT LINES OF lt_new_employees INTO lt_employees INDEX 1.

LOOP AT lt_employees INTO ls_employee.
  WRITE: / ls_employee-id, ls_employee-nom, ls_employee-departement.
ENDLOOP.

Résumé
#

  • INSERT → ajouter une ligne, une ligne vide ou plusieurs lignes d’une autre table.
  • INDEX → contrôle la position de la ou des lignes.

[!TIP] glisser des fiches dans un classeur à l’emplacement désiré, en copiant ou créant de nouvelles fiches.

[!IMPORTANT] définir clairement la structure, vérifier la table cible et éviter les boucles pour insérer plusieurs lignes.

Append to itab
#

Objectifs
#

  • Comprendre le fonctionnement de l’instruction APPEND pour les tables internes
  • Savoir ajouter une structure, une ligne vide, ou des lignes d’une autre table à la fin d’une table
  • Identifier les limitations selon le type de table interne
  • Comparer APPEND et INSERT selon le type de table

Définition
#

APPEND { ls | {INITIAL LINE} | {LINES OF jtab [FROM idx1] [TO idx2]} }
       TO itab.

L’instruction APPEND ajoute des données toujours à la fin d’une table interne (itab).
Elle fonctionne comme INSERT, mais le paramètre de destination est toujours TO itab.

Imaginez un classeur :

  • Vous collez toujours les nouvelles fiches à la fin.
  • Vous pouvez :
    • Ajouter une fiche complète (STRUCTURE)
    • Glisser une page blanche (INITIAL LINE)
    • Copier des pages d’une autre table interne (LINES OF itab)
  • APPEND est simple et rapide pour STANDARD et RANGE TABLE.
  • Pour HASHED ou SORTED TABLE, il faut utiliser INSERT INTO TABLE pour respecter les contraintes.

Exemple standard table
#

ls_citizen-country = 'ES'.
ls_citizen-name    = 'Luiza'.
ls_citizen-age     = '31'.
APPEND ls_citizen TO lt_citizen1.

ls_citizen-country = 'BR'.
ls_citizen-name    = 'Felipe'.
ls_citizen-age     = '25'.
APPEND ls_citizen TO lt_citizen1.

Contenu final de lt_citizen1 :

COUNTRY NAME AGE
BR Renata 27
FR Floriane 32
FR Thierry 24
ES Luiza 31
BR Felipe 25

Limitations pour sorted et hashed table
#

  • APPEND fonctionne uniquement pour STANDARD et RANGE TABLE.
  • Pour HASHED ou SORTED TABLE, il faut INSERT INTO TABLE.
  • Sur une SORTED TABLE, ajouter en fin peut violé l’ordre défini par la clé → DUMP.

Exemple sorted table – Dump
#

TYPES: BEGIN OF ty_country,
         land TYPE char3,
       END OF ty_country.

DATA: lt_country TYPE SORTED TABLE OF ty_country WITH NON-UNIQUE KEY land,
      ls_country TYPE ty_country.

ls_country-land = 'ES'.
APPEND ls_country TO lt_country.

ls_country-land = 'BR'.
APPEND ls_country TO lt_country.  " DUMP : ordre non respecté

Exemple sorted table – Pas de dump
#

ls_country-land = 'BR'.
APPEND ls_country TO lt_country.

ls_country-land = 'ES'.
APPEND ls_country TO lt_country.  " Ordre respecté, pas de DUMP
  • APPEND ne contrôle pas l’ordre sur SORTED TABLE.
  • L’usage correct dépend de la clé et de l’ordre défini.
  • HASHED TABLE ne peut jamais utiliser APPEND car il n’y a pas d’ordre séquentiel.

Bonnes pratiques
#

Bonne pratique Explication
Vérifier le type de table avant APPEND Évite DUMP sur SORTED ou HASHED TABLE
Utiliser APPEND uniquement pour STANDARD/RANGE Garantit insertion en fin sans violation de clé
Pour SORTED/HASHED TABLE, privilégier INSERT Maintient l’ordre ou l’unicité des clés
Vérifier l’ordre des clés avant insertion Prévenir erreurs et DUMP

Exercices
#

1 – Ajouter des employés a une standard table
#

Déclarer lt_employees avec la structure ty_employee :

  • id (CHAR5)
  • nom (CHAR20)
  • departement (CHAR10)

Ajouter deux employés avec APPEND et afficher la table.

SOLUTION
DATA: lt_employees TYPE TABLE OF ty_employee,
      ls_employee  TYPE ty_employee.

ls_employee-id         = 'E001'.
ls_employee-nom        = 'Dupont'.
ls_employee-departement = 'RH'.
APPEND ls_employee TO lt_employees.

ls_employee-id         = 'E002'.
ls_employee-nom        = 'Martin'.
ls_employee-departement = 'IT'.
APPEND ls_employee TO lt_employees.

LOOP AT lt_employees INTO ls_employee.
  WRITE: / ls_employee-id, ls_employee-nom, ls_employee-departement.
ENDLOOP.

2 – Ajouter une ligne vide
#

Ajouter une ligne vide à la fin de lt_employees et afficher la table.

SOLUTION
APPEND INITIAL LINE TO lt_employees.

LOOP AT lt_employees INTO ls_employee.
  WRITE: / ls_employee-id, ls_employee-nom, ls_employee-departement.
ENDLOOP.

3 – Copier des lignes d’une autre table
#

Copier toutes les lignes de lt_new_employees à la fin de lt_employees.

SOLUTION
INSERT LINES OF lt_new_employees INTO TABLE lt_employees.  " ou APPEND si STANDARD

Résumé
#

  • APPEND → ajoute toujours à la fin d’une table interne.
  • Compatible avec STANDARD et RANGE, interdit sur SORTED/HASHED sauf précaution.

[!CAUTION] DUMP si l’ordre est violé sur SORTED TABLE.

[!TIP] coller de nouvelles fiches à la fin d’un classeur, en respectant l’ordre si nécessaire.

[!IMPORTANT] vérifier le type de table et utiliser INSERT pour SORTED/HASHED.

Modify where
#

Objectifs
#

  • Comprendre le fonctionnement de MODIFY ... WHERE
  • Savoir modifier des lignes spécifiques d’une table interne en utilisant une condition
  • Identifier la différence avec MODIFY INDEX et MODIFY TABLE
  • Utiliser TRANSPORTING pour limiter les champs modifiés

Définition
#

MODIFY itab FROM ls
            TRANSPORTING comp1 comp2 ...
            WHERE cond.

MODIFY ... WHERE met à jour une table interne (itab) en utilisant une condition pour sélectionner les lignes à modifier.
La structure ls fournit les nouvelles valeurs et TRANSPORTING permet de modifier uniquement certains champs.

Imaginez un classeur

  • Vous cherchez les fiches correspondant à un critère précis (WHERE)
  • Vous modifiez uniquement les informations nécessaires
  • Les autres fiches restent inchangées
  • Fonctionne pour STANDARD, SORTED et HASHED TABLE
  • Utile lorsque la clé n’est pas connue ou lorsqu’une condition complexe doit être appliquée
  • Comparable à un WHERE dans SQL

Déclaration et exemple
#

TYPES: BEGIN OF ty_country,
         land TYPE char3,
         age  TYPE i,
       END OF ty_country.

DATA: lt_country TYPE HASHED TABLE OF ty_country WITH UNIQUE KEY land,
      ls_country TYPE ty_country.

" Remplissage initial
ls_country-land = 'FR'.
ls_country-age  = 23.
COLLECT ls_country INTO lt_country.

ls_country-land = 'IT'.
ls_country-age  = 20.
COLLECT ls_country INTO lt_country.

ls_country-land = 'IT'.
ls_country-age  = 55.
COLLECT ls_country INTO lt_country.

ls_country-land = 'FR'.
ls_country-age  = 5.
COLLECT ls_country INTO lt_country.

" CLEAR de la clé pour modification conditionnelle
CLEAR ls_country-land.
ls_country-age  = 10.

" Modification avec WHERE
MODIFY lt_country FROM ls_country TRANSPORTING age
                  WHERE land = 'IT'.
  • La clause WHERE sélectionne la ou les lignes à modifier
  • TRANSPORTING restreint la modification aux champs listés
  • Contrairement à MODIFY TABLE, la recherche ne se fait pas via la clé mais via la condition
  • Idéal pour des modifications conditionnelles complexes

État de la table
#

Avant le MODIFY :

LAND AGE
FR 28
IT 75

Après le MODIFY :

LAND AGE
FR 28
IT 10

Bonnes pratiques
#

Bonne pratique Explication
Vérifier la clause WHERE Assure que seule la ligne souhaitée sera modifiée
Utiliser TRANSPORTING pour champs ciblés Limite la modification aux champs nécessaires
Initialiser correctement la structure Évite de réécrire des valeurs indésirables
Comparer avec MODIFY TABLE Savoir quand utiliser la clé ou une condition
Tester sur un sous-ensemble de la table Prévenir les modifications accidentelles

Exercices
#

1 – Modifier par condition simple
#

Modifier l’âge des pays 'FR' à 35.

SOLUTION
CLEAR ls_country-land.
ls_country-age = 35.
MODIFY lt_country FROM ls_country TRANSPORTING age
                  WHERE land = 'FR'.

2 – Modifier plusieurs lignes avec condition
#

Ajouter 5 ans à tous les pays dont l’âge est inférieur à 30.

SOLUTION
LOOP AT lt_country INTO ls_country.
  IF ls_country-age < 30.
    ls_country-age = ls_country-age + 5.
    MODIFY lt_country FROM ls_country TRANSPORTING age
                      WHERE land = ls_country-land.
  ENDIF.
ENDLOOP.

3 – Comparaison avec modify table
#

Expliquer la différence pratique entre MODIFY TABLE et MODIFY WHERE.

Explication
  • MODIFY TABLE : modifie une ligne via la clé
  • MODIFY WHERE : modifie une ou plusieurs lignes via une condition
  • WHERE est nécessaire lorsque la clé n’est pas connue ou plusieurs lignes doivent être mises à jour
  • TRANSPORTING reste utile pour modifier uniquement certains champs

Résumé
#

  • MODIFY ... WHERE met à jour des lignes d’une table interne selon une condition
  • Permet de modifier tous les champs ou seulement certains via TRANSPORTING
  • Différence avec MODIFY INDEX : sélection par condition au lieu d’un index
  • Différence avec MODIFY TABLE : sélection par condition au lieu de la clé

[!TIP] modifier certaines fiches dans un classeur en fonction d’un critère précis

[!IMPORTANT] vérifier la clause WHERE, initialiser la structure et utiliser TRANSPORTING

Modify with index
#

Objectifs
#

  • Comprendre le fonctionnement de MODIFY ... INDEX
  • Savoir modifier des lignes spécifiques d’une table interne en utilisant une condition
  • Identifier la différence avec MODIFY INDEX et MODIFY TABLE
  • Utiliser TRANSPORTING pour limiter les champs modifiés

Définition
#

Pour l’instruction MODIFY, il existe trois formes de syntaxe possibles.

MODIFY itab [INDEX idx] FROM ls
            [TRANSPORTING comp1 comp2 ...].

L’instruction MODIFY va modifier la table interne itab à partir de la structure ls_. Il est possible d’indiquer l’index de la ligne à modifier (INDEX idx) ainsi que la liste des champs à modifier (TRANSPORTING comp1 comp2…).

Déclaration et exemple
#

TYPES: BEGIN OF ty_country,
         land   TYPE char3,
         age(3) TYPE i,
       END OF ty_country.

DATA: lt_country TYPE STANDARD TABLE OF ty_country WITH NON-UNIQUE KEY land,
      ls_country TYPE ty_country.

ls_country-land = 'FR'.
ls_country-age  = 23.
COLLECT ls_country INTO lt_country.

ls_country-land = 'IT'.
ls_country-age  = 20.
COLLECT ls_country INTO lt_country.

ls_country-land = 'IT'.
ls_country-age  = 55.
COLLECT ls_country INTO lt_country.

ls_country-land = 'FR'.
ls_country-age  = 5.
COLLECT ls_country INTO lt_country.

ls_country-land = 'FR'.
ls_country-age  = 10.
MODIFY lt_country INDEX 1 FROM ls_country TRANSPORTING age.

Avant le MODIFY, la structure ls_country est initialisée avec les valeurs souhaitées. Ensuite, le programme va modifier la table interne lt_country à l’index 1, à partir de la structure ls_country, afin de modifier uniquement le champ AGE.

lt_country avant le MODIFY

LAND AGE
FR 28
IT 75

lt_country après le MODIFY

LAND AGE
FR 10
IT 75

Copy table
#

Objectifs
#

  • Copier toutes les lignes d’une table interne vers une autre
  • Comprendre l’usage des crochets [] pour copier le contenu complet
  • Savoir que cette opération duplique toutes les données et non la référence
  • Connaître les précautions à prendre avant une copie
  • Être capable de vérifier la réussite d’une copie

Définition
#

itab_dest[] = itab_src[]

L’instruction COPY TABLE (écrite en ABAP sous la forme itab_dest[] = itab_src[]) permet de copier toutes les lignes d’une table interne vers une autre.

Imaginez deux classeurs

  • itab_src = classeur d’origine rempli de fiches
  • itab_dest = classeur vide
    Copier itab_src[] vers itab_dest[] revient à photocopier toutes les fiches du premier pour les ranger dans le second.

Exemples
#

1 – Copie complète d’une table interne
#

TYPES: BEGIN OF ty_citizen,
         country TYPE char3,
         name    TYPE char20,
         age     TYPE numc2,
       END OF ty_citizen.

DATA: lt_citizen_src  TYPE STANDARD TABLE OF ty_citizen,
      lt_citizen_dest TYPE STANDARD TABLE OF ty_citizen,
      ls_citizen      TYPE ty_citizen.

" REMPLISSAGE DE LA TABLE SOURCE
ls_citizen-country = 'FR'.
ls_citizen-name    = 'Thierry'.
ls_citizen-age     = '24'.
APPEND ls_citizen TO lt_citizen_src.

ls_citizen-country = 'ES'.
ls_citizen-name    = 'Luis'.
ls_citizen-age     = '32'.
APPEND ls_citizen TO lt_citizen_src.

" COPIE DE TOUTES LES LIGNES
lt_citizen_dest[] = lt_citizen_src[].

" AFFICHAGE DE LA TABLE DESTINATION
LOOP AT lt_citizen_dest ASSIGNING FIELD-SYMBOLS(<lfs_citizen>).
  WRITE:/ <lfs_citizen>-country, <lfs_citizen>-name, <lfs_citizen>-age.
ENDLOOP.

La table lt_citizen_dest contient maintenant exactement les mêmes lignes que lt_citizen_src.

Si lt_citizen_dest contenait déjà des données, elles seront remplacées (pas ajoutées).

2 – Copie avec structure identique mais vide
#

DATA: lt_empty_src TYPE STANDARD TABLE OF ty_citizen,
      lt_copy     TYPE STANDARD TABLE OF ty_citizen.

lt_copy[] = lt_empty_src[].

Si la table source est vide, la table de destination sera vide aussi.
Cela peut être utile pour réinitialiser une table sans utiliser CLEAR.

3 – Copie avec déclaration dynamique
#

FIELD-SYMBOLS: <lfs_src>  TYPE STANDARD TABLE,
               <lfs_dest> TYPE STANDARD TABLE.

DATA: lt_people TYPE STANDARD TABLE OF ty_citizen.

ASSIGN lt_people TO <lfs_src>.
ASSIGN lt_citizen_dest TO <lfs_dest>.

IF <lfs_src> IS ASSIGNED AND <lfs_dest> IS ASSIGNED.
  <lfs_dest>[] = <lfs_src>[].
ENDIF.

Cette méthode est utilisée dans les programmes où les noms de tables varient selon les contextes.
Elle permet de copier dynamiquement sans connaître le nom exact des tables.

Utile dans les modules génériques, les fonctions réutilisables, ou les boucles traitant plusieurs tables internes différentes.

Bonnes pratiques
#

Bonne pratique Explication
Toujours vérifier le contenu avec LINES() Permet de confirmer que la copie a bien été effectuée
Utiliser [] pour indiquer le contenu complet Sans crochets, seule la référence de la table serait copiée, pas ses données
Préparer la table destination Si elle contient déjà des données, elles seront remplacées
Eviter les copies inutiles Pour des grandes tables, cela peut ralentir le programme
Favoriser les FIELD-SYMBOLS pour modifier Si le but est de manipuler directement, pas besoin de dupliquer les données

Résumé
#

itab_dest[] = itab_src[] est la méthode la plus simple pour copier intégralement une table interne.

  • Les crochets [] signifient “copie de tout le contenu”
  • Les données sont dupliquées, pas seulement la référence
  • Les anciennes lignes sont remplacées
  • Possibilité d’utiliser des FIELD-SYMBOLS pour un traitement dynamique

[!TIP] Copier une table, c’est comme scanner un classeur entier pour en faire une copie fidèle, sans toucher à l’original.

Move corresponding
#

Objectifs
#

  • Copier uniquement les valeurs des champs correspondants entre tables internes
  • Comprendre la différence entre COPY TABLE et MOVE-CORRESPONDING
  • Savoir combiner plusieurs tables sources vers une même table cible
  • Apprendre à manipuler des structures différentes sans erreur de type

Définition
#

MOVE-CORRESPONDING itab_src TO itab_dest.

L’instruction MOVE-CORRESPONDING permet de copier seulement les champs portant le même nom entre une table interne source et une table interne destination.

Imaginez deux formulaires avec des rubriques similaires (par exemple : Nom, Pays, Âge).
MOVE-CORRESPONDING copie seulement les rubriques ayant le même intitulé, sans toucher aux autres champs.

  • Si la source et la destination ont des champs différents, seuls les champs correspondants sont copiés.
  • Les champs qui n’existent pas dans l’autre structure sont ignorés sans erreur.
  • L’opération peut être répétée pour fusionner plusieurs tables dans la même cible.

Exemple 1 – Copie entre tables différentes
#

TYPES: BEGIN OF ty_citizen_src,
         country TYPE char3,
         name    TYPE char20,
         age     TYPE numc2,
       END OF ty_citizen_src.

TYPES: BEGIN OF ty_citizen_dest,
         name    TYPE char20,
         country TYPE char3,
       END OF ty_citizen_dest.

DATA: lt_citizen_src  TYPE STANDARD TABLE OF ty_citizen_src,
      lt_citizen_dest TYPE STANDARD TABLE OF ty_citizen_dest,
      ls_src          TYPE ty_citizen_src.

" --- REMPLISSAGE DE LA TABLE SOURCE ---
ls_src-country = 'FR'.
ls_src-name    = 'Thierry'.
ls_src-age     = '24'.
APPEND ls_src TO lt_citizen_src.

ls_src-country = 'ES'.
ls_src-name    = 'Luis'.
ls_src-age     = '32'.
APPEND ls_src TO lt_citizen_src.

" --- TRANSFERT DES CHAMPS CORRESPONDANTS ---
MOVE-CORRESPONDING lt_citizen_src TO lt_citizen_dest.

" --- VERIFICATION ---
LOOP AT lt_citizen_dest ASSIGNING FIELD-SYMBOLS(<llfs_dest>).
  WRITE:/ <llfs_dest>-country, <llfs_dest>-name.
ENDLOOP.
  • lt_citizen_src contient un champ age absent dans lt_citizen_dest.
  • MOVE-CORRESPONDING ne copie que les champs country et name, car ils existent dans les deux structures.

Le système gère automatiquement la correspondance des noms sans tenir compte de l’ordre des champs.

Exemple 2 – Fusion de plusieurs tables
#

DATA: lt_additional TYPE STANDARD TABLE OF ty_citizen_src.

" Remplissage d'une autre table source
ls_src-country = 'DE'.
ls_src-name    = 'Klaus'.
ls_src-age     = '28'.
APPEND ls_src TO lt_additional.

" Copie successive dans la table cible
MOVE-CORRESPONDING lt_citizen_src TO lt_citizen_dest.
MOVE-CORRESPONDING lt_additional  TO lt_citizen_dest.

Comme remplir un registre commun à partir de plusieurs listes :
chaque MOVE-CORRESPONDING ajoute les lignes compatibles sans provoquer d’erreur.

Les lignes ne sont pas fusionnées champ par champ, mais ajoutées à la table destination.
Cela peut créer des doublons si les données se répètent.

Exemple 3 – Avec déclarations dynamiques
#

FIELD-SYMBOLS: <lfs_src>  TYPE STANDARD TABLE,
               <lfs_dest> TYPE STANDARD TABLE.

DATA: lt_source TYPE STANDARD TABLE OF ty_citizen_src,
      lt_target TYPE STANDARD TABLE OF ty_citizen_dest.

ASSIGN lt_source TO <lfs_src>.
ASSIGN lt_target TO <lfs_dest>.

IF <lfs_src> IS ASSIGNED AND <lfs_dest> IS ASSIGNED.
  MOVE-CORRESPONDING <lfs_src> TO <lfs_dest>.
ENDIF.

Ce type d’instruction est très utile dans les programmes génériques ou les rapports qui manipulent différentes structures dynamiquement.

Préférer cette approche quand le programme doit traiter plusieurs types de tables internes avec des champs similaires.

Différence avec copy table
#

Instruction Description Type de correspondance
itab1[] = itab2[] Copie tous les champs (même structure obligatoire) Correspondance totale
MOVE-CORRESPONDING itab2 TO itab1 Copie uniquement les champs de même nom, structures différentes acceptées Correspondance partielle
  • COPY TABLE = copie brute (toutes les colonnes doivent exister).
  • MOVE-CORRESPONDING = copie intelligente (seules les colonnes communes sont transférées).

Bonnes pratiques
#

Bonne pratique Explication
Toujours vérifier les noms des champs La correspondance se base sur les noms, pas sur la position
Utiliser MOVE-CORRESPONDING pour structures différentes Évite les erreurs de type
Vérifier les doublons lors de fusions Plusieurs MOVE-CORRESPONDING peuvent ajouter des lignes identiques
Préférer les FIELD-SYMBOLS pour programmes génériques Permet de manipuler des structures inconnues à l’avance

Résumé
#

MOVE-CORRESPONDING permet de transférer uniquement les champs communs entre deux structures ou tables internes.

  • Idéal pour les structures différentes mais similaires
  • Ignore les champs inexistants sans erreur

Delete
#

Objectifs
#

  • Comprendre le fonctionnement de l’instruction DELETE pour les tables internes
  • Savoir supprimer des lignes en fonction de l’index, de la clé ou d’une condition WHERE
  • Identifier les limitations selon le type de table interne
  • Utiliser DELETE de manière sûre et performante

Définition
#

DELETE { TABLE itab { FROM ls }
        | { WITH TABLE KEY [keyname COMPONENTS]
                {comp_name1|(name1)} = operand1
                {comp_name2|(name2)} = operand2 ...}
        | itab INDEX idx
        | itab WHERE cond }.

L’instruction DELETE retire des lignes d’une table interne (itab).
Trois formes principales

  • DELETE itab INDEX idx : supprime la ligne à l’index spécifié
  • DELETE itab FROM ls : supprime la ligne correspondant à la structure / clé
  • DELETE itab WHERE cond : supprime toutes les lignes respectant la condition

Imaginez un classeur

  • Retirer une fiche à une position précise
  • Supprimer la fiche correspondant à un identifiant
  • Retirer toutes les fiches correspondant à un critère spécifique
  • Les lignes supprimées disparaissent définitivement
  • Les index des lignes suivantes sont ajustés automatiquement pour les STANDARD TABLE
  • HASHED TABLE et SORTED TABLE gèrent la suppression via clé ou condition

Exemples
#

Delete par index
#

" Supprimer la première ligne de lt_country (STANDARD TABLE uniquement)
DELETE lt_country INDEX 1.

Delete par structure / Clé
#

ls_country-land = 'FR'.
DELETE lt_country FROM ls_country.  " Supprime la ligne dont la clé LAND = 'FR'

Delete avec where
#

DELETE lt_country WHERE age < 30.  " Supprime toutes les lignes avec age < 30
  • INDEX : applicable uniquement aux STANDARD TABLE
  • FROM / clé : fonctionne pour STANDARD et HASHED TABLE (basé sur la clé)
  • WHERE : applicable à toutes les tables, permet de supprimer plusieurs lignes selon un critère
  • Les lignes supprimées sont retirées définitivement et l’index des lignes suivantes est ajusté automatiquement

Bonnes pratiques
#

Bonne pratique Explication
Vérifier le type de table INDEX uniquement pour STANDARD
Initialiser correctement la structure Assurer la suppression ciblée avec FROM
Utiliser WHERE pour plusieurs lignes Supprime toutes les lignes répondant à la condition
Éviter DELETE en boucle inutile Prévenir des impacts sur les performances
Confirmer les lignes à supprimer Limiter les suppressions accidentelles

Exercices
#

1 – Delete par index
#

supprimer la première ligne de lt_country.

SOLUTION
DELETE lt_country INDEX 1.

2 – Delete par structure / Clé
#

supprimer la ligne avec LAND = ‘IT’.

SOLUTION
CLEAR ls_country-land.
ls_country-land = 'IT'.
DELETE lt_country FROM ls_country.

3 – Delete avec where
#

supprimer toutes les lignes où AGE < 25.

SOLUTION
DELETE lt_country WHERE age < 25.

4 – Comparaison des méthodes
#

expliquer quand utiliser INDEX, FROM, WHERE.

Explication
  • DELETE INDEX : rapide, applicable uniquement aux STANDARD TABLE
  • DELETE FROM : supprime la ligne correspondant à la clé ou à la structure
  • DELETE WHERE : supprime toutes les lignes correspondant à un critère, utile pour des suppressions conditionnelles
  • Utiliser WHERE pour des suppressions multiples et INDEX/FROM pour des suppressions ciblées

Résumé
#

  • DELETE supprime une ou plusieurs lignes d’une table interne selon l’index, la clé ou une condition WHERE

[!TIP] retirer des fiches d’un classeur soit par position, soit par identifiant, soit par critère spécifique

[!IMPORTANT] vérifier le type de table, initialiser la structure, utiliser WHERE pour plusieurs lignes et éviter les suppressions inutiles en boucle

Delete Adjacent Duplicates
#

Objectifs
#

  • Comprendre le fonctionnement de DELETE ADJACENT DUPLICATES
  • Savoir supprimer les doublons dans une table interne selon une clé ou des champs spécifiques
  • Identifier les contraintes liées au type de table et à l’ordre des données
  • Utiliser correctement COMPARING pour sélectionner les champs pertinents

Définition
#

DELETE ADJACENT DUPLICATES FROM itab
                          [COMPARING {comp1 comp2 ...}].

L’instruction DELETE ADJACENT DUPLICATES supprime les lignes consécutives en doublon dans une table interne (itab).

  • Si aucun champ n’est précisé avec COMPARING, la suppression se base sur la clé primaire de la table.
  • Si des champs sont précisés via COMPARING, seuls ces champs sont utilisés pour détecter les doublons.

Imaginez un classeur trié

  • Les fiches consécutives avec le même identifiant ou les mêmes informations sont fusionnées en une seule
  • Les fiches uniques restent intactes
  • Pour STANDARD TABLE, un tri préalable est obligatoire avant suppression
  • Pour SORTED TABLE, le tri est assuré automatiquement par la clé
  • La suppression ne retire que les doublons adjacents, pas les doublons dispersés

Déclaration et exemples
#

Table sorted
#

TYPES: BEGIN OF ty_citizen,
         country TYPE char3,
         name    TYPE char20,
         age     TYPE numc2,
       END OF ty_citizen.

DATA: lt_citizen TYPE SORTED TABLE OF ty_citizen WITH NON-UNIQUE KEY country,
      ls_citizen TYPE ty_citizen.

" Insertion des données
ls_citizen-country = 'FR'.
ls_citizen-name    = 'Thierry'.
ls_citizen-age     = '24'.
INSERT ls_citizen INTO TABLE lt_citizen.

ls_citizen-country = 'ES'.
ls_citizen-name    = 'Luis'.
ls_citizen-age     = '32'.
INSERT ls_citizen INTO TABLE lt_citizen.

ls_citizen-country = 'BR'.
ls_citizen-name    = 'Renata'.
ls_citizen-age     = '27'.
INSERT ls_citizen INTO TABLE lt_citizen.

ls_citizen-country = 'FR'.
ls_citizen-name    = 'Floriane'.
ls_citizen-age     = '32'.
INSERT ls_citizen INTO TABLE lt_citizen.

" Suppression des doublons adjacents (clé primaire)
DELETE ADJACENT DUPLICATES FROM lt_citizen.

Table standard
#

DATA: lt_citizen_std TYPE TABLE OF ty_citizen.

" Ajout des données
APPEND ls_citizen TO lt_citizen_std.
" ... (autres enregistrements)

" Tri obligatoire avant suppression
SORT lt_citizen_std BY country.
DELETE ADJACENT DUPLICATES FROM lt_citizen_std COMPARING country.
  • STANDARD TABLE : tri obligatoire pour que les doublons soient adjacents
  • SORTED TABLE : suppression basée automatiquement sur la clé
  • COMPARING permet de cibler les champs précis pour détecter les doublons
  • Les champs listés dans COMPARING doivent correspondre à ceux utilisés pour le tri

Bonnes pratiques
#

Bonne pratique Explication
Toujours trier la table avant suppression Nécessaire pour STANDARD TABLE
Utiliser COMPARING si clé non pertinente Cible uniquement les champs nécessaires
Vérifier les doublons avant suppression Prévenir la perte de données importantes
Respecter l’ordre des champs Aligné avec le tri pour éviter des suppressions incorrectes
Appliquer sur tables conséquentes Eviter la suppression incomplète si doublons non adjacents

Exercices
#

1 – Supprimer les doublons sur sorted table
#

supprimer les doublons consécutifs sur la clé country.

SOLUTION
DELETE ADJACENT DUPLICATES FROM lt_citizen.

2 – Supprimer les doublons sur standard table
#

supprimer les doublons consécutifs sur le champ country.

SOLUTION
SORT lt_citizen_std BY country.
DELETE ADJACENT DUPLICATES FROM lt_citizen_std COMPARING country.

3 – Supprimer les doublons sur plusieurs champs
#

supprimer les doublons où country et age sont identiques.

SOLUTION
SORT lt_citizen_std BY country age.
DELETE ADJACENT DUPLICATES FROM lt_citizen_std COMPARING country age.

Résumé
#

  • DELETE ADJACENT DUPLICATES supprime les lignes consécutives en doublon dans une table interne
  • Sans COMPARING : suppression basée sur la clé primaire
  • Avec COMPARING : suppression basée sur les champs spécifiés
  • STANDARD TABLE : trier avant suppression
  • SORTED TABLE : suppression basée sur la clé primaire automatiquement

[!TIP] retirer les fiches identiques consécutives dans un classeur trié

Read Table
#

Objectifs
#

  • Lire une ligne d’une table interne avec READ TABLE
  • Utiliser les options WITH KEY, INDEX pour localiser la ligne
  • Comprendre les modes de stockage du résultat : INTO, ASSIGNING, TRANSPORTING NO FIELDS
  • Maîtriser l’usage de FIELD-SYMBOLS pour manipuler directement la mémoire
  • Vérifier les retours avec SY-SUBRC et connaître l’index via SY-TABIX

Définition
#

READ TABLE itab
  { INTO ls | ASSIGNING <lfs_> | TRANSPORTING NO FIELDS }
  { FROM ls | WITH KEY { comp1 = obj1 comp2 = obj2 ... } [BINARY SEARCH] | INDEX idx }.

L’instruction READ TABLE permet de lire une ligne d’une table interne (itab) selon différents critères.

rechercher une fiche dans un classeur, soit par exemple de fiche, soit par critère précis, soit par numéro.

Exemples avec structure
#

Read avec une structure et condition
#

Version simple du READ avec une condition où les données de la ligne trouvée/lue sont stockées dans une structure déclarée en amont.

Les conditions sont indispensables pour identifier la ligne souhaité. Il est donc impératif de bien renseigner le ou les conditions nécessaires à son identification.

DATA: ls_struct TYPE ty_struct.

READ TABLE lt_citizen INTO ls_struct WITH KEY country = 'FR'.
IF sy-subrc = 0.
  WRITE:/ 'READ FROM structure :', ls_struct-country, ls_struct-name, ls_struct-age.
ENDIF.

Read avec une structure et conditions
#

Version simple du READ avec plusieurs conditions où les données de la ligne trouvée/lue sont stockées dans une structure déclarée en amont.

Les conditions sont indispensables pour identifier la ligne souhaité. Il est donc impératif de bien renseigner le ou les conditions nécessaires à son identification.

DATA: ls_struct TYPE ty_struct.

READ TABLE lt_citizen INTO ls_struct WITH KEY country = 'FR' name = 'Thierry'.
IF sy-subrc = 0.
  WRITE:/ 'READ FROM structure :', ls_struct-country, ls_struct-name, ls_struct-age.
ENDIF.

Read avec une structure sur la 1ère ligne (index 1)
#

Version du READ ciblant la 1ère ligne où les données de cette ligne sont pointées dans un field-symbol déclaré en amont.

DATA: ls_struct TYPE ty_struct.

READ TABLE lt_citizen INTO ls_struct INDEX 1.
IF sy-subrc = 0.
  WRITE:/ 'READ FROM structure :', ls_struct-country, ls_struct-name, ls_struct-age.
ENDIF.

Read avec une structure et condition + paramètre transporting no fields
#

Version simple du READ avec une condition où aucune donnée n’est récupérée. Ici le READ sert avant tout a vérifier la présence d’une entrée correspondante.

Les conditions sont indispensables pour identifier la ligne souhaité. Il est donc impératif de bien renseigner le ou les conditions nécessaires à son identification.

DATA: ls_struct TYPE ty_struct.

READ TABLE lt_citizen WITH KEY country = 'FR' TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
  WRITE:/ 'Nous avons bien trouvé une ligne !'.
ENDIF.

Read avec structure déclarée dynamiquement
#

Version simple du READ avec plusieurs conditions où les données de la ligne trouvée/lue sont stockées dans une structure déclarée dynamiquement.

Les conditions sont indispensables pour identifier la ligne souhaité. Il est donc impératif de bien renseigner le ou les conditions nécessaires à son identification.

READ TABLE lt_citizen INTO DATA(ls_struct) WITH KEY country = 'FR' name = 'Thierry'.
IF sy-subrc = 0.
  WRITE:/ 'READ FROM structure :', ls_struct-country, ls_struct-name, ls_struct-age.
ENDIF.

Exemples avec field-symbol
#

Read avec field-symbol et condition
#

Version du READ ciblant une ligne via condition et où les données de cette ligne sont pointées dans un field-symbol déclaré en amont.

Les conditions sont indispensables pour identifier la ligne souhaité. Il est donc impératif de bien renseigner le ou les conditions nécessaires à son identification.

FIELD-SYMBOLS: <lfs_citizen> TYPE ty_citizen.

READ TABLE lt_citizen ASSIGNING <lfs_citizen> WITH KEY country = 'FR'.
IF sy-subrc = 0.
  WRITE:/ 'READ FROM structure :', <lfs_citizen>-country, <lfs_citizen>-name, <lfs_citizen>-age.
ENDIF.

Read avec field-symbol et conditions
#

Version du READ ciblant une ligne via conditions et où les données de cette ligne sont pointées dans un field-symbol déclaré en amont.

Les conditions sont indispensables pour identifier la ligne souhaité. Il est donc impératif de bien renseigner le ou les conditions nécessaires à son identification.

FIELD-SYMBOLS: <lfs_citizen> TYPE ty_citizen.

READ TABLE lt_citizen ASSIGNING <lfs_citizen> WITH KEY country = 'FR' name = 'Thierry'.
IF sy-subrc = 0.
  WRITE:/ 'READ FROM structure :', <lfs_citizen>-country, <lfs_citizen>-name, <lfs_citizen>-age.
ENDIF.

Read avec field-symbol sur la 1ère ligne (index 1)
#

Version du READ ciblant la 1ère ligne où les données de cette ligne sont pointées dans un field-symbol déclaré en amont.

FIELD-SYMBOLS: <lfs_citizen> TYPE ty_citizen.

READ TABLE lt_citizen ASSIGNING <lfs_citizen> INDEX 1.
IF sy-subrc = 0.
  WRITE:/ 'READ FROM structure :', <lfs_citizen>-country, <lfs_citizen>-name, <lfs_citizen>-age.
ENDIF.

Read avec field-symbol avec condition + paramètre transporting no fields
#

Version du READ avec une condition où aucune donnée n’est récupérée. Ici le READ sert avant tout a vérifier la présence d’une entrée correspondante.

Les conditions sont indispensables pour identifier la ligne souhaité. Il est donc impératif de bien renseigner le ou les conditions nécessaires à son identification.

FIELD-SYMBOLS: <lfs_citizen> TYPE ty_citizen.

READ TABLE lt_citizen ASSIGNING <lfs_citizen> WITH KEY country = 'FR' TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
  WRITE:/ 'Nous avons bien trouvé une ligne !'.
ENDIF.

Read avec field-symbol déclarée dynamiquement
#

Version simple du READ avec plusieurs conditions où les données de la ligne trouvée/lue sont pointées dans une structure déclarée dynamiquement.

Les conditions sont indispensables pour identifier la ligne souhaité. Il est donc impératif de bien renseigner le ou les conditions nécessaires à son identification.

READ TABLE lt_citizen ASSIGNING FIELD-SYMBOL(<lfs_citizen>) WITH KEY country = 'FR' name = 'Thierry'.
IF sy-subrc = 0.
  WRITE:/ 'READ FROM structure :', <lfs_citizen>-country, <lfs_citizen>-name, <lfs_citizen>-age.
ENDIF.

Bonnes pratiques
#

Bonne pratique Explication
Toujours tester SY-SUBRC Assure que la ligne a été trouvée avant d’accéder aux champs
Utiliser ASSIGNING <fs> pour performance Évite la copie de la ligne, modifie directement la mémoire
TRANSPORTING NO FIELDS pour vérification Vérifie juste l’existence sans copier ni modifier
Comparer avec READ TABLE INDEX et KEY Savoir choisir la méthode adaptée au type de table et à la clé

Résumé
#

READ TABLE permet de localiser et accéder à une ligne dans une table interne.

  • Options de recherche : WITH KEY, INDEX
  • Options de récupération : INTO, ASSIGNING, TRANSPORTING NO FIELDS
  • Variables système : SY-SUBRC et SY-TABIX

[!TIP] rechercher une fiche dans un classeur et pointer directement dessus pour modification.

Binary Search #

Objectifs
#

  • Comprendre l’option BINARY SEARCH avec READ TABLE
  • Savoir l’utiliser pour optimiser les recherches dans une table interne
  • Connaître la condition nécessaire pour que la recherche binaire fonctionne
  • Identifier les avantages par rapport à une recherche linéaire

Définition
#

L’option BINARY SEARCH utilisée avec READ TABLE permet de réaliser une recherche binaire dans une table interne, optimisant ainsi les performances du programme.

Principe de la recherche binaire

  • Comparer la valeur recherchée à la valeur du milieu de la plage
  • Si égal → retour de l’index, fin de recherche
  • Si valeur > milieu → recherche dans la moitié inférieure
  • Si valeur < milieu → recherche dans la moitié supérieure
  • Répéter jusqu’à trouver la valeur ou épuiser la plage

la table doit être triée (SORT) sauf si elle est de type SORTED.

Chercher un nom dans un annuaire trié par ordre alphabétique en ouvrant toujours à la page du milieu pour diviser les recherches.

Exemple
#

TYPES: BEGIN OF ty_citizen,
         country TYPE char3,
         name    TYPE char20,
         age     TYPE numc2,
       END OF ty_citizen.

DATA: lt_citizen TYPE STANDARD TABLE OF ty_citizen,
      ls_citizen TYPE ty_citizen.

FIELD-SYMBOLS: <lfs_citizen> TYPE ty_citizen.

" Remplissage de la table
ls_citizen-country = 'FR'. ls_citizen-name = 'Thierry'. ls_citizen-age = '24'. APPEND ls_citizen TO lt_citizen.
ls_citizen-country = 'ES'. ls_citizen-name = 'Luis'.    ls_citizen-age = '32'. APPEND ls_citizen TO lt_citizen.
ls_citizen-country = 'BR'. ls_citizen-name = 'Renata'.  ls_citizen-age = '27'. APPEND ls_citizen TO lt_citizen.
ls_citizen-country = 'FR'. ls_citizen-name = 'Floriane'.ls_citizen-age = '32'. APPEND ls_citizen TO lt_citizen.

" Tri obligatoire pour BINARY SEARCH
SORT lt_citizen BY country name.

" Recherche binaire
READ TABLE lt_citizen WITH KEY country = 'FR' name = 'Floriane' BINARY SEARCH ASSIGNING <lfs_citizen>.
IF sy-subrc = 0.
  WRITE:/ 'Enregistrement trouvé à la ligne :', sy-tabix, 'Pays:', <lfs_citizen>-country, 'Nom:', <lfs_citizen>-name.
ENDIF.

Bonnes pratiques
#

Bonne pratique Explication
Trier la table avant BINARY SEARCH Obligatoire pour tables STANDARD
Utiliser ASSIGNING pour performance Évite la copie de la ligne, modifie directement la mémoire
Vérifier SY-SUBRC S’assurer que l’enregistrement a été trouvé
Comparer BINARY SEARCH vs recherche linéaire Réduction significative du nombre de comparaisons
Utiliser BY avec tous les champs clés Permet une recherche précise et correcte

Exercices
#

1 – Recherche binaire simple + déclaration dynamique en field-symbol
#

Trier lt_citizen par country puis name et lire l’enregistrement dont country = 'ES' et name = 'Luis' en utilisant BINARY SEARCH. Afficher age.

SOLUTION
SORT lt_citizen BY country name.

READ TABLE lt_citizen WITH KEY country = 'ES' name = 'Luis' BINARY SEARCH ASSIGNING FIELD-SYMBOL(<lfs_citizen>).
IF sy-subrc = 0.
  WRITE:/ 'Âge du citoyen Luis en ES :', <lfs_citizen>-age.
ENDIF.

2 – Vérifier l’existence sans copier
#

Vérifier si un enregistrement country = 'BR' et name = 'Renata' existe dans lt_citizen avec BINARY SEARCH, sans copier la ligne (TRANSPORTING NO FIELDS). Afficher un message.

SOLUTION
READ TABLE lt_citizen WITH KEY country = 'BR' name = 'Renata' BINARY SEARCH TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
  WRITE:/ 'Enregistrement BR-Renata trouvé !'.
ELSE.
  WRITE:/ 'Enregistrement BR-Renata non trouvé.'.
ENDIF.

Résumé
#

BINARY SEARCH permet une recherche rapide dans une table interne triée.

  • Condition : table triée ou de type SORTED
  • Réduit le nombre de comparaisons par rapport à une recherche linéaire
  • Retourne l’INDEX via SY-TABIX et le code retour via SY-SUBRC

[!TIP] feuilleter un annuaire trié en ouvrant toujours au milieu pour diviser les recherches et trouver la personne plus rapidement.

Loop At
#

Objectifs
#

  • Parcourir une table interne ligne par ligne avec LOOP AT
  • Utiliser les options INTO, ASSIGNING <fs> et TRANSPORTING NO FIELDS
  • Filtrer avec WHERE, FROM et TO
  • Déclarer dynamiquement les structures et FIELD-SYMBOLS pour plus de flexibilité
  • Modifier directement les lignes via FIELD-SYMBOLS
  • Comprendre les variables système SY-SUBRC et SY-TABIX
  • Utiliser les ruptures AT FIRST, AT NEW, AT END OF, AT LAST
  • Utiliser des filtres complexes avec WHERE sur un ou plusieurs champs

Définition
#

LOOP AT itab
  { INTO ls | ASSIGNING <lfs_> | TRANSPORTING NO FIELDS }
  [FROM idx1] [TO idx2]
  [WHERE condition]
  ...
  AT ...
    ...
  ENDAT.
  ...
ENDLOOP.

L’instruction LOOP AT permet de parcourir une table interne (itab) ligne par ligne.
Les données peuvent être copiées (INTO), référencées en mémoire (ASSIGNING <fs>) ou simplement vérifiées (TRANSPORTING NO FIELDS).

Parcourir un classeur ligne par ligne

  • INTO = photocopier la fiche
  • ASSIGNING <lfs\_> = pointer directement sur la fiche pour modifier
  • TRANSPORTING NO FIELDS = juste vérifier si la fiche existe

Exemples simples
#

Loop avec into
#

DATA: ls_citizen TYPE ty_citizen.

LOOP AT lt_citizen INTO ls_citizen WHERE country = 'FR'.
  WRITE:/ 'Pays:', ls_citizen-country, 'Nom:', ls_citizen-name, 'Âge:', ls_citizen-age.
ENDLOOP.

Copie de la ligne dans ls_citizen. Modification de ls_citizen n’affectera pas lt_citizen.

Loop avec assigning field-symbol
#

FIELD-SYMBOLS: <lfs_citizen> TYPE ty_citizen.

LOOP AT lt_citizen ASSIGNING <lfs_citizen> WHERE country = 'ES'.
  <lfs_citizen>-age = <lfs_citizen>-age + 1.
  WRITE:/ 'Pays:', <lfs_citizen>-country, 'Nom:', <lfs_citizen>-name, 'Nouvel âge:', <lfs_citizen>-age.
ENDLOOP.

Modification directe dans la table sans utiliser MODIFY.

Loop avec transporting no fields
#

LOOP AT lt_citizen TRANSPORTING NO FIELDS WHERE name = 'Renata'.
  IF sy-subrc = 0.
    WRITE:/ 'Renata est présente dans la table.'.
  ENDIF.
ENDLOOP.

Vérifier simplement l’existence sans copier ni modifier la ligne.

Loop avec from / to
#

LOOP AT lt_citizen INTO ls_citizen FROM 2 TO 3.
  WRITE:/ 'Pays:', ls_citizen-country, 'Nom:', ls_citizen-name.
ENDLOOP.

Limite la boucle aux lignes 2 et 3 pour traiter une plage précise.

Loop avec déclaration dynamique
#

DATA: lt_dyn TYPE STANDARD TABLE OF ty_citizen.

LOOP AT lt_dyn INTO DATA(ls_dyn).
  ls_dyn-country = 'IT'.
  WRITE:/ 'Pays mis à jour:', ls_dyn-country, 'Nom:', ls_dyn-name.
ENDLOOP.

LOOP AT lt_dyn ASSIGNING FIELD-SYMBOLS(<lfs_dyn_row>).
  <lfs_dyn_row>-country = 'IT'.
  WRITE:/ 'Pays mis à jour:', <lfs_dyn_row>-country, 'Nom:', <lfs_dyn_row>-name.
ENDLOOP.

Utile pour créer ou manipuler des structures au fur et à mesure, et pour éviter les conflits de FIELD-SYMBOLS.

Loop avec at first / at new / at end of / at last
#

SORT lt_citizen BY country.

LOOP AT lt_citizen ASSIGNING <lfs_citizen>.
  AT FIRST.
    WRITE: 'Début de la liste'.
    ULINE.
  ENDAT.

  AT NEW country.
    WRITE:/ 'Début pays : ', <lfs_citizen>-country.
  ENDAT.

  WRITE:/ 'Nom : ', <lfs_citizen>-name, 'Age : ', <lfs_citizen>-age.

  AT END OF country.
    WRITE:/ 'Fin pays : ', <lfs_citizen>-country.
    ULINE.
  ENDAT.

  AT LAST.
    WRITE: 'Fin de la liste'.
  ENDAT.
ENDLOOP.

Permet de gérer des ruptures pour grouper ou démarquer des sections dans la table.

Exemples avancés – where
#

1 – Where sur un champ
#

LOOP AT lt_citizen INTO ls_citizen WHERE country = 'FR'.
  WRITE:/ 'Pays:', ls_citizen-country, 'Nom:', ls_citizen-name.
ENDLOOP.

Vérifie toutes les lignes dont le champ country = ‘FR’.

2 – Where sur deux champs (clé et non-clé)
#

LOOP AT lt_citizen ASSIGNING <lfs_citizen> WHERE country = 'ES' AND age > '30'.
  WRITE:/ 'Pays:', <lfs_citizen>-country, 'Nom:', <lfs_citizen>-name, 'Âge:', <lfs_citizen>-age.
ENDLOOP.

On peut combiner plusieurs champs avec AND.

les champs non-clés peuvent être utilisés pour filtrer.

3 – Where avec comparaisons multiples
#

LOOP AT lt_citizen INTO ls_citizen WHERE age >= '25' AND age <= '32'.
  WRITE:/ 'Nom:', ls_citizen-name, 'Âge:', ls_citizen-age.
ENDLOOP.

Permet de sélectionner des plages de valeurs.

chercher toutes les fiches entre 25 et 32 ans.

4 – Where sur plusieurs champs clés et non-clés
#

LOOP AT lt_citizen ASSIGNING <lfs_citizen> WHERE country = 'FR' AND age = '24' AND name = 'Thierry'.
  WRITE:/ 'Citoyen trouvé:', <lfs_citizen>-name, 'Pays:', <lfs_citizen>-country.
ENDLOOP.

Si la table n’est pas triée correctement pour les clés, l’utilisation d’AT NEW avec ce filtre pourrait ne pas fonctionner comme attendu.

5 – Where avec conditions complexes
#

LOOP AT lt_citizen INTO ls_citizen WHERE (country = 'BR' OR country = 'IT') AND age < '30'.
  WRITE:/ 'Nom:', ls_citizen-name, 'Pays:', ls_citizen-country, 'Âge:', ls_citizen-age.
ENDLOOP.

On peut combiner AND et OR en respectant la priorité des parenthèses.

6 – Where dynamique (avec field-symbol)
#

DATA: lv_country TYPE char3 VALUE 'ES'.

LOOP AT lt_citizen ASSIGNING FIELD-SYMBOLS(<dyn_citizen>) WHERE country = lv_country AND age > '30'.
  WRITE:/ 'Nom:', <dyn_citizen>-name, 'Pays:', <dyn_citizen>-country, 'Âge:', <dyn_citizen>-age.
ENDLOOP.

Permet d’utiliser des variables dynamiques dans les conditions.

Bonnes pratiques
#

Bonne pratique Explications
Toujours trier la table avant AT NEW Nécessaire pour les tables STANDARD si vous utilisez des ruptures
Préférer ASSIGNING pour modifier Évite la copie et permet de travailler directement en mémoire
Utiliser WHERE pour filtrer Réduit le nombre de lignes parcourues
Vérifier SY-SUBRC Utile si vous utilisez TRANSPORTING NO FIELDS
FIELD-SYMBOLS uniques par scope Évite les erreurs et conflits dans les boucles imbriquées
FROM/TO pour limiter les plages Optimise les traitements si seules certaines lignes sont concernées
Parenthèses avec AND/OR Clarifie les conditions complexes et évite les erreurs

Exercices
#

1 – Where sur un seul champ
#

Parcourir lt_citizen et afficher les citoyens dont country = 'FR'.

SOLUTION
LOOP AT lt_citizen INTO ls_citizen WHERE country = 'FR'.
  WRITE:/ 'Pays:', ls_citizen-country, 'Nom:', ls_citizen-name.
ENDLOOP.

2 – Where sur plusieurs champs
#

Afficher les citoyens dont country = 'ES' et age > 30.

SOLUTION
LOOP AT lt_citizen ASSIGNING <lfs_citizen> WHERE country = 'ES' AND age > '30'.
  WRITE:/ 'Nom:', <lfs_citizen>-name, 'Pays:', <lfs_citizen>-country, 'Âge:', <lfs_citizen>-age.
ENDLOOP.

3 – Where avec plage d’âge
#

Afficher les citoyens âgés entre 25 et 32 ans.

SOLUTION
LOOP AT lt_citizen INTO ls_citizen WHERE age >= '25' AND age <= '32'.
  WRITE:/ 'Nom:', ls_citizen-name, 'Âge:', ls_citizen-age.
ENDLOOP.

4 – Where dynamique
#

Afficher tous les citoyens dont country = lv_country et age > 30.

SOLUTION
DATA: lv_country TYPE char3 VALUE 'ES'.

LOOP AT lt_citizen ASSIGNING FIELD-SYMBOLS(<dyn_citizen>) WHERE country = lv_country AND age > '30'.
  WRITE:/ 'Nom:', <dyn_citizen>-name, 'Pays:', <dyn_citizen>-country, 'Âge:', <dyn_citizen>-age.
ENDLOOP.

5 – Where complexe avec or et and
#

Afficher tous les citoyens dont country = 'BR' ou country = 'IT' et age < 30.

SOLUTION
LOOP AT lt_citizen INTO ls_citizen WHERE (country = 'BR' OR country = 'IT') AND age < '30'.
  WRITE:/ 'Nom:', ls_citizen-name, 'Pays:', ls_citizen-country, 'Âge:', ls_citizen-age.
ENDLOOP.

Résumé
#

LOOP AT permet de parcourir les tables internes ligne par ligne.

  • INTO : copie de la ligne
  • ASSIGNING : référence directe en mémoire
  • TRANSPORTING NO FIELDS : vérification uniquement
  • WHERE : filtrage simple ou complexe (un ou plusieurs champs, AND/OR, variables dynamiques)
  • FROM / TO : filtrage par plage
  • FIELD-SYMBOLS : modification directe
  • SY-SUBRC / SY-TABIX : code retour et index
  • AT FIRST / AT NEW / AT END OF / AT LAST : gestion des ruptures

Articles connexes

Les conditions en ABAP
··19 mins· loading · loading
SAP ERP Back-End
Types ITAB en ABAP
··15 mins· loading · loading
SAP ERP Back-End
Les instructions en ABAP
··24 mins· loading · loading
SAP ERP Back-End
Introduction ABAP
·16 mins· loading · loading
SAP ERP Back-End
Structure ITAB en ABAP
··6 mins· loading · loading
ERP SAP Back-End
Structure d'un programme ABAP
··14 mins· loading · loading
SAP ERP Back-End