User Tools

Site Tools


abap:dynamic_programming

Programmation dynamique

La programmation dynamique en ABAP est un art particulier qui requiert acrobaties et équilibrismes…

Les field-symbols

Note : les field-symbols ont été en grande partie remplacés par les références (les fs sont la précédente génération). Une référence permet de faire tout ce que fait un fs et d'autres choses encore.

L'élément central de la programmation dynamique : les field-symbols.

/!\ Ne pas tenter de manipuler un field-symbol non assigné, sinon gare au GETWA_NOT_ASSIGNED ! /!\

Déclaration

  FIELD-SYMBOLS : <et_plip> TYPE STANDARD TABLE, " Table
                  <ls_plop> TYPE any, " Whatever
                  <fs1>. "Whatever, short form...

Assignation

ASSIGN ls_plop TO <ls_plop>. "Var
ASSIGN (ls_plop) TO <fs1>. "Content of var. ie. if ls_foo-bar = '1234' ; ls_plop = 'ls_foo-bar' then <fs1> = '1234'.
ASSIGN et_plip[] TO <et_plip>[]. "Table content

Références

Déclaration

DATA wldv_val TYPE REF TO i. "Déclaration typée
DATA wldv_val TYPE REF TO data. "Sans type
DATA wldv_val TYPE REF TO cl_gui_alv_grid. "Type objet

Référencement/déréférencement

GET REFERENCE OF wlv_val INTO wldv_val. "Référencement
wldv_val->* = wlv_val2. "Déréférencement

Différences avec les field-symbols

  • Un fs peut être assigné dynamiquement sans connaitre le nom de la variable / Une référence peut être instanciée sans connaitre le type de la variable (et a fortiori son nom).
  • Un fs ne peut référencer qu'une variable vivant dans le scope du programme. Une référence peut référencer une variable dans l'ABAP memory (et donc être transmis lors des appels de méthode, par exemple).

Typage dynamique

Au delà de l'assignation de field-symbols depuis des sources instanciées et typées (même si le type peut ne pas être connu à l'avance), il faut aussi parfois pouvoir manipuler des données qui vont être crées lors de l'exécution et dont le type est inconnu à l'avance. Pour cela il va falloir recourir à des commandes particulières et à des fonctions qui vont puiser des informations directement auprès du kernel (autrefois des FM ALV, aujourd'hui des classes dédiées).

Typage par comparaison

DATA: dy_line  TYPE REF TO data.
 
CREATE DATA dy_line LIKE LINE OF <et_plip>.
ASSIGN dy_line->* TO <les_plop>.

Jouer avec les composants d'une structure

Quelques classes utiles :

  • cl_abap_tabledescr
  • cl_abap_structdescr
  • cl_abap_typedescr

Exemple pratique : un MOVE-CORRESPONDING dynamique (agnostique sur la structure d'entrée comme de sortie) !

DATA:  ls_line TYPE abap_compdescr.
  REFRESH <et_plip>.
  LOOP AT lit_ausp ASSIGNING <ls_ausp>.
    " Get output structure components
    descr_ref ?= cl_abap_typedescr=>describe_by_data( <ls_ausp> ).
    LOOP AT  descr_ref->components INTO ls_line.
      ASSIGN COMPONENT ls_line-name OF STRUCTURE <ls_ausp> TO <fs1>.
      IF sy-subrc NE 0.
        EXIT.
      ENDIF.
      ASSIGN COMPONENT ls_line-name OF STRUCTURE <ls_plop> TO <fs2>.
      IF sy-subrc = 0.
        <fs2> = <fs1>.
      ENDIF.
    ENDLOOP.
    APPEND <ls_plop> TO <et_plip>.
  ENDLOOP.

NB : il est évidemment possible d'enrichir ce code avec des fonctionnalités pour par exemple ne pas transporter les champs vides de la structure 1 vers la 2 ou encore faire des transcos au passage…

NB2 : Si la classe cl_abap_typedescr n'est pas dispo, zieuter vers GET_COMPONENT_LIST et GET_GLOBAL_SYMBOLS.

Créer une itab ex nihilo

Sauce

    METHOD create_data.
        DATA:
          lo_structdescr         TYPE REF TO cl_abap_structdescr,
          lo_typedescr           TYPE REF TO cl_abap_typedescr,
          lo_tabledescr          TYPE REF TO cl_abap_tabledescr,
          lt_lvc_scol            TYPE lvc_t_scol,
          lt_lvc_styl            TYPE lvc_t_styl,
          lt_comp_all            TYPE cl_abap_structdescr=>component_table.
        FIELD-SYMBOLS:
          <component>            TYPE LINE OF abap_component_tab.
 
        APPEND INITIAL LINE TO lt_comp_all ASSIGNING <component>.
        <component>-type ?= cl_abap_datadescr=>describe_by_data( lt_lvc_styl ).
        <component>-name = lc_fieldname_t_styl.
 
        APPEND INITIAL LINE TO lt_comp_all ASSIGNING <component>.
        <component>-type ?= cl_abap_datadescr=>describe_by_data( lt_lvc_scol ).
        <component>-name = lc_fieldname_t_color.
 
    * create structure description
        lo_structdescr = cl_abap_structdescr=>create( lt_comp_all ).
 
    * create table description for structure
        lo_tabledescr = cl_abap_tabledescr=>create(
                        p_line_type  = lo_structdescr
                        p_table_kind = cl_abap_tabledescr=>tablekind_std
                        p_unique     = abap_false ).
 
    * create data object
        CREATE DATA rr_dispodata TYPE HANDLE lo_tabledescr.
 
      ENDMETHOD.

Exemples

Select dans table dynamique

abap/dynamic_programming.txt · Last modified: 2017/08/01 17:31 by ginko