====== 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 : TYPE STANDARD TABLE, " Table
TYPE any, " Whatever
. "Whatever, short form...
==== Assignation ====
ASSIGN ls_plop TO . "Var
ASSIGN (ls_plop) TO . "Content of var. ie. if ls_foo-bar = '1234' ; ls_plop = 'ls_foo-bar' then = '1234'.
ASSIGN et_plip[] TO []. "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 **[[https://ginkobox.fr/work/wiki/doku.php?id=abap:memory#memoire_vive|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 .
ASSIGN dy_line->* TO .
==== 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 .
LOOP AT lit_ausp ASSIGNING .
" Get output structure components
descr_ref ?= cl_abap_typedescr=>describe_by_data( ).
LOOP AT descr_ref->components INTO ls_line.
ASSIGN COMPONENT ls_line-name OF STRUCTURE TO .
IF sy-subrc NE 0.
EXIT.
ENDIF.
ASSIGN COMPONENT ls_line-name OF STRUCTURE TO .
IF sy-subrc = 0.
= .
ENDIF.
ENDLOOP.
APPEND TO .
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 ====
[[https://wiki.scn.sap.com/wiki/display/Snippets/Steps+to+Create+Type+Dynamically|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:
TYPE LINE OF abap_component_tab.
APPEND INITIAL LINE TO lt_comp_all ASSIGNING .
-type ?= cl_abap_datadescr=>describe_by_data( lt_lvc_styl ).
-name = lc_fieldname_t_styl.
APPEND INITIAL LINE TO lt_comp_all ASSIGNING .
-type ?= cl_abap_datadescr=>describe_by_data( lt_lvc_scol ).
-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 ====
[[http://wiki.scn.sap.com/wiki/display/ABAP/Dynamic+Internal+table?original_fqdn=wiki.sdn.sap.com]]