BAPIs (Business Application Programming Interfaces) sind standardisierte Schnittstellen für den Zugriff auf SAP-Geschäftsobjekte. Sie folgen strengen Konventionen und ermöglichen eine einheitliche Integration.
BAPI-Konventionen
| Konvention | Beschreibung |
|---|---|
| Namensgebung | BAPI_<OBJEKT>_<AKTION> |
| RETURN-Parameter | Immer BAPIRET2 oder BAPIRET2_T |
| Kein COMMIT | Aufrufer ist verantwortlich |
| Keine Dialoge | Keine Popups oder Messages |
| RFC-fähig | Remotefähiger Funktionsbaustein |
BAPIRET2-Struktur
| Feld | Beschreibung |
|---|---|
| TYPE | S/E/W/I/A (Success/Error/Warning/Info/Abort) |
| ID | Nachrichtenklasse |
| NUMBER | Nachrichtennummer |
| MESSAGE | Vollständiger Nachrichtentext |
| MESSAGE_V1-V4 | Variablen |
| LOG_NO | Log-Nummer |
| LOG_MSG_NO | Log-Nachrichtennummer |
Beispiele
1. Standard-BAPI aufrufen
" BAPI zum Lesen eines KundenDATA: ls_address TYPE bapicustomer_04, lt_return TYPE TABLE OF bapiret2.
CALL FUNCTION 'BAPI_CUSTOMER_GETDETAIL2' EXPORTING customerno = '0000001000' IMPORTING customeraddress = ls_address TABLES return = lt_return.
" FehlerprüfungIF line_exists( lt_return[ type = 'E' ] ). " Fehler behandeln LOOP AT lt_return INTO DATA(ls_error) WHERE type = 'E'. WRITE: / ls_error-message. ENDLOOP.ELSE. " Erfolg WRITE: / ls_address-name, ls_address-city.ENDIF.2. BAPI mit COMMIT
DATA: lt_return TYPE TABLE OF bapiret2.
" Bestellung anlegenCALL FUNCTION 'BAPI_PO_CREATE1' EXPORTING poheader = ls_header poheaderx = ls_headerx TABLES poitem = lt_items poitemx = lt_itemsx return = lt_return.
" FehlerprüfungREAD TABLE lt_return WITH KEY type = 'E' TRANSPORTING NO FIELDS.
IF sy-subrc <> 0. " Erfolg - COMMIT durchführen CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' EXPORTING wait = abap_true. " Warten auf Commit
WRITE: / 'Bestellung angelegt'.ELSE. " Fehler - ROLLBACK CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
" Fehlermeldungen ausgeben LOOP AT lt_return INTO DATA(ls_msg) WHERE type CA 'EAX'. WRITE: / ls_msg-message. ENDLOOP.ENDIF.3. Eigenen BAPI erstellen
" Funktionsbaustein: Z_BAPI_CUSTOMER_GETLISTFUNCTION z_bapi_customer_getlist.*"----------------------------------------------------------------------*"*"Lokale Schnittstelle:*" IMPORTING*" VALUE(IV_COUNTRY) TYPE LAND1 OPTIONAL*" VALUE(IV_MAX_ROWS) TYPE I DEFAULT 100*" EXPORTING*" VALUE(ET_CUSTOMERS) TYPE ZTT_CUSTOMER_LIST*" TABLES*" RETURN STRUCTURE BAPIRET2*"----------------------------------------------------------------------
" Eingabevalidierung IF iv_max_rows < 1 OR iv_max_rows > 10000. append_return( EXPORTING iv_type = 'E' iv_id = 'ZCUST' iv_number = '001' iv_v1 = CONV #( iv_max_rows ) CHANGING ct_return = return[] ). RETURN. ENDIF.
" Daten lesen TRY. SELECT kunnr, name1, ort01, land1 FROM kna1 WHERE land1 = @iv_country OR @iv_country IS INITIAL INTO CORRESPONDING FIELDS OF TABLE @et_customers UP TO @iv_max_rows ROWS.
IF sy-subrc <> 0. append_return( EXPORTING iv_type = 'I' iv_id = 'ZCUST' iv_number = '002' CHANGING ct_return = return[] ). ELSE. append_return( EXPORTING iv_type = 'S' iv_id = 'ZCUST' iv_number = '003' iv_v1 = CONV #( lines( et_customers ) ) CHANGING ct_return = return[] ). ENDIF.
CATCH cx_root INTO DATA(lx_error). append_return( EXPORTING iv_type = 'E' iv_id = 'ZCUST' iv_number = '004' iv_v1 = lx_error->get_text( )(50) CHANGING ct_return = return[] ). ENDTRY.
ENDFUNCTION.
" Hilfsmethode zum Hinzufügen von RETURN-EinträgenFORM append_return USING iv_type TYPE sy-msgty iv_id TYPE sy-msgid iv_number TYPE sy-msgno iv_v1 TYPE clike OPTIONAL iv_v2 TYPE clike OPTIONAL iv_v3 TYPE clike OPTIONAL iv_v4 TYPE clike OPTIONAL CHANGING ct_return TYPE bapiret2_t.
DATA: ls_return TYPE bapiret2, lv_text TYPE string.
MESSAGE ID iv_id TYPE iv_type NUMBER iv_number WITH iv_v1 iv_v2 iv_v3 iv_v4 INTO lv_text.
ls_return-type = iv_type. ls_return-id = iv_id. ls_return-number = iv_number. ls_return-message = lv_text. ls_return-message_v1 = iv_v1. ls_return-message_v2 = iv_v2. ls_return-message_v3 = iv_v3. ls_return-message_v4 = iv_v4.
APPEND ls_return TO ct_return.ENDFORM.4. BAPI-Wrapper-Klasse
CLASS zcl_customer_bapi DEFINITION. PUBLIC SECTION. TYPES: BEGIN OF ty_customer, kunnr TYPE kunnr, name1 TYPE name1_gp, ort01 TYPE ort01_gp, land1 TYPE land1_gp, END OF ty_customer, ty_customers TYPE STANDARD TABLE OF ty_customer WITH KEY kunnr.
METHODS: get_customer IMPORTING iv_kunnr TYPE kunnr RETURNING VALUE(rs_customer) TYPE ty_customer RAISING zcx_bapi_error.
METHODS: get_customers_by_country IMPORTING iv_country TYPE land1 RETURNING VALUE(rt_customers) TYPE ty_customers RAISING zcx_bapi_error.
METHODS: create_customer IMPORTING is_data TYPE ty_customer RETURNING VALUE(rv_kunnr) TYPE kunnr RAISING zcx_bapi_error.
PRIVATE SECTION. METHODS: check_return IMPORTING it_return TYPE bapiret2_t RAISING zcx_bapi_error.ENDCLASS.
CLASS zcl_customer_bapi IMPLEMENTATION. METHOD get_customer. DATA: ls_address TYPE bapicustomer_04, lt_return TYPE TABLE OF bapiret2.
CALL FUNCTION 'BAPI_CUSTOMER_GETDETAIL2' EXPORTING customerno = iv_kunnr IMPORTING customeraddress = ls_address TABLES return = lt_return.
check_return( lt_return ).
rs_customer = VALUE #( kunnr = iv_kunnr name1 = ls_address-name ort01 = ls_address-city land1 = ls_address-country ). ENDMETHOD.
METHOD get_customers_by_country. DATA: lt_address TYPE TABLE OF bapicustomer_04, lt_return TYPE TABLE OF bapiret2.
CALL FUNCTION 'BAPI_CUSTOMER_GETLIST' TABLES addressdata = lt_address return = lt_return.
check_return( lt_return ).
rt_customers = VALUE #( FOR ls_addr IN lt_address WHERE ( country = iv_country OR iv_country IS INITIAL ) ( kunnr = ls_addr-customer name1 = ls_addr-name ort01 = ls_addr-city land1 = ls_addr-country ) ). ENDMETHOD.
METHOD create_customer. DATA: lt_return TYPE TABLE OF bapiret2.
" BAPI zum Anlegen... CALL FUNCTION 'BAPI_CUSTOMER_CREATE...' " Parameter... TABLES return = lt_return.
check_return( lt_return ).
" Bei Erfolg COMMIT CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' EXPORTING wait = abap_true.
rv_kunnr = '...'. " Neue Kundennummer ENDMETHOD.
METHOD check_return. " Fehler in RETURN prüfen LOOP AT it_return INTO DATA(ls_return) WHERE type CA 'EAX'.
RAISE EXCEPTION TYPE zcx_bapi_error EXPORTING textid = zcx_bapi_error=>bapi_error msgid = ls_return-id msgno = ls_return-number msgv1 = ls_return-message_v1 msgv2 = ls_return-message_v2 msgv3 = ls_return-message_v3 msgv4 = ls_return-message_v4. ENDLOOP. ENDMETHOD.ENDCLASS.
" VerwendungTRY. DATA(lo_customer) = NEW zcl_customer_bapi( ). DATA(ls_customer) = lo_customer->get_customer( '0000001000' ).
WRITE: / ls_customer-name1, ls_customer-ort01.
CATCH zcx_bapi_error INTO DATA(lx_error). WRITE: / 'Fehler:', lx_error->get_text( ).ENDTRY.5. BAPI für Massenverarbeitung
FUNCTION z_bapi_orders_create_mass.*"----------------------------------------------------------------------*" IMPORTING*" VALUE(IT_ORDERS) TYPE ZTT_ORDER_CREATE*" EXPORTING*" VALUE(ET_SUCCESS) TYPE ZTT_ORDER_NUMBERS*" VALUE(ET_FAILED) TYPE ZTT_ORDER_FAILED*" TABLES*" RETURN STRUCTURE BAPIRET2*"----------------------------------------------------------------------
DATA: lt_order_return TYPE TABLE OF bapiret2, lv_order_no TYPE vbeln.
LOOP AT it_orders INTO DATA(ls_order). CLEAR: lt_order_return, lv_order_no.
" Einzelne Bestellung anlegen CALL FUNCTION 'BAPI_SALESORDER_CREATEFROMDAT2' EXPORTING order_header_in = ls_order-header IMPORTING salesdocument = lv_order_no TABLES return = lt_order_return order_items_in = ls_order-items order_partners = ls_order-partners.
" Prüfen READ TABLE lt_order_return WITH KEY type = 'E' TRANSPORTING NO FIELDS.
IF sy-subrc <> 0 AND lv_order_no IS NOT INITIAL. " Erfolg CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' EXPORTING wait = abap_true.
APPEND VALUE #( order_no = lv_order_no ) TO et_success.
APPEND VALUE #( type = 'S' id = 'ZORD' number = '001' message = |Bestellung { lv_order_no } angelegt| ) TO return. ELSE. " Fehler CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
APPEND VALUE #( index = sy-tabix messages = lt_order_return ) TO et_failed.
APPEND LINES OF lt_order_return TO return. ENDIF. ENDLOOP.
" Zusammenfassung APPEND VALUE #( type = 'I' id = 'ZORD' number = '002' message = |{ lines( et_success ) } erfolgreich, { lines( et_failed ) } fehlgeschlagen| ) TO return.
ENDFUNCTION.6. BAPI Exception-Klasse
CLASS zcx_bapi_error DEFINITION INHERITING FROM cx_static_check CREATE PUBLIC.
PUBLIC SECTION. INTERFACES: if_t100_message.
CONSTANTS: BEGIN OF bapi_error, msgid TYPE symsgid VALUE 'ZBAPI', msgno TYPE symsgno VALUE '001', attr1 TYPE scx_attrname VALUE 'MSGV1', attr2 TYPE scx_attrname VALUE 'MSGV2', attr3 TYPE scx_attrname VALUE 'MSGV3', attr4 TYPE scx_attrname VALUE 'MSGV4', END OF bapi_error.
DATA: msgid TYPE sy-msgid, msgno TYPE sy-msgno, msgv1 TYPE sy-msgv1, msgv2 TYPE sy-msgv2, msgv3 TYPE sy-msgv3, msgv4 TYPE sy-msgv4.
METHODS: constructor IMPORTING textid LIKE if_t100_message=>t100key OPTIONAL previous LIKE previous OPTIONAL msgid TYPE sy-msgid OPTIONAL msgno TYPE sy-msgno OPTIONAL msgv1 TYPE sy-msgv1 OPTIONAL msgv2 TYPE sy-msgv2 OPTIONAL msgv3 TYPE sy-msgv3 OPTIONAL msgv4 TYPE sy-msgv4 OPTIONAL.
CLASS-METHODS: from_bapiret2 IMPORTING is_return TYPE bapiret2 RETURNING VALUE(ro_error) TYPE REF TO zcx_bapi_error.
CLASS-METHODS: from_bapiret2_table IMPORTING it_return TYPE bapiret2_t RETURNING VALUE(ro_error) TYPE REF TO zcx_bapi_error.ENDCLASS.
CLASS zcx_bapi_error IMPLEMENTATION. METHOD constructor. super->constructor( previous = previous ).
me->msgid = msgid. me->msgno = msgno. me->msgv1 = msgv1. me->msgv2 = msgv2. me->msgv3 = msgv3. me->msgv4 = msgv4.
IF textid IS INITIAL. if_t100_message~t100key = bapi_error. ELSE. if_t100_message~t100key = textid. ENDIF. ENDMETHOD.
METHOD from_bapiret2. ro_error = NEW #( msgid = is_return-id msgno = is_return-number msgv1 = is_return-message_v1 msgv2 = is_return-message_v2 msgv3 = is_return-message_v3 msgv4 = is_return-message_v4 ). ENDMETHOD.
METHOD from_bapiret2_table. " Erste Fehlermeldung verwenden LOOP AT it_return INTO DATA(ls_return) WHERE type CA 'EAX'. ro_error = from_bapiret2( ls_return ). RETURN. ENDLOOP. ENDMETHOD.ENDCLASS.7. BAPI über RFC aufrufen
DATA: lt_return TYPE TABLE OF bapiret2.
" RFC-DestinationDATA(lv_destination) = 'PRD_CLNT100'.
CALL FUNCTION 'BAPI_CUSTOMER_GETLIST' DESTINATION lv_destination TABLES addressdata = lt_address return = lt_return EXCEPTIONS communication_failure = 1 MESSAGE lv_message system_failure = 2 MESSAGE lv_message OTHERS = 3.
IF sy-subrc <> 0. WRITE: / 'RFC-Fehler:', lv_message.ELSE. " BAPI-Rückgabe prüfen check_return( lt_return ).ENDIF.8. BAPI mit Update Task
FUNCTION z_bapi_document_save.*"----------------------------------------------------------------------*" IMPORTING*" VALUE(IS_DOCUMENT) TYPE TY_DOCUMENT*" TABLES*" RETURN STRUCTURE BAPIRET2*"----------------------------------------------------------------------
" Validierung perform_validation( EXPORTING is_document = is_document CHANGING ct_return = return[] ).
IF line_exists( return[ type = 'E' ] ). RETURN. ENDIF.
" Speicherung in Update Task CALL FUNCTION 'Z_UPDATE_DOCUMENT' IN UPDATE TASK EXPORTING is_document = is_document.
" Erfolgsmeldung APPEND VALUE bapiret2( type = 'S' id = 'ZDOC' number = '001' message = 'Dokument wird gespeichert' ) TO return.
" COMMIT wird vom Aufrufer durchgeführt!
ENDFUNCTION.9. BAPI-Hilfsfunktionen
CLASS zcl_bapi_helper DEFINITION. PUBLIC SECTION. " Prüft ob RETURN Fehler enthält CLASS-METHODS: has_errors IMPORTING it_return TYPE bapiret2_t RETURNING VALUE(rv_error) TYPE abap_bool.
" Filtert Nachrichten nach Typ CLASS-METHODS: get_messages_by_type IMPORTING it_return TYPE bapiret2_t iv_type TYPE sy-msgty RETURNING VALUE(rt_messages) TYPE bapiret2_t.
" Konvertiert RETURN zu String CLASS-METHODS: return_to_string IMPORTING it_return TYPE bapiret2_t RETURNING VALUE(rv_string) TYPE string.
" Fügt Nachricht hinzu CLASS-METHODS: add_message IMPORTING iv_type TYPE sy-msgty iv_id TYPE sy-msgid iv_number TYPE sy-msgno iv_v1 TYPE clike OPTIONAL iv_v2 TYPE clike OPTIONAL iv_v3 TYPE clike OPTIONAL iv_v4 TYPE clike OPTIONAL CHANGING ct_return TYPE bapiret2_t.ENDCLASS.
CLASS zcl_bapi_helper IMPLEMENTATION. METHOD has_errors. rv_error = xsdbool( line_exists( it_return[ type = 'E' ] ) OR line_exists( it_return[ type = 'A' ] ) OR line_exists( it_return[ type = 'X' ] ) ). ENDMETHOD.
METHOD get_messages_by_type. rt_messages = FILTER #( it_return WHERE type = iv_type ). ENDMETHOD.
METHOD return_to_string. LOOP AT it_return INTO DATA(ls_return). IF rv_string IS NOT INITIAL. rv_string = rv_string && cl_abap_char_utilities=>newline. ENDIF. rv_string = rv_string && |{ ls_return-type }: { ls_return-message }|. ENDLOOP. ENDMETHOD.
METHOD add_message. DATA: ls_return TYPE bapiret2, lv_text TYPE string.
MESSAGE ID iv_id TYPE iv_type NUMBER iv_number WITH iv_v1 iv_v2 iv_v3 iv_v4 INTO lv_text.
ls_return = VALUE #( type = iv_type id = iv_id number = iv_number message = lv_text message_v1 = iv_v1 message_v2 = iv_v2 message_v3 = iv_v3 message_v4 = iv_v4 ).
APPEND ls_return TO ct_return. ENDMETHOD.ENDCLASS.
" VerwendungDATA: lt_return TYPE bapiret2_t.
zcl_bapi_helper=>add_message( EXPORTING iv_type = 'S' iv_id = 'ZMSG' iv_number = '001' iv_v1 = 'Erfolg' CHANGING ct_return = lt_return).
IF zcl_bapi_helper=>has_errors( lt_return ). DATA(lv_errors) = zcl_bapi_helper=>return_to_string( lt_return ). MESSAGE lv_errors TYPE 'E'.ENDIF.10. BAPI Explorer (BAPI)
Transaktion: BAPI
1. Business Object auswählen (z.B. Customer)2. Methoden anzeigen (GetList, GetDetail, Create, etc.)3. Dokumentation und Parameter einsehen4. Funktionsbaustein-Name ermitteln5. Testmöglichkeit über SE3711. Wichtige Standard-BAPIs
" KundenCALL FUNCTION 'BAPI_CUSTOMER_GETLIST'. " Kunden auflistenCALL FUNCTION 'BAPI_CUSTOMER_GETDETAIL2'. " KundendetailsCALL FUNCTION 'BAPI_CUSTOMER_CREATEFROMDAT1'. " Kunde anlegen
" LieferantenCALL FUNCTION 'BAPI_VENDOR_GETLIST'. " Lieferanten auflistenCALL FUNCTION 'BAPI_VENDOR_GETDETAIL'. " Lieferantendetails
" MaterialienCALL FUNCTION 'BAPI_MATERIAL_GETLIST'. " Materialien auflistenCALL FUNCTION 'BAPI_MATERIAL_GET_DETAIL'. " Materialdetails
" BestellungenCALL FUNCTION 'BAPI_PO_CREATE1'. " Bestellung anlegenCALL FUNCTION 'BAPI_PO_CHANGE'. " Bestellung ändernCALL FUNCTION 'BAPI_PO_GETDETAIL'. " Bestelldetails
" AufträgeCALL FUNCTION 'BAPI_SALESORDER_CREATEFROMDAT2'. " Auftrag anlegenCALL FUNCTION 'BAPI_SALESORDER_GETLIST'. " Aufträge auflistenCALL FUNCTION 'BAPI_SALESORDER_CHANGE'. " Auftrag ändern
" BuchungenCALL FUNCTION 'BAPI_ACC_DOCUMENT_POST'. " FI-Beleg buchen
" TransaktionssteuerungCALL FUNCTION 'BAPI_TRANSACTION_COMMIT'. " CommitCALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'. " RollbackBAPI Checkliste
✓ Funktionsbaustein ist RFC-fähig✓ RETURN-Parameter vom Typ BAPIRET2✓ Kein COMMIT WORK im BAPI✓ Keine MESSAGE-Anweisungen✓ Keine Dialogaufrufe (Popups)✓ Vollständige Fehlerbehandlung✓ Dokumentation der Parameter✓ Berechtigungsprüfung implementiert✓ Eingabevalidierung vorhanden✓ Testbar über SE37Wichtige Hinweise / Best Practice
- COMMIT WORK nie im BAPI – der Aufrufer entscheidet.
- RETURN immer mit aussagekräftigen Nachrichten füllen.
- RFC-fähig für Remote-Aufrufe markieren.
- Keine MESSAGE-Statements – nur RETURN befüllen.
- Berechtigungsprüfung im BAPI implementieren.
- Eingabevalidierung vor Verarbeitung.
- Wrapper-Klassen für einfache Verwendung.
- BAPI Explorer (Transaktion BAPI) für Dokumentation.
- Massenverarbeitung mit einzelnen COMMITs pro Datensatz.
- Kombinieren Sie mit Exception Classes für OO-Integration.