ABAP ALV avec CL_SALV_TABLE : Affichage de tables moderne

Catégorie
ABAP-Statements
Publié
Auteur
Johannes

CL_SALV_TABLE est l’API orientée objet moderne pour ALV (ABAP List Viewer). Elle remplace les anciens modules de fonctions (REUSE_ALV_*) et offre une interface propre et typée pour l’affichage de tables.

Structure de base

DATA: lo_alv TYPE REF TO cl_salv_table.
TRY.
" Créer ALV
cl_salv_table=>factory(
IMPORTING r_salv_table = lo_alv
CHANGING t_table = lt_data
).
" Configuration...
" Afficher
lo_alv->display( ).
CATCH cx_salv_msg INTO DATA(lx_error).
WRITE: / lx_error->get_text( ).
ENDTRY.

Exemples

1. Affichage ALV le plus simple

REPORT z_alv_simple.
TYPES: BEGIN OF ty_customer,
id TYPE i,
name TYPE string,
city TYPE string,
END OF ty_customer.
DATA: lt_customers TYPE TABLE OF ty_customer,
lo_alv TYPE REF TO cl_salv_table.
" Données de test
lt_customers = VALUE #(
( id = 1 name = 'Müller GmbH' city = 'Berlin' )
( id = 2 name = 'Schmidt AG' city = 'München' )
( id = 3 name = 'Weber KG' city = 'Hamburg' )
).
TRY.
cl_salv_table=>factory(
IMPORTING r_salv_table = lo_alv
CHANGING t_table = lt_customers
).
lo_alv->display( ).
CATCH cx_salv_msg.
ENDTRY.

2. Configurer les colonnes

DATA: lo_columns TYPE REF TO cl_salv_columns_table,
lo_column TYPE REF TO cl_salv_column.
TRY.
cl_salv_table=>factory(
IMPORTING r_salv_table = lo_alv
CHANGING t_table = lt_customers
).
" Obtenir l'objet colonnes
lo_columns = lo_alv->get_columns( ).
" Optimiser la largeur des colonnes
lo_columns->set_optimize( abap_true ).
" Configurer une colonne individuelle
lo_column = lo_columns->get_column( 'ID' ).
lo_column->set_short_text( 'ID' ).
lo_column->set_medium_text( 'Kunden-ID' ).
lo_column->set_long_text( 'Kundennummer' ).
lo_column->set_output_length( 10 ).
lo_column = lo_columns->get_column( 'NAME' ).
lo_column->set_long_text( 'Kundenname' ).
lo_column = lo_columns->get_column( 'CITY' ).
lo_column->set_long_text( 'Stadt' ).
lo_alv->display( ).
CATCH cx_salv_not_found cx_salv_msg.
ENDTRY.

3. Masquer une colonne

TRY.
lo_column = lo_columns->get_column( 'INTERNAL_FIELD' ).
lo_column->set_visible( abap_false ).
CATCH cx_salv_not_found.
ENDTRY.

4. Activer la barre d’outils

DATA: lo_functions TYPE REF TO cl_salv_functions_list.
" Activer toutes les fonctions standard
lo_functions = lo_alv->get_functions( ).
lo_functions->set_all( abap_true ).
" Ou des fonctions individuelles
lo_functions->set_export_xml( abap_true ).
lo_functions->set_export_spreadsheet( abap_true ).
lo_functions->set_print( abap_true ).
lo_functions->set_find( abap_true ).
lo_functions->set_aggregation( abap_true ).
lo_functions->set_filter( abap_true ).
lo_functions->set_sort_asc( abap_true ).
lo_functions->set_sort_desc( abap_true ).

5. Définir un tri

DATA: lo_sorts TYPE REF TO cl_salv_sorts.
lo_sorts = lo_alv->get_sorts( ).
TRY.
" Trier par ville (croissant)
lo_sorts->add_sort(
columnname = 'CITY"
position = 1
sequence = if_salv_c_sort=>sort_up
).
" Deuxième tri par nom
lo_sorts->add_sort(
columnname = 'NAME"
position = 2
sequence = if_salv_c_sort=>sort_up
).
CATCH cx_salv_not_found cx_salv_existing cx_salv_data_error.
ENDTRY.

6. Définir un filtre

DATA: lo_filters TYPE REF TO cl_salv_filters.
lo_filters = lo_alv->get_filters( ).
TRY.
" Filtrer par ville
lo_filters->add_filter(
columnname = 'CITY"
sign = 'I"
option = 'EQ"
low = 'Berlin"
).
CATCH cx_salv_not_found cx_salv_existing cx_salv_data_error.
ENDTRY.

