Application Development Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with cl_abap_tabledescr=>describe_by_data

Former Member
0 Kudos

Hello Xperts,

from the following code we are calling a method READ_SELECTIVELY:


    TYPES:
          t_struct    TYPE TABLE OF /BIC/VBPPP01j
    DATA:
        t_all_data    TYPE t_struct, 
        w_dref  type ref to data.

    GET REFERENCE OF t_all_data into w_dref.

    CALL METHOD ZCL_B_TECHNICAL_UTILITY=>READ_SELECTIVELY
      IMPORTING
        P_SEL_READ_DATA = w_dref.

Pls note: it is coded like this because method READ_SELECTIVELY is supposed to work generically with t_struct being a table of any type.

Declarations of method READ_SELECTIVELY:


method READ_SELECTIVELY.
public section.
  type-pools RSDRC .

  class-methods READ_CUBE_SELECTIVELY
    exporting
      !P_CUBE_SEL_READ_DATA type ref to DATA .

Coding of method READ_SELECTIVELY:


method READ_SELECTIVELY.
  DATA:
    go_sdescr        TYPE REF TO cl_abap_structdescr,
    go_sdescr_new    TYPE REF TO cl_abap_structdescr,
    go_tdescr        TYPE REF TO cl_abap_tabledescr,

    gdo_handle       TYPE REF TO data,
    gs_element       TYPE REF TO cl_abap_elemdescr,
    gt_components    type cl_abap_structdescr=>component_table,
    gs_component     like line of gt_components,
    gs_comp          like line of gt_components.

  field-symbols:
    <g_t_data>       TYPE STANDARD TABLE.

  go_tdescr ?= cl_abap_tabledescr=>describe_by_data( P_CUBE_SEL_READ_DATA ).
  go_sdescr ?= go_tdescr->get_table_line_type( ).

* Begin create dynamic standard table copy of P_CUBE_SEL_READ_DATA
  "   Create instances of dynamic structure and dynamic internal table
  go_sdescr_new  = cl_abap_structdescr=>create( P_COMPONENTS = gt_components p_strict = abap_false ).
  go_tdescr      = cl_abap_tabledescr=>create( go_sdescr_new ).

  "   Create data refence followed by table creation
  CREATE DATA gdo_handle TYPE HANDLE go_tdescr.
  ASSIGN gdo_handle->* TO <g_t_data>.
* End create dynamic standard table copy of P_CUBE_SEL_READ_DATA
...

The idea is to create a copy of the table passed thru parameter P_CUBE_SEL_READ_DATA. After that the copy will be filled and in a loop appended to P_CUBE_SEL_READ_DATA which will be returned to the calling coding (i.e. the first code snippet above). Makes sense?

Unfortunately it fails at the statement:


  go_tdescr ?= cl_abap_tabledescr=>describe_by_data( P_CUBE_SEL_READ_DATA ).

Any suggestions are very appreciated.

1 ACCEPTED SOLUTION

MarcinPciak
Active Contributor
0 Kudos

If you want to pass the table and modify it within method's body, you need to use changing parameter. I guess describe_by_data fails as P_CUBE_SEL_READ_DATA has initial value at that point (you marked it only as EXPORTING parameter so it receives this initial value and method entry). Changing the parameter signature should do the job, as at point of describe_by_data call this data reference won't be empty anymore.

Another issue is that you should be using method DESCRIBE_BY_DATA_REF not DESCRIBE_BY_DATA as the expected parameter type is data reference in first case, and simple data in the latter one.

So the correct snippet would be


"signature
 class-methods READ_CUBE_SELECTIVELY
    changing
      !P_CUBE_SEL_READ_DATA type ref to DATA .

"method
if P_CUBE_SEL_READ_DATA is bound.
   go_tdescr ?= cl_abap_tabledescr=>DESCRIBE_BY_DATA_REF( P_CUBE_SEL_READ_DATA ).
   ....
else.
   "raise some exception saying that data reference is initial
endif.

Regards

Marcin

6 REPLIES 6

MarcinPciak
Active Contributor
0 Kudos

If you want to pass the table and modify it within method's body, you need to use changing parameter. I guess describe_by_data fails as P_CUBE_SEL_READ_DATA has initial value at that point (you marked it only as EXPORTING parameter so it receives this initial value and method entry). Changing the parameter signature should do the job, as at point of describe_by_data call this data reference won't be empty anymore.

