Developer ToolsFree generatorPDF, Excel, Word exportSAP ECC 6.0All SAP ECC 6.0 tools

BAPI_PO_CHANGE Example Generator for SAP ABAP

This generator writes an ABAP program for SAP ECC 6.0 that changes one purchase order item with BAPI_PO_CHANGE: quantity, net price, delivery date on a schedule line, delete, undelete or block. It runs as a test first, checks the return table, and commits only when you untick test run and no errors are returned.

Fill in

QTY quantity, PRIC net price, DATE delivery date, DEL delete, UNDL undelete, BLCK block

Generated code
Download:

Program

REPORT ZMM_PO_CHANGE_BAPI.

PARAMETERS: p_ebeln TYPE ekko-ebeln               DEFAULT '4500012345',
            p_ebelp TYPE ekpo-ebelp               DEFAULT '00010',
            p_mode  TYPE char4                    DEFAULT 'DATE',
            p_menge TYPE bapimepoitem-quantity    DEFAULT '120',
            p_netpr TYPE bapimepoitem-net_price   DEFAULT '14.50',
            p_peinh TYPE bapimepoitem-price_unit  DEFAULT '1',
            p_eindt TYPE sy-datum                 DEFAULT '20261130',
            p_etenr TYPE eket-etenr               DEFAULT '0001',
            p_test  AS CHECKBOX                   DEFAULT 'X'.

DATA: lv_ebeln   TYPE ekko-ebeln,
      lt_item    TYPE STANDARD TABLE OF bapimepoitem,
      ls_item    TYPE bapimepoitem,
      lt_itemx   TYPE STANDARD TABLE OF bapimepoitemx,
      ls_itemx   TYPE bapimepoitemx,
      lt_sched   TYPE STANDARD TABLE OF bapimeposchedule,
      ls_sched   TYPE bapimeposchedule,
      lt_schedx  TYPE STANDARD TABLE OF bapimeposchedulx,
      ls_schedx  TYPE bapimeposchedulx,
      lt_return  TYPE STANDARD TABLE OF bapiret2,
      ls_return  TYPE bapiret2,
      lv_extdate TYPE c LENGTH 10,
      lv_error   TYPE c.

START-OF-SELECTION.

  CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
    EXPORTING
      input  = p_ebeln
    IMPORTING
      output = lv_ebeln.

  ls_item-po_item   = p_ebelp.
  ls_itemx-po_item  = p_ebelp.
  ls_itemx-po_itemx = 'X'.

  CASE p_mode.
    WHEN 'QTY'.
*     With several schedule lines, change POSCHEDULE quantities instead
      ls_item-quantity  = p_menge.
      ls_itemx-quantity = 'X'.
    WHEN 'PRIC'.
      ls_item-net_price   = p_netpr.
      ls_item-price_unit  = p_peinh.
      ls_itemx-net_price  = 'X'.
      ls_itemx-price_unit = 'X'.
    WHEN 'DATE'.
*     DELIVERY_DATE is in external (user) format, so convert first
      CALL FUNCTION 'CONVERT_DATE_TO_EXTERNAL'
        EXPORTING
          date_internal = p_eindt
        IMPORTING
          date_external = lv_extdate
        EXCEPTIONS
          OTHERS        = 1.
      ls_sched-po_item        = p_ebelp.
      ls_sched-sched_line     = p_etenr.
      ls_sched-delivery_date  = lv_extdate.
      APPEND ls_sched TO lt_sched.
      ls_schedx-po_item       = p_ebelp.
      ls_schedx-sched_line    = p_etenr.
      ls_schedx-po_itemx      = 'X'.
      ls_schedx-sched_linex   = 'X'.
      ls_schedx-delivery_date = 'X'.
      APPEND ls_schedx TO lt_schedx.
    WHEN 'DEL'.
      ls_item-delete_ind  = 'L'.
      ls_itemx-delete_ind = 'X'.
    WHEN 'UNDL'.
      ls_item-delete_ind  = space.
      ls_itemx-delete_ind = 'X'.
    WHEN 'BLCK'.
      ls_item-delete_ind  = 'S'.
      ls_itemx-delete_ind = 'X'.
    WHEN OTHERS.
      MESSAGE 'Unknown change type' TYPE 'E'.
  ENDCASE.

  APPEND ls_item  TO lt_item.
  APPEND ls_itemx TO lt_itemx.

  CALL FUNCTION 'BAPI_PO_CHANGE'
    EXPORTING
      purchaseorder = lv_ebeln
      testrun       = p_test
    TABLES
      return        = lt_return
      poitem        = lt_item
      poitemx       = lt_itemx
      poschedule    = lt_sched
      poschedulex   = lt_schedx.

  LOOP AT lt_return INTO ls_return.
    WRITE: / ls_return-type, ls_return-id, ls_return-number, ls_return-message.
    IF ls_return-type = 'E' OR ls_return-type = 'A'.
      lv_error = 'X'.
    ENDIF.
  ENDLOOP.

  IF lv_error = 'X' OR p_test = 'X'.
    CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
    IF lv_error = 'X'.
      WRITE: / 'Errors found, nothing saved'.
    ELSE.
      WRITE: / 'Test run OK, nothing saved. Untick test run to post.'.
    ENDIF.
  ELSE.
    CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
      EXPORTING
        wait   = 'X'
      IMPORTING
        return = ls_return.
    WRITE: / 'Purchase order', lv_ebeln, 'changed'.
  ENDIF.

