1. Introduction:
In SAP ABAP, Purchase Orders (POs) can be created programmatically using standard BAPIs, which ensure data consistency and follow SAP business rules.
This blog explains how to create a Purchase Order using transaction SE38 by calling the standard BAPI BAPI_PO_CREATE1.
The example demonstrates:
Material number conversion
PO header and item population
Usage of HeaderX and ItemX structures
Error handling and transaction commit
βββββββββββββββββββββββββββββββββ
β Start β
βββββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββββββββββββββββββββ
β Execute ABAP Report (SE38) β
βββββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββ
β Convert Material Number to Internal β
β Format (CONVERSION_EXIT_MATN1_INPUT) β
βββββββββββββββββ¬ββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββ
β Fill PO Header Data β
β (Company Code, Vendor, etc.) β
βββββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββββββββββββββββββββ
β Fill PO HeaderX (Indicators) β
β Mark fields with ‘X’ β
βββββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββββββββββββββββββββ
β Fill PO Item Data β
β (Material, Qty, Plant, UOM) β
βββββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββββββββββββββββββββ
β Fill PO ItemX (Indicators) β
β Mark item fields with ‘X’ β
βββββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββββββββββββββββββββ
β Call BAPI_PO_CREATE1 β
βββββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββββββββββββββββββββ
β Check Return Messages β
β (BAPIRET2 Table) β
βββββββββββββββββ¬ββββββββββββββββ
βββββββββ΄βββββββββ
β β
βββββββββββββββββββ ββββββββββββββββββββββββ
β PO Created? β β Error / Abort Message β
β (PO Number β β Display Error Text β
β Returned) β βββββββββββββ¬βββββββββββ
βββββββββ¬ββββββββββ β
β βββββββββββββββββ
ββββββββββββββββββββββββ β End β
β BAPI_TRANSACTION_ β βββββββββββββββββ
β COMMIT (WAIT = ‘X’) β
βββββββββββββ¬βββββββββββ
β
ββββββββββββββββββββββββ
β Display PO Number β
βββββββββββββ¬βββββββββββ
β
ββββββββββββββββββββββββ
β End β
ββββββββββββββββββββββββ
Program Declaration & Data Definitions:
Purpose
All required BAPI structures are declared for header, item, return messages, and output PO number.
DATA: wa_poheader TYPE bapimepoheader,
wa_poheaderx TYPE bapimepoheaderx,
it_poitem TYPE TABLE OF bapimepoitem,
it_poitemx TYPE TABLE OF bapimepoitemx,
wa_poitem TYPE bapimepoitem,
wa_poitemx TYPE bapimepoitemx,
it_bapiret2 TYPE TABLE OF bapiret2,
wa_bapiret2 TYPE bapiret2,
v_ebeln TYPE bapimepoheader-po_number.
Explanation
BAPIMEPOHEADER β PO header data
BAPIMEPOHEADERX β Flags indicating which header fields are filled
BAPIMEPOITEM / ITEMX β PO item data and change indicators
BAPIRET2 β Return messages (success / error / warning)
Material Number ConversionΒ
Why Needed?
SAP stores material numbers internally in 18-character format with leading zeros.
To avoid errors, conversion is mandatory.
DATA: lv_matnr_raw TYPE matnr,
lv_matnr_conv TYPE matnr.
lv_matnr_raw = ’93’.
CALL FUNCTION ‘CONVERSION_EXIT_MATN1_INPUT’
EXPORTING
input = lv_matnr_raw
IMPORTING
output = lv_matnr_conv.
Β
Full Code to pass the Parameters and mandatory values while creating :
DATA: wa_poheader TYPE bapimepoheader,
wa_poheaderx TYPE bapimepoheaderx,
it_poitem TYPE TABLE OF bapimepoitem,
it_poitemx TYPE TABLE OF bapimepoitemx,
wa_poitem TYPE bapimepoitem,
wa_poitemx TYPE bapimepoitemx,
it_bapiret2 TYPE TABLE OF bapiret2,
wa_bapiret2 TYPE bapiret2,
v_ebeln TYPE bapimepoheader-po_number.
DATA: lv_matnr_raw TYPE matnr,
lv_matnr_conv TYPE matnr.
* Convert material number to 18-digit (leading zero padding)
lv_matnr_raw = ’93’.
CALL FUNCTION ‘CONVERSION_EXIT_MATN1_INPUT’
EXPORTING
input = lv_matnr_raw
IMPORTING
output = lv_matnr_conv.
* Fill PO Header
CLEAR wa_poheader.
wa_poheader-comp_code = ‘UN01’.
wa_poheader-doc_type = ‘NB’.
wa_poheader-purch_org = ‘UN04’.
wa_poheader-pur_group = ‘001’.
wa_poheader-vendor = ‘TATA STEEL’.
wa_poheader-langu = sy-langu.
wa_poheader-item_intvl = ‘00010’.
wa_poheader-created_by = sy-uname.
wa_poheader-currency = ‘INR’.
* Fill HeaderX
CLEAR wa_poheaderx.
wa_poheaderx-comp_code = ‘X’.
wa_poheaderx-doc_type = ‘X’.
wa_poheaderx-purch_org = ‘X’.
wa_poheaderx-pur_group = ‘X’.
wa_poheaderx-vendor = ‘X’.
wa_poheaderx-langu = ‘X’.
wa_poheaderx-item_intvl = ‘X’.
wa_poheaderx-created_by = ‘X’.
wa_poheaderx-currency = ‘X’.
* Only one item β no loop needed here unless dynamic
CLEAR wa_poitem.
wa_poitem-po_item = ‘00010’.
wa_poitem-short_text = ‘STELL’.
wa_poitem-quantity = ‘2000’.
wa_poitem-orderpr_un = ‘KG’.
wa_poitem-material = lv_matnr_conv.
wa_poitem-plant = ‘UN02’.
APPEND wa_poitem TO it_poitem.
CLEAR wa_poitemx.
wa_poitemx-po_item = ‘00010’.
wa_poitemx-short_text = ‘X’.
wa_poitemx-quantity = ‘X’.
wa_poitemx-orderpr_un = ‘X’.
wa_poitemx-material = ‘X’.
wa_poitemx-plant = ‘X’.
APPEND wa_poitemx TO it_poitemx.
* Call BAPI
CALL FUNCTION ‘BAPI_PO_CREATE1’
EXPORTING
poheader = wa_poheader
poheaderx = wa_poheaderx
IMPORTING
exppurchaseorder = v_ebeln
TABLES
return = it_bapiret2
poitem = it_poitem
poitemx = it_poitemx.
* Check creation
IF v_ebeln IS NOT INITIAL.
CALL FUNCTION ‘BAPI_TRANSACTION_COMMIT’
EXPORTING
wait = ‘X’.
WRITE: / ‘Purchase Order Created:’, v_ebeln.
ELSE.
LOOP AT it_bapiret2 INTO wa_bapiret2 WHERE type = ‘E’ OR type = ‘A’.
WRITE: / ‘Error:’, wa_bapiret2-message.
ENDLOOP.
ENDIF.
All mandatory fields required for Purchase Order creation must be populated in the PO Header and PO Item structures; otherwise, the BAPI will return error messages.
For every field filled in POHEADER or POITEM, the corresponding field in POHEADERX and POITEMX must be marked with ‘X’.
If the X indicator is missing, the BAPI will ignore the value, even if it is provided.
Header dataΒ Company Code, Vendor, Purchasing Organization, Currency, etc. controls the overall PO, while Item dataΒ Material, Quantity, Plant, UOM, etc. defines line-level details.
Material numbers must be passed in internal SAP formatΒ 18-character format with leading zeros. Use the relevant conversion exit to avoid material-related errors.
Always check the RETURN table BAPIRET2Β after calling the BAPI to identify errors, warnings, or success messages.
The Purchase Order is not saved automatically after BAPI execution.
You must explicitly call BAPI_TRANSACTION_COMMIT to reflect the PO in standard SAP tablesΒ EKKO, EKPO, etc.
Use WAIT = ‘X’ in the commit function to ensure the transaction is completed before further processing.
If errors TYPE = ‘E’ or TYPE = ‘A’Β are returned, the commit should not be executed, and the error messages should be displayed or logged.
Always validate the generated PO number before confirming successful creation.
This BAPI-based approach ensures data consistency, follows SAP standard validation logic, and is recommended over direct table updates.
Final Output:
After successful execution of the SE38 report, the system generates a Purchase Order number.
You can cross-check this output by navigating to SE37, where the same PO number can be passed to validate and review the Purchase Order details.
Conclusion:
Using BAPI_PO_CREATE1 in SE38 is a safe and SAP-recommended approach to create Purchase Orders programmatically.
By correctly filling Header and Item structures, handling material conversion, and committing the transaction, we can ensure reliable PO creation.
This method is ideal for:
Interface programs
File-based uploads
Mass PO creation
Integration scenarios
Thank You ..
Chandu Kumar.
Β
βΒ 1. Introduction:In SAP ABAP, Purchase Orders (POs) can be created programmatically using standard BAPIs, which ensure data consistency and follow SAP business rules.This blog explains how to create a Purchase Order using transaction SE38 by calling the standard BAPI BAPI_PO_CREATE1.The example demonstrates:Material number conversionPO header and item populationUsage of HeaderX and ItemX structuresError handling and transaction commit βββββββββββββββββββββββββββββββββ
β Start β
βββββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββββββββββββββββββββ
β Execute ABAP Report (SE38) β
βββββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββ
β Convert Material Number to Internal β
β Format (CONVERSION_EXIT_MATN1_INPUT) β
βββββββββββββββββ¬ββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββ
β Fill PO Header Data β
β (Company Code, Vendor, etc.) β
βββββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββββββββββββββββββββ
β Fill PO HeaderX (Indicators) β
β Mark fields with ‘X’ β
βββββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββββββββββββββββββββ
β Fill PO Item Data β
β (Material, Qty, Plant, UOM) β
βββββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββββββββββββββββββββ
β Fill PO ItemX (Indicators) β
β Mark item fields with ‘X’ β
βββββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββββββββββββββββββββ
β Call BAPI_PO_CREATE1 β
βββββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββββββββββββββββββββ
β Check Return Messages β
β (BAPIRET2 Table) β
βββββββββββββββββ¬ββββββββββββββββ
βββββββββ΄βββββββββ
β β
βββββββββββββββββββ ββββββββββββββββββββββββ
β PO Created? β β Error / Abort Message β
β (PO Number β β Display Error Text β
β Returned) β βββββββββββββ¬βββββββββββ
βββββββββ¬ββββββββββ β
β βββββββββββββββββ
ββββββββββββββββββββββββ β End β
β BAPI_TRANSACTION_ β βββββββββββββββββ
β COMMIT (WAIT = ‘X’) β
βββββββββββββ¬βββββββββββ
β
ββββββββββββββββββββββββ
β Display PO Number β
βββββββββββββ¬βββββββββββ
β
ββββββββββββββββββββββββ
β End β
ββββββββββββββββββββββββProgram Declaration & Data Definitions:PurposeAll required BAPI structures are declared for header, item, return messages, and output PO number.DATA: wa_poheader TYPE bapimepoheader,
wa_poheaderx TYPE bapimepoheaderx,
it_poitem TYPE TABLE OF bapimepoitem,
it_poitemx TYPE TABLE OF bapimepoitemx,
wa_poitem TYPE bapimepoitem,
wa_poitemx TYPE bapimepoitemx,
it_bapiret2 TYPE TABLE OF bapiret2,
wa_bapiret2 TYPE bapiret2,
v_ebeln TYPE bapimepoheader-po_number.ExplanationBAPIMEPOHEADER β PO header dataBAPIMEPOHEADERX β Flags indicating which header fields are filledBAPIMEPOITEM / ITEMX β PO item data and change indicatorsBAPIRET2 β Return messages (success / error / warning)Material Number ConversionΒ Why Needed?SAP stores material numbers internally in 18-character format with leading zeros.To avoid errors, conversion is mandatory.DATA: lv_matnr_raw TYPE matnr,
lv_matnr_conv TYPE matnr.
lv_matnr_raw = ’93’.
CALL FUNCTION ‘CONVERSION_EXIT_MATN1_INPUT’
EXPORTING
input = lv_matnr_raw
IMPORTING
output = lv_matnr_conv.Β Full Code to pass the Parameters and mandatory values while creating :DATA: wa_poheader TYPE bapimepoheader,
wa_poheaderx TYPE bapimepoheaderx,
it_poitem TYPE TABLE OF bapimepoitem,
it_poitemx TYPE TABLE OF bapimepoitemx,
wa_poitem TYPE bapimepoitem,
wa_poitemx TYPE bapimepoitemx,
it_bapiret2 TYPE TABLE OF bapiret2,
wa_bapiret2 TYPE bapiret2,
v_ebeln TYPE bapimepoheader-po_number.
DATA: lv_matnr_raw TYPE matnr,
lv_matnr_conv TYPE matnr.
* Convert material number to 18-digit (leading zero padding)
lv_matnr_raw = ’93’.
CALL FUNCTION ‘CONVERSION_EXIT_MATN1_INPUT’
EXPORTING
input = lv_matnr_raw
IMPORTING
output = lv_matnr_conv.
* Fill PO Header
CLEAR wa_poheader.
wa_poheader-comp_code = ‘UN01’.
wa_poheader-doc_type = ‘NB’.
wa_poheader-purch_org = ‘UN04’.
wa_poheader-pur_group = ‘001’.
wa_poheader-vendor = ‘TATA STEEL’.
wa_poheader-langu = sy-langu.
wa_poheader-item_intvl = ‘00010’.
wa_poheader-created_by = sy-uname.
wa_poheader-currency = ‘INR’.
* Fill HeaderX
CLEAR wa_poheaderx.
wa_poheaderx-comp_code = ‘X’.
wa_poheaderx-doc_type = ‘X’.
wa_poheaderx-purch_org = ‘X’.
wa_poheaderx-pur_group = ‘X’.
wa_poheaderx-vendor = ‘X’.
wa_poheaderx-langu = ‘X’.
wa_poheaderx-item_intvl = ‘X’.
wa_poheaderx-created_by = ‘X’.
wa_poheaderx-currency = ‘X’.
* Only one item β no loop needed here unless dynamic
CLEAR wa_poitem.
wa_poitem-po_item = ‘00010’.
wa_poitem-short_text = ‘STELL’.
wa_poitem-quantity = ‘2000’.
wa_poitem-orderpr_un = ‘KG’.
wa_poitem-material = lv_matnr_conv.
wa_poitem-plant = ‘UN02’.
APPEND wa_poitem TO it_poitem.
CLEAR wa_poitemx.
wa_poitemx-po_item = ‘00010’.
wa_poitemx-short_text = ‘X’.
wa_poitemx-quantity = ‘X’.
wa_poitemx-orderpr_un = ‘X’.
wa_poitemx-material = ‘X’.
wa_poitemx-plant = ‘X’.
APPEND wa_poitemx TO it_poitemx.
* Call BAPI
CALL FUNCTION ‘BAPI_PO_CREATE1’
EXPORTING
poheader = wa_poheader
poheaderx = wa_poheaderx
IMPORTING
exppurchaseorder = v_ebeln
TABLES
return = it_bapiret2
poitem = it_poitem
poitemx = it_poitemx.
* Check creation
IF v_ebeln IS NOT INITIAL.
CALL FUNCTION ‘BAPI_TRANSACTION_COMMIT’
EXPORTING
wait = ‘X’.
WRITE: / ‘Purchase Order Created:’, v_ebeln.
ELSE.
LOOP AT it_bapiret2 INTO wa_bapiret2 WHERE type = ‘E’ OR type = ‘A’.
WRITE: / ‘Error:’, wa_bapiret2-message.
ENDLOOP.
ENDIF.All mandatory fields required for Purchase Order creation must be populated in the PO Header and PO Item structures; otherwise, the BAPI will return error messages.For every field filled in POHEADER or POITEM, the corresponding field in POHEADERX and POITEMX must be marked with ‘X’.If the X indicator is missing, the BAPI will ignore the value, even if it is provided.Header dataΒ Company Code, Vendor, Purchasing Organization, Currency, etc. controls the overall PO, while Item dataΒ Material, Quantity, Plant, UOM, etc. defines line-level details.Material numbers must be passed in internal SAP formatΒ 18-character format with leading zeros. Use the relevant conversion exit to avoid material-related errors.Always check the RETURN table BAPIRET2Β after calling the BAPI to identify errors, warnings, or success messages.The Purchase Order is not saved automatically after BAPI execution.You must explicitly call BAPI_TRANSACTION_COMMIT to reflect the PO in standard SAP tablesΒ EKKO, EKPO, etc.Use WAIT = ‘X’ in the commit function to ensure the transaction is completed before further processing.If errors TYPE = ‘E’ or TYPE = ‘A’Β are returned, the commit should not be executed, and the error messages should be displayed or logged.Always validate the generated PO number before confirming successful creation.This BAPI-based approach ensures data consistency, follows SAP standard validation logic, and is recommended over direct table updates.Final Output:After successful execution of the SE38 report, the system generates a Purchase Order number.You can cross-check this output by navigating to SE37, where the same PO number can be passed to validate and review the Purchase Order details.Conclusion:Using BAPI_PO_CREATE1 in SE38 is a safe and SAP-recommended approach to create Purchase Orders programmatically.By correctly filling Header and Item structures, handling material conversion, and committing the transaction, we can ensure reliable PO creation.This method is ideal for:Interface programsFile-based uploadsMass PO creationIntegration scenariosThank You ..Chandu Kumar.Β Β Β Read MoreΒ Technology Blog Posts by Members articlesΒ
#SAP
#SAPTechnologyblog