Run Blitz Uploads in Excel Copy link

Description
Category: Getting Started
Plugin: Blitz Report Excel Add-in Skills (br-run-uploads)
Works with: Claude in Excel, Microsoft 365 Copilot in Excel
Updates EBS creates or updates Oracle EBS data through Blitz Uploads, only after your confirmation

Create, load or update Oracle EBS records from Excel with Blitz Uploads via the BLITZ REPORT ADD-IN (the br_* worksheet functions) - journals, invoices, purchase documents, items, suppliers, customers, assets and more (GL, AP, AR, PO, INV, WIP, HR, FA, CE).

When to use it

  • Use whenever the user says they want to UPLOAD, LOAD, POST, ENTER, CREATE or UPDATE any EBS data or document ("upload a journal entry", "upload journals", "load invoices", "create a PO", "post a journal").
  • In this add-in "upload" means sending data INTO Oracle EBS - it does NOT mean the user is attaching a file to the chat, so never ask them to attach one and never hand-build a mock table in the sheet instead.
  • NOT for the standalone Blitz Upload template file (UploadTemplate.xlsm with bu_* functions) - that is bu-fill-upload's territory.
  • This WRITES to Oracle EBS.
Install
  1. Download the skill zip. br-run-uploads.zip
  2. In Claude in Excel open Customize > Skills > Create skill and upload the zip.
  3. Connect the Blitz Report Excel add-in to your Oracle EBS instance, then ask Claude for the task in your own words.

Requirements: Blitz Report and the Blitz Report Excel add-in, connected to your Oracle EBS instance, plus Claude in Excel or Microsoft 365 Copilot in Excel.

A Blitz Upload loads data INTO Oracle EBS — it creates or updates real records (purchase documents, invoices, items, journals, etc.). This is the opposite of a Blitz Report, which only reads. Uploads change EBS data, so treat every upload as consequential: confirm intent, review what will be sent, and always read the per-row results afterward.

The Blitz Report add-in must be loaded and connected to an environment + responsibility (the user does this once via the ribbon). #BLITZ_NOT_CONNECTED → ask them to connect via the Blitz Report ribbon first. Environment/responsibility selection works exactly as in the br-run-reports skill (same br_environments_external() / br_responsibilities_external() discovery, same optional trailing environment/responsibility args, same sticky selection) — see that skill for the detail; this skill covers only what is different for uploads.

Read vs write — pick the right skill

  • The user wants to see / analyze existing data → use br-run-reports.
  • The user wants to create / update / load data into EBS → this skill. Uploads appear in the same catalogue as reports but with Type = U.

br* vs bu* — two different Blitz products, never mix them

This skill drives the Blitz Report add-in (br_* functions). The separate standalone Blitz Upload template file exposes bu_* functions and has its own skills (bu-fill-upload, bu-ap-invoice-upload). The families are not interchangeable — the wrong one returns #NAME?. If =br_ai_ping() returns #NAME? but the workbook is a standalone upload template (an Upload + Parameters sheet, bu_ai_ping() works), switch to the bu skills; otherwise the report add-in simply isn't loaded — ask the user to load/connect it. Never retry the other family's function to work around a #NAME?.

Keep the workbook tidy

Do discovery on a throwaway helper sheet named blitz_ (create it, delete it when done), exactly as in br-run-reports. The upload grid itself lands on its own new sheet created by br_run_upload_external — that is the working deliverable the user edits; leave it visible.

🚨 NEVER activate the blitz_ sheet. You can write formulas to it and read their results without it being the active sheet — so just don't call activate() on it. Activating it (a) puts your scratch sheet in the user's face instead of their deliverable, and (b) leaves it as the ACTIVE sheet, which breaks the prepare/process step: those run the add-in's Autofill and Validate, which act on whatever sheet is active. The upload sheet should be the active one throughout.

Every one of these functions SPILLS, so give each one clear space below and to the right, and always check the returned cell for #SPILL! — it means the result did not land at all (something is in its way), not that there was nothing to report. Reuse ONE area per purpose and clear it before re-running, rather than working down the sheet into ground you already used.