Optional: change the price through the condition (PB00) instead of NET_PRICE

* When the price comes from conditions, change the gross price condition:
*  DATA: lt_cond  TYPE STANDARD TABLE OF bapimepocond,
*        ls_cond  TYPE bapimepocond,
*        lt_condx TYPE STANDARD TABLE OF bapimepocondx,
*        ls_condx TYPE bapimepocondx.
*  ls_cond-itm_number  = p_ebelp.
*  ls_cond-cond_type   = 'PB00'.
*  ls_cond-cond_value  = p_netpr.
*  ls_cond-change_id   = 'U'.
*  APPEND ls_cond TO lt_cond.
*  ls_condx-itm_number = p_ebelp.
*  ls_condx-itm_numberx = 'X'.
*  ls_condx-cond_type  = 'X'.
*  ls_condx-cond_value = 'X'.
*  ls_condx-change_id  = 'X'.
*  APPEND ls_condx TO lt_condx.
*  Pass pocond = lt_cond and pocondx = lt_condx in the TABLES of BAPI_PO_CHANGE.
*  Verify BAPIMEPOCOND and BAPIMEPOCONDX field names in SE11 before use.

Verify in SE11 that BAPIMEPOITEM(X) and BAPIMEPOSCHEDULE / BAPIMEPOSCHEDULX carry the fields used here, and in the BAPI documentation (SE37) how your release treats NET_PRICE versus POCOND. DELETE_IND L deletes and S blocks an item in ECC 6.0. The program starts in test run mode on purpose; untick the checkbox to save.

Get a PO mass-change tool reviewed

Send us your scenario and we return a reviewed program that changes PO dates or quantities from a file, with test mode and a log.

Optional. The tool and every export work without this. No spam.

Was this tool useful?

How BAPI_PO_CHANGE expects data

POITEM carries the new values and POITEMX says which fields to change: PO_ITEM is the key, PO_ITEMX = X marks the key as filled, and each changed field gets an X. Delivery dates are not in POITEM but in POSCHEDULE with PO_ITEM and SCHED_LINE, with POSCHEDULEX flags including PO_ITEMX and SCHED_LINEX. DELIVERY_DATE in POSCHEDULE is a 10-character field in the user's external date format, which is why the code converts the internal date first. TESTRUN = X runs all checks without saving.

  • Quantity and price: POITEM / POITEMX.
  • Delivery date: POSCHEDULE / POSCHEDULEX.
  • Deletion and block: DELETE_IND L or S, blank to undo.

How to use it

Enter PO number, item, change type and only the value that type needs. Paste the code into SE38 and run it with test run ticked. Read the messages: warnings about tolerance or release strategy are normal, errors stop the change. Untick test run and run again to save. For mass changes, wrap the CASE block in a loop over a file or table and call BAPI_PO_CHANGE once per PO with all its items.

Worked example

PO 4500012345, item 00010, mode DATE, date 20261130, schedule line 0001. The program converts the date to the user format, for example 30.11.2026, sends POSCHEDULE with DELIVERY_DATE and the X flags, and the test run returns the standard message that the PO would be changed. After the real run, ME23N shows the new date on the delivery schedule tab and EKET-EINDT holds 20261130. If a release strategy applies, the change may reset the release status.

Gotchas

Setting NET_PRICE has no effect when the price is determined from conditions that override it; then change the PB00 condition through POCOND as in the optional block, or check the BAPI documentation for your release. A PO in use by ME22N returns a lock error. Items with goods receipts cannot get a quantity below the received quantity. Do not commit after a test run: the program rolls back on purpose. Read every message in RETURN, not only the first, because the real error is often further down.

Frequently Asked Questions

How do I change the delivery date with BAPI_PO_CHANGE?

Fill POSCHEDULE with PO_ITEM, SCHED_LINE and DELIVERY_DATE in external format, and POSCHEDULEX with the same keys plus PO_ITEMX, SCHED_LINEX and DELIVERY_DATE set to X. Also pass the item in POITEM and POITEMX with PO_ITEMX = X. Commit with BAPI_TRANSACTION_COMMIT.

How do I delete a PO item with BAPI_PO_CHANGE?

Set DELETE_IND = L in POITEM and DELETE_IND = X in POITEMX for that PO_ITEM. To block the item instead, use S. To undo deletion or block, send DELETE_IND blank with the X flag. Items with follow-on documents may only be marked, not physically removed.

Why does BAPI_PO_CHANGE return success but nothing changes?

Usually the X flag for the field is missing, the program ran with TESTRUN = X, or BAPI_TRANSACTION_COMMIT was not called. For prices, a condition may override NET_PRICE. Check that each changed field has its X flag and that the commit runs after a run without E or A messages.

Which BAPIs exist for purchase orders in ECC?

BAPI_PO_CREATE1 creates, BAPI_PO_CHANGE changes, BAPI_PO_GETDETAIL1 reads details, BAPI_PO_RELEASE releases and BAPI_PO_RESET_RELEASE cancels a release. BAPI_PO_GETITEMS lists items across POs. All need BAPI_TRANSACTION_COMMIT after write calls.

If you want buyers to ask about open POs and, with approval, change dates or quantities in plain English on your own servers, we can build that over your ECC system.

ArchRay builder
Design the on-prem AI stack for SAP ECC 6.0: model, GPUs, RAG pipeline, guardrails
See memory, speed and cost as you swap parts, then export the diagram. Free, in your browser.
Open the builder

Keep exploring

Free tools

ERP fixes and how-tos

Integrations