Thursday, October 26, 2006

ALV List Display dinámico!


Seguramente, algunas vez le han pedido mostrar varios ALV's en una sola pantalla...Pues ahí es donde es útil el ALV_LIST_DISPLAY, que nos permite mostrar varias listas...El problema claro está, es que necesitamos una tabla interna por lista...Eso no está mal...Pero...Que pasa si no sabemos cuantas listas son??? Que pasa por ejemplo si por cada Líneas Aerea, debemos mostrar su detalle...Pues bueno...Con un poco de creatividad y tablas internas dinámicas -:D Podemos resolver el problema. ( Ojo: Solo funciona para 20 listas...Cosas de SAP -:( ).

Agradecimientos especiales a Nacho por su Macro para limpiar tablas internas -;)

El reporte quedería así -:)



Y su código es este:

************************************************************************
* INFORMACION GENERAL *
*-----------------------------------------------------------------------
* Nombre del programa: Z_DUMMY_TREE *
* Fecha/Autor: 26.08.2006 / Alvaro Tejada Galindo. *
************************************************************************
REPORT Z_DUMMY_TREE.

*----------------------------------------------------------------------*
* DECLARACION DE TYPE-POOLS *
*----------------------------------------------------------------------*
TYPE-POOLS: SLIS.

*----------------------------------------------------------------------*
* DECLARACION DE TABLAS *
*----------------------------------------------------------------------*
TABLES: SCARR, SPFLI.

*----------------------------------------------------------------------*
* VARIABLES *
*----------------------------------------------------------------------*
DATA: G_FIELDCAT TYPE SLIS_T_FIELDCAT_ALV,
G_SORT TYPE SLIS_T_SORTINFO_ALV WITH HEADER LINE,
GT_PRINT TYPE SLIS_PRINT_ALV,
GS_LAYOUT TYPE SLIS_LAYOUT_ALV,
GT_EVENTS TYPE SLIS_T_EVENT,
G_PROGRAM TYPE SY-REPID,
TAB_NAME TYPE STRING,
W_TABIX TYPE STRING,
G_LINES TYPE STRING.

*----------------------------------------------------------------------*
* TYPES *
*----------------------------------------------------------------------*
TYPES: BEGIN OF TY_SPFLI,
MANDT TYPE SPFLI-MANDT,
CARRID TYPE SPFLI-CARRID,
CONNID TYPE SPFLI-CONNID,
COUNTRYFR TYPE SPFLI-COUNTRYFR,
CITYFROM TYPE SPFLI-CITYFROM,
AIRPFROM TYPE SPFLI-AIRPFROM,
COUNTRYTO TYPE SPFLI-COUNTRYTO,
CITYTO TYPE SPFLI-CITYTO.
TYPES: END OF TY_SPFLI.

TYPES: BEGIN OF TY_STUFF,
TABNAME TYPE TABNAME,
TDREF TYPE REF TO DATA,
END OF TY_STUFF.

DATA T_STUFF TYPE TABLE OF TY_STUFF WITH NON-UNIQUE KEY TABNAME.

DATA: DESCR_STRUCT_REF TYPE REF TO CL_ABAP_STRUCTDESCR,
DATAREF TYPE REF TO DATA,
WA_FCAT TYPE LVC_S_FCAT,
IT_FIELDCATALOG TYPE LVC_T_FCAT.

*----------------------------------------------------------------------*
* FIELD-SYMBOLS *
*----------------------------------------------------------------------*
FIELD-SYMBOLS: <LINE> TYPE ANY,
<FIELD> TYPE ANY,
<COMPONENT> TYPE ABAP_COMPDESCR,
<DYN_TABLE> TYPE STANDARD TABLE,
<FS> TYPE ANY,
<DYN_WA>,
<TABLE>.

*----------------------------------------------------------------------*
* TABLAS INTERNAS *
*----------------------------------------------------------------------*
DATA: T_SPFLI TYPE STANDARD TABLE OF TY_SPFLI WITH HEADER LINE,
T_SPFLI_HEADER TYPE STANDARD TABLE OF TY_SPFLI WITH HEADER LINE,
T_SPFLI_DETAIL TYPE STANDARD TABLE OF TY_SPFLI WITH HEADER LINE.

