'How to call BAPI_MATERIAL_SAVEDATA with custom fields from NCo?

In our current project we are using SAPNCO3 with RFC calls. The requirement is to create material with the function "BAPI_MATERIAL_SAVEDATA" and some custom fields (via EXTENSIONIN). The problem now is how to extend the needed structures "BAPI_TE_MARA/X" so that they can carry the custom fields? I cannot found any function for this.

Please have a look at the Code snippet at the bottom.

Thank you!

Tobias

            var BAPI_TE_MARA = repo.GetStructureMetadata("BAPI_TE_MARA");
            IRfcStructure structure = BAPI_TE_MARA.CreateStructure();
           
            structure.SetValue("MATERIAL", material.Number);
            //structure.SetValue("ZMM_JOB_REFERENCE", "f");


Solution 1:[1]

BAPI_MATERIAL_SAVEDATA has two table parameters EXTENSIONIN and EXTENSIONINX to which you pass lines with the values of your custom fields.

These table parameters have to indicate what extension structures you want to use and their values.

As these custom fields may extend different tables of the material, you have to indicate different extension structures depending on which table these fields belong to:

  • For the table MARA, the extension structures are BAPI_TE_MARA and BAPI_TE_MARAX.
  • For the table MARC, the extension structures are BAPI_TE_MARC and BAPI_TE_MARCX.

These extension structures should preferably have character-like fields to simplify the programming (and to support IDocs, as rule-of-thumb).

For instance, if you have the custom fields ZZCNAME (7 characters) and ZZCTEXT (50 characters) in the table MARA, they will also be defined in BAPI_TE_MARA and have the same names and types. In BAPI_TE_MARAX, you also have two fields with the same names, but always of length 1 character and their values must be 'X' to indicate that a value is passed in BAPI_TE_MARA (useful in case a blank value is passed that must not be ignored). The X extension structures are essential especially in "change" BAPIs.

If you want to pass values to the BAPI, you must first initialize these structures:

  • BAPI_TE_MARA:
    MATERIAL      ZZCNAME  ZZCTEXT
    ------------  -------  -------
    000000012661  NAME     TEXT    
    
  • BAPI_TE_MARAX:
    MATERIAL      ZZCNAME  ZZCTEXT
    ------------  -------  -------
    000000012661  X        X     
    

Then, you must initialize the two parameters of the BAPI:

  • EXTENSIONIN (notice that there are 3 spaces in NAME TEXT because the technical length of ZZCNAME is 7 characters and its value "NAME" occupies only 4 characters):
    STRUCTURE     VALUEPART1 (240 Char)    VALUEPART2 (240)  VALUEPART3 (240)  VALUEPART4 (240)
    ------------  -----------------------  ----------------  ----------------  ----------------
    BAPI_TE_MARA  000000012661NAME   TEXT
    
  • EXTENSIONINX:
    STRUCTURE      VALUEPART1 (240 Char)  VALUEPART2 (240)  VALUEPART3 (240)  VALUEPART4 (240)
    -------------  ---------------------  ----------------  ----------------  ----------------
    BAPI_TE_MARAX  000000012661XX
    

Consequently, your program must:

  • concatenate all BAPI_TE_MARA fields together and copy the resulting string into fields VALUEPART1 to VALUEPART4 of EXTENSIONIN as if it was a 960 characters field
  • concatenate all BAPI_TE_MARAX fields together and copy the resulting string into fields VALUEPART1 to VALUEPART4 of EXTENSIONINX

I guess you may use ToString() to get one concatenated string of characters of all fields of a structure, and to set the value of VALUEPART1, VALUEPART2, etc., you'll probably need to initialize them individually from the string of characters with Substring.

Solution 2:[2]

My comment was half by half correct and incorrect, I wasn't aware of the extension technique in this BAPI, so I wasn't aware of this structure is really used in this BAPI.

You asked

The problem now is how to extend the needed structures "BAPI_TE_MARA/X" so that they can carry the custom fields?`

and what I said is indeed stays valid: you cant extend the interface from NCo, only on backend.

You writes:

At this If I load BAPI_TE_MARA there aren't any custom fields but the material

and this get me to the idea that your ABAP developers made only half of the work. The things to be done on the SAP backend:

  1. Extend MARA table with custom Z fields (in SAP it is called Append structure)
  2. Extend interface structure BAPI_TE_MARA with the fields which should exactly correspond to the MARA fields

This is how it must look like on backend

enter image description here

If you don't see any custom fields in BAPI_TE_MARA except MATERIAL probably step 2 is missing on SAP side. As what I got from your comments, they created structure ZMM_S_MATMAS_ADDITION but appended it only to MARA, but not to BAPI_TE_MARA.

What is missing from Sandra excellent holistic answer is step 3: for all this construction to work some customizing need to be done.

  1. T130F table must contain your custom fields. To maintain the entry for T130F go to transaction SPRO or directly to maintenance view V_130F.

SPRO way: go to SPRO -> Logistics-General -> Material Master -> Field Selection -> Assign fields to field Selection Groups and maintain the entry in the table

Sample ABAP code that does the thing:

DATA: ls_headdata      TYPE bapimathead,
      lt_extensionin   TYPE STANDARD TABLE OF bapiparex,
      ls_extensionin   LIKE LINE OF lt_extensionin,
      lt_extensioninx  TYPE STANDARD TABLE OF bapiparexx,
      ls_extensioninx  LIKE LINE OF lt_extensioninx,
      lt_messages      TYPE bapiret2_t,
      ls_bapi_te_mara  TYPE bapi_te_mara,
      ls_bapi_te_marax TYPE bapi_te_marax.

ls_headdata-material = |{ ls_headdata-material ALPHA = IN }|.
ls_headdata-basic_view = 'X'.

ls_bapi_te_mara-material = ls_headdata-material.
ls_bapi_te_mara-zztest1  = '322223'.

ls_bapi_te_marax-material = ls_headdata-material.
ls_bapi_te_marax-zztest1  = 'X'.

ls_extensionin-structure  = 'BAPI_TE_MARA'.
ls_extensionin-valuepart1 = ls_bapi_te_mara
APPEND ls_extensionin TO lt_extensionin.

ls_extensioninx-structure = 'BAPI_TE_MARAX'.
ls_extensioninx-valuepart1 = ls_bapi_te_marax-zztest1.
APPEND ls_extensioninx TO lt_extensioninx.

CALL FUNCTION 'BAPI_MATERIAL_SAVEDATA'
  EXPORTING
    headdata       = ls_headdata
  TABLES
    returnmessages = lt_messages
    extensionin    = lt_extensionin
    extensioninx   = lt_extensioninx.

CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
  EXPORTING
    wait = 'X'.

Based on this you can model your .Net code for BAPI calling.

P.S. Pay attention to the first line with ALPHA = IN. The input to the material number field must be in fully qualified 18-char format with leading zeroes, e.g. 000000000000323, otherwise the update will fail.

Solution 3:[3]

Always extend structure EMARA and not MARA, BAPI_TE_MARA, ... directly.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Sandra Rossi
Solution 2 Suncatcher
Solution 3 user18939979