ABAP – How to create/modify Source lists

In this code snippet I’ll demonstrate how to create or modify a source list (TCode ME01). I did’t find a suitable “standard way” how to do it, but after digging in the function module which processes inboud IDOC for source list (IDOC_INPUT_SRCLST) I managed to replicate the functionality in my own code.

I tried several ways how to do it:

Source list via BDC – batch input

One possible solution is a batch input. But this one is not very practical when you need to modify source list’s line items (especially when there are more line items), because it’s quite difficult to adress line items apeearing on later pages of the list. So you can’t easily access them via index… but anyway, if anyone is interested, you can use the following code:

DATA:
  gt_bdcdata TYPE TABLE OF bdcdata,
  gt_return  TYPE TABLE OF bdcmsgcoll,
  gv_message TYPE string.

START-OF-SELECTION.
  PERFORM bdc_dynpro USING 'SAPLMEOR'       '0200'.
  PERFORM bdc_field  USING 'BDC_CURSOR'     'EORD-MATNR'.
  PERFORM bdc_field  USING 'BDC_OKCODE'     '/00'.
  PERFORM bdc_field  USING 'EORD-MATNR'     '1000001974'.
  PERFORM bdc_field  USING 'EORD-WERKS'     '0040'.

* Modify validity dates of the 5th line of source list
  PERFORM bdc_dynpro USING 'SAPLMEOR'       '0205'.
  PERFORM bdc_field  USING 'BDC_CURSOR'     'EORD-BDATU(01)'.
  PERFORM bdc_field  USING 'BDC_OKCODE'     '=NS'.
  PERFORM bdc_field  USING 'EORD-VDATU(05)' '01.04.2016'.
  PERFORM bdc_field  USING 'EORD-BDATU(05)' '02.04.2016'.

* Add new line item in the source list
  PERFORM bdc_dynpro USING 'SAPLMEOR'       '0205'.
  PERFORM bdc_field  USING 'BDC_CURSOR'     'EORD-VDATU(02)'.
  PERFORM bdc_field  USING 'BDC_OKCODE'     '=BU'.
  PERFORM bdc_field  USING 'EORD-VDATU(02)' '10.04.2016'.
  PERFORM bdc_field  USING 'EORD-BDATU(02)' '10.04.2016'.
  PERFORM bdc_field  USING 'EORD-LIFNR(02)' '510769'.
  PERFORM bdc_field  USING 'EORD-EKORG(02)' '0040'.
  PERFORM bdc_field  USING 'EORD-MEINS(02)' 'PC'.
  PERFORM bdc_field  USING 'EORD-EBELN(02)' '5500000667'.
  PERFORM bdc_field  USING 'EORD-EBELP(02)' '0010'.
  PERFORM bdc_field  USING 'EORD-AUTET(02)' '2'.


  CALL TRANSACTION 'ME01' USING gt_bdcdata
                          MODE  'N'
                          UPDATE 'S'
                          MESSAGES INTO gt_return.

  LOOP AT gt_return ASSIGNING FIELD-SYMBOL(<ls_return>).
    MESSAGE ID <ls_return>-msgid
            TYPE <ls_return>-msgtyp
            NUMBER <ls_return>-msgnr
            WITH <ls_return>-msgv1
                 <ls_return>-msgv2
                 <ls_return>-msgv3
                 <ls_return>-msgv4
            INTO gv_message.
    WRITE:/ gv_message.
  ENDLOOP.

FORM bdc_field USING fnam fval.
  DATA: ls_bdcdata TYPE bdcdata.

  ls_bdcdata-fnam = fnam.
  ls_bdcdata-fval  = fval.
  APPEND ls_bdcdata TO gt_bdcdata.
ENDFORM.

FORM bdc_dynpro USING prog scr.
  DATA: ls_bdcdata TYPE bdcdata.

  ls_bdcdata-program = prog.
  ls_bdcdata-dynpro  = scr.
  ls_bdcdata-dynbegin = 'X'.
  APPEND ls_bdcdata TO gt_bdcdata.
ENDFORM.

Source list via IDOC

I also tried to use inbound IDOC method, because I don’t have to care about adressing the item row numbers and everything is done by SAP standard. The problem is that the IDOC completely IGNORES the MSGFN field. Therefore you are not able to neither modify nor delete line items of a source list. The only action you can do this way is to INSERT new items.

