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
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 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!
| User | Count |
|---|---|
| 4 | |
| 2 | |
| 2 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 |