IDocs (Intermediate Documents) sind SAPs Standardformat für den elektronischen Datenaustausch (EDI). Sie ermöglichen die asynchrone Kommunikation zwischen SAP-Systemen und externen Partnern.
IDoc-Struktur
| Komponente | Beschreibung |
|---|---|
| Control Record | Steuerinformationen (EDIDC) |
| Data Records | Nutzdaten in Segmenten (EDIDD) |
| Status Records | Verarbeitungsstatus (EDIDS) |
IDoc-Typen und Message-Types
| Element | Transaktion | Beschreibung |
|---|---|---|
| IDoc-Typ | WE30 | Struktur der Daten |
| Message-Type | WE81 | Geschäftsprozess |
| Segment | WE31 | Datencontainer |
| Partner | WE20 | Kommunikationspartner |
Grundlegende Beispiele
IDoc manuell erstellen
DATA: lt_edidc TYPE TABLE OF edidc, ls_edidc TYPE edidc, lt_edidd TYPE TABLE OF edidd, ls_edidd TYPE edidd.
" Control Record füllenls_edidc-mestyp = 'ORDERS'.ls_edidc-idoctp = 'ORDERS05'.ls_edidc-rcvprt = 'LS'.ls_edidc-rcvprn = 'PARTNER01'.ls_edidc-sndprt = 'LS'.ls_edidc-sndprn = sy-sysid.APPEND ls_edidc TO lt_edidc.
" Data Segment E1EDK01 - Headerls_edidd-segnam = 'E1EDK01'.ls_edidd-sdata = 'Bestellkopfdaten...'.APPEND ls_edidd TO lt_edidd.
" Data Segment E1EDP01 - Positionls_edidd-segnam = 'E1EDP01'.ls_edidd-sdata = 'Positionsdaten...'.APPEND ls_edidd TO lt_edidd.
" IDoc erstellenCALL FUNCTION 'IDOC_INBOUND_ASYNCHRONOUS' TABLES idoc_control_rec_40 = lt_edidc idoc_data_rec_40 = lt_edidd.IDoc mit Struktur befüllen
TYPES: BEGIN OF ty_e1edk01, belnr TYPE char35, datum TYPE char8, waers TYPE char3, END OF ty_e1edk01.
DATA: ls_e1edk01 TYPE ty_e1edk01, ls_edidd TYPE edidd.
ls_e1edk01-belnr = '4500000123'.ls_e1edk01-datum = '20250115'.ls_e1edk01-waers = 'EUR'.
ls_edidd-segnam = 'E1EDK01'.ls_edidd-sdata = ls_e1edk01. " Strukturzuweisung
APPEND ls_edidd TO lt_edidd.IDoc lesen und analysieren
DATA: lv_docnum TYPE edi_docnum VALUE '0000000000012345', ls_edidc TYPE edidc, lt_edidd TYPE TABLE OF edidd, lt_edids TYPE TABLE OF edids.
" Control Record lesenSELECT SINGLE * FROM edidc INTO ls_edidc WHERE docnum = lv_docnum.
" Data Records lesenSELECT * FROM edid4 INTO TABLE lt_edidd WHERE docnum = lv_docnum ORDER BY segnum.
" Status Records lesenSELECT * FROM edids INTO TABLE lt_edids WHERE docnum = lv_docnum ORDER BY countr DESCENDING.
LOOP AT lt_edidd INTO DATA(ls_data). WRITE: / ls_data-segnam, ls_data-sdata(50).ENDLOOP.IDoc-Outbound über Master-IDoc
DATA: ls_master_idoc TYPE edidc, lt_comm_idocs TYPE TABLE OF edidc.
" Master-IDoc Parameterls_master_idoc-mestyp = 'MATMAS'.ls_master_idoc-idoctp = 'MATMAS05'.ls_master_idoc-rcvprt = 'LS'.ls_master_idoc-rcvprn = 'CLNT800'.
" IDoc-Versand auslösenCALL FUNCTION 'MASTER_IDOC_DISTRIBUTE' EXPORTING master_idoc_control = ls_master_idoc TABLES communication_idoc_control = lt_comm_idocs master_idoc_data = lt_edidd EXCEPTIONS error_in_idoc_control = 1 error_writing_idoc_status = 2 error_in_idoc_data = 3 sending_logical_system_unknown = 4 OTHERS = 5.
IF sy-subrc = 0. COMMIT WORK. LOOP AT lt_comm_idocs INTO DATA(ls_comm). WRITE: / 'IDoc erstellt:', ls_comm-docnum. ENDLOOP.ENDIF.IDoc-Status setzen
DATA: lt_status TYPE TABLE OF bdidocstat, ls_status TYPE bdidocstat.
ls_status-docnum = lv_docnum.ls_status-status = '53'. " Application document postedls_status-msgty = 'S'.ls_status-msgid = 'E0'.ls_status-msgno = '000'.ls_status-msgv1 = 'Erfolgreich verarbeitet'.APPEND ls_status TO lt_status.
CALL FUNCTION 'IDOC_STATUS_WRITE_TO_DATABASE' EXPORTING idoc_number = lv_docnum TABLES idoc_status = lt_status EXCEPTIONS idoc_foreign_lock = 1 idoc_not_found = 2 idoc_status_records_empty = 3 OTHERS = 4.
COMMIT WORK.Inbound-Funktionsbaustein für eigenen IDoc-Typ
FUNCTION z_idoc_inbound_orders.*"----------------------------------------------------------------------*" IMPORTING*" VALUE(INPUT_METHOD) TYPE BDWFAP_PAR-INPUTMETHD*" VALUE(MASS_PROCESSING) TYPE BDWFAP_PAR-MASS_PROC*" EXPORTING*" VALUE(WORKFLOW_RESULT) TYPE BDWFAP_PAR-RESULT*" VALUE(APPLICATION_VARIABLE) TYPE BDWFAP_PAR-APPL_VAR*" VALUE(IN_UPDATE_TASK) TYPE BDWFAP_PAR-UPDATETASK*" VALUE(CALL_TRANSACTION_DONE) TYPE BDWFAP_PAR-CALLTRANS*" TABLES*" IDOC_CONTRL STRUCTURE EDIDC*" IDOC_DATA STRUCTURE EDIDD*" IDOC_STATUS STRUCTURE BDIDOCSTAT*" RETURN_VARIABLES STRUCTURE BDWFRETVAR*" SERIALIZATION_INFO STRUCTURE BDI_SER*"----------------------------------------------------------------------
DATA: ls_order TYPE zorder_header, ls_item TYPE zorder_item, lt_items TYPE TABLE OF zorder_item.
LOOP AT idoc_contrl INTO DATA(ls_control). " IDoc-Daten verarbeiten LOOP AT idoc_data INTO DATA(ls_data) WHERE docnum = ls_control-docnum.
CASE ls_data-segnam. WHEN 'Z1ORDER_HEADER'. ls_order = ls_data-sdata.
WHEN 'Z1ORDER_ITEM'. ls_item = ls_data-sdata. APPEND ls_item TO lt_items. ENDCASE. ENDLOOP.
" Bestellung anlegen TRY. " Business-Logik hier
" Erfolgsstatus DATA(ls_status) = VALUE bdidocstat( docnum = ls_control-docnum status = '53' msgty = 'S' msgid = 'ZMM' msgno = '001' ). APPEND ls_status TO idoc_status.
CATCH cx_root INTO DATA(lx_error). " Fehlerstatus ls_status = VALUE #( docnum = ls_control-docnum status = '51' msgty = 'E' msgid = 'ZMM' msgno = '002' msgv1 = lx_error->get_text( ) ). APPEND ls_status TO idoc_status. ENDTRY. ENDLOOP.
ENDFUNCTION.ALE-Verteilung konfigurieren
" Verteilungsmodell lesenDATA: lt_receivers TYPE TABLE OF bdcp_receiver.
CALL FUNCTION 'ALE_MODEL_DETERMINE_RECEIVERS' EXPORTING message_type = 'MATMAS' sending_logical_system = 'SRCCLNT100' TABLES receivers = lt_receivers EXCEPTIONS no_entry_in_model = 1 OTHERS = 2.
LOOP AT lt_receivers INTO DATA(ls_receiver). WRITE: / 'Empfänger:', ls_receiver-rcvprn.ENDLOOP.IDocs selektieren und auswerten
SELECT edidc~docnum, edidc~status, edidc~credat, edidc~cretim, edidc~mestyp, edidc~idoctp, edidc~rcvprn FROM edidc WHERE mestyp = 'ORDERS' AND status IN ('51', '56') " Fehler-Status AND credat >= @( sy-datum - 7 ) INTO TABLE @DATA(lt_error_idocs).
LOOP AT lt_error_idocs INTO DATA(ls_idoc). WRITE: / ls_idoc-docnum, ls_idoc-status, ls_idoc-credat.ENDLOOP.IDoc erneut verarbeiten
DATA: lt_docnum TYPE TABLE OF edi_docnum.
APPEND lv_docnum TO lt_docnum.
CALL FUNCTION 'EDI_DOCUMENT_OPEN_FOR_PROCESS' EXPORTING document_number = lv_docnum EXCEPTIONS document_foreign_lock = 1 document_not_exist = 2 document_not_open = 3 status_is_unable_proc = 4 OTHERS = 5.
IF sy-subrc = 0. " IDoc erneut verarbeiten CALL FUNCTION 'IDOC_INBOUND_SINGLE' EXPORTING pi_idoc_number = lv_docnum EXCEPTIONS parameter_error = 1 idoc_not_found = 2 lock_error = 3 OTHERS = 4.
CALL FUNCTION 'EDI_DOCUMENT_CLOSE_PROCESS' EXPORTING document_number = lv_docnum.ENDIF.Change Pointer für IDoc-Erstellung
" Change Pointer aktivieren (BD52/BD61)" BD50: Message-Type <-> Objekt" BD52: Change Pointer aktiv
" Change Pointer manuell erzeugenDATA: lt_cp TYPE TABLE OF bdcp2.
APPEND VALUE #( mestyp = 'MATMAS' objkey = 'MATNR' tabkey = '000000000000100000' chngid = 'U' cdchgid = sy-datum cdchgtm = sy-uzeit) TO lt_cp.
CALL FUNCTION 'CHANGE_POINTERS_CREATE' TABLES change_pointers = lt_cp.
" Change Pointer verarbeiten (RBDMIDOC)CALL FUNCTION 'RBDMIDOC' EXPORTING mestyp = 'MATMAS'.Segment-Daten mit Struktur verarbeiten
" Dynamisches Segment-MappingDATA: lo_struct TYPE REF TO cl_abap_structdescr.
LOOP AT lt_edidd INTO DATA(ls_segment). " Struktur zum Segment ermitteln DATA(lv_segdef) = 'E1' && ls_segment-segnam+2.
TRY. lo_struct ?= cl_abap_typedescr=>describe_by_name( lv_segdef ).
DATA: lr_data TYPE REF TO data. CREATE DATA lr_data TYPE HANDLE lo_struct. ASSIGN lr_data->* TO FIELD-SYMBOL(<fs_segment>).
" Daten übertragen <fs_segment> = ls_segment-sdata.
" Felder verarbeiten LOOP AT lo_struct->components INTO DATA(ls_comp). ASSIGN COMPONENT ls_comp-name OF STRUCTURE <fs_segment> TO FIELD-SYMBOL(<fs_value>). IF sy-subrc = 0. WRITE: / ls_comp-name, '=', <fs_value>. ENDIF. ENDLOOP.
CATCH cx_sy_move_cast_error. " Segment unbekannt ENDTRY.ENDLOOP.IDoc per RFC versenden
DATA: lt_edidc TYPE TABLE OF edidc40, lt_edidd TYPE TABLE OF edidd40.
" Control und Data Records aufbauen...
" IDoc an RFC-Destination sendenCALL FUNCTION 'IDOC_INBOUND_ASYNCHRONOUS' DESTINATION 'RFC_DEST_TARGET' TABLES idoc_control_rec_40 = lt_edidc idoc_data_rec_40 = lt_edidd EXCEPTIONS system_failure = 1 communication_failure = 2.
IF sy-subrc = 0. WRITE: / 'IDoc erfolgreich gesendet'.ELSE. WRITE: / 'Fehler beim Versand'.ENDIF.IDoc-Serialisierung
" Serialisierung für abhängige IDocsDATA: lt_serial TYPE TABLE OF bdi_ser.
" Serialisierungsobjekt definierenAPPEND VALUE #( session = '001' rcvpor = 'SAPEDI' rcvprt = 'LS' rcvprn = 'TARGET' mestyp = 'ORDERS' serial = 'ORDERS_SERIAL') TO lt_serial.
" IDoc mit Serialisierung versendenCALL FUNCTION 'IDOC_INBOUND_ASYNCHRONOUS' TABLES idoc_control_rec_40 = lt_edidc idoc_data_rec_40 = lt_edidd idoc_serialization = lt_serial.IDoc-Status-Übersicht
| Status | Beschreibung | Richtung |
|---|---|---|
| 01 | IDoc erzeugt | Outbound |
| 03 | IDoc an Port übergeben | Outbound |
| 30 | IDoc bereit zur Übertragung | Outbound |
| 50 | IDoc zum Anwendung hinzugefügt | Inbound |
| 51 | Anwendungsdokument nicht gebucht | Inbound |
| 53 | Anwendungsdokument gebucht | Inbound |
| 56 | IDoc mit EDI-Syntax-Fehler | Inbound |
Best Practices
- Fehlerbehandlung: Aussagekräftige Status-Nachrichten schreiben
- Monitoring: Transaktion WE02/WE05 für IDoc-Überwachung
- Performance: Massenverarbeitung mit Paketen implementieren
- Serialisierung: Bei abhängigen IDocs Reihenfolge sicherstellen
- Archivierung: Alte IDocs regelmäßig archivieren (SARA)
- Testing: WE19 für Einzeltest, BD87 für Nachverarbeitung
Wichtige Transaktionen
| Transaktion | Beschreibung |
|---|---|
| WE02/WE05 | IDoc-Anzeige |
| WE19 | IDoc-Testumgebung |
| WE20 | Partnervereinbarungen |
| WE21 | Ports |
| BD54 | Logische Systeme |
| BD64 | Verteilungsmodell |
| BD87 | IDoc-Nachverarbeitung |
Verwandte Themen
- BAPI-Entwicklung - Synchrone Schnittstellen
- RFC und Destinationen - Remote Function Calls
- XML-Verarbeitung - Alternative Formate
- Background Jobs - Asynchrone Verarbeitung