How to do a VA01 mass upload from Excel
PostNow.ai does a VA01 mass upload from Excel by calling BAPI_SALESORDER_CREATEFROMDAT2 once per order: an H row carries the header and sold-to, D rows carry the items and schedule lines. SAP prices it and checks availability and credit as in VA01. PostNow.ai commits only when SAP returns no error and writes each order number back as a link to VA03.
- An order on credit block or with an incompletion log is a created order. It has a number. Release or complete it in SAP; never re-run the row.
- Check the result on confirmed quantity and price, not on how many rows turned green.
This page is about one transaction, and it is where SAP sales order automation usually starts: sales orders from a spreadsheet that arrive in SAP priced, confirmed and ready to deliver. 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 sales orders from Excel
PostNow.ai treats a sales order upload as a BAPI template: a designer builds it once against your SAP system, publishes it, and operators run their own files through it under their own SAP login.
1. Pick the BAPI and pull its structure from SAP
In the BAPI Explorer, pick BAPI_SALESORDER_CREATEFROMDAT2 from the quick list or search it. PostNow.ai reads the interface from your system, so the mapper shows the fields your release has, including the S/4HANA ones.
2. Map header, partner, item and schedule line columns
Header columns go to ORDER_HEADER_IN, the sold-to to ORDER_PARTNERS with a fixed partner role, item columns to ORDER_ITEMS_IN, and quantity and requested date to ORDER_SCHEDULES_IN. An H/D loop on a marker column (or flat rows with a split column) turns one H row and its D rows into one order. PostNow.ai fills the X-structures for you.
3. Fix what should not vary, restrict what can
Give the partner role, the division or a single order type a fixed value. Put a value list on sales organisation and order type and switch on Restrict, so Validate refuses another team's sales area. Customer number columns get leading zeros added automatically, because the SAP field uses the ALPHA conversion, so 200371 reaches SAP as 0000200371.
4. Validate, then Simulate
Validate checks the file offline: required fields, lengths, formats, dates, allowed values. Pre-Validation also asks SAP whether the customers and materials exist. Simulate calls the BAPI for real and then BAPI_TRANSACTION_ROLLBACK instead of a commit, so you see SAP's messages for pricing, partners and incompleteness without creating an order.
5. Run, and write the order number back
Run calls the BAPI once per order. If SAP returns no E or A message, PostNow.ai calls BAPI_TRANSACTION_COMMIT with wait, so the order is on the database before the next one starts; otherwise it rolls back. Map the $DOC_NO result token to an "SAP order" column and set VA03 as the Call Transaction, and each order number becomes a link that opens VA03 with the order filled in.
6. Re-run only what failed
Retry Failed re-posts only the orders whose Run Log starts with ERROR, each rebuilt whole. A normal Run checks the Run Log first and, if orders in scope were already posted, offers Skip posted rows, Post again or Cancel, so a second click on Run posts nothing twice unless someone chooses Post again.
A ready-made sheet for this is the free VA01 sales order template (H/D layout, column-to-BAPI field guide), listed with the other SD templates on the sales and distribution templates page.
BAPI_SALESORDER_CREATEFROMDAT2 vs a VA01 BDC recording: which to use
PostNow.ai can post sales orders either way. For orders with more than one item we build on the BAPI, and the table shows why.
| Route | How it posts | Use it when | Watch out for |
|---|---|---|---|
| PostNow.ai: BAPI_SALESORDER_CREATEFROMDAT2 | One RFC call per order; commit only if SAP returns no error | Multi-item orders, repeat loads, run-only templates for operators | Internal keys, quantity in the schedule line, item numbers matching across tables |
| PostNow.ai: VA01 recording | CALL TRANSACTION on an SHDB recording | One item per order, or a custom field only the screen reaches | Screens that appear only sometimes: availability check, incompleteness dialog, ship-to selection |
IDoc ORDERS (process code ORDE) | ALE/EDI inbound processing | Orders from a customer's system on EDI, run by IT | Partner profiles and IDoc monitoring; not a spreadsheet tool |
Why recordings struggle with VA01. The item overview is a table control addressed by row index (RV45A-MABNR(01), RV45A-KWMENG(01), then (02)), and how many rows are visible depends on screen size unless the default size is forced. VA01 also shows extra screens only for some orders: practitioners report recordings that work for one item and break when an item has no stock, because the availability check screen appeared. The BAPI has no screens. The general trade-off between the two methods is in BAPI vs BDC in SAP, and how to record so a recording replays is in the BDC recording guide.
BAPI_SALESORDER_CREATEFROMDAT2 structures: what goes where
PostNow.ai shows the BAPI's parameters as SAP defines them. In a standard VA01 upload you will use these:
| Parameter | Filled from | Typical fields |
|---|---|---|
ORDER_HEADER_IN / ORDER_HEADER_INX | H row, once per order | DOC_TYPE, SALES_ORG, DISTR_CHAN, DIVISION, PURCH_NO_C (customer PO number), REQ_DATE_H, PMNTTRMS |
ORDER_PARTNERS | H row | PARTN_ROLE (fixed AG), PARTN_NUMB (the customer) |
ORDER_ITEMS_IN / ORDER_ITEMS_INX | Each D row | ITM_NUMBER (10, 20, 30), MATERIAL, PLANT, SALES_UNIT, ITEM_CATEG, SHORT_TEXT |
ORDER_SCHEDULES_IN / ORDER_SCHEDULES_INX | Each D row | ITM_NUMBER (same as the item), REQ_QTY, REQ_DATE |
ORDER_CONDITIONS_IN / ORDER_CONDITIONS_INX | D row, only for manual prices | ITM_NUMBER, COND_TYPE, COND_VALUE, CURRENCY |
SALESDOCUMENT (export) | Returned by SAP | The new order number; PostNow.ai's $DOC_NO token reads it |
RETURN | Returned by SAP | Every message, type S, W, I, E or A |
- Quantity goes in the schedule line.
REQ_QTYinORDER_SCHEDULES_INis the order quantity, linked to its item byITM_NUMBER. MapITM_NUMBERonce, on the item: PostNow.ai copies it into the schedule line built from the same D row when that line has no item number of its own. Confirm on the first Simulate that each schedule line reached the right item. - The X-structures say which fields you sent. Every field filled in
ORDER_HEADER_INneeds anXin the same field ofORDER_HEADER_INX; item and schedule line X rows also carry the key values. PostNow.ai fills both from the field types it reads from SAP and sends ambiguous cases to a review dialog. - Use SAP's internal keys. Order type and partner function are language-dependent. In an English logon VA01 shows order type
ORand partner functionsSPandSH, while the database holdsTA,AGandWE; the screen converts them through conversion exits (for order types, tableTAUUM). PostNow.ai applies the ALPHA conversion (leading zeros) for you; put the internal keys in the template as fixed values, or test the BAPI'sCONVERTflag ("Conversion of Partner Function + Order Type") on one order. - The BAPI does not commit on its own. "It said saved but VA03 can't find it" comes from calling it without
BAPI_TRANSACTION_COMMIT; PostNow.ai commits after every clean order.
Order type, sales area and partners in the Excel file
PostNow.ai sends what the H row holds; SAP decides almost everything else from the order type, the sales area and the sold-to. That is why these three columns deserve allow-lists and a pilot.
- Order type (
DOC_TYPE) carries the document's rules, among them whether an incomplete order may be saved and the duplicate PO check. Keep one order type per template unless the file really mixes them. - Sales area is sales organisation, distribution channel and division together. The customer needs sales area data for exactly that combination, and each material needs its sales view for the sales organisation and channel. A customer that exists in KNA1 but not in this sales area is the most common reason a whole file fails on day one.
- Sold-to goes into
ORDER_PARTNERSwith roleAG, not into a header field. Leave the ship-to out and SAP's documentation says the sold-to is used as ship-to. Partner determination then fills bill-to and payer from the customer master. - One partner line per header. In PostNow.ai a table parameter in header scope is read once from the H row, which gives one
ORDER_PARTNERSline: the sold-to. If customers order for several ship-to parties, prove how your template sends the ship-to on a Simulate first. - Customer PO number (
PURCH_NO_C) is your duplicate guard. With "Check purchase order no." set toAon the order type (VOV8), SAP warns with messageV4 115when the sold-to already has an order with that PO number. RaiseV4 115to an error in OVAH and the BAPI returns E, PostNow.ai rolls back, and the row shows ERROR instead of creating a duplicate.
Items, schedule lines and pricing
PostNow.ai creates the orders in sheet order, one after another, and SAP prices and checks availability for each one as it is created.
- Row order is an allocation rule. The availability check confirms against what earlier orders have already taken. When stock is short, the customers at the top of the sheet get it. Sort the file on purpose (priority, requested date) before you run it, not after.
- Requested is not confirmed. You send
REQ_QTYandREQ_DATE; SAP writes the confirmed quantity and date into the schedule lines inVBEP. An order with zero confirmed quantity is still a created order. - Let pricing find the price. Leave
ORDER_CONDITIONS_INempty and the pricing procedure reads the condition records, exactly as in VA01. If those records came from a VK11 load, the VK11 upload guide shows how to prove they are the ones pricing reads. - Manual prices depend on the condition type. Whether a
PR00value from the file wins depends on the condition type's manual entry setting in V/06. Practitioners report the BAPI price ignored, or a secondPR00line next to the determined one. Simulate one order with a manual price and read the item's Conditions tab before you rely on it. - Wrong prices rarely raise errors. A customer with the wrong price group gets a valid price from a valid record. Compare net value per order against what the file expects for a sample, every time.