CLASS lcl_idoc DEFINITION.
 PUBLIC SECTION.
   METHODS:
     send_idoc.

 PRIVATE SECTION.
   CONSTANTS:
     co_idoc_header_segment TYPE edilsegtyp VALUE 'E1EORDH',
     co_idoc_item_segment TYPE edilsegtyp VALUE 'E1EORDM',
     co_idoc_message_type TYPE edi_mestyp VALUE 'SRCLST',
     co_idoc_basic_type TYPE edi_idoctp VALUE 'SRCLST01'.

   DATA:
     ms_control_rec TYPE edidc,
     mt_idoc_data TYPE TABLE OF edidd,
     ms_process_data TYPE tede2.

   METHODS:
     create_control_record,
     create_header_segment,
     create_item_segments,
     create_idoc_db,
     post_idoc_inbound.
ENDCLASS.

CLASS lcl_idoc IMPLEMENTATION.
 METHOD send_idoc.
   ir_idoc->create_control_record( ).
   ir_idoc->create_header_segment( ).
   ir_idoc->create_item_segments( ).
   ir_idoc->create_idoc_db( ).
   ir_idoc->post_idoc_inbound( ).
 ENDMETHOD.


 METHOD create_control_record.
   DATA:
     lv_logsys type LOGSYS.

   ms_control_rec-mestyp = co_idoc_message_type.
   ms_control_rec-idoctp = co_idoc_basic_type.
   ms_control_rec-direct = 2. " 1 = outbound, 2 = inbound

   CALL FUNCTION 'OWN_LOGICAL_SYSTEM_GET'
     IMPORTING
       OWN_LOGICAL_SYSTEM = lv_logsys.

   ms_control_rec-rcvprt = 'LS'.
   ms_control_rec-rcvprn = lv_logsys.

   ms_control_rec-sndprt = 'LS'.
   ms_control_rec-sndprn = lv_logsys.
   ms_control_rec-sndpor = 'DUMMY'.

 ENDMETHOD.


 METHOD create_header_segment.
   DATA:
     ls_header TYPE e1eordh.

   CALL FUNCTION 'OWN_LOGICAL_SYSTEM_GET'
     IMPORTING
       OWN_LOGICAL_SYSTEM = ls_header-logsy.

   ls_header-msgfn = '005'. "This is ignored!!!
   ls_header-matnr = '1000001974'.
   ls_header-werks = '0040'.

   APPEND INITIAL LINE TO mt_idoc_data 
     ASSIGNING FIELD-SYMBOL(<ls_header>).

   <ls_header>-segnam = co_idoc_header_segment.
   <ls_header>-sdata  = ls_header.
 ENDMETHOD.


 METHOD create_item_segments.
   DATA:
     ls_item TYPE e1eordm,
     lv_isocode type ISOCD_UNIT.

*  IDOC accepts ISO codes ONLY!!! (e.g. 'PC' => 'PCE')
   SELECT SINGLE isocode 
     FROM t006 INTO lv_isocode
     WHERE msehi = 'PC'.

*  INSERT new line item 
   ls_item-erdat = sy-datum. 
   ls_item-ernam = sy-uname. 
   ls_item-vdatu = '20160401'.
   ls_item-bdatu = '20160401'.
   ls_item-lifnr = '0000510769'.
   ls_item-ebeln = '5500000667'.
   ls_item-ebelp = '00010'.
   ls_item-ekorg = '0040'.

*  L = scheduling agreement
   ls_item-vrtyp = 'L'. " L = scheduling agreement"

*  '0' = Standard
*  '2' = Consignment
   ls_item-eortp = '0'. " category of source list record 

