Introduction
Application des techniques et concepts de base
Utilisation des classes locales
Lecture des données de la base de données
Utilisation d'objets de données structurés
Utilisation de tables internes complexes
Implémentation de mises à jour de base de données à l'aide d'objets de gestion
Description du modèle de programmation d'applications ABAP RESTful

Utilisation des structures de contrôle dans ABAP

Objectives

After completing this lesson, you will be able to:
  • Implémentez la ramification conditionnelle.
  • Gérer les exceptions.
  • Implémentez des itérations.

Branchement conditionnel

Une ramification conditionnelle est une structure de contrôle qui vous permet de rendre l'exécution du code dépendante des conditions logiques.

La ramification conditionnelle la plus courante est constituée d'une paire de mots-clés IF et ENDIF. Le bloc de code entre IF et ENDIF est exécuté uniquement si la condition après IF est remplie.

Vous pouvez ajouter d'autres blocs de code en étendant la structure IF … ENDIF avec jusqu'à un mot-clé ELSE et un nombre arbitraire de mots-clés ELSEIF. En ajoutant le mot-clé ELSE, vous vous assurez que toujours exactement un des blocs de code est exécuté. Si ELSE est manquant, il peut arriver qu'aucun des blocs de code ne soit exécuté.

Le bloc de code à exécuter est déterminé comme suit :

  • Tout d'abord, la condition IF est évaluée. S'il est rempli, le bloc de code associé est exécuté et le programme continue après ENDIF.
  • La condition après la première instruction ELSEIF est analysée uniquement si la condition IF n'est pas remplie. S'il est rempli, le bloc de code associé est exécuté et le programme continue après ENDIF.
  • Cette opération est effectuée consécutivement pour toutes les conditions ELSEIF. Si aucune des conditions n'est remplie et que la structure contient ELSE, le bloc de code après ELSE est exécuté. Sinon, aucun des blocs de code n'est exécuté.

Astuce

Contrairement à de nombreux autres langages de programmation, ABAP requiert un séparateur (.) après chacune des conditions logiques et même après le mot-clé ELSE.

Les conditions logiques sont une combinaison de comparaisons, d'opérations logiques, d'expressions et de fonctions que le système d'exécution évalue pour décider si la condition est vraie ou fausse.

Le cas d'utilisation le plus courant pour les conditions logiques est après les mots-clés IF ou ELSEIF dans une IF ... ENDIF. structure.

Le premier exemple est une comparaison simple : la condition est vraie si les deux objets de données x et y ont la même valeur.

Le deuxième example est un peu plus sophistiqué: Soit la valeur de x est supérieure ou égale à y et inférieure à deux fois la valeur de y, soit elle est inférieure ou égale à y et supérieure à deux fois la valeur de y.

Le troisième exemple utilise la fonction arithmétique abs( ) et l'expression logique BETWEEN <expression1> AND <expression2>. La condition est vraie si la valeur absolue de x est comprise entre la valeur absolue de y et la valeur absolue de deux fois y.

Pour des comparaisons de valeurs simples, vous pouvez utiliser les opérateurs =, <>, >, <, >= et <=. Vous pouvez non seulement comparer les valeurs des objets de données, mais aussi les valeurs de nombreuses autres expressions, comme l'expression arithmétique 2 * y dans l'exemple.

Remarque

ABAP utilise le même symbole (=) pour les valorisations et pour les comparaisons de valeurs. La distinction est faite en fonction de la position.

Vous pouvez utiliser les opérateurs AND et OR pour combiner des expressions logiques et l'opérateur NOT pour inverser une expression. Sans parenthèses, NE LIT PAS plus fort que ET et ET plus fort que OU.

ABAP connaît certaines expressions logiques spéciales :

  • <objet de données> IS INITIAL est vrai si <objet de données> contient sa valeur initiale spécifique au type
  • <objet de données> N'EST PAS INITIAL est vrai si <objet de données> contient une valeur différente de la valeur initiale spécifique au type.
  • <objet de données> BETWEEN <expression1> AND <expression2>

Certaines fonctions ABAP spéciales sont des fonctions de prédicat. Cela signifie qu'il s'agit de conditions logiques elles-mêmes. Contient( ) est une fonction qui compare des valeurs alphanumériques et line_exist( ) effectue un contrôle d'existence pour une ligne dans une table interne.

Une deuxième technique de branchement conditionnel est la CASE … WHEN .. Structure de contrôle ENDCASE.

