Skip to Content
Technical Articles
Author's profile photo Philip Davy

ABAP Lesser Known Heroes Series – Value Operator : Part 2

This is a continuation of my post series,

Part 1 : https://blogs.sap.com/2021/07/09/abap-lesser-known-heroes-series-group-column-part-1/comment-page-1/#comment-580377

Value Operator

Value operator is a relatively new addition to the ABAP language and the developers already  have started extensively using this feature. But here I am writing about one of its functionality which is not widely noticed . 

More about value operator from ABAP documentation,

https://help.sap.com/doc/abapdocu_750_index_htm/7.50/en-US/abenconstructor_expression_value.htm

Value operator is particularly helpful in feeding internal table with values .

REPORT ZSAMPLE_VALUE.

TYPES: gtt_sflight  TYPE STANDARD TABLE OF SFLIGHT WITH DEFAULT KEY .

DATA(lt_flights) = VALUE gtt_sflight( ( carrid = 'AA' connid = '0017'  fldate = '26.11.2020' price = '422,94' )
                                      ( carrid = 'AZ' connid = '0018'  fldate = '29.12.2020' price = '100.89' )
                                      ( carrid = 'DL' connid = '0019'  fldate = '30.05.2021' price = '422,94' ) ).

And here is the utility of ‘value’ operator which I accidently found out while using ‘where used’ list of a BAPI.

   CALL FUNCTION 'BAPI_MATERIAL_SAVEDATA'
      EXPORTING
        headdata             = VALUE bapimathead( material_long = rv_matnr
                                                  ind_sector    = 'M'
                                                  matl_type     = 'FERT'
                                                  basic_view    = 'X'
                                                  storage_view  = 'X'
                                                  account_view  = 'X'
                                                  purchase_view = 'X' )
        clientdata           = VALUE bapi_mara( matl_group    = get_material_group( )
                                                base_uom      = get_unconverted_uom( )
                                                net_weight    = '10'
                                                unit_of_wt    = 'KG' )
        clientdatax          = VALUE bapi_marax( matl_group    = 'X'
                                                 base_uom      = 'X'
                                                 net_weight    = 'X'
                                                 unit_of_wt    = 'X' )
        plantdata            = VALUE bapi_marc( plant = get_plant( )
                                                pur_group = get_purch_group( ) )
        plantdatax           = VALUE bapi_marcx( plant     = get_plant( )
                                                 pur_group = 'X' )
        valuationdata        = VALUE bapi_mbew( val_area      = get_valuation_area( )
                                                price_ctrl    = lv_price_ctrl
                                                std_price     = '10.00'
                                                price_unit    = lv_price_unit
                                                moving_pr     = '10.00'
                                                val_class     = get_valuation_class( iv_matl_type = 'FERT' ) ) "3300/7920 depends on system
        valuationdatax       = VALUE bapi_mbewx( val_area      = get_valuation_area( )
                                                 price_ctrl    = 'X'
                                                 std_price     = 'X'
                                                 moving_pr     = 'X'
                                                 price_unit    = 'X'
                                                 val_class     = 'X' )
        storagelocationdata  = VALUE bapi_mard( plant    = get_plant( )
                                                stge_loc = get_storage_location( ) )
        storagelocationdatax = VALUE bapi_mardx( plant    = get_plant( )
                                                 stge_loc = get_storage_location( ) )
      TABLES
        materialdescription  = lt_create_material_matdscr
        returnmessages       = lt_returnmessages.

    Code from CL_API_RESERVATION_DOC_DPC_EXT – Local Test Class

    We no more have to declare the input structures for a FM/BAPI separately . We could use the value statement with the corresponding structure and feed with the values for the parameters. This feature is useful particularly when used in test classes. The icing on the cake is, we could even assign a functional method to the parameter list. Easy huh ??