Another issue is that you should be using method DESCRIBE_BY_DATA_REF not DESCRIBE_BY_DATA as the expected parameter type is data reference in first case, and simple data in the latter one.

So the correct snippet would be


"signature
 class-methods READ_CUBE_SELECTIVELY
    changing
      !P_CUBE_SEL_READ_DATA type ref to DATA .

"method
if P_CUBE_SEL_READ_DATA is bound.
   go_tdescr ?= cl_abap_tabledescr=>DESCRIBE_BY_DATA_REF( P_CUBE_SEL_READ_DATA ).
   ....
else.
   "raise some exception saying that data reference is initial
endif.

Regards

Marcin

0 Kudos

Dear Marcin,

thanks for your answer. U r great! I would never have been able to figure that out

So thanx to u we got a step further, but now the failure occurs at


    go_sdescr_new  = cl_abap_structdescr=>create( P_COMPONENTS = gt_components p_strict = abap_false ).

More specifically after exiting out of:


method CONSTRUCTOR.
CALL METHOD SUPER->CONSTRUCTOR
EXPORTING
TEXTID = TEXTID
PREVIOUS = PREVIOUS
COMPONENT_NAME = COMPONENT_NAME
COMPONENT_NUMBER = COMPONENT_NUMBER
.
 IF textid IS INITIAL.
   me->textid = CX_SY_STRUCT_ATTRIBUTES .
 ENDIF.
endmethod.

Aprreciate ur help. thankx again.

Greetings,

Martin

0 Kudos
field-symbols:
    <g_t_data>       TYPE STANDARD TABLE.
 
  go_tdescr ?= cl_abap_tabledescr=>describe_by_data( P_CUBE_SEL_READ_DATA ).
  go_sdescr ?= go_tdescr->get_table_line_type( ).
 
* Begin create dynamic standard table copy of P_CUBE_SEL_READ_DATA
  "   Create instances of dynamic structure and dynamic internal table
  go_sdescr_new  = cl_abap_structdescr=>create( P_COMPONENTS = gt_components p_strict = abap_false ).
  go_tdescr      = cl_abap_tabledescr=>create( go_sdescr_new ).
 
  "   Create data refence followed by table creation
  CREATE DATA gdo_handle TYPE HANDLE go_tdescr.
  ASSIGN gdo_handle->* TO <g_t_data>.
* End create dynamic standard table copy of P_CUBE_SEL_READ_DATA

Hello Martin,

If i understand correctly, you want to create the dynamic table from the data ref. P_CUBE_SEL_READ_DATA.

Instead of using the RTTC technique( CREATE* methods), you can directly dereference P_CUBE_SEL_READ_DATA. Something like this:

field-symbols: <g_t_data> TYPE STANDARD TABLE.

ASSIGN P_CUBE_SEL_READ_DATA->* TO <g_t_data>.

Later on if you want to analyse the structure of this table you can use the DESCRIBE_BY_DATA( ) on <g_t_data> or DESCRIBE_BY_DATA_REF( ) on P_CUBE_SEL_READ_DATA !

@Marcin: I don't think OP needs the RTTI at all. He can just de-reference the variable to some "compatible" field-symbol. Watsay?

BR,

Suhas

0 Kudos

@Marcin: I don't think OP needs the RTTI at all. He can just de-reference the variable to some "compatible" field-symbol. Watsay?

Misleading here might be this statement

  • Begin create dynamic standard table copy of P_CUBE_SEL_READ_DATA

I so thought he needs local copy of the table. But of coure is he only needs to change original one, no reason to use RTTS, but working directly with table behind P_CUBE_SEL_READ_DATA suffice.

Regards

Marcin

0 Kudos

Dear Marcin & Suhas,

yes indeed I need to create a copy of the table and it works now.

Thanks to both of you for your input.

Greetings,

Martin

MarcinPciak
Active Contributor
0 Kudos

Well, unless you need components of the table for some purpose (i.e. to add new components dynamically), there is no need to break down table into structure then into components. By using only describe_by_data_ref method you already get description of this table type under go_tdescr . So you simply use this object reference to create your local copy of table which P_CUBE_SEL_READ_DATA "points" to.

So in fact you need only


go_tdescr ?= cl_abap_tabledescr=>describe_by_data_ref( P_CUBE_SEL_READ_DATA ).

CREATE DATA gdo_handle TYPE HANDLE go_tdescr.

That's it.

Regards

Marcin