*  ' ' = Source list record not relevant to MRP
*  '1' = Record relevant to MRP
*  '2' = Recored relevant to MRP, sch.lines generated automatically
   ls_item-autet = '2'. 

   ls_item-meins = lv_isocode.

   APPEND INITIAL LINE TO mt_idoc_data 
     ASSIGNING FIELD-SYMBOL(<ls_item>).

   <ls_item>-segnam = 'E1EORDM'.
   <ls_item>-sdata = ls_item.

 ENDMETHOD.


 METHOD create_idoc_db.

   CALL FUNCTION 'IDOC_INBOUND_WRITE_TO_DB'
     IMPORTING
       pe_idoc_number = ms_control_rec-docnum
       pe_inbound_process_data = ms_process_data
     TABLES
       t_data_records = mt_idoc_data
     CHANGING
       pc_control_record = ms_control_rec
     EXCEPTIONS
       idoc_not_saved = 1
     OTHERS = 2.
   IF sy-subrc <> 0.
     MESSAGE ID sy-msgid 
             TYPE sy-msgty 
             NUMBER sy-msgno 
             WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
   ELSE.
     COMMIT WORK AND WAIT.
   ENDIF.

 ENDMETHOD.

 METHOD post_idoc_inbound.
   DATA:
     lt_control_recs TYPE TABLE OF edidc.

   APPEND ms_control_rec TO lt_control_recs.

   CALL FUNCTION 'IDOC_START_INBOUND'
     EXPORTING
       pi_inbound_process_data = ms_process_data
       pi_called_online = 'X'
       succ_show_flag = 'X'
     TABLES
       t_control_records = lt_control_recs
     EXCEPTIONS
       invalid_document_number = 1
       error_before_call_application = 2
       inbound_process_not_possible = 3
       old_wf_start_failed = 4
       wf_task_error = 5
       serious_inbound_error = 6
       OTHERS = 7.

   IF sy-subrc <> 0.
     MESSAGE ID sy-msgid 
             TYPE sy-msgty 
             NUMBER sy-msgno 
             WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
   ENDIF.

 ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  CREATE OBJECT gr_idoc.
  gr_idoc->send_idoc( ).

The reason why it’s not possible to modify or delete data is hidden in SAP standard FM ‘IDOC_INPUT_SRCLST’. If you dig in and check it’s form FILL_APPL_STRUCTURES_SRCLST you will find this:

Clear ZEORD

  1. In the called form READ_SEG_E1EORDM you won’t find a row, where ZEORD is read.
  2. Even if the ZEAORD was read, on line #127 it is cleared.

This means the even if you try to address line items from EORD by their positions (ZEORD), it will be cleared (by standard!!!) and everything will be treated as new line items.

Next bad thing is hidden later in FM IDOC_INPUT_SRCLST, where it’s hardcoded, that all lines will be treated as NEW entries.

IDOC problem

Therefore you can’t use the IDOC method for updating or deleting entries unless you want to modify SAP standard.

Source list via ME_DIRECT_INPUT_SOURCE_LIST

Finally I’ve discovered a fully functional way how to

  1. CREATE
  2. UPDATE
  3. DELETE

entries from the source list.

I managed to do it by more or less replicating code from the IDOC_INPUT_SCRLST, where I re-used some function modules called there in the following order:

  1. ME_INITIALIZE_SOURCE_LIST
  2. ME_DIRECT_INPUT_SOURCE_LIST
  3. ME_POST_SOURCE_LIST_NEW
  4. ME_WRITE_DISP_RECORD_SOS
  5. COMMIT WORK AND WAIT

The following code takes two input parameters (validity of the new line in source list) on the selection screen, invalidates all existing lines in source list which validity time frame overlap with the new line’s validity and creates the new line with given validity dates.

Here you can see source list status BEFORE the program execution

ME01 - before execution

On the program’s selection screen I enter validity of the new line item in the source list

Selection screen

And here is the status of the source list AFTER the program was executed

Updated source list

DATA:
 gv_new_sag   TYPE ebeln,
 gv_new_lifnr TYPE lifnr,
 gv_matnr     TYPE matnr,
 gv_werks     TYPE werks_d.

SELECTION-SCREEN BEGIN OF BLOCK bl01.
  PARAMETERS:
    p_vdatu LIKE eord-vdatu,
    p_bdatu LIKE eord-bdatu.
SELECTION-SCREEN END OF BLOCK bl01.


FORM update_source_list USING uv_new_sag TYPE ebeln
                              uv_new_lifnr TYPE lifnr
                              uv_matnr TYPE matnr
                              uv_werks TYPE werks_d.
  DATA:
    lt_eordu TYPE TABLE OF eordu,
    lt_eord TYPE TABLE OF eord,
    lt_tupel TYPE TABLE OF metup,
    lv_lifnr TYPE lifnr.