Footnote:  But one strange thing which I noticed is that , we can only feed structures with a value to the function modules/BAPI’s but not internal tables. I wonder why. May be the list gets longer? But could have been good enough for testing classes with one or two line items?

 TABLES
        materialdescription  = value t_bapi_makt( ( langu = 'D'
                                                  langu_iso = 'DE'
                                                  matl_desc = 'Sample Material'
                                                  del_flag  = ' ' ) )
        returnmessages       = value cfx_bi_tt_bapi_matreturn2( ( type = 'E'
                                                                ID   = 'SD'
                                                                number = '120'
                                                                message = 'Sample' ) ).

The above code throws error when used with BAPI ‘BAPI_MATERIAL_SAVEDATA’ .

May be Horst Keller can show some light on this ?

Philip Davy

Assigned Tags

      10 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Andrea Borgia
      Andrea Borgia

      Yup, VALUE is really an unsung hero, especially in unit tests!

      However, I'm not sure I understand the limitation you mention in the footnote. To me it looks like a set of parentheses is missing.

      Author's profile photo Philip Davy
      Philip Davy
      Blog Post Author
      Does not work with extra paranthesis also. I think the below explanation from

      Sandra Rossi suffix for an answer .
      Author's profile photo Sandra Rossi
      Sandra Rossi

      My 2 cents: I guess this doesn't work because the parameter type TABLES is obsolete (*), there's no equivalent data type corresponding to those old variables made of a table body and a header line.

      EDIT: (*) except with RFC.

      But this is possible:

        DATA(message_handles) = VALUE bal_t_msgh( ).
        CALL FUNCTION 'BAL_DB_LOAD'
          EXPORTING
            i_t_log_handle = VALUE bal_t_logh( ( '2b8vp{1g7kUFtcq7VMjsyG' ) )
          IMPORTING
            e_t_msg_handle = message_handles.
      Author's profile photo Philip Davy
      Philip Davy
      Blog Post Author

      Sandra Rossi ,

      Very good observation. Tables parameter type  is obsolete and that may be the reason . Most old school BAPI's and  function modules use tables parameters and it could have been nice to add the value parameter to the tables statements.

      Author's profile photo Sandra Rossi
      Sandra Rossi

      I think it's always the same thing: either it's additional work for them (like doing an additional conversion from the constructed value to the tables parameter so that it can be used by the form or function module, due to that problematic header line), or other issues like performance, too much headache for no actual interest (function modules are more and more abandoned). Who knows...

      Author's profile photo Suhas Saha
      Suhas Saha

      If i remember correctly, constructor operators don't work with CHANGING parameters as well. IMHO, TABLES parameters are similar to CHANGING and therefore VALUE isn't supported for them too.

      Unfortunately i couldn't find any reference to this behaviour in the official ABAP documentation.

      Author's profile photo Matthew Billingham
      Matthew Billingham

      The RFC warning isn't always applicable.

      The parameter contains a data type that, in the external system, can lead to a high memory consumption and poorer performance.

      I've never encountered such an issue. So perhaps the RFC warning is even just covering a rare case.

      Uwe Schieferstein points out here: https://answers.sap.com/questions/5671452/using-table-types-in-rfc.html

      Since TABLES parameters are obsolete you should always use table types for "itab" parameters.

      The system will always show you a warning about possible performance problems which you can ignore.

      ...if you ever really run into a performance problem with these table type parameters you could do a transformation within the RFC-fm (itab -> XML binary stream) and make the re-transformation (XML binary stream -> itab) in your calling program

      Author's profile photo Scott Lawton
      Scott Lawton

      I think I even saw a semi-official declaration from SAP once that this RFC warning was no longer accurate, but of course, that was several years ago and I have no idea where I saw it anymore. In any case, my experience has been the same, that I have never seen an actual performance issue from using table types with IMPORTING/EXPORTING parameters.

      Author's profile photo Matthew Billingham
      Matthew Billingham

      I vaguely remember such a thing as well.

      Author's profile photo Suhas Saha
      Suhas Saha

      The really "unsung" hero(es) are the OPTIONAL & DEFAULT additions of VALUE operator.

      The former is really useful to avoid handling the CX_SY_ITAB_LINE_NOT_FOUND exception.