简体   繁体   中英

Return a list of all atributes of a persistent class in abap

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 (eg as ALV)?

Can I call an instance function if i click on it somehow?

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.

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:

  • on every call there is very much logic to do
  • the attribute is not used

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:

  • Everything is redundant,
  • each setter has to get changed

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.)

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 eG 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM