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: 

How to get table- and fieldname based on TYPE used in a locally defined structure?

BaerbelWinkler
Active Contributor
0 Kudos

Hi Folks,

I have a requirement to get the labels for fields in a locally defined structure, something like this:

    TYPES: BEGIN OF ty_out,
             kunnr TYPE kna1-kunnr,
             vkorg TYPE knvv-vkorg,
             vtweg TYPE knvv-vtweg,
             kukla TYPE kna1-kukla,
             vtext TYPE tkukt-vtext,
             pltyp TYPE knvv-pltyp,            
             .....           
           END of ty_out.

All the fields in the structure are typed based on existing SAP table fields.

I'd like to make use of function module DDIF_FIELDINFO_GET (unless there's an equivalent class method for this?) to get the field descriptions via the returned table dfies_tab:

    CALL FUNCTION 'DDIF_FIELDINFO_GET'
      EXPORTING
        tabname        = i_tablename
        fieldname      = i_fieldname
        langu          = sy-langu
      TABLES
        dfies_tab      = lt_dfies
      EXCEPTIONS
        not_found      = 1
        internal_error = 2
        OTHERS         = 3.
    
     IF sy-subrc EQ 0.
       READ TABLE lt_dfies INTO ls_dfies INDEX 1.
       IF sy-subrc EQ 0.
         r_descr = ls_dfies-scrtext_m.       
       ELSE.         
         r_descr = i_fieldname.       
       ENDIF.
     ELSE.       
       r_descr = i_fieldname.
     ENDIF.

I already searched for suitable methods to get the table- and fieldname based on the structure but haven't been lucky. The closest I got was using cl_abap_typedescr=>describe_by_data but that just returns the fieldname and actual type and length of the field. Is there a comparable straightforward method which goes "one step further" and also returns what comes after TYPE but split into tablename and fieldname?

For now - and to be able to test my program quickly, I did it the "hard way" by providing i_tablename and i_fieldname like this (which I don't really like - esp. as the structure is fairly large):

    get_field_descr( EXPORTING i_tablename = 'KNA1'
                               i_fieldname = 'KUNNR'
                     RECEIVING r_descr     = lv_descr ).

I'd like to stick with a locally defined structure as it's only needed for one program so there's no real reason to define it in the dictionary (we have a bit of an "interesting" process for DDIC-changes so try to avoid them as much as possible, in case you are wondering why I mention this).

We are on NW750 with EHP8.

Cheers

Baerbel

1 ACCEPTED SOLUTION

chaouki_akir
Contributor

Hello,

another try with a shorter technique to get labels of fields of a local structure

REPORT toti.
**&---------------------------------------------------------------------*
PERFORM local_routine.

FORM local_routine.
  TYPES: BEGIN OF ty_out,
           kunnr TYPE kna1-kunnr,
           vkorg TYPE knvv-vkorg,
           vtweg TYPE knvv-vtweg,
           kukla TYPE kna1-kukla,
           vtext TYPE tkukt-vtext,
           pltyp TYPE knvv-pltyp,
         END OF ty_out.
  DATA ls_out TYPE ty_out.
  DATA lo_rtti_struct TYPE REF TO cl_abap_structdescr.


*DATA(lo_rtti_struct) = cl_rodps_odp_rt=>get_structdescr_from_input( ls_out ).
*  CL_GENIOS_CUST_PARAMETER    GET_STRUCT_DESCR
  DATA(lo_typedescr) = cl_abap_structdescr=>describe_by_data( ls_out ).
  IF ( lo_typedescr->kind = cl_abap_typedescr=>kind_struct ).
    lo_rtti_struct ?= lo_typedescr.
    DATA(lt_dfies) = cl_salv_data_descr=>read_structdescr( lo_rtti_struct ).
  ENDIF.

ENDFORM.

Chaouki

14 REPLIES 14

raymond_giuseppi
Active Contributor

Did you try some RTTS class tools such as

" Fast dirty code in case of a structure, should be adapted and optimized.
DATA: structure TYPE REF TO cl_abap_structdescr,
      components TYPE abap_component_tab,
      ddic_object TYPE dd_x031l_table.
FIELD-SYMBOLS <field> TYPE abap_componentdescr.
structure ?= cl_abap_structdescr=>describe_by_data( p_data = myvar ).
components = structure->get_components( ).
LOOP AT components ASSIGNING <field>.
  IF <field>-type->is_ddic_type( ) EQ abap_true.
    <field>-type->get_ddic_object(
      RECEIVING
        p_object     = ddic_object ).
    " fill your internal table here
  ENDIF.
ENDLOOP.

0 Kudos

Thanks, Raymond.

That's basically the logic I already tried (and deleted from the code instead of just commenting it out for reference, stupid me!). From looking at the provided information via debugging, it only returns the fieldname used in the structure and not the table- plus fieldname used in the type specification for each field.

The function module DDIF_FIELDINFO_GET expects to get tablename and fieldname to return the information. I'm not wedded to using this particular FM, it's just what I had seen used in one of our Z-programs.

cl_abap_elemdescr has method get_ddic_field, which returns structure where you can find for example scrtext_m 🙂

EDIT: it is what Holger Janz is using at the end of his code

lr_elemdescr ?= cl_abap_elemdescr=>describe_by_data( <l_comp> ).
lr_elemdescr->get_ddic_field(
                EXPORTING
                  p_langu      = sy-langu   " Current Language
                RECEIVING
                  p_flddescr   = ls_ddic    " Field Description
                EXCEPTIONS
                  not_found    = 1
                  no_ddic_type = 2
                  OTHERS       = 3
              ).
-- Tomas --

Second version...

DATA: structure TYPE REF TO cl_abap_structdescr,
      components TYPE abap_component_tab,
      ddic_object TYPE dd_x031l_table,
      element TYPE REF TO cl_abap_elemdescr,
      dfies TYPE dfies,
      dfies_tab TYPE dfies_tab.
FIELD-SYMBOLS <field> TYPE abap_componentdescr.

structure ?= cl_abap_structdescr=>describe_by_data( p_data = myvar ).
components = structure->get_components( ).
LOOP AT components ASSIGNING <field>.
  IF <field>-type->is_ddic_type( ) EQ abap_true.
    element ?= <field>-type.
    dfies = element->get_ddic_field( sy-langu ) .
    APPEND dfies TO dfies_tab.
  ENDIF.
ENDLOOP.

holger_janz
Explorer

Example to get text from component of structure if all components are type with data element:

*example type
types:
  begin of my_struct,
    comp1 type snap-datum,
  end of my_struct.

* result data
data:
  begin of ddic_text,
    comp_name type c length 30,
    comp_text type c length 255,
  end of ddic_text,
  ddic_texts like table of ddic_text with empty key.

data(rtti_struct) = cast cl_abap_structdescr( cl_abap_typedescr=>describe_by_name( 'MY_STRUCT' ) ).

* without error handling, just to illustrate
ddic_texts = value #( for <comp> in rtti_struct->components(
  comp_name = <comp>-name
  comp_text =
  cast cl_abap_elemdescr( rtti_struct->get_component_type( <comp>-name ) )->get_ddic_field( )-scrtext_l ) ).