7. Agrégation (Totaux)

DATA: lo_aggregations TYPE REF TO cl_salv_aggregations.
lo_aggregations = lo_alv->get_aggregations( ).
TRY.
" Total pour la colonne montant
lo_aggregations->add_aggregation(
columnname = 'AMOUNT"
aggregation = if_salv_c_aggregation=>total
).
" Moyenne
lo_aggregations->add_aggregation(
columnname = 'QUANTITY"
aggregation = if_salv_c_aggregation=>average
).
CATCH cx_salv_not_found cx_salv_existing cx_salv_data_error.
ENDTRY.

8. Bandes zébrées et mise en page

DATA: lo_display TYPE REF TO cl_salv_display_settings.
lo_display = lo_alv->get_display_settings( ).
" Motif zébré (couleurs de lignes alternées)
lo_display->set_striped_pattern( abap_true ).
" Définir le titre
lo_display->set_list_header( 'Kundenliste' ).
" Lignes horizontales
lo_display->set_horizontal_lines( abap_true ).
" Lignes verticales
lo_display->set_vertical_lines( abap_true ).

9. Gérer les événements (Double-clic)

" Classe gestionnaire d'événements
CLASS lcl_event_handler DEFINITION.
PUBLIC SECTION.
METHODS: on_double_click
FOR EVENT double_click OF cl_salv_events_table
IMPORTING row column.
METHODS: on_link_click
FOR EVENT link_click OF cl_salv_events_table
IMPORTING row column.
ENDCLASS.
CLASS lcl_event_handler IMPLEMENTATION.
METHOD on_double_click.
" Lire les données
READ TABLE lt_customers INTO DATA(ls_cust) INDEX row.
IF sy-subrc = 0.
MESSAGE |Doppelklick auf { ls_cust-name }| TYPE 'I'.
ENDIF.
ENDMETHOD.
METHOD on_link_click.
MESSAGE |Link geklickt: Zeile { row }, Spalte { column }| TYPE 'I'.
ENDMETHOD.
ENDCLASS.
" Programme principal
DATA: lo_events TYPE REF TO cl_salv_events_table,
lo_handler TYPE REF TO lcl_event_handler.
TRY.
cl_salv_table=>factory(
IMPORTING r_salv_table = lo_alv
CHANGING t_table = lt_customers
).
" Enregistrer le gestionnaire d'événements
lo_events = lo_alv->get_event( ).
lo_handler = NEW #( ).
SET HANDLER lo_handler->on_double_click FOR lo_events.
SET HANDLER lo_handler->on_link_click FOR lo_events.
lo_alv->display( ).
CATCH cx_salv_msg.
ENDTRY.

10. Hotspot (Cellules cliquables)

TRY.
lo_column = lo_columns->get_column( 'ID' ).
" Marquer la colonne comme hotspot (lien)
lo_column->set_cell_type( if_salv_c_cell_type=>hotspot ).
CATCH cx_salv_not_found.
ENDTRY.

11. Définir les couleurs

TYPES: BEGIN OF ty_colored_line,
id TYPE i,
name TYPE string,
status TYPE c LENGTH 1,
t_color TYPE lvc_t_scol, " Informations de couleur
END OF ty_colored_line.
DATA: lt_data TYPE TABLE OF ty_colored_line,
ls_color TYPE lvc_s_scol.
" Remplir les données avec des couleurs
lt_data = VALUE #(
( id = 1 name = 'OK' status = 'G' )
( id = 2 name = 'Error' status = 'R' )
( id = 3 name = 'Warning' status = 'Y' )
).
" Définir les couleurs
LOOP AT lt_data ASSIGNING FIELD-SYMBOL(<ls_line>).
CLEAR ls_color.
ls_color-fname = 'STATUS'.
CASE <ls_line>-status.
WHEN 'G'.
ls_color-color-col = col_positive. " Vert
WHEN 'R'.
ls_color-color-col = col_negative. " Rouge
WHEN 'Y'.
ls_color-color-col = col_total. " Jaune
ENDCASE.
APPEND ls_color TO <ls_line>-t_color.
ENDLOOP.
" ALV avec couleurs
TRY.
cl_salv_table=>factory(
IMPORTING r_salv_table = lo_alv
CHANGING t_table = lt_data
).
" Assigner la colonne de couleur
lo_columns = lo_alv->get_columns( ).
lo_columns->set_color_column( 'T_COLOR' ).
" Masquer la colonne de couleur
lo_column = lo_columns->get_column( 'T_COLOR' ).
lo_column->set_visible( abap_false ).
lo_alv->display( ).
CATCH cx_salv_not_found cx_salv_msg.
ENDTRY.

