Run Blitz Uploads in Excel Copy link
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.
- Download the skill zip. br-run-uploads.zip
- In Claude in Excel open Customize > Skills > Create skill and upload the zip.
- Connect the Blitz Report Excel add-in to your Oracle EBS instance, then ask Claude for the task in your own words.
- Download the skill folder from GitHub. br-run-uploads
- Copy the folder into Documents/Copilot/Microsoft Excel/Skills in your OneDrive.
- Open Excel with the Blitz Report add-in connected and ask Copilot for the task.
- Add the Enginatics marketplace in Claude Code.
/plugin marketplace add enginatics/ai-skills - Install the Excel add-in skills plugin.
/plugin install blitz-report-excel-addin-ai-skills@enginatics - Run the setup skill; it installs or updates the skills in Claude in Excel or Microsoft 365 Copilot in Excel.
/blitz-report-excel-addin-ai-skills:excel-skills-setup
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 onblitz_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 returnedSheet Columnletter — 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 = Yesmeans 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 = Yeswith a blankValidate From Listmeans 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
Find the upload. On
blitz_:=br_report_list_external("<search words>")and choose a row whoseTypeisU. (If the user gave the exact upload name, skip discovery and go to step 3; a wrong name returns#BLITZ_REPORT_NOT_FOUNDinstantly.)Inspect its parameters (the download parameters, not the data columns):
=br_report_params_external("<Upload Name>"). SameMust 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 withORA-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.Creategives 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?=Yesrow) automatically. Template names are NOT the same thing as parameter values.Functional Actualsis a TEMPLATE;Journal Type=Actualis a PARAMETER. Never tell the user a real template "isn't a template".
Run the upload. On
blitz_, in an empty cell:=br_run_upload_external("<Upload Name>","<params>","<template or blank>")paramsformat is identical to reports:"Name=Value; Name2=A,B,C". For uploads that HAVE an Upload Mode parameter it defaults toCreate, Update(passUpload Mode=Createfor 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_statusforDONE: <n> rows on sheet '<name>'/ERROR: <message>. Wait forDONEbefore touching the sheet.
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 —
Createwhen the record is new,Updatewhen it already exists. If you put a value there the add-in respects yours instead of deciding, so a wrong guess (Updateon a record that doesn't exist yet, orCreateon 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 theblitz_sheet — always pass the 4th argument naming the upload sheet, so the lookup reads that sheet's row context while the returned list lands onblitz_and never litters the deliverable grid. (Omitting it makes the function read the sheet the formula sits on, which answers#BLITZ_NOT_UPLOAD_SHEETfromblitz_.) It returnsValue | Description, exactly what a user gets by double-clicking that cell. This is the grid-column lookup;br_param_values_externalserves the download parameters and correctly answers#BLITZ_PARAM_NOT_FOUNDfor a grid column likeLedger 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)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.— its 3rd argument is **parent parameter values** ("Name=Value; ..." - 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 Namein row 3, then ask forPeriodwith 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 asearch.#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.
- 🚨 The two lookups do NOT take the same arguments. Grid column:
- Some columns auto-fill from others (e.g. entering
ItemfillsCategory,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/2026is 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.)
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_statustoDONE: <n> succeeded, <n> errored (request <id>)orERROR:. - 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 leftoverprocess_triggerednext 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 nosetTimeout, and hammering the workbook collides with the add-in's background write). _blitz_run_statuskeeps the PREVIOUS value until the new run finishes — aDONE: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 aDONE:/ERROR:that belongs to this step. The same applies BEFORE you start: anERROR:(even a bareERROR: 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.
Report the outcome. When
DONE:- Read the per-row results with
=br_validation_results_external(FALSE, "<Upload Sheet Name>")onblitz_— it lists every row that errored with its Action, Status and exact Message (BLITZ_OKmeans everything succeeded). PassTRUEas 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).
- Read the per-row results with
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:
- 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. - 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.
- Run FND Lookup Values with
Type=<that Code>: one row per upload column the document fills. Code is the column (INVOICE_NUMBERis the headerInvoice Number), Description says where the value is on the document, Tag is the value when the document does not show it. - 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 this | Not 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 thesheetargument), put the two trigger formulas well to the right of the grid, never write marker text such asprocess_triggered, and clear any scratch you did put on the sheet before you report the outcome. Deleteblitz_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 withbr_report_list_external(filter toType = 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-readbr_report_params_externaland drop it. Do NOT retry the same call, and do NOT conclude the environment is broken or try aCOPY 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/statusfailures mean the concurrent request itself failed (report the request id so the user can check the request log).- A
DONEwithN erroredis 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."
=br_report_list_external("purchasing document upload")→PO Purchasing Document Upload(Type U).=br_report_params_external("PO Purchasing Document Upload")→ note Upload Mode, Operating Unit, Document Type.=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.=_blitz_run_status→DONE: 778 rows on sheet 'PO Purchasing Document Upload'.- Find document 6504's rows, edit the business columns as requested (or add a new row).
=br_process_upload_external()→ poll →DONE: 1 succeeded, 0 errored (request <id>).- Read row's Status =
Success, Message = the confirmation; report it.
The functions (reference)
| Function | Purpose | Returns |
|---|---|---|
br_run_upload_external(name, [params], [template], [environment], [responsibility]) | run a type-U upload; populates a new editable upload sheet | BLITZ_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 place | BLITZ_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 name | Sheet 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 name | Row \| 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 name | Value \| Description |
br_report_list_external, br_report_params_external, br_param_values_external, br_environments_external, br_responsibilities_external | discovery — SAME as br-run-reports (uploads are Type = U) | see br-run-reports |
_blitz_run_status (workbook name) | run/process completion signal | RUNNING: / PROCESSING: / DONE: … / ERROR: … |