How to mass create outbound deliveries in SAP from Excel
PostNow.ai does SAP mass outbound delivery creation by calling BAPI_OUTB_DELIVERY_CREATE_SLS once per group of rows in an Excel sheet: shipping point and selection date go in once per call, and each row names a sales order item and the quantity to ship. SAP runs the same availability check, shipping point and route logic as VL01N. PostNow.ai commits when SAP returns no error, rolls back when it does, and writes the delivery number back to the sheet as a link to VL03N. Picking and goods issue stay a separate step. If your list is simply "everything due by Friday", SAP's own delivery due list (VL10A) already does the job.
- Check the delivery number column. The BAPI can return no error and create nothing, so the delivery number column is your success check.
- Filter delivery blocks out of the file. SAP documents that this BAPI can create a delivery for an order with a header delivery block.
This page is about one transaction: turning a list of order items somebody has chosen into outbound deliveries, the step between the sales order upload (VA01) and billing. For choosing a method across all SAP objects, see SAP mass upload from Excel; for a first upload of any kind, how to upload data into SAP from Excel.
How PostNow.ai creates outbound deliveries from Excel
PostNow.ai treats delivery creation as a BAPI template: a designer builds it once against your SAP system and publishes it, and shipping clerks run their own files through it under their own SAP login.
1. Pick the BAPI and pull its interface from SAP
In the BAPI Explorer, search for BAPI_OUTB_DELIVERY_CREATE_SLS, or ask Find with AI for "VL01N": its built-in transaction list maps VL01N to this BAPI. PostNow.ai reads the interface from your system, so the mapper shows the parameters your release really has.
2. Map one row per order item, grouped per call
Map the sales order and item to SALES_ORDER_ITEMS-REF_DOC and REF_ITEM, the quantity to DLV_QTY and the unit to SALES_UNIT. SHIP_POINT and DUE_DATE are single values per call. In flat-row mode, set the Sales Order column as the split column, so all items of one order go into one call and the header values are read from the group's first row. Without a split, a flat sheet without a loop sends one call per row, and every item becomes its own delivery.
3. Fix what should not vary
Give the shipping point a fixed value, or a value list with Restrict on, so Validate refuses another warehouse's shipping point. Switch on Leading Zeros for the order column (target length 10) and the item column (6), so 4471 reaches SAP as 0000004471 and item 10 as 000010, whatever Excel did to the cell. Set the date column's format so the selection date arrives as a date, not as text.
4. Validate, then Simulate
Validate checks the file offline: required fields, lengths, formats, dates, allowed values. Simulate calls the BAPI for real and then BAPI_TRANSACTION_ROLLBACK instead of a commit, so you see SAP's messages for each call without creating a delivery. Because each simulated delivery is rolled back, it leaves its stock for the next one, so check that available stock covers the whole file before the run.
5. Run, and write the delivery number back
Run calls the BAPI once per group. If SAP returns no E or A message, PostNow.ai calls BAPI_TRANSACTION_COMMIT with wait; otherwise it rolls back and the group's first row shows ERROR. The new number comes back in the BAPI's DELIVERY export: point the template's document number at that export and write it to a "Delivery" column, and write NUM_DELIVERIES to a second column. With VL03N as the Call Transaction, each delivery number becomes a link that opens VL03N with the delivery filled in.
6. Re-run only what failed
Retry Failed re-posts only the groups whose Run Log starts with ERROR, scanning from the current Start Row down. A normal Run checks the Run Log first and, if rows in scope were already posted, offers Skip posted rows, Post again or Cancel.
A ready-made sheet is the free VL01N outbound delivery template (one row per order item, column-to-BAPI field guide), listed with the other SD templates on the sales and distribution templates page. Add the Sales Order split described in step 2 before you run it.
VL01N mass upload: BAPI, recording or the VL10 delivery due list
PostNow.ai can create deliveries through the BAPI or through a VL01N recording. SAP also ships its own mass route, and for a routine shipping run it is often the right one.
| Route | How it creates | Use it when | Watch out for |
|---|---|---|---|
| PostNow.ai: BAPI_OUTB_DELIVERY_CREATE_SLS | One RFC call per order (or per group you define); commit only if SAP returns no error | The list of items and quantities was decided outside SAP; partial quantities per line; repeat loads by operators | Header delivery blocks; empty results without an error; one shipping point and date per call |
| PostNow.ai: VL01N recording | CALL TRANSACTION on an SHDB recording | Full deliveries of whole orders, where the screen sequence never changes | Item rows on the overview screen are addressed by position; Simulate checks the screen flow, and recorded runs use synchronous update, so each delivery number returns at once in the Run Log |
| VL10A / VL10C delivery due list | SAP selects due order items by shipping point and date and creates the deliveries, online or as a background job (scheduled with VL10BATCH) | Ship everything that is due, every day | Selection is by criteria, not by an arbitrary list; user role and F-code profile settings decide what the background run does; KBA 2297715 covers background runs that create nothing |
BAPI_OUTB_DELIVERY_CREATE_STO / VL10B | Deliveries for stock transport orders | Plant-to-plant transfers | A separate BAPI and template; the sales order BAPI does not handle purchase orders |
When VL10 is the better tool. SAP's delivery due list processes "all order items that are due for delivery at a certain time or within a certain period" and checks which items can be combined into one delivery (SAP Help). If that describes your run, schedule it and keep Excel out of it. A file earns its place when someone has made a decision the selection screen cannot express: these 40 orders and not the other 300, 60 of 100 units for this customer, the priority accounts first when stock is short.
Why we build on the BAPI. A VL01N recording that delivers whole orders is short and stable. Once you send partial quantities, the recording has to address item rows in the overview table by position, and one extra item in an order shifts every row. The general trade-off is in BAPI vs BDC in SAP, and how to record so a recording replays is in the BDC recording guide.
BAPI_OUTB_DELIVERY_CREATE_SLS parameters: what goes where
PostNow.ai shows the BAPI's parameters as your system defines them. For a delivery upload you will use these:
| Parameter | Filled from | Notes |
|---|---|---|
SHIP_POINT (import) | First row of each group, or a fixed value | Shipping point; one per call |
DUE_DATE (import) | First row of each group | Data element LEDAT, the delivery creation date: the selection date of VL01N |
SALES_ORDER_ITEMS (table) | Every row of the group | REF_DOC (sales order), REF_ITEM (item, 000010), DLV_QTY, SALES_UNIT, SALES_UNIT_ISO |
SERIAL_NUMBERS (table) | Only for serialised materials | REF_DOC, REF_ITEM, SERIALNO |
DELIVERY (export) | Returned by SAP | The delivery number; map it to PostNow.ai's document number |
NUM_DELIVERIES (export) | Returned by SAP | How many deliveries the call created |
DELIVERIES, CREATED_ITEMS (tables) | Returned by SAP | Every delivery and delivery item created, with the order item it came from |
RETURN (table) | Returned by SAP | Messages of type S, W, I, E or A |
- The BAPI does not commit on its own. "It returned a number but VL03N can't find it" is the classic symptom of a missing
BAPI_TRANSACTION_COMMIT. PostNow.ai commits after every clean call. - One call can create several deliveries. SAP splits an order into several deliveries when its items have different shipping criteria, such as route or ship-to (SAP Learning). The
DELIVERYexport holds one number, so a row whose NUM_DELIVERIES column shows 2 has a second delivery to find in VL06O or the order's document flow. - No error does not mean a delivery. Practitioners on SAP Community report calls that returned an empty
RETURNtable and an emptyCREATED_ITEMStable, with nothing created. PostNow.ai commits any call without an E or A message, so read the Delivery column with the Run Log: a row with no error and an empty Delivery cell is a row SAP did not deliver. - Sales orders only. Scheduling agreements and stock transport orders need other routes; for transfers that is
BAPI_OUTB_DELIVERY_CREATE_STO.
Shipping point and selection date in a mass delivery file
PostNow.ai sends one shipping point and one selection date per call, and SAP decides which schedule lines those two values let through.
- The selection date filters schedule lines. In VL01N "you can only deliver schedule lines" whose material availability date or transportation planning date is on or before the selection date, and the system proposes today (SAP Help). A line confirmed for next Tuesday is not delivered by a file dated Friday. In VL01N this is message
VL248, "No schedule lines due for delivery up to the selected date". - The shipping point was set on the order. SAP determines it per order item from the shipping conditions, the material's loading group and the delivering plant, and each delivery is processed by exactly one shipping point (SAP Help). The file's shipping point has to match the one on the order item; it does not move the item to another warehouse.
- Group by shipping point and date. One shipping point and date per call means a file for two warehouses is two groups. Sorting by shipping point, then by order, keeps the split column honest.
- The delivery type comes from the order. With reference to a sales order, SAP proposes the delivery type from the order type, normally
LF(SAP Help). There is no reason to send it.
The easiest way to build the file is to start from what SAP says is due. In PostNow.ai, the Report Library's Delivery-Due List (SD-14) puts the order schedule lines due within a date range into Excel, with confirmed quantity, material availability date and transport date. Its selection mirrors VL10. Filter and cut that list to the decision you have made, then paste it into the delivery template.
Partial deliveries and stock: what the run will actually ship
PostNow.ai creates the deliveries in sheet order, one call after another, and SAP checks availability again for each one as it is created.