break-point. " result in ddic_texts

matt
Active Contributor
0 Kudos

Hi Holger Janz

Please use the "code" button in the editor when putting in ABAP into an answer. Use right click "Paste as plain text" to copy paste from the editor, otherwise formatting HTML is also pasted.

This makes your code easier to read. I've done it for you this time.

Matt Billingham - SAP Community Moderator

0 Kudos

Hello Holger

It is really interesting. But it is difficult to understand it at the beginning, becuase u have used ABAP 740, where Raymond has used the classic code. So I can say, your code wonderfull, easy and short who uses ABAP 740. So I like ABAP 740.

Best regards

Ebrahim Hatem

Thanks for the code snippet, Holger! It works like a charm (but I'll readily admit that - being as ABAP-OO-challenged as I still am - I don't necessarily understand everything which is going on there).

When I first copied and pasted your code into a test-program, I did get a syntax-error which I couldn't quite parse. But Ebrahim's screenshot helped to see what the little issue was: a missing blank between rtti_struct->components and the opening bracket in this line of code:

ddic_texts = value #( for <comp> in rtti_struct->components(

This will make my code quite a bit shorter as I can eliminate one method completely and shorten the other considerably.

Cheers

Baerbel

chaouki_akir
Contributor

Hello,

another try with a shorter technique to get labels of fields of a local structure

REPORT toti.
**&---------------------------------------------------------------------*
PERFORM local_routine.

FORM local_routine.
  TYPES: BEGIN OF ty_out,
           kunnr TYPE kna1-kunnr,
           vkorg TYPE knvv-vkorg,
           vtweg TYPE knvv-vtweg,
           kukla TYPE kna1-kukla,
           vtext TYPE tkukt-vtext,
           pltyp TYPE knvv-pltyp,
         END OF ty_out.
  DATA ls_out TYPE ty_out.
  DATA lo_rtti_struct TYPE REF TO cl_abap_structdescr.