branchement conditionnel avec CASE .. ENDCASE est un cas particulier de branchement plus général avec IF … ENDIF. Vous pouvez utiliser CASE dans les cas où la ramification dépend de la valeur d'un objet de données individuel, que vous comparez successivement à un ensemble de valeurs possibles, à l'aide d'une comparaison égale à chaque fois.

Dans l'exemple, la valeur du numéro d'objet de données est comparée aux valeurs 1 et 2. Si la valeur est égale à 1, <code_block_1> est exécuté et si la valeur euqals 2, <code_blocl_2> est exécuté à la place. Pour toute autre valeur, le bloc de code après WHEN OTHERS est exécuté.

Toute ramification conditionnelle avec CASE … ENDCASE peut également être implémentée avec une structure IF … ENDIF. Ceci est illustré par l'exemple à droite.

Astuce

Vous devez utiliser CASE … ENDCASE lorsque vous traitez le cas particulier pour améliorer la lisibilité de votre code.

Essayer : branche conditionnelle

  1. Comme dans le premier exercice de ce cours, créez une nouvelle classe globale qui implémente l'interface IF_OO_ADT_CLASSRUN.
  2. Copiez l'extrait de code suivant dans la partie implémentation de la méthode if_oo_adt_classrun~main( ) :
    Code Snippet
    1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
    * Declarations ********************************************************************** CONSTANTS c_number TYPE i VALUE 0. * CONSTANTS c_number TYPE i VALUE 1. * CONSTANTS c_number TYPE i VALUE 2. * CONSTANTS c_number TYPE i VALUE -1. * CONSTANTS c_number TYPE i VALUE -2. * Example 1: Simple IF ... ENDIF. ********************************************************************** out->write( `--------------------------------` ). out->write( `Example 1: Simple IF ... ENDIF.` ). out->write( `-------------------------------` ). IF c_number = 0. out->write( `The value of C_NUMBER equals zero` ). ELSE. out->write( `The value of C_NUMBER is NOT zero` ). ENDIF. * Example 2: Optional Branches ELSEIF and ELSE ********************************************************************** out->write( `--------------------------------------------` ). out->write( `Example 2: Optional Branches ELSEIF and ELSE` ). out->write( `--------------------------------------------` ). IF c_number = 0. out->write( `The value of C_NUMBER equals zero` ). ELSEIF c_number > 0. out->write( `The value of C_NUMBER is greater than zero` ). ELSE. out->write( `The value of C_NUMBER is less than zero` ). ENDIF. * Example 3: CASE ... ENDCASE ********************************************************************** out->write( `---------------------------` ). out->write( `Example 3: CASE ... ENDCASE` ). out->write( `---------------------------` ). CASE c_number. WHEN 0. out->write( `The value of C_NUMBER equals zero` ). WHEN 1. out->write( `The value of C_NUMBER equals one` ). WHEN 2. out->write( `The value of C_NUMBER equals two` ). WHEN OTHERS. out->write( `The value of C_NUMBER equals non of the above` ). ENDCASE.
  3. Appuyez sur CTRL + F3 pour activer la classe et SUR F9 pour l'exécuter en tant qu'application console.
  4. Analysez la sortie de la console. Jouez avec le code source pour vous familiariser avec les concepts ; Retirer le commentaire des différentes déclarations de constante c_number avec différentes valeurs à voir, quelles branches du code sont exécutées.

Gestion des exceptions

Exceptions

En ABAP, une exception est une situation d'erreur lors de l'exécution d'un programme ABAP. Une exception est déclenchée par le code qui détecte la situation d'erreur.

Selon qui déclenche l'exception, nous faisons la distinction entre les exceptions système et les exceptions d'application.

En l'absence d'autres mesures, les exceptions entraînent des erreurs d'exécution. Une erreur d'exécution interrompt le programme et est documentée par défaut dans un vidage d'une partie de la mémoire.

Vous pouvez éviter l'erreur d'exécution si l'exception en question peut être interceptée. Une exception pouvant être interceptée peut être traitée dans le programme à l'aide des instructions TRY … CATCH … ENDTRY.

Toutes les exceptions d'application et de nombreuses exceptions système peuvent être interceptées. Plus tard dans ce cours, vous apprendrez à déclencher des exceptions de candidature. À ce stade, nous nous concentrerons sur la gestion des exceptions du système pouvant être interceptées.

La vidéo suivante présente quelques exemples d'erreurs d'exécution.

Gestion des exceptions

Pour éviter l'interruption d'un programme en raison d'une exception pouvant être interceptée, vous devez entourer le code d'où provient l'exception avec les instructions TRY et ENDTRY. Ce faisant, le code fait partie du bloc TRY de la structure TRY … ENDTRY.

