06-21-2018 7:11 AM
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
06-21-2018 12:20 PM
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
06-21-2018 7:55 AM
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.
06-21-2018 10:51 AM
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.
06-21-2018 12:09 PM
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
).
06-21-2018 12:45 PM
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.
06-21-2018 8:44 AM
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
06-21-2018 9:55 AM
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
06-21-2018 11:05 AM
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
06-21-2018 11:30 AM
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
06-21-2018 12:20 PM
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
06-21-2018 2:02 PM
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
06-21-2018 3:19 PM
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)
06-21-2018 2:39 PM
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.
06-21-2018 6:17 PM
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
06-22-2018 2:14 PM
Hello to everybody.
I really enjoy this question. I think that it could be split into two different parts: