Reputation: 2617
I got a persistent class on a custom table. Now with GET_PERSISTENT_BY_QUERY I can get a list of objects. How can I now get those Objects with all of their atributes printed to the user (e.g as ALV)?
Can I call an instance function if i click on it somehow?
Upvotes: 3
Views: 1596
Reputation: 2617
Based on the answer of gert beukema I have written a helper class (with major improvements like accepting more than public simple atributes without failing).
class ZCL_PS_OBJECT_TO_STRUCTURE_HLP definition
public
create private .
public section.
class-methods REFTAB_TO_STRUCTURE_LIST
importing
!IT_REFRENCE_TABLE type OSREFTAB
returning
value(RR_OBJECT_ATTRIBUTES_TABLE) type ref to DATA .
class-methods CREATE_FIELDCAT
importing
!IR_OBJ_DESC type ref to CL_ABAP_CLASSDESCR
returning
value(RO_FIELD_CAT) type LVC_T_FCAT .
protected section.
private section.
ENDCLASS.
CLASS ZCL_PS_OBJECT_TO_STRUCTURE_HLP IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_PS_OBJECT_TO_STRUCTURE_HLP=>CREATE_FIELDCAT
* +-------------------------------------------------------------------------------------------------+
* | [--->] IR_OBJ_DESC TYPE REF TO CL_ABAP_CLASSDESCR
* | [<-()] RO_FIELD_CAT TYPE LVC_T_FCAT
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD CREATE_FIELDCAT.
LOOP AT IR_obj_desc->attributes ASSIGNING FIELD-SYMBOL(<fs_attr_desc>).
APPEND INITIAL LINE TO ro_field_cat ASSIGNING FIELD-SYMBOL(<fs_field_cat>).
<fs_field_cat>-fieldname = <fs_attr_desc>-name.
<fs_field_cat>-intlen = <fs_attr_desc>-length.
<fs_field_cat>-datatype = <fs_attr_desc>-type_kind.
<fs_field_cat>-outputlen = calculate a good outputlength (double when hex)
ENDLOOP.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_PS_OBJECT_TO_STRUCTURE_HLP=>REFTAB_TO_STRUCTURE_LIST
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_REFRENCE_TABLE TYPE OSREFTAB
* | [<-()] RR_OBJECT_ATTRIBUTES_TABLE TYPE REF TO DATA
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD reftab_to_structure_list.
DATA: lr_obj_desc TYPE REF TO cl_abap_classdescr,
lr_query_data TYPE REF TO data,
lt_fieldcat TYPE lvc_t_fcat.
FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE.
LOOP AT it_refrence_table ASSIGNING FIELD-SYMBOL(<fs_object>).
AT FIRST.
lr_obj_desc ?= cl_abap_typedescr=>describe_by_object_ref( p_object_ref = <fs_object> ).
lt_fieldcat = create_fieldcat( ir_obj_desc = lr_obj_desc ).
CALL METHOD cl_alv_table_create=>create_dynamic_table
EXPORTING
* i_style_table =
it_fieldcatalog = lt_fieldcat
* i_length_in_byte =
IMPORTING
ep_table = rr_object_attributes_table
* ep_table = lr_query_data
* e_style_fname =
EXCEPTIONS
generate_subpool_dir_full = 1
OTHERS = 2.
* IF sy-subrc <> 0.
* do some errorhandling here
* ENDIF.
ASSIGN rr_object_attributes_table->* TO <fs_table>.
* ASSIGN lr_query_data->* TO <fs_table>.
ENDAT. "first
APPEND INITIAL LINE TO <fs_table> ASSIGNING FIELD-SYMBOL(<fs_line>).
LOOP AT lr_obj_desc->attributes ASSIGNING FIELD-SYMBOL(<fs_attr_desc>).
ASSIGN COMPONENT <fs_attr_desc>-name OF STRUCTURE <fs_line> TO FIELD-SYMBOL(<fs_attr_value>).
DATA(getter) = 'GET_' && <fs_attr_desc>-name.
TRY .
CALL METHOD <fs_object>->(getter) RECEIVING result = <fs_attr_value>.
CATCH cx_sy_dyn_call_illegal_method. "get_method is protected or private
CLEAR <fs_attr_value>.
CATCH cx_sy_dyn_call_illegal_type.
"what to do with a list?
ENDTRY.
ENDLOOP.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
Now with that helperclass I do not have to recode it always I want a list out of a Object.
In a programm the call is e.G like this:
DATA: lt_query_data TYPE osreftab,
lt_query_table TYPE REF TO data.
FIELD-SYMBOLS <fs_table>.
lt_query_data = zca_ps_user=>agent->if_os_ca_persistency~get_persistent_by_query(
i_query = cl_os_system=>get_query_manager( )->create_query( )
).
CALL METHOD zcl_ps_object_to_structure_hlp=>reftab_to_structure_list
EXPORTING
it_refrence_table = lt_query_data
RECEIVING
rr_object_attributes_table = lt_query_table.
IF lt_query_table IS INITIAL.
LEAVE.
ENDIF.
ASSIGN lt_query_table->* TO <fs_table>.
*Create a ALV
DATA: lr_alv TYPE REF TO cl_salv_table .
cl_salv_table=>factory( IMPORTING r_salv_table = lr_alv
CHANGING t_table = <fs_table> )
.
lr_alv->display( ).
Ps: I wanted to edit the answer, but it was not accepted.
Upvotes: 0
Reputation: 2617
One more way is to define a instance atribute called list. Then, the generated getter can be overwritten as following, which is addresed from anywhere.
if me->list is initial.
DATA: WA TYPE ZMM_SMATERIAL.
WA-ERNAM = GET_ERNAM( ).
wa-ERSDA = GET_ERSDA( ).
WA-LAEDA = GET_LAEDA( ).
WA-MATNR = GET_MATNR( ).
WA-MTART = GET_MTART( ).
.
.
.
me->list = WA.
endif.
result = me->list
" GET_LIST
endmethod.
The ... stands for each attribute I want in the List.
Additionaly to that, I need to CLEAR
the list on every setter.
The big con to that is that the generator overwrites everything. (Without any warning.)
Upvotes: 0
Reputation: 2565
Here is a dynamic solution, query_data is the result returned from the call to get_persistent_by_query( ). In the end the data will be stored in structured table <table>, you can use this to display in your ALV. Note that there is little control over the order of the field. For real use you'd have to add some error handling as well.
DATA: pers_obj_desc TYPE REF TO cl_abap_classdescr,
pers_query_data TYPE REF TO data,
field_cat TYPE lvc_t_fcat.
FIELD-SYMBOLS: <table> TYPE STANDARD TABLE.
LOOP AT query_data ASSIGNING FIELD-SYMBOL(<pers_data>).
AT FIRST.
pers_obj_desc ?= cl_abap_typedescr=>describe_by_object_ref( p_object_ref = <pers_data> ).
LOOP AT pers_obj_desc->attributes ASSIGNING FIELD-SYMBOL(<attr_desc>).
APPEND INITIAL LINE TO field_cat ASSIGNING FIELD-SYMBOL(<field_cat>).
<field_cat>-fieldname = <attr_desc>-name.
<field_cat>-intlen = <attr_desc>-length.
<field_cat>-datatype = <attr_desc>-type_kind.
ENDLOOP.
cl_alv_table_create=>create_dynamic_table(
EXPORTING
it_fieldcatalog = field_cat
IMPORTING
ep_table = pers_query_data
).
ASSIGN pers_query_data->* TO <table>.
ENDAT. " first
APPEND INITIAL LINE TO <table> ASSIGNING FIELD-SYMBOL(<line>).
LOOP AT pers_obj_desc->attributes ASSIGNING <attr_desc>.
ASSIGN COMPONENT <attr_desc>-name OF STRUCTURE <line> TO FIELD-SYMBOL(<field>).
data(getter) = 'GET_' && <attr_desc>-name.
CALL METHOD <pers_data>->(getter) RECEIVING result = <field>.
ENDLOOP.
ENDLOOP.
Upvotes: 1
Reputation: 2617
An other (I do not think good) way is to define a instance atribute called list. Then, on the initialize, the list gets prepared.
DATA: WA TYPE ZMM_SMATERIAL.
WA-ERNAM = GET_ERNAM( ).
wa-ERSDA = GET_ERSDA( ).
WA-LAEDA = GET_LAEDA( ).
WA-MATNR = GET_MATNR( ).
WA-MTART = GET_MTART( ).
.
.
.
LIST = WA.
endmethod.
The ... stands for each attribute I want in the List.
Then, on every setter, also in this list it gets changed
The CONS to this solution:
Upvotes: 0
Reputation: 2617
One (i do not think good) way is to define a instance atribute called list. Then, the generated getter can be overwritten as following, which is addresed from anywhere.
DATA: WA TYPE ZMM_SMATERIAL.
WA-ERNAM = GET_ERNAM( ).
wa-ERSDA = GET_ERSDA( ).
WA-LAEDA = GET_LAEDA( ).
WA-MATNR = GET_MATNR( ).
WA-MTART = GET_MTART( ).
.
.
.
result = WA.
" GET_LIST
endmethod.
The ... stands for each attribute I want in the List.
The CONS to this solution:
Upvotes: 0