Académique Documents
Professionnel Documents
Culture Documents
Suite à un sujet lancé sur le forum pour savoir si la création d'une zone de texte multi-ligne sur un
dynpro était possible et si oui, comment? On m'a suggéré, fin Devenherbe devrais-je dire, d'écrire
un article avec tout ce que je savais afin d'aider ceux qui souhaiteraient mettre ce genre de
composants sur un écran.
Ce n'est qu'une succession de champs texte uni-ligne, mais ce n'est pas beau à l'écran et c'est un
peu ennuyant (pour être poli) à mettre en place car ce sont quatre champs texte qui portent des
noms différents et qu'il va falloir gérer individuellement... Je te laisse imaginer un peu la misère.
On peut voir facilement que c'est une zone de texte avec le "Hello World" qui j'ai écris à
l'intérieur et si tu es très observateur, tu remarqueras facilement que c'est le même type de
composant qui est utilisé pour l'éditeur ABAP (SE38 ou SE80) sur ECC5 en tout cas, je ne sais
pas si ça a changé sur ECC6, je le saurais lors d'une prochaine montée de version.
Alors de suite, il faut savoir que ce genre de composants ne peut être ajouté que sur un dynpro et
non sur un écran de sélection. Sur un écran de sélection, ce n'est pas possible et il n'a aucune utilité,
car comme son nom l'indique, un écran de sélection permet de renseigner des données pour
conditionner les requêtes sur les tables de la Base de Données principalement.
Je vais commencer par créer un programme de test, puis le dynpro et pour finir, le composant avec
quelques traitements qui permettront de le remplir et de récupérer le contenu.
Pour créer le programme, rien de compliqué, on lance soit la SE38 ou la SE80, on renseigne un nom
de programme commençant par 'Z' (ou 'Y', SAP oblige). De mon coté j'ai créé le programme
'ZTEST_TEXTEDIT', oui je suis très inspiré le soir quand l'heure de débaucher arrive.
Maintenant que mon programme est prêt, il ne me reste plus qu'à créer le dynpro, disons le dynpro
0100.
(Cette partie concerne la création d'un dynpro, pour ceux qui maitrisent cette
étape, passer à la partie suivante.)
Dans la logique d'exécution (Onglet "Log. exec." ) du dynpro tu devrais voir cela :
Code
PROCESS BEFORE OUTPUT.
* MODULE STATUS_0100.
*
PROCESS AFTER INPUT.
* MODULE USER_COMMAND_0100.
Au cas où tu n'aurais que peu, voire pas du tout, de connaissance dans les dynpros, je vais
t'expliquer en gros ce que signifient "PROCESS BEFORE OUTPUT" et "PROCESS AFTER
INPUT." car il faut comprendre cela pour savoir comment on va pouvoir gérer notre futur zone de
texte.
Le PROCESS BEFORE OUTPUT, communément appelé PBO, contiendra les Modules qui devront
être exécutés avant l'affichage de l'écran. Ici, il sera utile d'y insérer l'initialisation de nos
composants, mais nous y reviendront plus tard.
Le PROCESS AFTER INPUT., communément appelé PAI, contiendra quant à lui tout les Modules
qui devront s'exécuter suite à une action fait sur l'écran par l'utilisateur.
Il y a deux autres PROCESS qui existent, le POV (ON VALUE-REQUEST) et le POH (ON HELP-
REQUEST), mais ils ne nous concernent pas ici.
Commencer par décommenter l'appel du Module STATUS_0100 double cliquer dessus pour le
créer. Personnellement j'ai la fâcheuse (pour certains) manie de tout mettre dans un Include à
chaque type de Module donc je vais créer mon Module dans un Include ZTEST_TEXTEDIT_PBO
pour les Modules OUTPUT et ZTEST_TEXTEDIT_PAI pour les Modules INPUT.
Code
*&---------------------------------------------------------------------*
*& Module STATUS_0100 OUTPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE status_0100 OUTPUT.
SET PF-STATUS 'STATUS'.
* SET TITLEBAR 'xxx'.
En double cliquant sur STATUS, on confirme la création et on arrive sur un nouvel écran.
Il faut remplir au minimum les éléments comme ci-dessus. Puis de cliquer sur chaque icône pour
enfin choisir le type d'action à effectuer et on mettra le Type 'E' pour EXIT-COMMAND
On active le STATUS GUI et l'Include PBO et on revient dans la Log. exec.
Code
PROCESS BEFORE OUTPUT.
MODULE STATUS_0100.
*
PROCESS AFTER INPUT.
* MODULE USER_COMMAND_0100.
Le 'AT EXIT-COMMAND' permet de spécifier que le Module ne sera exécuté que lors d'une
commande pour quitter l'écran.
Code
*&---------------------------------------------------------------------*
*& Module M900_USER_EXIT INPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE m900_user_exit INPUT.
SET SCREEN 0.
LEAVE PROGRAM.
Pour ajouter une zone de texte sur un dynpro, il faut en fait ajouter un conteneur (comme pour les
ALV LVC si certains connaissent). Le composant est un "Custom Control".
Pour ajouter un "Custom Control", qui sera notre conteneur, faire comme suit:
Définir la fin du bloque pour le conteneur en sélectionnant l'endroit sur la zone de couleur (en rouge
pour moi) et cliquer sur 'Marquer fin contrôle'.
Et définir ses attributs, dont le nom du conteneur, pour moi c'est 'CONTAINER'
Et voilà notre composant placé.
On revient en arrière et c'est fini.
Une fois le composant placé, il apparaît comme ci-dessous sur le dynpro (dans l'éditeur, quand le
programme est lancé, rien n'apparait pour l'instant).
Une fois le composant placé, lui affecter un nom soit dans la barre du haut (qui devrait devenir
rouge si le conteneur est sélectionné soit en double-cliquant sur ce dernier pour faire apparaître la
fenêtre des attributs.
On lui donne un nom, pour moi c'est 'CONTAINER'. On enregistre et on active.
Maintenant, il va falloir dire dans notre programme que ce conteneur va servir à afficher une zone
de texte. Et c'est à partir de maintenant que l'on va rentrer dans du développement ABAP OO.
Comme toutes recettes de cuisines, il va nous falloir des ingrédients qu'on va placer dans notre
Include TOP.
Code
*&---------------------------------------------------------------------*
*& Include ZTEST_TEXTEDIT_TOP
*&
*&---------------------------------------------------------------------*
Alors, peut-être une instruction qui est nouvelle pour toi, c'est l'instruction TYPE REF TO. En fait
cette instruction permet de dire que cette variable sera une instance de classe, une instance doit être
comprise comme un objet image de la classe.
J'ai définit :
- une variable g_conteneur qui sera une instance de la classe CL_GUI_CUSTOM_CONTAINER,
cette variable, ou objet, va permettre de gérer notre conteneur placé sur le dynpro
- une variable g_editeur qui sera une instance de la classe CL_GUI_TEXTEDIT, cette variable sera
notre zone de texte.
- une structure de type TDLINE qui sera une ligne de notre zone de texte avec la table qui va avec.
- je n'aime pas trop les valeurs rentrées en dur dans un programme donc j'ai ajouté des variables
avec les valeurs souhaitées.
Revenons sur nos instances g_conteneur et g_editeur, pour l'instant elles ne sont pas utilisable...
Pourquoi ?? Tout simplement parce que cette simple déclaration ne suffit pas à créer des objets, il
va falloir également les initialiser avec des attributs. Par exemple, dire à g_conteneur qu'il va devoir
gérer le conteneur 'CONTAINER' du dynpro 0100 et dire à g_éditeur dans quel conteneur il va
devoir se placer.
En gros, je vais donner un exemple (avec la classe CL_GUI_TEXTEDIT) pour ceux qui sont
habitués à un langage proche du C#/Java.
La déclaration revient à faire :
CL_GUI_TEXTEDIT g_editeur;
Mais avec cette simple déclaration, g_editeur = null.
Pour initialiser un objet, on le fait à la déclaration ou plus tard dans le traitement comme ci-dessous:
CL_GUI_TEXTEDIT g_editeur = new CL_GUI_TEXTEDIT();
Ou
CL_GUI_TEXTEDIT g_editeur;
g_editeur = new CL_GUI_TEXTEDIT();
Pour initialiser un objet, il faut utiliser l'instruction CREATE OBJECT, qui revient à faire le new vu
au-dessus. Seulement cette instruction diffère d'un objet à un autre, pour ne pas se tromper, on a
meilleur temps de passer par les modèles ABAP (Ctrl + F6), dans la section 'Modèles
objets ABAP', on peut générer facilement cette instruction en passant par cet outil.
Je pense que tu auras deviné facilement que cette instruction est à placer dans le PBO. On va donc y
placer un nouveau Module.
Code
PROCESS BEFORE OUTPUT.
MODULE STATUS_0100.
MODULE m000_init_screen.
*
PROCESS AFTER INPUT.
* MODULE USER_COMMAND_0100.
*&---------------------------------------------------------------------*
*& Module M000_DYNP_INIT OUTPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE m000_dynp_init OUTPUT.
IF g_container IS INITIAL.
ENDIF.
ENDIF.
Note la présence des conditions IF. ENDIF. Pour tester si l'objet à déjà été instancié (créé). On ne va
pas réinitialiser l'objet avant chaque affichage de l'écran, surtout que l'objet vit après son
instanciation et donc ses attributs changent et on risquerait de les perdre. Donc on initialise l'objet
une seule fois.
Sinon pour g_conteneur, tu peux voir que je lui indique qu'il pointe vers le conteneur
'CONTAINER' du dynpro 100 du programme ZTEST_TEXTEDIT.
Et pour g_editeur, on lui dit que son 'parent' c'est à dire son composant père où il doit aller se placer
est l'objet g_conteneur pointant vers le composant de l'écran.
Code
*&---------------------------------------------------------------------*
*& Report ZTEST_TEXTEDIT
*&
*&---------------------------------------------------------------------*
*& Programme de test Zone de texte avec ligne multiple
*&
*&---------------------------------------------------------------------*
REPORT ztest_textedit.
START-OF-SELECTION.
On va mettre en place un traitement tout simple, mettre un texte par défaut dans la zone de texte au
lancement du programme. Et on va utiliser la méthode 'SET_TEXT_AS_R3TABLE'
Code
*&---------------------------------------------------------------------*
*& Module M100_FILL_CNT OUTPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE m100_fill_cnt OUTPUT.
CLEAR s_tdline.
REFRESH t_tdline.
Maintenant, si je te propose de récupérer le texte d'une zone de texte et de la mettre dans une autre
zone de texte.
Et après l'appui sur le bouton.
Pour cela j'ai crée un bouton avec le code fonction 'TRA' et un deuxième conteneur et donc j'ai crée
un g_conteneur2 et un g_editeur2.
La procédure est la même pour afficher la deuxième zone de texte à l'écran donc revenir au début de
cette partie si jamais.
Maintenant pour alimenter la deuxième zone de texte c'est en fait très simple, il existe une méthode
permettant de récupérer le texte. C'est 'GET_TEXT_AS_R3TABLE', je pense que c'était facile à
prévoir pour ceux dont les Getters et les Setters sont familiers.
Il va donc falloir capturer l'action faite sur le bouton et faire nos traitements.
On va donc rajouter le module USER_COMMAND_0100 dans le PAI du dynpro.
Code
*&---------------------------------------------------------------------*
*& Module USER_COMMAND_0100 INPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE user_command_0100 INPUT.
WHEN 'TRA'.
PERFORM f100_transfert.
WHEN OTHERS.
* Ne rien faire
ENDCASE. "sy-ucomm
Code
*&---------------------------------------------------------------------*
*& Form F100_TRANSFERT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM f100_transfert .
Je crois que ça suffira pour les bases sur les zones de texte multi-lignes et surtout ça prouve bien
que c'est possible. Mais il ne faut pas s'enflammer pour autant, ça reste un composant à utiliser
quand dans certains cas particuliers.
Tu peux également aller explorer la classe CL_GUI_TEXTEDIT par le biais de la transaction SE24
pour voir toutes les méthodes qui sont mises à notre disposition pour gérer la zone de texte.
Notamment tu peux enlever la barre d'outils et la barre de statut.
Voila.
Cordialement,
Celdrøn.
*&---------------------------------------------------------------------*
*& Report ZTEST_TEXTEDIT
*&
*&---------------------------------------------------------------------*
*& Programme de test Zone édition ligne multiple
*&
*&---------------------------------------------------------------------*
REPORT ztest_textedit.
*&---------------------------------------------------------------------*
*& Include ZTEST_TEXTEDIT_TOP
*&
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Include ZTEST_TEXTEDIT_PBO
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Module M000_DYNP_INIT OUTPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE m000_dynp_init OUTPUT.
*&---------------------------------------------------------------------*
*& Module M100_FILL_CNT OUTPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE m100_fill_cnt OUTPUT.
CLEAR s_tdline.
REFRESH t_tdline.
*&---------------------------------------------------------------------*
*& Module STATUS_0100 OUTPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE status_0100 OUTPUT.
SET PF-STATUS 'STATUS'.
* SET TITLEBAR 'xxx'.
*&---------------------------------------------------------------------*
*& Include ZTEST_TEXTEDIT_PAI
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Module M900_USER_EXIT INPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE m900_user_exit INPUT.
SET SCREEN 0.
LEAVE PROGRAM.
CASE sy-ucomm.
WHEN 'TRA'.
PERFORM f100_transfert.
WHEN OTHERS.
* Ne rien faire
ENDCASE.
*&---------------------------------------------------------------------*
*& Form F000_CREATE_N_INIT_TEXTEDIT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM f000_create_n_init_textedit USING p_container TYPE feld-name
p_conteneur LIKE g_conteneur
p_editeur LIKE g_editeur.
IF p_conteneur IS INITIAL.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
ENDIF.
ENDIF.
*&---------------------------------------------------------------------*
*& Form F100_TRANSFERT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM f100_transfert .
*&---------------------------------------------------------------------*
*& Logique d'exécution de l'écran 100.
*&---------------------------------------------------------------------*
PROCESS BEFORE OUTPUT.
MODULE status_0100.
MODULE m000_dynp_init.
* MODULE m100_fill_cnt.
*
PROCESS AFTER INPUT.
MODULE user_command_0100.