Avant l'instruction ENDTRY, vous devez ajouter une instruction CATCH suivie de l'ID de l'exception que vous voulez traiter. Facultativement, vous pouvez ajouter plusieurs instructions CATCH pour gérer plusieurs exceptions différentes. Chaque instruction CATCH doit être suivie du code pour gérer cette exception. Ce code est appelé bloc CATCH.

Lorsque l'exécution du programme atteint l'instruction TRY, elle continue avec le code dans le bloc TRY. Trois choses peuvent alors se produire :

  1. Si aucune exception n'est déclenchée pendant le bloc TRY, les blocs CATCH sont ignorés. L'exécution se poursuit après l'instruction ENDTRY.
  2. Si une exception est déclenchée pendant le bloc TRY, pour lequel il existe un CATCH correspondant, l'exécution du bloc TRY est interrompue et le bloc CATCH pour cette exception est exécuté. Ensuite, l'exécution se poursuit après l'instruction ENDTRY.
  3. Si une exception est déclenchée pendant le bloc TRY pour lequel il n'existe pas de CATCH correspondant, le programme s'interrompt avec une erreur d'exécution.

Maintenant que vous avez appris les exceptions, voyons comment les gérer.

Essayer : gestion des exceptions

  1. Comme dans le premier exercice de ce cours, créez une nouvelle classe globale qui implémente l'interface IF_OO_ADT_CLASSRUN.
  2. Copiez l'extrait de code suivant dans la partie implémentation de la méthode if_oo_adt_classrun~main( ) :
    Code Snippet
    1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
    * Declarations ********************************************************************** DATA result TYPE i. DATA numbers TYPE TABLE OF i. * Preparation ********************************************************************** APPEND 123 TO numbers. * Example 1: Conversion Error (no Number) ********************************************************************** CONSTANTS c_text TYPE string VALUE 'ABC'. * CONSTANTS c_text TYPE string VALUE '123'. out->write( `---------------------------` ). out->write( `Example 1: Conversion Error` ). out->write( `---------------------------` ). TRY. result = c_text. out->write( |Converted content is { result }| ). CATCH cx_sy_conversion_no_number. out->write( |Error: { c_text } is not a number!| ). ENDTRY. * Example 2: Division by Zero ********************************************************************** CONSTANTS c_number TYPE i VALUE 0. * CONSTANTS c_number TYPE i VALUE 7. out->write( `---------------------------` ). out->write( `Example 2: Division by Zero` ). out->write( `---------------------------` ). TRY. result = 100 / c_number. out->write( |100 divided by { c_number } equals { result }| ). CATCH cx_sy_zerodivide. out->write( `Error: Division by zero is not defined!` ). ENDTRY. * Example 3: Itab Error (Line Not Found) ********************************************************************** CONSTANTS c_index TYPE i VALUE 2. * CONSTANTS c_index TYPE i VALUE 1. out->write( `-------------------------` ). out->write( `Example 3: Line Not Found` ). out->write( `-------------------------` ). TRY. result = numbers[ c_index ]. out->write( |Content of row { c_index } equals { result }| ). CATCH cx_sy_itab_line_not_found. out->write( `Error: Itab has less than { c_index } rows!` ). ENDTRY. * Example 4: Combination of Different Exceptions ********************************************************************** * CONSTANTS c_char TYPE c LENGTH 1 VALUE 'X'. * CONSTANTS c_char TYPE c length 1 value '0'. CONSTANTS c_char TYPE c LENGTH 1 VALUE '1'. * CONSTANTS c_char TYPE c length 1 value '2'. out->write( `----------------------` ). out->write( `Example 4: Combination` ). out->write( `----------------------` ). TRY. result = numbers[ 2 / c_char ]. out->write( |Result: { result } | ). CATCH cx_sy_zerodivide. out->write( `Error: Division by zero is not defined` ). CATCH cx_sy_conversion_no_number. out->write( |Error: { c_char } is not a number! | ). CATCH cx_sy_itab_line_not_found. out->write( |Error: Itab contains less than { 2 / c_char } rows| ). ENDTRY.
  3. Appuyez sur CTRL + F3 pour activer la classe et SUR F9 pour l'exécuter en tant qu'application console.
  4. Analysez la sortie de la console. Jouez avec le code source pour vous familiariser avec le concept:
    • Commentez le traitement des exceptions pour signaler une erreur d'exécution.
    • Modifiez les valeurs des constantes c_number, c_text, c_index et c_charin de manière à ce qu'aucune exception ne soit déclenchée.

