Para crear un ALV OO tenemos que crearnos una nueva DYNPRO y
dentro de esta insertar un “Custom
control”. Este control será el que contenga al ALV.
Definimos los objetos para el ALV y para el contenedor
* ALV Grid
DATA gref_alvgrid TYPE REF TO cl_gui_alv_grid.
* Contenedor ALV
DATA gref_ccontainer TYPE REF TO cl_gui_custom_container.
DATA gref_alvgrid TYPE REF TO cl_gui_alv_grid.
* Contenedor ALV
DATA gref_ccontainer TYPE REF TO cl_gui_custom_container.
Cuando queramos lanzar el ALV tenemos que hacer lo siguiente:
- Creamos el objeto contenedor. Tenemos que
pasarle el nombre que hemos dado al “Custom
control” de la Dynpro que hemos creado.
CREATE OBJECT gref_ccontainer
EXPORTING
container_name = gc_custom_control_name
EXCEPTIONS
cntl_error = 1
cntl_system_error = 2
create_error = 3
lifetime_error = 4
lifetime_dynpro_dynpro_link = 5
OTHERS = 6.
CREATE OBJECT gref_ccontainer
EXPORTING
container_name = gc_custom_control_name
EXCEPTIONS
cntl_error = 1
cntl_system_error = 2
create_error = 3
lifetime_error = 4
lifetime_dynpro_dynpro_link = 5
OTHERS = 6.
- Creamos el objeto del ALV. Tenemos que pasarle
el objeto contenedor que acabamos de crear.
CREATE OBJECT gref_alvgrid
EXPORTING
i_parent = gref_ccontainer
EXCEPTIONS
error_cntl_create = 1
error_cntl_init = 2
error_cntl_link = 3
error_dp_create = 4
OTHERS = 5.
CREATE OBJECT gref_alvgrid
EXPORTING
i_parent = gref_ccontainer
EXCEPTIONS
error_cntl_create = 1
error_cntl_init = 2
error_cntl_link = 3
error_dp_create = 4
OTHERS = 5.
Además de esto también debemos definir:
- Catálogo de campos
FORM preparar_catalogo_campos CHANGING po_fieldcat TYPE lvc_t_fcat.
DATA ls_fcat TYPE lvc_s_fcat .
CLEAR: po_fieldcat.
REFRESH: po_fieldcat.
* Indicador
CLEAR ls_fcat.
ls_fcat-col_pos = 1.
ls_fcat-coltext = 'Ind.'.
ls_fcat-fieldname = 'IND'.
ls_fcat-outputlen = 6.
ls_fcat-no_out = ' '.
ls_fcat-key = 'X'.
APPEND ls_fcat TO po_fieldcat.
* Status
CLEAR ls_fcat.
ls_fcat-col_pos = 2.
ls_fcat-coltext = 'Status'.
ls_fcat-fieldname = 'MSGNR'.
ls_fcat-outputlen = 6.
ls_fcat-no_out = ' '.
ls_fcat-key = 'X'.
APPEND ls_fcat TO po_fieldcat.
FORM preparar_catalogo_campos CHANGING po_fieldcat TYPE lvc_t_fcat.
DATA ls_fcat TYPE lvc_s_fcat .
CLEAR: po_fieldcat.
REFRESH: po_fieldcat.
* Indicador
CLEAR ls_fcat.
ls_fcat-col_pos = 1.
ls_fcat-coltext = 'Ind.'.
ls_fcat-fieldname = 'IND'.
ls_fcat-outputlen = 6.
ls_fcat-no_out = ' '.
ls_fcat-key = 'X'.
APPEND ls_fcat TO po_fieldcat.
* Status
CLEAR ls_fcat.
ls_fcat-col_pos = 2.
ls_fcat-coltext = 'Status'.
ls_fcat-fieldname = 'MSGNR'.
ls_fcat-outputlen = 6.
ls_fcat-no_out = ' '.
ls_fcat-key = 'X'.
APPEND ls_fcat TO po_fieldcat.
- Características
del layout
FORM preparar_salida CHANGING po_layout TYPE lvc_s_layo.
po_layout-grid_title = text-002.
* po_layout-smalltitle = gc_marca.
po_layout-stylefname = 'BOTON'.
po_layout-no_rowmark = 'X'.
*Los siguientes dos campos son necesarios si queremos definir estilos sobre las celdas
* po_layout-ctab_fname = 'CELLCOLORS'.
* po_layout-info_fname = 'ROWCOLOR'.
*El siguiente campo lo informaremos si queremos que las filas del ALV sean seleccionables
* po_layout-sel_mode = ''.
FORM preparar_salida CHANGING po_layout TYPE lvc_s_layo.
po_layout-grid_title = text-002.
* po_layout-smalltitle = gc_marca.
po_layout-stylefname = 'BOTON'.
po_layout-no_rowmark = 'X'.
*Los siguientes dos campos son necesarios si queremos definir estilos sobre las celdas
* po_layout-ctab_fname = 'CELLCOLORS'.
* po_layout-info_fname = 'ROWCOLOR'.
*El siguiente campo lo informaremos si queremos que las filas del ALV sean seleccionables
* po_layout-sel_mode = ''.
- Ordenación
FORM prepare_sort_table CHANGING pt_sort TYPE lvc_t_sort .
DATA ls_sort TYPE lvc_s_sort .
ls_sort-spos = '1' .
ls_sort-fieldname = 'ZZDOCUMENO' .
ls_sort-up = 'X' . "A to Z
ls_sort-down = space .
APPEND ls_sort TO pt_sort .
ls_sort-spos = '2' .
ls_sort-fieldname = 'ZZVERSION' .
ls_sort-up = space .
ls_sort-down = 'X' . "Z to A
APPEND ls_sort TO pt_sort .
FORM prepare_sort_table CHANGING pt_sort TYPE lvc_t_sort .
DATA ls_sort TYPE lvc_s_sort .
ls_sort-spos = '1' .
ls_sort-fieldname = 'ZZDOCUMENO' .
ls_sort-up = 'X' . "A to Z
ls_sort-down = space .
APPEND ls_sort TO pt_sort .
ls_sort-spos = '2' .
ls_sort-fieldname = 'ZZVERSION' .
ls_sort-up = space .
ls_sort-down = 'X' . "Z to A
APPEND ls_sort TO pt_sort .
Si queremos quitar botones estándar de la barra del ALV hay que indicárselo al ALV excluyendo esos
botones:
* Botones excluidos del ALV
APPEND cl_gui_alv_grid=>mc_fc_refresh TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_check TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_info TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_append_row TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_copy TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_copy_row TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_cut TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_delete_row TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_insert_row TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_move_row TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_paste TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_paste_new_row TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_undo TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_graph TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_refresh TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_check TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_info TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_append_row TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_copy TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_copy_row TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_cut TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_delete_row TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_insert_row TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_move_row TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_paste TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_paste_new_row TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_loc_undo TO lt_excl_func1.
APPEND cl_gui_alv_grid=>mc_fc_graph TO lt_excl_func1.
Por otro lado si lo que queremos es añadir botones (a los
que podamos dar funcionalidad) a la barra del ALV lo tenemos que hacer mediante
el evento “handle_toolbar”. Ademas
debemos indicar al ALV que la barra va a ser interactiva. Para esto llamamos al
método “CALL METHOD gref_alvgrid->set_toolbar_interactive.”
Para añadir los botones hacemos lo siguiente:
FORM handle_toolbar CHANGING p_e_object TYPE REF TO cl_alv_event_toolbar_set
p_e_interactive TYPE char01.
DATA gs_toolbar TYPE stb_button.
CLEAR gs_toolbar.
MOVE 'FICH' TO gs_toolbar-function.
MOVE icon_write_file TO gs_toolbar-icon.
MOVE 'Generar fichero' TO gs_toolbar-quickinfo.
MOVE 'Generar fichero' TO gs_toolbar-text.
MOVE ' ' TO gs_toolbar-disabled.
APPEND gs_toolbar TO p_e_object->mt_toolbar.
CLEAR gs_toolbar.
p_e_interactive TYPE char01.
DATA gs_toolbar TYPE stb_button.
CLEAR gs_toolbar.
MOVE 'FICH' TO gs_toolbar-function.
MOVE icon_write_file TO gs_toolbar-icon.
MOVE 'Generar fichero' TO gs_toolbar-quickinfo.
MOVE 'Generar fichero' TO gs_toolbar-text.
MOVE ' ' TO gs_toolbar-disabled.
APPEND gs_toolbar TO p_e_object->mt_toolbar.
CLEAR gs_toolbar.
Además de todo esto podemos añadir muchos eventos al ALV,
tantos como los que estén definidos en la clase CL_GUI_ALV_GRID.
En este ejemplo vamos a ver 5 (Uno de ellos es el handle_toolbar explicado en el apartado anterior):
En este ejemplo vamos a ver 5 (Uno de ellos es el handle_toolbar explicado en el apartado anterior):
- handle_user_command
FORM handle_user_command USING p_e_ucomm TYPE syucomm.
CASE p_e_ucomm .
WHEN 'FICH'.
PERFORM generar_fichero.
ENDCASE.
FORM handle_user_command USING p_e_ucomm TYPE syucomm.
CASE p_e_ucomm .
WHEN 'FICH'.
PERFORM generar_fichero.
ENDCASE.
- handle_double_click
FORM handle_double_click USING p_e_row TYPE lvc_s_row
p_e_column TYPE lvc_s_col
p_es_row_no TYPE lvc_s_roid.
READ TABLE t_lecturas INDEX p_es_row_no-row_id.
IF sy-subrc = 0.
CASE p_e_column-fieldname.
WHEN 'MATNR'.
SET PARAMETER ID 'MAT' FIELD t_lecturas-matnr.
CALL TRANSACTION 'MM03' AND SKIP FIRST SCREEN.
ENDCASE.
ENDIF.
FORM handle_double_click USING p_e_row TYPE lvc_s_row
p_e_column TYPE lvc_s_col
p_es_row_no TYPE lvc_s_roid.
READ TABLE t_lecturas INDEX p_es_row_no-row_id.
IF sy-subrc = 0.
CASE p_e_column-fieldname.
WHEN 'MATNR'.
SET PARAMETER ID 'MAT' FIELD t_lecturas-matnr.
CALL TRANSACTION 'MM03' AND SKIP FIRST SCREEN.
ENDCASE.
ENDIF.
-
handle_data_changed
FORM handle_data_changed USING p_er_data_changed TYPE REF TO cl_alv_changed_data_protocol.
DATA: line TYPE lvc_s_modi,
indice TYPE sy-tabix,
selected_row TYPE lvc_t_roid,
l_sel_row TYPE lvc_s_roid.
CLEAR: line,
indice.
READ TABLE p_er_data_changed->mt_mod_cells INTO line INDEX 1.
IF sy-subrc = 0.
indice = line-row_id.
IF indice IS NOT INITIAL.
REFRESH selected_row.
l_sel_row-row_id = indice.
APPEND l_sel_row TO selected_row.
* Seleccionamos la linea que ha sido modificada
CALL METHOD gref_alvgrid->set_selected_rows
EXPORTING
it_row_no = selected_row.
ENDIF.
ENDIF.
FORM handle_data_changed USING p_er_data_changed TYPE REF TO cl_alv_changed_data_protocol.
DATA: line TYPE lvc_s_modi,
indice TYPE sy-tabix,
selected_row TYPE lvc_t_roid,
l_sel_row TYPE lvc_s_roid.
CLEAR: line,
indice.
READ TABLE p_er_data_changed->mt_mod_cells INTO line INDEX 1.
IF sy-subrc = 0.
indice = line-row_id.
IF indice IS NOT INITIAL.
REFRESH selected_row.
l_sel_row-row_id = indice.
APPEND l_sel_row TO selected_row.
* Seleccionamos la linea que ha sido modificada
CALL METHOD gref_alvgrid->set_selected_rows
EXPORTING
it_row_no = selected_row.
ENDIF.
ENDIF.
- handle_click
FORM handle_click USING p_es_col_id TYPE lvc_s_col
p_es_row_no TYPE lvc_s_roid.
DATA: es_row_no TYPE lvc_s_roid,
es_row_info TYPE lvc_s_row,
es_col_info TYPE lvc_s_col.
CLEAR: es_row_no,
es_row_info,
es_col_info.
IF p_es_col_id = 'IND'.
PERFORM modificar_status USING p_es_row_no-row_id.
ENDIF.
FORM handle_click USING p_es_col_id TYPE lvc_s_col
p_es_row_no TYPE lvc_s_roid.
DATA: es_row_no TYPE lvc_s_roid,
es_row_info TYPE lvc_s_row,
es_col_info TYPE lvc_s_col.
CLEAR: es_row_no,
es_row_info,
es_col_info.
IF p_es_col_id = 'IND'.
PERFORM modificar_status USING p_es_row_no-row_id.
ENDIF.
Además para que el evento “handle_data_changed”
se dispare hay que llamar al método “register_edit_event”.
CALL METHOD gref_alvgrid->register_edit_event
EXPORTING
i_event_id = cl_gui_alv_grid=>mc_evt_modified.
CALL METHOD gref_alvgrid->register_edit_event
EXPORTING
i_event_id = cl_gui_alv_grid=>mc_evt_modified.
Finalmente para lanzar el ALV se debe hacer lo siguiente:
CALL METHOD gref_alvgrid->set_table_for_first_display
EXPORTING
is_layout = gs_layout
it_toolbar_excluding = lt_excl_func1
CHANGING
it_outtab = t_lecturas[]
it_fieldcatalog = gi_fieldcat
EXCEPTIONS
invalid_parameter_combination = 1
program_error = 2
too_many_lines = 3
OTHERS = 4.
CALL METHOD gref_alvgrid->set_table_for_first_display
EXPORTING
is_layout = gs_layout
it_toolbar_excluding = lt_excl_func1
CHANGING
it_outtab = t_lecturas[]
it_fieldcatalog = gi_fieldcat
EXCEPTIONS
invalid_parameter_combination = 1
program_error = 2
too_many_lines = 3
OTHERS = 4.
Si hemos modificado la tabla interna
que muestra el ALV y queremos que estos cambios se reflejen al ALV llamamos al
siguiente método:
* Refresca el ALV
CALL METHOD gref_alvgrid->refresh_table_display
EXCEPTIONS
finished = 1
OTHERS = 2.
CALL METHOD gref_alvgrid->refresh_table_display
EXCEPTIONS
finished = 1
OTHERS = 2.
Si al lanzar algún evento no queremos
que los scroll se nos inicialicen hacemos lo siguiente antes y después del código
que estemos ejecutando (Recuperamos la situación del scroll antes de ejecutar
nuestro código, y al finalizar nuestro código le indicamos cual queremos que
sea la situación del scroll):
CALL METHOD gref_alvgrid->get_scroll_info_via_id
IMPORTING
es_row_no = es_row_no
es_row_info = es_row_info
es_col_info = es_col_info.
IMPORTING
es_row_no = es_row_no
es_row_info = es_row_info
es_col_info = es_col_info.
Si queremos saber que líneas de la tabla
interna se están visualizando en pantalla y cuales no (por que se ha aplicado
algún filtro) llamamos al siguiente método:
CALL METHOD gref_alvgrid->get_filtered_entries
IMPORTING
et_filtered_entries = et_filtered_entries.
IMPORTING
et_filtered_entries = et_filtered_entries.
Si queremos dar a alguna columna
alguna apariencia diferente (por ejemplo de botón) hacemos lo siguiente:
- En la tabla interna que contiene los datos que
se muestran en el ALV definimos un nuevo campo de tipo LVC_T_STYL. Este campo
contendrá las características de cada fila.
- Despues al rellenar la tabla interna tendremos
que completar este nuevo campo. En este caso, en el que queremos darle la
apariencia de botón hacemos lo siguiente:
CLEAR ls_style.
ls_style-fieldname = 'IND'.
ls_style-style = cl_gui_alv_grid=>mc_style_button.
APPEND ls_style TO t_lecturas-boton.
CLEAR ls_style.
ls_style-fieldname = 'IND'.
ls_style-style = cl_gui_alv_grid=>mc_style_button.
APPEND ls_style TO t_lecturas-boton.
Con esto le estamos indicando que la columna “IND” va a tener la apariencia de
un botón.
Finalmente en la
definición del layout tenemos que indicarle que campo de nuestra tabla interna
es la que define las características de cada fila.po_layout-stylefname = 'BOTON'.
Si a tu código le vas a seguir metiendo sub-rutinas(form) entonces ya dejó de ser orientado a objetos porque las subrutinas han sido creadas para la programación estructurada, deberías crear y usar tus propios métodos(ya sean privados, públicos, protegidos o estáticos) y utilizarlos en vez de subrutinas. Buen post.
ResponderEliminarGracias por tu comentario!!Tienes razón en que el programa no es 100% orientado a objetos. Muchas veces en SAP este tipo de clases se utilizan dentro de programas estrucuturados, de ahí que veas los FORM. Yo casi siempre los he utilizado de esta forma, de ahí que en los ejemplos aparezcan los FORM. Tomo nota de tus comentarios. Gracias!!
EliminarLo que dicen ambos es cierto,en mi caso cuando utilizo clases locales siempre las mezclo con FORM, pero cuando creo clases globales no le meto ningun FORM, bye.
Eliminar