*----------------------------------------------------------------------*
* MACROS *
*----------------------------------------------------------------------*
DEFINE LIMPIAR_TABLA.
CLEAR &1.
REFRESH &1.
END-OF-DEFINITION.

*----------------------------------------------------------------------*
* CRITERIOS DE SELECCIÓN *
*----------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK B01 WITH FRAME TITLE TEXT-B01.
SELECT-OPTIONS:
S_CARRID FOR SCARR-CARRID.
SELECTION-SCREEN END OF BLOCK B01.

*----------------------------------------------------------------------*
* PRINCIPAL
*----------------------------------------------------------------------*
START-OF-SELECTION.

PERFORM OBTENER_DATOS.
PERFORM GENERAR_ALV.
PERFORM GENERAR_ALV_LIST.

*---------------------------------------------------------------------*
* FORM OBTENER_DATOS *
*---------------------------------------------------------------------*
* Obtenemos los datos *
*---------------------------------------------------------------------*
FORM OBTENER_DATOS.

SELECT MANDT CARRID CONNID COUNTRYFR CITYFROM
AIRPFROM COUNTRYTO CITYTO
INTO TABLE T_SPFLI
FROM SPFLI
WHERE CARRID IN S_CARRID.

IF NOT T_SPFLI[] IS INITIAL.
T_SPFLI_HEADER[] = T_SPFLI[].
DELETE ADJACENT DUPLICATES FROM T_SPFLI_HEADER
COMPARING CARRID.
ENDIF.

ENDFORM.

*&---------------------------------------------------------------------*
*& Form GENERAR_ALV *
*&---------------------------------------------------------------------*
* Creamos el ALV *
*----------------------------------------------------------------------*
FORM GENERAR_ALV.

IF NOT T_SPFLI_HEADER[] IS INITIAL.
PERFORM FORMATEAR_DATOS_ALV USING G_FIELDCAT[].
PERFORM BUILD_SORT.
ENDIF.

ENDFORM. "GENERAR_ALV

*&---------------------------------------------------------------------*
*& Form FORMATEAR_DATOS_ALV *
*&---------------------------------------------------------------------*
* Establecemos el catalogo de ALV. *
*----------------------------------------------------------------------*
FORM FORMATEAR_DATOS_ALV USING T_FIELDCAT TYPE SLIS_T_FIELDCAT_ALV.

DATA: L_FIELDCAT TYPE SLIS_FIELDCAT_ALV.

CLEAR: T_FIELDCAT.
REFRESH: T_FIELDCAT.

CLEAR L_FIELDCAT.
L_FIELDCAT-TABNAME = 'T_SPFLI'.
L_FIELDCAT-FIELDNAME = 'CARRID'.
L_FIELDCAT-SELTEXT_L = 'Airline carrier ID'.
L_FIELDCAT-COL_POS = 1.
L_FIELDCAT-OUTPUTLEN = 15.
APPEND L_FIELDCAT TO T_FIELDCAT.

CLEAR L_FIELDCAT.
L_FIELDCAT-TABNAME = 'T_SPFLI'.
L_FIELDCAT-FIELDNAME = 'CONNID'.
L_FIELDCAT-SELTEXT_L = 'Flight connection Id'.
L_FIELDCAT-COL_POS = 2.
L_FIELDCAT-OUTPUTLEN = 15.
APPEND L_FIELDCAT TO T_FIELDCAT.

CLEAR L_FIELDCAT.
L_FIELDCAT-TABNAME = 'T_SPFLI'.
L_FIELDCAT-FIELDNAME = 'COUNTRYFR'.
L_FIELDCAT-SELTEXT_L = 'Country key'.
L_FIELDCAT-COL_POS = 3.
L_FIELDCAT-OUTPUTLEN = 15.
APPEND L_FIELDCAT TO T_FIELDCAT.

CLEAR L_FIELDCAT.
L_FIELDCAT-TABNAME = 'T_SPFLI'.
L_FIELDCAT-FIELDNAME = 'CITYFROM'.
L_FIELDCAT-SELTEXT_L = 'City of departure'.
L_FIELDCAT-COL_POS = 4.
L_FIELDCAT-OUTPUTLEN = 15.
APPEND L_FIELDCAT TO T_FIELDCAT.