* Get all existing source list's line items for given MATNR, WERKS, LIFNR
  SELECT *
    INTO CORRESPONDING FIELDS OF TABLE lt_eordu
    FROM eord
    WHERE matnr = uv_matnr
      AND werks = uv_werks
      AND (
            ( vdatu <= p_vdatu AND bdatu >= p_vdatu )
         OR ( vdatu <= p_bdatu AND bdatu >= p_bdatu )
         OR ( vdatu >= p_vdatu AND bdatu <= p_bdatu )
      ).

* Make sure there's at least one source list's line item
  CHECK lt_eordu IS NOT INITIAL.

  SORT lt_eordu BY vdatu bdatu.
  LOOP AT lt_eordu ASSIGNING FIELD-SYMBOL(<ls_eordu>).
    APPEND INITIAL LINE TO lt_eord 
      ASSIGNING FIELD-SYMBOL(<ls_eord>).
    MOVE-CORRESPONDING <ls_eordu> TO <ls_eord>.

* Item which is valid at beginning of the new source list entry will be updated
* It can be only one line
    IF <ls_eordu>-vdatu < p_vdatu AND 
       <ls_eordu>-bdatu >= p_vdatu.

* Update the item so it's validity ends before validity of the new entry
      <ls_eordu>-bdatu = p_vdatu - 1.
      <ls_eordu>-kz = 'U'.
    ELSE.

* Source list's items which are NOT valid at beginning of the new source list's entry will be deleted
      <ls_eordu>-kz = 'D'.

    ENDIF.

  ENDLOOP.


  READ TABLE lt_eordu ASSIGNING <ls_eordu> INDEX 1.
* We use this line as a template for the new source list's entry
  APPEND INITIAL LINE TO lt_eordu 
    ASSIGNING FIELD-SYMBOL(<ls_eordu_new>).
  <ls_eordu_new> = <ls_eordu>.

* Set correct data for the new source list's entry
  CLEAR <ls_eordu_new>-zeord.
  <ls_eordu_new>-kz = 'I'.
  <ls_eordu_new>-vdatu = p_vdatu.
  <ls_eordu_new>-bdatu = p_bdatu.

  CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
    EXPORTING
      input = uv_new_lifnr
    IMPORTING
      output = <ls_eordu_new>-lifnr.

  <ls_eordu_new>-ebeln = uv_new_sag.


  CALL FUNCTION 'ME_INITIALIZE_SOURCE_LIST'.

  CALL FUNCTION 'ME_DIRECT_INPUT_SOURCE_LIST'
    EXPORTING
      i_matnr = uv_matnr
      i_werks = uv_werks
      i_vorga = 'B'
    TABLES
      t_eord = lt_eordu
    EXCEPTIONS
      plant_missing = 1
      material_missing = 2
      OTHERS = 3.
  IF sy-subrc = 0.
    APPEND INITIAL LINE TO lt_tupel 
      ASSIGNING FIELD-SYMBOL(<ls_tupel>).
    <ls_tupel>-matnr = uv_matnr.
    <ls_tupel>-werks = uv_werks.

    CALL FUNCTION 'ME_POST_SOURCE_LIST_NEW'.

    CALL FUNCTION 'ME_WRITE_DISP_RECORD_SOS' IN UPDATE TASK
      TABLES
        eord_alt = lt_eord
        eord_neu = lt_eordu
        tupel = lt_tupel.

    COMMIT WORK AND WAIT.
  ENDIF.

ENDFORM.

INITIALIZATION.
  p_vdatu = sy-datum + 1.
  p_bdatu = '99991231'.


START-OF-SELECTION.
  gv_new_sag = '5500000667'.
  gv_new_lifnr = '510769'.

  gv_matnr = '1000001974'.
  gv_werks = '0040'.

  PERFORM update_source_list USING gv_new_sag
                                   gv_new_lifnr
                                   gv_matnr
                                   gv_werks.

9 thoughts on “ABAP – How to create/modify Source lists

  1. FOR THE CODE IT IS TRIGGERING A SYNTAX ERROR LIKE THIS -{Field “FIELD-SYMBOLS” is unknown. It is neither in one of the
    specified tables nor defined by a “DATA” statement. “DATA” statement}.

  2. Hi
    Can i get the rest of the code in last ABAP Option. Currently its only till start of selection.

    Thanks
    GSP

  3. Hi,

    How do we activate change log to view change history after successful Source List update via this method?

    Thanks…

Leave a Reply