12. Sauvegarder/Charger la mise en page

DATA: lo_layout TYPE REF TO cl_salv_layout,
ls_key TYPE salv_s_layout_key.
" Définir la clé de mise en page
ls_key-report = sy-repid.
lo_layout = lo_alv->get_layout( ).
lo_layout->set_key( ls_key ).
" L'utilisateur peut sauvegarder la mise en page
lo_layout->set_save_restriction( if_salv_c_layout=>restrict_none ).
" Mise en page par défaut
lo_layout->set_default( abap_true ).

13. Ajouter des boutons personnalisés

" Possible uniquement en mode plein écran !
DATA: lo_functions TYPE REF TO cl_salv_functions.
" Définir le GUI Status (pour les boutons personnalisés)
lo_alv->set_screen_status(
pfstatus = 'ZSTATUS"
report = sy-repid
set_functions = lo_alv->c_functions_all
).
" Gestionnaire d'événements pour les commandes utilisateur
CLASS lcl_handler DEFINITION.
PUBLIC SECTION.
METHODS: on_user_command
FOR EVENT added_function OF cl_salv_events
IMPORTING e_salv_function.
ENDCLASS.
CLASS lcl_handler IMPLEMENTATION.
METHOD on_user_command.
CASE e_salv_function.
WHEN 'ZREFRESH'.
" Actualiser les données
refresh_data( ).
lo_alv->refresh( ).
WHEN 'ZEXPORT'.
" Export personnalisé
export_data( ).
ENDCASE.
ENDMETHOD.
ENDCLASS.
" Enregistrer le gestionnaire
DATA: lo_events TYPE REF TO cl_salv_events.
lo_events = lo_alv->get_event( ).
SET HANDLER lo_handler->on_user_command FOR lo_events.

14. ALV dans un conteneur (Screen)

" Pour la programmation d'écran
DATA: lo_container TYPE REF TO cl_gui_custom_container.
" Créer un conteneur (dans l'écran : Custom Control 'CC_ALV')
lo_container = NEW #( container_name = 'CC_ALV' ).
TRY.
" ALV dans le conteneur
cl_salv_table=>factory(
EXPORTING r_container = lo_container
IMPORTING r_salv_table = lo_alv
CHANGING t_table = lt_data
).
" Configuration...
lo_alv->display( ).
CATCH cx_salv_msg.
ENDTRY.

15. Actualiser les données (Refresh)

" Les données ont été modifiées
lt_customers = VALUE #(
( id = 1 name = 'Neu' city = 'Berlin' )
( id = 2 name = 'Aktualisiert' city = 'München' )
).
" Actualiser l'ALV
lo_alv->refresh( ).
" Avec conservation de la position de défilement
lo_alv->refresh(
s_stable = VALUE lvc_s_stbl( row = abap_true col = abap_true )
).

16. ALV éditable

" Malheureusement pas directement possible avec CL_SALV_TABLE !
" Pour ALV éditable : utiliser CL_GUI_ALV_GRID
" Solution de contournement : lire les données de la table après affichage
" (La table a été passée en tant que CHANGING)

17. Fonctions d’export

DATA: lo_functions TYPE REF TO cl_salv_functions_list.
lo_functions = lo_alv->get_functions( ).
" Activer l'export Excel
lo_functions->set_export_spreadsheet( abap_true ).
" Export XML
lo_functions->set_export_xml( abap_true ).
" Toutes les options d'export
lo_functions->set_group_export( abap_true ).

18. Exemple complet