CLEAR L_FIELDCAT.
L_FIELDCAT-TABNAME = 'T_SPFLI'.
L_FIELDCAT-FIELDNAME = 'AIRPFROM'.
L_FIELDCAT-SELTEXT_L = 'Airport of departure'.
L_FIELDCAT-COL_POS = 5.
L_FIELDCAT-OUTPUTLEN = 15.
APPEND L_FIELDCAT TO T_FIELDCAT.

CLEAR L_FIELDCAT.
L_FIELDCAT-TABNAME = 'T_SPFLI'.
L_FIELDCAT-FIELDNAME = 'COUNTRYTO'.
L_FIELDCAT-SELTEXT_L = 'Country key'.
L_FIELDCAT-COL_POS = 6.
L_FIELDCAT-OUTPUTLEN = 15.
APPEND L_FIELDCAT TO T_FIELDCAT.

CLEAR L_FIELDCAT.
L_FIELDCAT-TABNAME = 'T_SPFLI'.
L_FIELDCAT-FIELDNAME = 'CITYTO'.
L_FIELDCAT-SELTEXT_L = 'Arrival city'.
L_FIELDCAT-COL_POS = 7.
L_FIELDCAT-OUTPUTLEN = 15.
APPEND L_FIELDCAT TO T_FIELDCAT.

ENDFORM. "FORMATEAR_DATOS_ALV

*&---------------------------------------------------------------------*
*& Form BUILD_SORT
*&---------------------------------------------------------------------*
* Crea el ordenamiento del reporte
*----------------------------------------------------------------------*
FORM BUILD_SORT.

CLEAR G_SORT.

G_SORT-SPOS = 1.
G_SORT-FIELDNAME = 'CARRID'.
G_SORT-UP = 'X'.
APPEND G_SORT.

ENDFORM.

*---------------------------------------------------------------------*
* FORM CREAR_ALV_LIST *
*---------------------------------------------------------------------*
* ........ *
*---------------------------------------------------------------------*
FORM GENERAR_ALV_LIST.

DATA L_STUFF TYPE TY_STUFF.

G_PROGRAM = SY-REPID.

CALL FUNCTION 'REUSE_ALV_BLOCK_LIST_INIT'
EXPORTING
I_CALLBACK_PROGRAM = G_PROGRAM.

LOOP AT T_SPFLI_HEADER.
W_TABIX = SY-TABIX.
LIMPIAR_TABLA T_SPFLI_DETAIL.
LOOP AT T_SPFLI INTO T_SPFLI_DETAIL
WHERE CARRID EQ T_SPFLI_HEADER-CARRID.
APPEND T_SPFLI_DETAIL.
ENDLOOP.

CONCATENATE 'TABLE_' W_TABIX INTO
TAB_NAME.

PERFORM CREATE_TABLE USING 'SPFLI' TAB_NAME.

LOOP AT T_SPFLI_DETAIL ASSIGNING <LINE>.
G_LINES = <LINE>.
ASSIGN <DYN_WA> TO <TABLE>.
<TABLE> = G_LINES.
APPEND <DYN_WA> TO <DYN_TABLE>.
ENDLOOP.

PERFORM CREAR_ALV_LIST TABLES <DYN_TABLE>.

ENDLOOP.

CALL FUNCTION 'REUSE_ALV_BLOCK_LIST_DISPLAY'
EXPORTING
IS_PRINT = GT_PRINT.

ENDFORM.

*---------------------------------------------------------------------*
* FORM CREAR_ALV_LIST *
*---------------------------------------------------------------------*
* ........ *
*---------------------------------------------------------------------*
FORM CREAR_ALV_LIST TABLES T_TABLE STRUCTURE T_SPFLI_DETAIL.

CALL FUNCTION 'REUSE_ALV_BLOCK_LIST_APPEND'
EXPORTING
IT_FIELDCAT = G_FIELDCAT
IS_LAYOUT = GS_LAYOUT
I_TABNAME = 'T_SPFLI'
IT_EVENTS = GT_EVENTS
TABLES
T_OUTTAB = T_TABLE.

ENDFORM.

*---------------------------------------------------------------------*
* FORM CREATE_TABLE *
*---------------------------------------------------------------------*
* ........ *
*---------------------------------------------------------------------*
FORM CREATE_TABLE USING MY_TAB TAB_NAME.

DATA L_STUFF TYPE TY_STUFF.

CREATE DATA DATAREF TYPE (MY_TAB).

ASSIGN DATAREF->* TO <FS>.