- Availability is checked again. When an item is rejected for lack of availability, VL01N writes it to the log rather than delivering it (SAP Help). An order confirmed three weeks ago competes with everything that happened since.
- Row order is an allocation rule. Each delivery takes stock before the next call runs. When a material is short, the orders at the top of the sheet ship and those at the bottom do not. Sort by the priority the business agreed before you run, not after.
- Partial quantities follow the order item. Send a
DLV_QTYbelow the open quantity and SAP creates a partial delivery, if the item allows it. The item's partial delivery indicator (fieldKZTLF) decides: blank allows partial deliveries up to the maximum number,AandBallow one delivery only,Callows complete delivery only, andDallows unlimited subsequent deliveries. With the complete delivery indicator set for the customer, all items of the order ship together and the item indicator must beC(SAP Help, Partial Delivery and Complete Delivery). Test one partial line per setting your customers use. - Combining orders needs the customer's consent. SAP combines several orders into one delivery only when the Order Combination field allows it. A split column on a "Group" column you fill yourself lets PostNow.ai send several orders in one call; SAP still decides whether they end up in one delivery.
Delivery blocks and credit blocks before a mass delivery run
PostNow.ai sends what the file says. Whether a block stops the delivery depends on where the block sits and which route creates the delivery, and the BAPI is the most permissive of the three.
| Block | BAPI_OUTB_DELIVERY_CREATE_SLS (PostNow.ai) | VL01N | VL10A |
|---|---|---|---|
| Header delivery block on the order | Can create the delivery anyway (KBA 2235831) | Can create it (KBA 2371164); a header block works only if it is assigned to the delivery type | Blocked (same KBA) |
| Schedule line delivery block | Test it; SAP documents the item-level gap for the S/4HANA OData API (KBA 3776513) | Blocked; "always effective" | Blocked |
| Block reason with "delivery due list" only | Not stopped | Not stopped | Blocked |
| Block reason with goods issue block | Test it | VL048 "Sales order is blocked for delivery" (KBA 2428074) | VL048 |
| Credit block | Release first | Not deliverable until released | Not deliverable until released |
The block rules come from SAP's shipping configuration: a header block "only takes effect" when assigned to the delivery type, a schedule line block is always effective, and a due-list block stops VL10 but "not the direct creation of an individual delivery" (SAP Help, Define Reasons for Blocking in Shipping).
The practical rule: take blocked orders out of the file. Every block was set by someone for a reason: a credit hold, an export check, a dispute. Validate works on the file's own values, and the BAPI may not stop at blocks, so check them before the run. Before the run, check VBAK-LIFSK (header) and VBEP-LIFSP (schedule line) for the file's orders; a designer can add both to a PostNow.ai query, or use SE16N. Credit-blocked orders go back to the credit team, who release them in VKM1/VKM3 on classic ECC credit management. On SAP Community, practitioners also report a fresh credit check at delivery creation when the delivery type has one (OVAD), so a released order can block again.
Picking and post goods issue are a separate step
PostNow.ai's delivery template creates the deliveries. Picking and goods issue follow as their own step, and they are where the stock actually moves.
- Picking. Without warehouse management, the picked quantity is entered on the delivery in VL02N. With WM or EWM, picking runs through transfer orders or warehouse tasks, and the warehouse owns that step. Only fully picked deliveries are offered for collective goods issue (SAP Help).
- Goods issue. Post it per delivery in VL02N, or for many at once from the outbound delivery monitor (VL06O, collective processing for goods issue). Goods issue reduces stock, creates the accounting documents and puts the delivery on the billing due list (SAP Learning).
- Goods issue from Excel. If the list of deliveries to issue lives in a spreadsheet, a second PostNow.ai BAPI template on
BAPI_OUTB_DELIVERY_CONFIRM_DECdoes it: the delivery number plusPOST_GI_FLG = XinHEADER_CONTROL. The free post goods issue template has the layout. SAP has a KBA for this BAPI not posting goods issue in an SE37 test without a commit (2270879); PostNow.ai commits after each clean call. Know the trade-off before you choose it: SAP built this BAPI to confirm deliveries from a decentralized warehouse system, and SAP KBA 1459993 states that it sets the delivery's distribution status to completed, so VL09 cannot reverse that goods issue (message VL633). Agree with your SD and FI teams how a wrong goods issue gets corrected, then test the template on a quality client. - Chaining both steps. A PostNow.ai Chain can run the goods issue template after a successful delivery on the same row, with the delivery number passed through a column. Use it only where items need no picking confirmation, and prove it in a quality client first.
BAPI_OUTB_DELIVERY_CONFIRM_DEC (KBA 1459993). Once the delivery is billed, practitioners on SAP Community cancel the invoice before they reverse.Worked example: 22 orders for shipping point 1010
PostNow.ai handles this with one published BAPI template and one run. It is Thursday. Customer service wants 22 orders for sales organisation 1010 shipped from shipping point 1010 (plant 1010) on Friday 14.11.2026, with sold-to 200371 first because it is the priority account. Material TG-1001 is short.
- Start from SAP's due list. The shipping lead runs the Delivery-Due List (SD-14) for plant
1010with material availability dates up to 14.11.2026 and cuts it to the 22 orders: 57 items. Item 20 of order4479is confirmed for 21.11, so it stays out of this file. - Lay out the sheet. One row per item: shipping point, due date 20261114, sales order, item, quantity, unit. Split column: Sales Order. Order
4471for200371takes 120 EA ofTG-1001on item 10, a partial quantity of the 200 ordered, agreed with the customer. - Sort and check blocks. Rows are sorted by customer priority, then requested date. A check of
VBAK-LIFSKfinds a header delivery block on order4485; it comes out of the file, because the BAPI might deliver it anyway. - Validate and Simulate. Validate is clean. Simulate returns an error for order
4472; VL01N givesVL461for the same order, and its long text shows the order is incomplete. It goes back to customer service and comes out of the file, leaving 20. - Pilot, then run. Run the first three orders and open them in VL03N. Order
4471shows NUM_DELIVERIES 2: item 30 has a different route, so SAP split it, and the second delivery is found in the document flow. Then set Start Row back to the first row and run the rest; the guard offers to skip the three already posted. - Read the results. 19 orders get delivery numbers, 20 deliveries in all. Order
4481has no error in its Run Log and an empty Delivery cell: its only item wasTG-1001, and the orders above it used the stock. It goes on the backorder list, and the warehouse gets the list of 20 deliveries for Friday's picking.
Checklist before SAP mass outbound delivery creation
PostNow.ai enforces formats and allow-lists in the template; this list covers the decisions that stay with the shipping team.
- The file comes from what SAP says is due (SD-14 or VL10), cut to a decision someone owns.
- Every row's shipping point matches the order item, and the selection date covers each line's availability or transport date.
- Rows are grouped by a split column, so one call carries one order (or one group you chose).
- The sheet is sorted by the agreed allocation rule for short materials.
- Header and schedule line delivery blocks and credit blocks are filtered out.
- Partial quantities have been tested once for each partial delivery setting in use.
- The Delivery and NUM_DELIVERIES columns are mapped, and someone checks the empty and the "2" rows.
- The warehouse knows how many deliveries are coming and for which day.
Delivery creation errors and what they mean
PostNow.ai writes SAP's error text into the Run Log of the group's first row; these are the ones you are most likely to meet.
| Message | What it usually means | Fix |
|---|---|---|
VL248 No schedule lines due for delivery up to the selected date | The line's availability or transport date is after the selection date, or nothing is confirmed | Check the schedule line in VA03; move the date only if the business agrees to ship early |
VL048 Sales order is blocked for delivery | A block reason with a goods issue block sits on the order (KBA 2428074) | Remove the row; the block owner releases it |
VL461 Order cannot be delivered (see long text) | The long text lists the cause: copy control, an incomplete order, a block | Read the long text in VL01N for the same order (KBA 2924512) |
| No error in the Run Log, empty Delivery cell | SAP returned no error and created nothing: no stock left, nothing due, or the item was already delivered | Look at the order's document flow; re-post the row only through Run Scope after fixing the cause |
| PostNow.ai: "No rows in the Run Log column (A) are marked ERROR" | Retry Failed found nothing to re-post from the current Start Row down | Set Start Row back to the first row after a pilot; empty-result rows are not errors |
For a failed group, AI Review in the run diagnostics explains SAP's messages in plain language. By default it receives the messages, the BAPI name and the field structure, never the cell values.
How to check deliveries after a mass upload
PostNow.ai gives you the first check per order: the Run Log, the Delivery column with its VL03N link, and the central audit, which records each call's template, SAP system, client, user, result and document number. The rest comes from SAP.
- VL03N for a sample: ship-to, items, delivery quantity against the file, and the dates.
- VL06O, the outbound delivery monitor, lists the run's deliveries by shipping point and date, including any second delivery from a split.
- Tables:
LIKPheader,LIPSitems withLFIMGand the reference order inVGBEL. On ECC the statuses are inVBUKandVBUP. - Report Library in PostNow.ai: Delivery 360 (SD-07) puts deliveries, items, picking and goods movement status into Excel, filtered by shipping point and created date, and Open Sales Orders (SD-13) shows what is still undelivered. Operators can run both under their own SAP authorisations. The report itself is described on the Delivery 360 report page.
Reconcile on three numbers per run: orders in the file against orders with a delivery, quantity requested against LFIMG, and deliveries created against what the warehouse was told to expect.
Deliveries grouped into shipments for transport are listed in a SAP shipment report, with carrier, stages and dates per shipment.
What to plan for in a delivery upload
PostNow.ai creates deliveries through SAP's BAPI or the VL01N screen, so SAP's own shipping rules decide every result.
- Sort the sheet by priority when stock is short. Rows are delivered in sheet order, so the orders at the top get the stock first.
- Check NUM_DELIVERIES when SAP splits a call. The row gets one delivery number back; NUM_DELIVERIES tells you how many SAP created, and the order's document flow shows the rest.
- Read the Delivery column with the Run Log. A call that created nothing has no E or A message, so it is committed like any other; the empty Delivery cell shows it.
- Correct created deliveries in VL02N. Stop cancels the calls not yet sent; created deliveries stay in SAP and are changed or deleted in VL02N.
- Schedule the routine run in VL10. Recordings follow the screen and run when a user starts them; the routine due-list run can be scheduled in VL10 as a background job.
- Keep the PostNow.ai portal reachable for approved templates. The approval check runs against the portal; if the portal cannot be reached, the check lets the run through.
Making a template like this repeatable for a team (designers who build, operators who only run, a published template in the central library) is covered in Excel to SAP automation.
Mass delivery creation on S/4HANA: what changes
PostNow.ai uses the same BAPI on ECC and S/4HANA on-premise, because BAPI_OUTB_DELIVERY_CREATE_SLS, VL01N and VL10 are still there; a few things around them moved.
- Status tables are gone. The status fields of
VBUKandVBUPmoved into the document tables, for deliveriesLIKPandLIPS(SAP Learning). PostNow.ai's Delivery 360 report switches its source when it detects S/4HANA. - The OData API has its own block behaviour. SAP documents that
API_OUTBOUND_DELIVERY_SRVcreates deliveries despite a schedule line delivery block, unlike VL01N (KBA 3776513). On S/4HANA, PostNow.ai runs the delivery upload through the BAPI. - Customers are Business Partners. Shipping conditions and partial delivery settings live in the BP's sales area data, maintained in BP. See customer master upload (XD01).
The wider SD picture, from order to invoice, is in SAP SD mass upload.