Incompletion log and credit block: what counts as success
PostNow.ai marks a row by what SAP did: committed or rolled back. SAP also saves orders that still need work, so read the outcomes like this:
| What SAP did | What you see | Order exists? | What to do |
|---|---|---|---|
| Saved, complete, no block | Success messages in RETURN (for example V4 233 "SALES_HEADER_IN has been processed successfully" and V1 311 "... has been saved"); order number in SALESDOCUMENT | Yes | Nothing |
| Saved with an incompletion log | Warning V1 555 "The sales document is not yet complete: Edit data" plus the save message | Yes | Complete it in VA02 (Edit › Incompletion log) or from the V.02 list. Do not re-run. |
| Saved and put on credit block | Often no credit message in RETURN at all; the order is saved with credit status B (not OK) | Yes | The credit team releases it. Do not re-run. |
| Rejected | E message(s), often ending with V4 219 "Sales document was not changed" | No (rolled back) | Read the messages above the last one, fix the row, Retry Failed |
Incompletion. Whether an incomplete order may be saved depends on the sales document type. Where it may, the BAPI saves with the warning, and the log blocks what its configuration says: missing payment terms, for example, allow delivery but block billing. In PostNow.ai the Run Log cell of a successful row shows SAP's first non-warning message, so read incompletion (V1 555) from the incomplete-orders check below, after every load.
Credit block. In classic credit management, OVA8 sets the reaction and the Status/Block indicator per credit control area, risk category and credit group. With the block on, the order is saved with credit status CMGST = B and waits for a release, in ECC usually in VKM1. On S/4HANA, SAP Credit Management may release through documented credit decisions instead; ask your credit team. Either way the row is a success, and re-running it creates a second order with the same demand.
Unclear outcomes. If a call times out or is interrupted after it may have reached SAP, PostNow.ai writes UNKNOWN rather than ERROR, so Retry Failed leaves it alone. Look the order up in VA05 by the customer PO number before doing anything else.
Worked example: 40 orders for sales organisation 1010
PostNow.ai handles this with one published BAPI template and one run. Customer service has 40 standard orders for sales organisation 1010, channel 10, division 00, plant 1010. Order 1 is for sold-to 200371, customer PO PO-77120, requested delivery 15.12.2026, with three items: 120 EA of TG-1001, 40 EA of TG-1002 and 15 EA of TG-1004 at a manually agreed price of 412.00 USD.
- Lay out the sheet. Row 2 is H: order type, the sales area,
200371,PO-77120, 20261215. Rows 3 to 5 are D: items 10, 20, 30 with material, quantity, unit and plant. Only row 5 fills the condition columns (PR00, 412.00, USD). - Sort first. Two materials are short this month, so the sheet is sorted by customer priority, then requested date.
- Validate. Formats, allow-lists and Pre-Validation are clean: every customer and material exists.
- Simulate. Order 17 fails: customer
200388exists, but not in sales organisation1010, channel10. Pre-Validation checks that a customer exists, not its sales area, so this is the step that catches it. That order is taken out and sent to master data. Order 6 showsV1 555, because its customer has no payment terms in this sales area. The other 38 come back clean. - Pilot, then run. If an approval policy covers the template, Run waits until someone other than the submitter approves this exact data. Run orders 1 to 5 and check them in VA03, including the Conditions tab of item 30. Then set the start row back to 2 and run the rest; the guard offers to skip the five already posted.
- Read the results. 39 orders get a number in the "SAP order" column. Order 6 is in V.02 for its payment terms. Order 22 for customer
200402is saved on credit block and goes to the credit team with its number. Neither is re-run.
Checklist before a VA01 mass upload
PostNow.ai enforces formats and allow-lists in the template; this list covers the decisions that stay with customer service and the SD team.
- Every customer has sales area data for the file's sales area; every material has its sales view.
- Order type and partner role go in the form your system accepts, proven on one test order.
- Schedule lines carry their item's number, and quantities are in
REQ_QTY. - The file is sorted by the allocation rule the business agreed.
- Manual price columns are empty unless intended, and one manual price has been checked on the Conditions tab.
- Customer PO numbers are filled, and you know whether
V4 115is a warning or an error. - Simulate shows no E messages, and five orders in a quality client match the file in VA03.
- Someone owns the blocked and incomplete orders the load will produce.
Sales order upload errors and what they mean
PostNow.ai writes SAP's error text into the Run Log of the order's header row; these are the ones you are most likely to meet on a first load.
| Message | What it usually means | Fix |
|---|---|---|
V4 219 Sales document was not changed | The summary line after a rejection. The real cause is in the messages before it: a missing mandatory field, a sales area the customer lacks, a missing configuration entry | Read the earlier E message, or create the same order once in VA01 and compare |
An error naming order type OR or partner function SP | The screen code was sent instead of the internal key | Send the internal key (TA for a standard order, AG for sold-to) or test the CONVERT flag |
| Material numbers provided in equivalent fields differ (S/4HANA) | Long material number handling: MATERIAL and MATERIAL_LONG disagree | Map the material to MATERIAL_LONG on S/4HANA and test one order with two items |
| 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 2 after a pilot; blocked and incomplete orders are not errors |
For a failed row, 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 sales orders after a mass upload
PostNow.ai gives you the first check per order: the Run Log, the order number column with its VA03 link, and the central audit, which records each order's template, SAP system, client, user, result and document number. The rest comes from SAP.
- VA03 for a sample: sold-to and ship-to on the partner screen, net value, the Conditions tab of an item, and the confirmed quantity on the schedule line.
- V.02 lists incomplete sales documents; VKM1 (ECC) lists credit-blocked ones; VA05 lists orders by sold-to, material or PO number.
- Tables:
VBAKheader,VBAPitems,VBEPschedule lines with confirmed quantity,VBPApartners,VBUVincompletion log. Credit statusCMGSTis inVBUKon ECC and inVBAKon S/4HANA. - Report Library in PostNow.ai: Sales Order 360 (SD-06) puts header, items, schedule lines with confirmed quantity and status into Excel, and Incomplete / Blocked Orders (SD-16) lists incompletion log entries by missing field, with header delivery and billing blocks; check credit status in your credit release transaction. Operators can run both under their own SAP authorisations. The columns of the first are shown on the SAP sales order report in Excel page; the rest is in the Report Library.
Reconcile on three numbers per load: orders created against orders in the file, requested against confirmed quantity, and expected against actual net value. A load where every row is green but half the quantity is unconfirmed has not finished its job.
What to plan for in a VA01 upload
PostNow.ai posts through the BAPI or the screen, so SAP's own sales rules decide every result.
- Sort the sheet by priority when stock is short. Orders are created in sheet order, so the orders at the top get the first claim on available stock. Product allocation or backorder processing in SAP can change the confirmation later.
- Correct created orders in VA02. Stop cancels the orders not yet sent; created orders stay in SAP and are corrected in VA02.
- Test the template for several explicit partners. The header row sends one partner line per order, so prove a template with extra partners on a Simulate first.
- Give configurable materials, free goods, third-party items and returns their own templates. They have their own data shapes or rules in SAP.
- Record on stable screens. Recordings follow the screen and run when a user starts them.
- 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.
VA01 mass upload on S/4HANA: what changes
PostNow.ai uses the same BAPI on ECC and S/4HANA, because BAPI_SALESORDER_CREATEFROMDAT2 and VA01 are still there; a few things around them moved.
- Status tables are gone. The header and item status fields of
VBUKandVBUPmoved intoVBAKandVBAP. Queries written for ECC that joinVBUKneed changing; PostNow.ai's Sales Order 360 report switches its source when it detects S/4HANA. - Customers are Business Partners. A sold-to needs the customer role and sales area data, maintained through BP. Missing BP roles surface as sales area or partner errors on the order.
- Long material numbers. If the 40-character material number is active, use the
MATERIAL_LONGfield that SAP added to the BAPI structures.
Customer master data for these orders is covered in customer master upload (XD01), the wider SD picture in SAP SD mass upload, and the order-to-cash steps around the order in SAP process automation.
