‎2005 Mar 04 11:57 AM
hello,
is there any chance to
extend a data structure at runtime?
normally you define a structure with
data: begin of x,
field1 type c,
field2 type n.
data: end of x.
this structure is the basis for your internal tables etc.
it would be definitely nice to add a third field at runtime if it is needed.
in other programming languages it would also be possible to add elements to an array. the question ist: how can i add fields to the structure dynamically?
it could be useful for a lot of situations.
dynamically generated fieldcatalogue for example.
i think i could succeed in changing the structure by using field symbols in combination with dynamically creating data objects by the "CREATE DATA" statement.
has anyone already done something similar?
‎2005 Mar 04 12:10 PM
Hello Gideon,
It is possible using ABAP runtime program generation like in code below.
This program generate a dinamic ALV with N fields. There is a parameter where the user type how many fields he wants to display (or generate).
Then form f_create_dynamic_table generate an internal table with N fields according to the number in the parameter.
You can change the program to generate a dinamic structure if you want, in fact it already does it.
Just cut and paste the program and execute in your system.
Regards,
Mauricio
REPORT zasmm008.
$$ Declarações -
-
TYPE-POOLS:
kkblo. "Tipos para lista especial
FIELD-SYMBOLS:
TYPE table.
PARAMETERS p_qtd TYPE i OBLIGATORY DEFAULT 10.
$$ Eventos -
-
INITIALIZATION.
%_p_qtd_%_app_%-text = 'Dinamic fields quantity'.
START-OF-SELECTION.
CHECK p_qtd > 0 AND p_qtd < 100.
PERFORM f_create_dynamic_table.
PERFORM f_fill_dynamic_table.
PERFORM f_create_alv.
$$ Forms -
-
*&----
*
*& Form f_create_dynamic_table
*&----
*
FORM f_create_dynamic_table.
DATA:
lv_line TYPE i,
lv_word(72) TYPE c,
lv_form(30) TYPE c VALUE 'TABLE_CREATE',
lv_message(240) TYPE c,
lp_table TYPE REF TO data,
lp_struc TYPE REF TO data,
lv_name LIKE sy-repid,
lv_cont(02) TYPE n,
lv_lng TYPE i,
lv_typesrting(6) TYPE c.
The dynamic internal table stucture
DATA: BEGIN OF lt_struct OCCURS 0,
fildname(8) TYPE c,
abptype TYPE c,
length TYPE i,
END OF lt_struct.
The dynamic program source table
DATA: BEGIN OF lt_inctabl OCCURS 0,
line(72),
END OF lt_inctabl.
Sample dynamic internal table stucture
DO p_qtd TIMES.
ADD 1 TO lv_cont.
CONCATENATE 'FIELD' lv_cont INTO lt_struct-fildname.
lt_struct-abptype = 'C'.
lt_struct-length = '4'.
APPEND lt_struct.
ENDDO.
Create the dynamic internal table definition in the dyn. program
lt_inctabl-line = 'PROGRAM ZDYNPRO.'.
APPEND lt_inctabl.
lt_inctabl-line = 'FORM TABLE_CREATE CHANGING P_TABLE P_STRUC.'.
APPEND lt_inctabl.
lt_inctabl-line = 'DATA: BEGIN OF DYNTAB OCCURS 0,'.
APPEND lt_inctabl.
LOOP AT lt_struct.
lt_inctabl-line = lt_struct-fildname.
lv_lng = strlen( lt_struct-fildname ).
IF NOT lt_struct-length IS INITIAL .
lv_typesrting(1) = '('.
lv_typesrting+1 = lt_struct-length.
lv_typesrting+5 = ')'.
CONDENSE lv_typesrting NO-GAPS.
lt_inctabl-line+lv_lng = lv_typesrting.
ENDIF.
lt_inctabl-line+15 = 'TYPE'.
lt_inctabl-line+21 = lt_struct-abptype.
lt_inctabl-line+22 = ','.
APPEND lt_inctabl.
ENDLOOP.
lt_inctabl-line = 'END OF DYNTAB.'.
APPEND lt_inctabl.
lt_inctabl-line = 'DATA: POINTER TYPE REF TO DATA.'.
APPEND lt_inctabl.
lt_inctabl-line = 'CREATE DATA POINTER LIKE DYNTAB[].'.
APPEND lt_inctabl.
lt_inctabl-line = 'P_TABLE = POINTER.'.
APPEND lt_inctabl.
lt_inctabl-line = 'CREATE DATA POINTER LIKE LINE OF DYNTAB.'.
APPEND lt_inctabl.
lt_inctabl-line = 'P_STRUC = POINTER.'.
APPEND lt_inctabl.
lt_inctabl-line = 'ENDFORM.'.
APPEND lt_inctabl.
CATCH SYSTEM-EXCEPTIONS generate_subpool_dir_full = 9.
GENERATE SUBROUTINE POOL lt_inctabl[] NAME lv_name
MESSAGE lv_message LINE lv_line WORD lv_word.
ENDCATCH.
PERFORM (lv_form) IN PROGRAM (lv_name) CHANGING lp_table lp_struc.
Dynamic table in <tb> and its header line in <st>
ASSIGN lp_table->* TO .
ENDFORM. " f_create_dynamic_table
*&----
*
*& Form f_create_alv
*&----
*
FORM f_create_alv.
DATA:
ls_layout TYPE slis_layout_alv,
lv_cont(02) TYPE n,
lt_fieldcat TYPE slis_t_fieldcat_alv WITH HEADER LINE.
DO p_qtd TIMES.
CLEAR lt_fieldcat.
ADD 1 TO lv_cont.
CONCATENATE 'FIELD' lv_cont INTO lt_fieldcat-fieldname.
CONCATENATE 'Campo' lv_cont INTO lt_fieldcat-seltext_s
SEPARATED BY space.
lt_fieldcat-seltext_m = lt_fieldcat-seltext_s.
lt_fieldcat-seltext_l = lt_fieldcat-seltext_s.
lt_fieldcat-outputlen = 10.
APPEND lt_fieldcat.
ENDDO.
ls_layout-zebra = 'X'.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
is_layout = ls_layout
it_fieldcat = lt_fieldcat[]
TABLES
t_outtab =
EXCEPTIONS
program_error = 1
OTHERS = 2.
ENDFORM. " f_create_alv
*&----
*
*& Form f_fill_dynamic_table
*&----
*
FORM f_fill_dynamic_table.
DATA:
lv_line(2) TYPE n,
lv_field(2) TYPE n.
DO 20 TIMES.
ADD 1 TO lv_line.
CLEAR lv_field.
DO p_qtd TIMES.
ADD 1 TO lv_field.
ASSIGN COMPONENT lv_field OF STRUCTURE .
ENDDO.
ENDFORM. " f_fill_dynamic_table
‎2005 Mar 04 12:10 PM
Hello Gideon,
It is possible using ABAP runtime program generation like in code below.
This program generate a dinamic ALV with N fields. There is a parameter where the user type how many fields he wants to display (or generate).
Then form f_create_dynamic_table generate an internal table with N fields according to the number in the parameter.
You can change the program to generate a dinamic structure if you want, in fact it already does it.
Just cut and paste the program and execute in your system.
Regards,
Mauricio
REPORT zasmm008.
$$ Declarações -
-
TYPE-POOLS:
kkblo. "Tipos para lista especial
FIELD-SYMBOLS:
TYPE table.
PARAMETERS p_qtd TYPE i OBLIGATORY DEFAULT 10.
$$ Eventos -
-
INITIALIZATION.
%_p_qtd_%_app_%-text = 'Dinamic fields quantity'.
START-OF-SELECTION.
CHECK p_qtd > 0 AND p_qtd < 100.
PERFORM f_create_dynamic_table.
PERFORM f_fill_dynamic_table.
PERFORM f_create_alv.
$$ Forms -
-
*&----
*
*& Form f_create_dynamic_table
*&----
*
FORM f_create_dynamic_table.
DATA:
lv_line TYPE i,
lv_word(72) TYPE c,
lv_form(30) TYPE c VALUE 'TABLE_CREATE',
lv_message(240) TYPE c,
lp_table TYPE REF TO data,
lp_struc TYPE REF TO data,
lv_name LIKE sy-repid,
lv_cont(02) TYPE n,
lv_lng TYPE i,
lv_typesrting(6) TYPE c.
The dynamic internal table stucture
DATA: BEGIN OF lt_struct OCCURS 0,
fildname(8) TYPE c,
abptype TYPE c,
length TYPE i,
END OF lt_struct.
The dynamic program source table
DATA: BEGIN OF lt_inctabl OCCURS 0,
line(72),
END OF lt_inctabl.
Sample dynamic internal table stucture
DO p_qtd TIMES.
ADD 1 TO lv_cont.
CONCATENATE 'FIELD' lv_cont INTO lt_struct-fildname.
lt_struct-abptype = 'C'.
lt_struct-length = '4'.
APPEND lt_struct.
ENDDO.
Create the dynamic internal table definition in the dyn. program
lt_inctabl-line = 'PROGRAM ZDYNPRO.'.
APPEND lt_inctabl.
lt_inctabl-line = 'FORM TABLE_CREATE CHANGING P_TABLE P_STRUC.'.
APPEND lt_inctabl.
lt_inctabl-line = 'DATA: BEGIN OF DYNTAB OCCURS 0,'.
APPEND lt_inctabl.
LOOP AT lt_struct.
lt_inctabl-line = lt_struct-fildname.
lv_lng = strlen( lt_struct-fildname ).
IF NOT lt_struct-length IS INITIAL .
lv_typesrting(1) = '('.
lv_typesrting+1 = lt_struct-length.
lv_typesrting+5 = ')'.
CONDENSE lv_typesrting NO-GAPS.
lt_inctabl-line+lv_lng = lv_typesrting.
ENDIF.
lt_inctabl-line+15 = 'TYPE'.
lt_inctabl-line+21 = lt_struct-abptype.
lt_inctabl-line+22 = ','.
APPEND lt_inctabl.
ENDLOOP.
lt_inctabl-line = 'END OF DYNTAB.'.
APPEND lt_inctabl.
lt_inctabl-line = 'DATA: POINTER TYPE REF TO DATA.'.
APPEND lt_inctabl.
lt_inctabl-line = 'CREATE DATA POINTER LIKE DYNTAB[].'.
APPEND lt_inctabl.
lt_inctabl-line = 'P_TABLE = POINTER.'.
APPEND lt_inctabl.
lt_inctabl-line = 'CREATE DATA POINTER LIKE LINE OF DYNTAB.'.
APPEND lt_inctabl.
lt_inctabl-line = 'P_STRUC = POINTER.'.
APPEND lt_inctabl.
lt_inctabl-line = 'ENDFORM.'.
APPEND lt_inctabl.
CATCH SYSTEM-EXCEPTIONS generate_subpool_dir_full = 9.
GENERATE SUBROUTINE POOL lt_inctabl[] NAME lv_name
MESSAGE lv_message LINE lv_line WORD lv_word.
ENDCATCH.
PERFORM (lv_form) IN PROGRAM (lv_name) CHANGING lp_table lp_struc.
Dynamic table in <tb> and its header line in <st>
ASSIGN lp_table->* TO .
ENDFORM. " f_create_dynamic_table
*&----
*
*& Form f_create_alv
*&----
*
FORM f_create_alv.
DATA:
ls_layout TYPE slis_layout_alv,
lv_cont(02) TYPE n,
lt_fieldcat TYPE slis_t_fieldcat_alv WITH HEADER LINE.
DO p_qtd TIMES.
CLEAR lt_fieldcat.
ADD 1 TO lv_cont.
CONCATENATE 'FIELD' lv_cont INTO lt_fieldcat-fieldname.
CONCATENATE 'Campo' lv_cont INTO lt_fieldcat-seltext_s
SEPARATED BY space.
lt_fieldcat-seltext_m = lt_fieldcat-seltext_s.
lt_fieldcat-seltext_l = lt_fieldcat-seltext_s.
lt_fieldcat-outputlen = 10.
APPEND lt_fieldcat.
ENDDO.
ls_layout-zebra = 'X'.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
is_layout = ls_layout
it_fieldcat = lt_fieldcat[]
TABLES
t_outtab =
EXCEPTIONS
program_error = 1
OTHERS = 2.
ENDFORM. " f_create_alv
*&----
*
*& Form f_fill_dynamic_table
*&----
*
FORM f_fill_dynamic_table.
DATA:
lv_line(2) TYPE n,
lv_field(2) TYPE n.
DO 20 TIMES.
ADD 1 TO lv_line.
CLEAR lv_field.
DO p_qtd TIMES.
ADD 1 TO lv_field.
ASSIGN COMPONENT lv_field OF STRUCTURE .
ENDDO.
ENDFORM. " f_fill_dynamic_table
‎2005 Mar 04 1:23 PM
hey mauricio, thanks for your quick and useful answer.
all problems are solved.
i didn´t know
the statement
"GENERATE SUBROUTINE POOL" before.
have a nice weekend!