REPORT z_alv_complete.
TYPES: BEGIN OF ty_order,
order_id TYPE i,
customer TYPE string,
amount TYPE p DECIMALS 2,
currency TYPE waers,
order_date TYPE d,
status TYPE c LENGTH 1,
END OF ty_order.
DATA: lt_orders TYPE TABLE OF ty_order,
lo_alv TYPE REF TO cl_salv_table.
CLASS lcl_handler DEFINITION.
PUBLIC SECTION.
METHODS: on_double_click
FOR EVENT double_click OF cl_salv_events_table
IMPORTING row column.
ENDCLASS.
CLASS lcl_handler IMPLEMENTATION.
METHOD on_double_click.
READ TABLE lt_orders INTO DATA(ls_order) INDEX row.
IF sy-subrc = 0.
MESSAGE |Bestellung { ls_order-order_id }: { ls_order-amount } { ls_order-currency }| TYPE 'I'.
ENDIF.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
" Données de test
lt_orders = VALUE #(
( order_id = 1001 customer = 'Müller' amount = '1500.00' currency = 'EUR' order_date = '20241101' status = 'A' )
( order_id = 1002 customer = 'Schmidt' amount = '2300.50' currency = 'EUR' order_date = '20241105' status = 'A' )
( order_id = 1003 customer = 'Weber' amount = '890.00' currency = 'EUR' order_date = '20241110' status = 'O' )
( order_id = 1004 customer = 'Bauer' amount = '3200.00' currency = 'EUR' order_date = '20241112' status = 'A' )
( order_id = 1005 customer = 'Klein' amount = '450.75' currency = 'EUR' order_date = '20241115' status = 'X' )
).
TRY.
" Créer ALV
cl_salv_table=>factory(
IMPORTING r_salv_table = lo_alv
CHANGING t_table = lt_orders
).
" Activer la barre d'outils
DATA(lo_functions) = lo_alv->get_functions( ).
lo_functions->set_all( abap_true ).
" Configurer les colonnes
DATA(lo_columns) = lo_alv->get_columns( ).
lo_columns->set_optimize( abap_true ).
DATA(lo_col_id) = lo_columns->get_column( 'ORDER_ID' ).
lo_col_id->set_long_text( 'Bestellnummer' ).
lo_col_id->set_cell_type( if_salv_c_cell_type=>hotspot ).
DATA(lo_col_cust) = lo_columns->get_column( 'CUSTOMER' ).
lo_col_cust->set_long_text( 'Kunde' ).
DATA(lo_col_amt) = lo_columns->get_column( 'AMOUNT' ).
lo_col_amt->set_long_text( 'Betrag' ).
DATA(lo_col_date) = lo_columns->get_column( 'ORDER_DATE' ).
lo_col_date->set_long_text( 'Bestelldatum' ).
" Total pour le montant
DATA(lo_agg) = lo_alv->get_aggregations( ).
lo_agg->add_aggregation( columnname = 'AMOUNT' aggregation = if_salv_c_aggregation=>total ).
" Tri
DATA(lo_sorts) = lo_alv->get_sorts( ).
lo_sorts->add_sort( columnname = 'ORDER_DATE' sequence = if_salv_c_sort=>sort_down ).
" Paramètres d'affichage
DATA(lo_display) = lo_alv->get_display_settings( ).
lo_display->set_striped_pattern( abap_true ).
lo_display->set_list_header( 'Bestellübersicht' ).
" Événements
DATA(lo_events) = lo_alv->get_event( ).
DATA(lo_handler) = NEW lcl_handler( ).
SET HANDLER lo_handler->on_double_click FOR lo_events.
" Afficher
lo_alv->display( ).
CATCH cx_salv_msg cx_salv_not_found cx_salv_existing cx_salv_data_error INTO DATA(lx_error).
WRITE: / lx_error->get_text( ).
ENDTRY.

Classes importantes

ClasseDescription
CL_SALV_TABLEClasse ALV principale
CL_SALV_COLUMNS_TABLECollection de colonnes
CL_SALV_COLUMNColonne individuelle
CL_SALV_FUNCTIONS_LISTFonctions de barre d’outils
CL_SALV_DISPLAY_SETTINGSParamètres d’affichage
CL_SALV_SORTSTris
CL_SALV_FILTERSFiltres
CL_SALV_AGGREGATIONSAgrégations
CL_SALV_EVENTS_TABLEGestion des événements
CL_SALV_LAYOUTGestion de la mise en page

Remarques importantes / Bonnes pratiques

  • CL_SALV_TABLE est l’API ALV moderne – préférez-la à REUSE_ALV*.
  • factory() crée l’objet ALV – CHANGING pour la table de données.
  • Optimisation des colonnes avec set_optimize( abap_true ) pour les largeurs automatiques.
  • Barre d’outils avec get_functions( )->set_all( abap_true ) pour l’activer.
  • Événements à enregistrer via SET HANDLER.
  • Hotspots rendent les cellules cliquables (set_cell_type).
  • Couleurs nécessitent une colonne de couleur de type LVC_T_SCOL.
  • Éditable uniquement possible avec CL_GUI_ALV_GRID.
  • Conteneur à utiliser pour l’intégration d’écran.
  • Mise en page permet aux utilisateurs de sauvegarder leurs paramètres.