*DATA(lo_rtti_struct) = cl_rodps_odp_rt=>get_structdescr_from_input( ls_out ).
*  CL_GENIOS_CUST_PARAMETER    GET_STRUCT_DESCR
  DATA(lo_typedescr) = cl_abap_structdescr=>describe_by_data( ls_out ).
  IF ( lo_typedescr->kind = cl_abap_typedescr=>kind_struct ).
    lo_rtti_struct ?= lo_typedescr.
    DATA(lt_dfies) = cl_salv_data_descr=>read_structdescr( lo_rtti_struct ).
  ENDIF.

ENDFORM.

Chaouki

0 Kudos

Thanks, Chaouki! That is most likely as short a coding as is possible to do for my requirement!

The DATA-definition for lt_fcat doesn't seem to be needed and I just needed to add a definition for LS_DFIES to make it possible to loop through LT_DFIES to then grab and concatenate the descriptions for my header line for the output file.

I do have one additional and more general question:

When using a function module it is apparent if it has been released or not in the attributes. Typically, a released FM also comes with a description. Is there a similar distinction for class-methods or can basically all methods be used at will if they are public? I'm asking because the class CL_RODPS_ODP_RT in your code doesn't have a description while CL_ABAP_STRUCTDESCR and CL_ABAP_ELEMDESCR have one even with short examples. I'm therefore wondering which of the two options - yours or Holger - to actually implement.

Cheers

Baerbel

0 Kudos

I updated the code : replace the use of the class CL_RODPS_ODP_RT with CLASS CL_ABAP_STRUCTDESCR.

You are right about SAP released objects. In se24, I found an information about the class CL_ABAP_STRUCTDESCR : even this class seems not to be released (if I understand well the SAP information)

former_member539238
Participant
0 Kudos

Hello,

You can do the following, The table name can be a table or structure with all fields in local structure(It can have any other fields).

  DATA:lt_fcat TYPE slis_t_fieldcat_alv,
       ls_fcat LIKE LINE OF lt_fcat.


  DATA:i_tablename TYPE ddobjname,
       lt_dfies    TYPE TABLE OF dfies,
       ls_dfies    LIKE LINE OF lt_dfies.


  i_tablename = 'Table with all fields' .


  CALL FUNCTION 'DDIF_FIELDINFO_GET'
    EXPORTING
      tabname        = i_tablename
*     fieldname      = i_fieldname
*     langu          = sy-langu
    TABLES
      dfies_tab      = lt_dfies
    EXCEPTIONS
      not_found      = 1
      internal_error = 2
      OTHERS         = 3.


  FIELD-SYMBOLS <fs_field> TYPE any.
  LOOP AT lt_dfies INTO ls_dfies.
    ASSIGN COMPONENT  ls_dfies-fieldname  OF STRUCTURE ls_vbrp TO <fs_field>.
    IF <fs_field> IS ASSIGNED.
      CLEAR ls_fcat.
      ls_fcat-seltext_l = ls_dfies-scrtext_l.
      ls_fcat-seltext_m = ls_dfies-scrtext_m.
      ls_fcat-seltext_s = ls_dfies-scrtext_s.
      ls_fcat-fieldname = ls_dfies-fieldname.
      APPEND ls_fcat TO lt_fcat.
    ENDIF.
  ENDLOOP.

BaerbelWinkler
Active Contributor
0 Kudos

Thanks all for providing answers to my question!

As sometimes happens, I would have liked to pick two instead of just one best answer as Chaouki's and Holger's responses both merited the selection. I went with Chaouki's as it's a bit more concise and easier to understand and therefore maintain for me.

Cheers

Baerbel

0 Kudos

Hello to everybody.

I really enjoy this question. I think that it could be split into two different parts:

  • do you want to know names and characteristics of all field (such as labels, lenght, data element, ..) or
  • do you want to know exactly the name of table and field used in declaration?
First question has already been replied here (so I don't add anything new), while I have not been able to find a general answer to the second one.
Years ago for this purpose I used function module REUSE_ALV_FIELDCATALOG_MERGE, but it hase some limits, i.e. fields must be declared using LIKE and not TYPE and all lines of source code must be shorter than 72 characters.
This function internally calls standard module ABAP_SCAN_DATA_DESCRIPTION, that read ABAP code and it parses it looking for all declaration. I tried to write a new method inspired to this function, but adding also some new features (like long lines and declarations non supported by standard functions). I have a scratch written years ago, but still I'm not sure it works always and now I forgot exactly how it works.I wonder if meanwhile there is some new standard feature doing so, but till I found nothing.
By the way... why I'm so interested in such a information? Because if you know the correspondance between a field and it origin, you could do some dynamic coding, like an "intelligent" move or build an "intellingent" field list for SELECT JOIN or any other similar idea.
So, have anybody any more ideas about this matter?