DESCR_STRUCT_REF ?= CL_ABAP_TYPEDESCR=>DESCRIBE_BY_DATA( <FS> ).

LIMPIAR_TABLA IT_FIELDCATALOG.

LOOP AT DESCR_STRUCT_REF->COMPONENTS ASSIGNING <COMPONENT>.
WA_FCAT-FIELDNAME = <COMPONENT>-NAME.
WA_FCAT-REF_TABLE = MY_TAB.
WA_FCAT-REF_FIELD = <COMPONENT>-NAME.
APPEND WA_FCAT TO IT_FIELDCATALOG.
ENDLOOP.

CALL METHOD CL_ALV_TABLE_CREATE=>CREATE_DYNAMIC_TABLE
EXPORTING
IT_FIELDCATALOG = IT_FIELDCATALOG
IMPORTING
EP_TABLE = DATAREF
EXCEPTIONS
OTHERS = 1.

ASSIGN DATAREF->* TO <DYN_TABLE>.

L_STUFF-TABNAME = TAB_NAME.
CREATE DATA L_STUFF-TDREF LIKE LINE OF <DYN_TABLE>.
ASSIGN L_STUFF-TDREF->* TO <DYN_WA>.

ENDFORM. "CREATE_TABLE

Saludos,

Blag.

3 comments:

Anonymous said...

Hola Blag, estoy con un desarrollo que utiliza CL_ALV_TABLE_CREATE para crear tablas dinamicas, mi problema es que tengo que pasar mas de 36 veces por ahi y eso me genera un dump por excepcion. Conoces alguna manera de evitar esto ?
Mcuas gracias

Alvaro "Blag" Tejada Galindo said...

Hola Martin:

Lastimosamente no...Como menciono en mi post, el límite para la creación dinámica de listas en ALV era de 20...Revisando el include LSKBHF06 de la clase que me indicas, encontré este código...


catch system-exceptions generate_subpool_dir_full = 9.
generate subroutine pool lt_source name l_name
message l_message line l_line word l_word.
endcatch.
case sy-subrc.
when 0.
when 9.
raise generate_subpool_dir_full.
when others.
message x000(0k) with l_message l_line l_word.
endcase.


Lo cual significa que si llenas el subpool con tablas generadas dinámicamente, el programa se va a caer...No se cuanto sea el límite...Asumo que debe seguir siendo 20...

Espero que SAP corrija esto en algún momento...

Saludos,

Blag.

Anonymous said...

La excepcion dice mas de 36, ahora estoy tratando de hacer un submit and return, pero me encuentro con la limitacion de los parametros. Envio el fieldcatalg por export a memoria, pero no puedo hacer un export de la tabla del tipo type ref to data. Trate exportando el field symbol pero en mi programa cuando hago el import de memoria desde mmi programa principal obtengo dump o por problema de tipo o por falta de asignacion al field symbol ... =( te muestro algo del codigo que estuve probando.

Desde ya mil gracias !!

pd.- fs_* son field symbols ..

****************************
ASSIGN fs_item TO fs_table.

EXPORT p_t_fcat TO SHARED MEMORY indx(st) ID '1234'.
SUBMIT ysacar AND RETURN.
IMPORT fs_table FROM SHARED MEMORY indx(st) ID 'ABCD'.

REPORT ysacar.

DATA: t_tabla_dyn TYPE REF TO data,
p_t_fcat TYPE lvc_t_fcat
.
FIELD-SYMBOLS: fs_table TYPE STANDARD TABLE.

IMPORT p_t_fcat FROM SHARED MEMORY indx(st) ID '1234'. "Armar ID unico.

CHECK sy-subrc EQ 0.

FREE MEMORY ID '1234'.

CALL METHOD cl_alv_table_create=>create_dynamic_table
EXPORTING
* i_style_table = space
it_fieldcatalog = p_t_fcat
IMPORTING
ep_table = t_tabla_dyn
EXCEPTIONS
generate_subpool_dir_full = 1
OTHERS = 2.

IF sy-subrc EQ 0.
ASSIGN t_tabla_dyn->* TO fs_table.
* EXPORT t_tabla_dyn TO SHARED MEMORY indx(st) ID 'ABCD'.

EXPORT fs_table TO SHARED MEMORY indx(st) ID 'ABCD'.
ENDIF.