The upload sheet layout (fixed, deterministic — do not probe)

  • Row 1 = the report-name banner + the run formula + a "Last run | Records: N" info cell — NOT data.
  • Row 2 = the column headers.
  • Row 3 onward = the data rows.
  • The first three data columns are always Action (A), Status (B), Message (C) — the framework columns. The business columns (e.g. PO Number, Item, Quantity) follow from column D.
  • Get the exact column contract from =br_upload_columns_external() (call it on blitz_ with the upload sheet name: =br_upload_columns_external(FALSE, "<Upload Sheet Name>")). It spills one row per column: Sheet Column | Column | Type | Required | Read Only | Has LOV | Validate From List | Comments — the REAL Excel column letter, the row-2 header text, the flags, and whether the list is binding. Always write cells by the returned Sheet Column letter — never derive a column's position by counting, because hidden columns sit between visible ones and counting drifts. Hidden columns are excluded from the spill so every listed column is safe to write (except the read-only ones).
  • Validate From List = Yes means the value MUST be one from the list — the server rejects anything else, so look it up (below) and never type your own. Has LOV = Yes with a blank Validate From List means the list only assists entry; a value outside it is allowed but still has to make sense to EBS, so prefer a looked-up value there too.
  • 🚨 The sheet has HIDDEN columns to the RIGHT of the last one the contract lists (framework internals and round-trip ids — often dozens). So "the last column" for the purpose of placing a trigger formula is NOT the last row of the contract spill: read the sheet's used range and go a few columns beyond that. A trigger dropped inside the hidden-column span is inside the grid, so the add-in refuses to clean it up and it is left behind as junk on the user's deliverable sheet.
  • Fallback on older add-in builds (#NAME? from the function): amber header = required, grey data cells = read-only; ignore anything past the visible columns.

Workflow — follow in order

  1. Find the upload. On blitz_: =br_report_list_external("<search words>") and choose a row whose Type is U. (If the user gave the exact upload name, skip discovery and go to step 3; a wrong name returns #BLITZ_REPORT_NOT_FOUND instantly.)

  2. Inspect its parameters (the download parameters, not the data columns): =br_report_params_external("<Upload Name>"). Same Must Set? rules as br-run-reports. The parameter list is the source of truth — only pass parameters that appear in it; sending one the upload doesn't define fails the whole run with ORA-20001: Parameter "<name>" not found.

    About half of the uploads have an Upload Mode parameter; the rest (e.g. GL Journal Upload) do not. When it IS listed:

    • Create, Update (the default) downloads the matching EXISTING records so you can edit them.
    • Create gives an EMPTY template to add brand-new records. Set filters (Operating Unit, Document Type, date ranges, etc.) to scope which existing rows come down in Create,Update mode. When it is NOT listed, don't pass it — the upload's own default applies (these are typically create-only templates).

2b. Choose the TEMPLATE — =br_report_templates_external("<Upload Name>") on blitz_. The template decides the column set you get, so this matters as much as the parameters. An upload often ships several (e.g. GL Journal Upload has Functional Actuals, Foreign Actuals, Budget Journal, Encumbrance Journal, and (with attachment) variants).

  • If the user named one ("Functional Actuals"), pass that exact template name.
  • If several plausibly match their wording (e.g. plain vs (with attachment)), ASK which — don't guess; this writes to EBS.
  • If they said nothing about a template, you may omit it: the run then uses the upload's default template (the Default? = Yes row) automatically. Template names are NOT the same thing as parameter values. Functional Actuals is a TEMPLATE; Journal Type=Actual is a PARAMETER. Never tell the user a real template "isn't a template".
  1. Run the upload. On blitz_, in an empty cell: =br_run_upload_external("<Upload Name>","<params>","<template or blank>")

    • params format is identical to reports: "Name=Value; Name2=A,B,C". For uploads that HAVE an Upload Mode parameter it defaults to Create, Update (pass Upload Mode=Create for an empty template); uploads without that parameter are run untouched, so never add it yourself.
    • The cell returns BLITZ_RUNNING: ...; a new upload sheet appears with the grid.
    • Immediately overwrite that formula cell with a plain value so a recalc can't re-fire a second run, then poll _blitz_run_status for DONE: <n> rows on sheet '<name>' / ERROR: <message>. Wait for DONE before touching the sheet.
  2. Fill / edit the data on the upload sheet (rows 3+):

    • Create new records: write values into the business columns of empty rows (from column D). Set only the columns you have values for; required columns (amber headers) must be filled.
    • Update existing records: change the business-column values in the downloaded rows. Leave the key columns that identify the record intact.
    • Do NOT write into read-only (grey) cells, the hidden columns, or the Action/Status/Message columns — the add-in manages those.
    • 🚨 Especially never write the Action column (A). The prepare step looks each row up in Oracle and sets Action itself — Create when the record is new, Update when it already exists. If you put a value there the add-in respects yours instead of deciding, so a wrong guess (Update on a record that doesn't exist yet, or Create on one that does) silently makes the row do the wrong thing. Leave A, B and C blank; they fill themselves.
    • NEVER invent a value for a list-of-values column — look it up and write only a value that is in the list. Use =br_column_values_external("<Column Header>", <row>, "<search>", "<Upload Sheet Name>") on the blitz_ sheet — always pass the 4th argument naming the upload sheet, so the lookup reads that sheet's row context while the returned list lands on blitz_ and never litters the deliverable grid. (Omitting it makes the function read the sheet the formula sits on, which answers #BLITZ_NOT_UPLOAD_SHEET from blitz_.) It returns Value | Description, exactly what a user gets by double-clicking that cell. This is the grid-column lookup; br_param_values_external serves the download parameters and correctly answers #BLITZ_PARAM_NOT_FOUND for a grid column like Ledger Name.
      • 🚨 The two lookups do NOT take the same arguments. Grid column: br_column_values_external(column, row, search, sheet) — 3rd argument is a search filter. Download parameter: br_param_values_external(report, parameter, parent_values, environment, responsibility) — its 3rd argument is **parent parameter values** ("Name=Value; ..." for a dependent LOV), NOT a search. Passing a search word there filters nothing and silently returns the whole list; read the returned list yourself instead.
      • Column LOVs are row-context dependent (Period depends on Ledger, GL segments on the chart of accounts), so pass the row you are filling and fill that row's PARENT columns first — e.g. write Ledger Name in row 3, then ask for Period with row 3.
      • If the user's wording doesn't match a returned value exactly (their "Manual" vs the actual Source values), show them the list and ask — don't pick a lookalike. This writes to EBS.
      • #BLITZ_LOV_TOO_LARGE → call again with a search. #BLITZ_LOV_EMPTY → the parent columns for that row aren't filled yet (or no values exist for that context). #BLITZ_NOT_LOV_COLUMN → free text, type the value directly.
    • Some columns auto-fill from others (e.g. entering Item fills Category, Unit of Measure, Price, Description). If a dependent column stays blank after you set its parent, fill it yourself with the correct value.

4a. Filling from source documents (the user attached or pasted invoices, bills, vouchers, statements, receipts — any document whose data should land in EBS):

  • Fill only what is printed on the document. Unknown field → leave it blank; never infer, never compute, never fill a gap with something plausible. Blank + validate beats guessed.
  • Amounts and dates verbatim. Copy the printed total exactly — do not recompute it from the lines, strip/add tax, or fix rounding. If the lines don't sum to the printed total, write the printed total and TELL THE USER about the discrepancy. Watch ambiguous date formats (03/04/2026 is 3 April in most of the world, 4 March in the US) — if the document doesn't disambiguate, ask.
  • Required ≠ must-type. A required column may be filled by the server (defaults, autofill derivation). Fill what the document gives, run the prepare step, and let the validation Message tell you authoritatively what is genuinely missing — don't invent values to satisfy an amber header.
  • Internal ids are never on the document. Supplier numbers, site codes, account ids etc. are the customer's own master data — resolve them with br_column_values_external (searching by the NAME printed on the document), never read them off the document or invent them.
  • Stop after ~3 unproductive fix rounds. If the same rows keep failing validation, show the user the exact messages and ask instead of iterating blindly.
  • Document-type specifics (which printed field maps to which column) live in dedicated skills — e.g. br-ap-invoice-upload for supplier invoices/bills into Oracle Payables.

4b. Review before submitting (recommended). In an empty cell on the upload sheet, in row 1, a few columns to the RIGHT of the sheet's used range — NOT the last column the contract listed, which is only the last VISIBLE one (see the hidden-column warning above): =br_prepare_upload_external() — this marks the rows you wrote, runs Autofill (deriving the dependent columns) and Validates, without sending anything to EBS. Poll _blitz_run_status for DONE: prepared <n> row(s) - <n> valid, <n> flagged, then read the per-row outcome with =br_validation_results_external(FALSE, "<Upload Sheet Name>") on blitz_ — it spills Row | Action | Status | Message for exactly the rows that need attention (or BLITZ_OK: no rows need attention). Fix the flagged rows' values and run the prepare again. Show the user this state before you submit anything non-trivial. The add-in clears the trigger cell itself when it finishes, so do NOT overwrite it with a marker value — that would just leave your marker behind as junk on the user's sheet. (Why marking is needed: your writes go through office-js, which does NOT fire the add-in's Excel events, so rows you fill have an empty Action/Status until this runs.)

  1. Process (submit) the upload. On the upload sheet (or blitz_), in an empty cell: =br_process_upload_external()

    • It performs the same mark → autofill → validate steps itself before submitting, so step 4b is an optional review point, never a prerequisite.
    • This runs the SAME circuit as the ribbon Upload button: it validates every row first (invalid rows are flagged and NOT sent), builds the file, submits it to EBS, waits for the concurrent request, and renders the per-row result back into the sheet (Status + Message), then sets _blitz_run_status to DONE: <n> succeeded, <n> errored (request <id>) or ERROR:.
    • Put it in row 1, a few columns to the RIGHT of the sheet's used range (hidden columns extend past the last column the contract lists). The cell returns BLITZ_PROCESSING: ...; the add-in clears that trigger cell itself when processing ends, so do NOT overwrite it with a marker (a leftover process_triggered next to the grid is exactly the junk this avoids). Just poll _blitz_run_status. Processing can take a while for large uploads — do ONE lightweight status check per turn and wait between turns (same "go quiet" rule as br-run-reports; office-js has no setTimeout, and hammering the workbook collides with the add-in's background write).
    • _blitz_run_status keeps the PREVIOUS value until the new run finishes — a DONE: that matches the last step (e.g. DONE: prepared ... right after you triggered a submit) is STALE, not a result. Keep polling until it changes to a DONE:/ERROR: that belongs to this step. The same applies BEFORE you start: an ERROR: (even a bare ERROR: ERROR) found in the workbook before you triggered anything is leftover from an earlier run or session — never abort, adapt, or report failure because of it; trigger your step and read only what appears afterwards.
  2. Report the outcome. When DONE:

    • Read the per-row results with =br_validation_results_external(FALSE, "<Upload Sheet Name>") on blitz_ — it lists every row that errored with its Action, Status and exact Message (BLITZ_OK means everything succeeded). Pass TRUE as the first argument to also list the succeeded rows when the user wants the full picture.
    • Summarise: how many succeeded, how many errored, and the specific error messages for the failed rows. Never claim success without reading the per-row results.
    • To retry failures: fix the flagged rows' values and run =br_process_upload_external() again (only rows that still need processing are sent).

Filling the sheet from documents (invoices, statements)

The customer can define how a document is read into an upload, as FND lookups maintained with the FND Lookup Upload. Check for one before reading documents into the sheet:

  1. Run the report FND Lookup Values with Type=XXEN_DOCUMENT_TYPES (as in br-run-reports). No rows, or the type is unknown: there are no document types, so read the documents as the upload-specific skill says.
  2. Take the row whose Tag is this upload; if several fit, ask which Meaning (the document type) the documents are. Its Description says how to read them (for example one row per invoice line, the header values repeated on every row). Its Code is the mapping.
  3. Run FND Lookup Values with Type=<that Code>: one row per upload column the document fills. Code is the column (INVOICE_NUMBER is the header Invoice Number), Description says where the value is on the document, Tag is the value when the document does not show it.
  4. Fill only those columns, as the descriptions say, with the Tag where the document is silent, and leave every other column to the upload's own defaults. The mapping is the customer's, so it wins over the generic reading guidance of an upload-specific skill.

Talk to the user in THEIR language, never in function names

The br_* functions, the blitz_ sheet, trigger cells and _blitz_run_status are your plumbing. The user never types them and should never have to read them — quoting a function name back at them turns a simple confirmation into homework. Describe what you are about to do, or what happened, in terms of their work:

Say thisNot this
"Ready to submit this invoice to Oracle Payables — shall I go ahead?""Say the word and I'll run br_process_upload_external() to submit it to EBS."
"I validated both lines against Oracle — both passed.""I ran br_prepare_upload_external() and _blitz_run_status came back DONE: prepared 2 row(s) - 2 valid."
"The supplier resolved to Advanced Network Devices, number 1013.""br_column_values_external returned Value/Description 1013."
"I couldn't find that PO in Oracle, so I left the PO field blank.""Invoice Po Number has Validate From List = Yes and the LOV returned no match."

Sheet, column and value names ARE fine — the user can see those on screen ("I left Invoice Po Number blank", "row 3", "the AP Invoice Upload sheet"). It is the add-in's internals that stay behind the curtain. Same for asking permission: ask about the action ("submit these 2 invoice lines to Oracle?"), never about the mechanism.

Rules & safety

  • This writes to Oracle EBS. If the user's request is ambiguous about creating vs updating, or about scope, confirm before running br_process_upload_external. Prefer showing them the filled grid first for anything non-trivial.
  • Use upload, parameter, and column names exactly as the discovery functions return them.
  • Leave the upload sheet clean. It is the user's deliverable. Keep every lookup on blitz_ (pass the upload sheet name as the sheet argument), put the two trigger formulas well to the right of the grid, never write marker text such as process_triggered, and clear any scratch you did put on the sheet before you report the outcome. Delete blitz_ when you are finished.
  • Do not write placeholder/sample data into an upload sheet. If you lack the real values, fill what you know, look up the LOV columns, and ask the user for the rest — a grid seeded with invented accounts and amounts looks ready to submit and is one br_process_upload_external() away from hitting EBS.
  • #BLITZ_NOT_CONNECTED → connect via the ribbon. #BLITZ_REPORT_NOT_FOUND → re-check the name with br_report_list_external (filter to Type = U). Environment/responsibility errors → same handling as br-run-reports.
  • ORA-20001: Parameter "<name>" not found → you passed a parameter this upload doesn't define. Re-read br_report_params_external and drop it. Do NOT retry the same call, and do NOT conclude the environment is broken or try a COPY OF: variant — the copy has the same parameter list.
  • _blitz_run_status = ERROR: ... on the RUN → report it, don't invent data. On the PROCESS → read the message; phase/status failures mean the concurrent request itself failed (report the request id so the user can check the request log).
  • A DONE with N errored is a partial success, not a failure — the succeeded rows DID commit to EBS. Report exactly which rows succeeded and which errored; do not re-process the whole sheet blindly (that would resend the already-committed rows).
  • Only pass parameters you have values for; respect Required / Must Set?.

Worked example

User: "Create a new standard PO line item on document 6504."

  1. =br_report_list_external("purchasing document upload") → PO Purchasing Document Upload (Type U).
  2. =br_report_params_external("PO Purchasing Document Upload") → note Upload Mode, Operating Unit, Document Type.
  3. =br_run_upload_external("PO Purchasing Document Upload","Operating Unit=Vision Operations; Document Type=Standard Purchase Order; Upload Mode=Create, Update") → a new sheet appears with existing standard POs.
  4. =_blitz_run_status → DONE: 778 rows on sheet 'PO Purchasing Document Upload'.
  5. Find document 6504's rows, edit the business columns as requested (or add a new row).
  6. =br_process_upload_external() → poll → DONE: 1 succeeded, 0 errored (request <id>).
  7. Read row's Status = Success, Message = the confirmation; report it.

The functions (reference)

FunctionPurposeReturns
br_run_upload_external(name, [params], [template], [environment], [responsibility])run a type-U upload; populates a new editable upload sheetBLITZ_RUNNING: ...; grid on a new sheet; _blitz_run_status → DONE/ERROR
br_prepare_upload_external()mark the rows you wrote + autofill + validate, WITHOUT submitting (review point)BLITZ_PREPARING: ...; _blitz_run_status → DONE: prepared <n> row(s) - <n> valid, <n> flagged
br_process_upload_external()mark + autofill + validate + submit the upload sheet the formula is on; render per-row results in placeBLITZ_PROCESSING: ...; _blitz_run_status → DONE: <n> succeeded, <n> errored / ERROR:
br_report_templates_external(name)list the upload's templates (the column set)Template \| Default? \| Description
br_upload_columns_external([include_hidden], [sheet])the upload sheet's column contract — real column letters, headers, required/read-only/LOV flags; call from blitz_ with sheet = the upload sheet nameSheet Column \| Column \| Type \| Required \| Read Only \| Has LOV \| Validate From List \| Comments
br_validation_results_external([include_valid], [sheet])per-row validation/upload outcome for rows needing attention (pass TRUE to include the valid/succeeded rows); call from blitz_ with sheet = the upload sheet nameRow \| Action \| Status \| Message, or BLITZ_OK: no rows need attention
br_column_values_external(column_header, [row], [search], [sheet])valid values for a GRID COLUMN under that row's context (what double-clicking the cell shows); call it from blitz_ and pass sheet = the upload sheet nameValue \| Description
br_report_list_external, br_report_params_external, br_param_values_external, br_environments_external, br_responsibilities_externaldiscovery — SAME as br-run-reports (uploads are Type = U)see br-run-reports
_blitz_run_status (workbook name)run/process completion signalRUNNING: / PROCESSING: / DONE: … / ERROR: …