Itérations

Les itérations sont des structures de contrôle qui définissent un bloc de code qui est exécuté plusieurs fois.

La forme d'itération la plus simple consiste en un bloc de code entouré d'une paire d'instructions DO et ENDDO. Sans mesures supplémentaires, cela établit une boucle sans fin qui doit être évitée par l'une des possibilités suivantes :

Nombre indiqué d'itérations

En étendant l'instruction DO avec une expression entière suivie du mot-clé TIMES, vous pouvez indiquer explicitement la fréquence d'itération du bloc de code. L'expression entière peut être aussi simple que le littéral de nombre, mais aussi les calculs arithmétiques sont une option. Si la valeur de l'expression est égale à 0, le bloc de code entre DO et ENDDO n'est pas exécuté du tout et le programme continue immédiatement avec le code après ENDDO.

Interrompre sur la base d'une condition logique

Vous pouvez interrompre une itération à tout moment à l'aide de l'instruction EXIT. Le programme poursuit ensuite avec le code après ENDDO. Notez qu'en dehors des itérations, EXIT a un effet différent. Il y interrompt le traitement du bloc de traitement actuel, par exemple la méthode actuelle.

En règle générale, EXIT est entouré de IF et ENDIF pour interrompre l'itération en fonction d'une condition d'interruption. Sachez que de telles itérations peuvent se transformer en boucles infinies, si la condition d'interruption n'est jamais vraie.

Bien entendu, il est possible de combiner les deux techniques, c'est-à-dire de spécifier explicitement le nombre d'itérations, puis de laisser l'itération avec EXIT. Ainsi, le nombre d'itérations devient un nombre maximal qui peut ne pas être atteint au moment de l'exécution.

Basé sur une table interne

Un troisième type d'itération est la structure LOOP … ENDLOOP utilisée pour lire consécutivement les lignes d'une table interne. Ici, le nombre d'itérations est déterminé par le nombre de lignes dans la table interne.

Dans le bloc de code entre DO et ENDDO, vous pouvez implémenter des accès en lecture à l'objet de données ABAP intégré sy-index. Cette variable entière sert de compteur d'itération, c'est-à-dire que la durée d'exécution ABAP l'augmente d'un au début de chaque nouvelle itération.

En contradiction avec ce que vous pouvez utiliser à partir d'autres langages de programmation, sy-index commence par la valeur 1 lors de la première itération.

La variable intégrée ABAP sy-tabix peut remplir un objectif similaire pour les itérations avec LOOP. Mais sachez qu'à proprement parler sy-tabix n'est pas vraiment un compteur mais il identifie la position de la ligne de table qui est traitée dans l'itération courante. Par la suite, nous verrons la différence lorsque toutes les lignes d'une table interne ne sont pas traitées dans une structure LOOP … ENDLOOP.

Essayer : itérations

  1. Comme dans le premier exercice de ce cours, créez une nouvelle classe globale qui implémente l'interface IF_OO_ADT_CLASSRUN.
  2. Copiez l'extrait de code suivant dans la partie implémentation de la méthode if_oo_adt_classrun~main( ) :
    Code Snippet
    12345678910111213141516171819202122232425262728293031323334353637383940414243
    * Declarations ********************************************************************** CONSTANTS c_number TYPE i VALUE 3. * CONSTANTS c_number TYPE i VALUE 5. * CONSTANTS c_number TYPE i VALUE 10. DATA number TYPE i. * Example 1: DO ... ENDDO with TIMES ********************************************************************** out->write( `----------------------------------` ). out->write( `Example 1: DO ... ENDDO with TIMES` ). out->write( `----------------------------------` ). DO c_number TIMES. out->write( `Hello World` ). ENDDO. * Example 2: DO ... ENDDO with Abort Condition ********************************************************************** out->write( `-------------------------------` ). out->write( `Example 2: With Abort Condition` ). out->write( `-------------------------------` ). number = c_number * c_number. " count backwards from number to c_number. DO. out->write( |{ sy-index }: Value of number: { number }| ). number = number - 1. "abort condition IF number <= c_number. EXIT. ENDIF. ENDDO.
  3. Appuyez sur CTRL + F3 pour activer la classe et SUR F9 pour l'exécuter en tant qu'application console.
  4. Analysez la sortie de la console. Faites le tour du code source pour vous familiariser avec les concepts ; retirez les commentaires des différentes déclarations de constante c_number pour voir comment les différentes valeurs affectent le résultat.