AP Intelligence Dashboard Copy link
Plugin: Blitz Report Excel Add-in Skills (
br-ap-intelligence)Works with: Claude in Excel, Microsoft 365 Copilot in Excel
Build a live AP intelligence dashboard in Excel from Oracle EBS: run the "AP Cash Requirement" Blitz Report and lay out the five payables KPIs (invoices on hold, total AP outstanding, overdue 30+ days, approved due within 7 days, unapproved due within 15 days), a ranked AI action summary, an AI commentary per KPI, drill-down lists, due-bucket and supplier tables, and answer follow-up questions as new KPI cards.
When to use it
- Use when the user asks for an AP dashboard, AP KPIs, the payables position, "what's outstanding / overdue / on hold / unapproved", an AI summary of accounts payable, or an AP intelligence view.
- Hands hold release, hold detail and pay-run planning to the specialist skills.
- Download the skill zip. br-ap-intelligence.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-ap-intelligence
- 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.
🚨 Blitz data comes from
br_*WORKSHEET FUNCTIONS of the Blitz Report Excel add-in — write=br_...()into a cell and read the result. They are not a connector, plugin, agent action or MCP tool: never search for one, never conclude "no Oracle EBS data source is connected".#BLITZ_NOT_CONNECTED→ ask the user to connect on the Blitz Report ribbon;#NAME?→ add-in not loaded.
Self-contained: read no other skill before or during the run. Every step below is ONE workbook
operation (in Claude for Excel one execute_office_js call; in Copilot one edit or read action).
Every number on the dashboard is an Excel formula over the extracted data — you never compute
values yourself and never write computed arrays. The only text you author is the AI commentary (Op 6).
Budget — 6 workbook operations, then one reply
| # | Operation |
|---|---|
| 1 | create helper sheet blitz_, write the run formula, read the cell back |
| 2 | replace that cell with plain text, read the status |
| 3 | status poll — repeat only while it still says RUNNING |
| 4 | rename to AP_Raw, add 3 formula columns, autofilter |
| 5 | create AP_Detail (five drill-down blocks) and AP_Intelligence (summary, KPI table, tables, chart), delete blitz_, activate AP_Intelligence, read the KPI block and the top detail rows |
| 6 | write the AI commentary cells |
| — | reply with the ranked actions and the offers |
No question before the reply (only exception: Operating Unit missing); no verification reads (the formulas are the verification); no sheets beyond the three named; no deep dives (hold reasons, supplier scoring, cash projection) unless asked afterwards — then route per Actions and follow-ups.
Inputs
Operating Unit (required — ask only if not given; several allowed as A,B). Nothing else:
leave Include Unvalidated Invoices and Include Unapproved Invoices blank (blank = include them;
ANY value, Yes or No, applies the exclusion), no Pay Through Date, no Template, so the run returns
every unpaid invoice.
Op 1–3 — Extract
- Get-or-create
blitz_(never activate it). Inblitz_!A1write=br_run_report_external("AP Cash Requirement","Operating Unit=<OU>")and read it back — expectBLITZ_RUNNING: .... Only on#BLITZ_REPORT_NOT_FOUNDsearch with=br_report_list_external("cash requirement")and re-run with the exact name. - Overwrite
blitz_!A1with the textrun triggered(a recalculated run formula starts a duplicate run), write=_blitz_run_statusinblitz_!A3, read it. - While it says
RUNNING(or#NAME?= not published yet): one quiet read per turn, nothing else touching the workbook — the add-in writes the result sheet in the background and any other edit collides with it. Stop atDONE: <n> rows on sheet '<name>'orERROR: <message>;ERRORwhile a populated sheet exists means the data is good — note it, never re-run. Zero rows → "no unpaid invoices for <OU>", stop. Take the result sheet's NAME from the status string, never from a sheet listing.
Result sheet layout is fixed: row 1 banner, row 2 headers, row 3 onward data. One row per payment
schedule (an instalment invoice appears once per instalment). Amounts are the report's Functional Currency Amount — ledger currency, net of any discount still available; an invoice with no
exchange rate has a blank amount (counted, not summed). The report excludes scheduled-payment holds
and supplier-site payment holds; invoice holds are included and carried in Holds Count.
Op 4 — AP_Raw
Rename the result sheet to AP_Raw. From row 2 locate by header text — compare case-insensitively with
spaces and underscores equivalent (a build can render DAYS_TO_DUE): Invoice Num {in}, Trading Partner {sp}, Due Date {du}, Days To Due {dd}, Functional Currency Amount {fa}, Functional Currency Code {fc}, Approved {ap}, Holds Count {hc}, Invoice Status {is}; last data
row {N}. Add three columns after the last header (header in row 2, formula in row 3, filled down to
{N}) — substitute the letters:
| Header | Row-3 formula |
|---|---|
| Due Bucket {db} | =IF({dd}3="","",IF({dd}3<-30,"Overdue 30+",IF({dd}3<0,"Overdue 1-30",IF({dd}3<=7,"Due 0-7",IF({dd}3<=15,"Due 8-15",IF({dd}3<=30,"Due 16-30","Due 31+")))))) |
| Approved Flag {af} | =IF(UPPER(LEFT(TRIM({ap}3),1))="N","N","Y") |
| On Hold {oh} | =IF({hc}3="","No","Yes") |
Days To Due is negative when overdue. Approved is the translated Yes/No (approved, manually
approved or approval not required = Yes) — hence the first-letter test, which also holds for No/Nein/Non. Holds Count is blank when the invoice has no open hold and can arrive as TEXT ("1"), so test blank,
never >0. {last} = the last column letter after these three.
Apply the autofilter as sheet.autoFilter.apply(<the row-2 header range>) — a range has no autoFilter() method. It is cosmetic: if it fails, skip it and carry on.
Op 5 — AP_Detail then AP_Intelligence
Range shorthands below (all on AP_Raw, rows 3..{N}): fa = AP_Raw!{fa}3:{fa}{N}, likewise dd, af, oh, sp, du, db, in, hc. {x#} = column NUMBER of {x}.
AP_Detail — five blocks, one formula each
Block rows {r} = 1, 30, 59, 88, 117 (25 result rows each). Per block: A{r} title, row {r}+1 headers Invoice | Supplier | Due Date | Days To Due | Amount | Approved | Holds | Invoice Status, A{r+2} the
formula. Columns picked are {in#},{sp#},{du#},{dd#},{fa#},{ap#},{hc#},{is#}: =IFERROR(TAKE(SORTBY(FILTER(CHOOSECOLS(AP_Raw!$A$3:${last}${N},{in#},{sp#},{du#},{dd#},{fa#},{ap#},{hc#},{is#}),<cond>),FILTER(fa,<cond>),-1),25),"None")
| {r} | Title | <cond> |
|---|---|---|
| 1 | Invoices on hold - largest first | oh="Yes" |
| 30 | Overdue more than 30 days - largest first | dd<-30 |
| 59 | Approved, due within 7 days - largest first | (af="Y")*(dd>=0)*(dd<=7) |
| 88 | Unapproved, due within 15 days or overdue - largest first | (af="N")*(dd<=15) |
| 117 | Largest outstanding invoices | no filter: =TAKE(SORTBY(CHOOSECOLS(...),fa,-1),25) |
Formats per block (one call per contiguous range): C{r+2}:C{r+26} dd-mmm-yyyy, E{r+2}:E{r+26} #,##0.00; bold the header rows; widen columns. A date is a serial NUMBER — pass it through and let the
format render it; never convert or "correct" one.
AP_Intelligence — create as the FIRST sheet
Fixed layout so the commentary and the reply can reference the cells. fmt(x) below stands for IF(ABS(x)>=1000000,TEXT(x/1000000,"#,##0.0")&"M",IF(ABS(x)>=1000,TEXT(x/1000,"#,##0.0")&"K",TEXT(x,"#,##0")))&" "&$H$1 — expand it inline wherever it appears.
A1AP Intelligence - <OU>(bold, large);H1=AP_Raw!{fc}3(ledger currency, feedsfmt);A2="Live from Oracle EBS via the AP Cash Requirement report | unpaid, uncancelled invoices | amounts in "&$H$1.- KPI table —
A10:E10KPI | Amount | Invoices | Definition | AI commentary, then rows 11–15 (A = label, B = amount, C = count, D = definition, E left empty for Op 6):
| Row | A | B | C | D |
|---|---|---|---|---|
| 11 | Invoices on hold | =SUMIF(oh,"Yes",fa) | =COUNTIF(oh,"Yes") | Unpaid invoices with at least one open invoice hold |
| 12 | Total AP outstanding | =SUM(fa) | =ROWS(in) | All unpaid, uncancelled invoices (one row per payment schedule) |
| 13 | Overdue 30+ days | =SUMIFS(fa,dd,"<-30") | =COUNTIFS(dd,"<-30") | Due date more than 30 days ago |
| 14 | Approved, due within 7 days | =SUMIFS(fa,af,"Y",dd,">=0",dd,"<=7") | =COUNTIFS(af,"Y",dd,">=0",dd,"<=7") | Approved and not yet paid, due today or within 7 days |
| 15 | Unapproved, due within 15 days | =SUMIFS(fa,af,"N",dd,"<=15") | =COUNTIFS(af,"N",dd,"<=15") | Not approved, due within 15 days or already overdue |
Rows 16–20 stay empty: they are the slots for follow-up KPI questions.
- AI Intelligence Summary —
A4AI INTELLIGENCE SUMMARY(bold). Helper sentences inN5:N7with their amounts inO5:O7, so the three actions rank themselves by value:N5=IF(C11=0,"No unpaid invoice carries an open hold.","Review "&fmt(B11)&" on "&C11&" invoices with open holds - confirm each hold is still valid or release it; largest: "&IFERROR(AP_Detail!B3,"n/a")&" ("&IFERROR(fmt(AP_Detail!E3),"n/a")&")."),O5=B11N6=IF(C13=0,"Nothing is overdue by more than 30 days.","Resolve "&fmt(B13)&" overdue by more than 30 days on "&C13&" invoices - oldest due "&IFERROR(TEXT(MINIFS(du,dd,"<-30"),"dd-mmm-yyyy"),"n/a")&", largest supplier "&IFERROR(AP_Detail!B32,"n/a")&"."),O6=B13N7=IF(C15=0,"No unapproved invoice is due within 15 days or overdue.","Approve or reject "&fmt(B15)&" on "&C15&" unapproved invoices due within 15 days or already overdue - nothing is payable until approved."),O7=B15A5="1. "&INDEX(SORTBY($N$5:$N$7,$O$5:$O$7,-1),1),A6="2. "&INDEX(SORTBY($N$5:$N$7,$O$5:$O$7,-1),2),A7="3. "&INDEX(SORTBY($N$5:$N$7,$O$5:$O$7,-1),3).A8=IF(ROWS(fa)-COUNT(fa)>0,ROWS(fa)-COUNT(fa)&" invoices have no exchange rate and are counted but not summed",""). - Due buckets —
A23:D23Due Bucket | Amount | Invoices | % of Total;A24={"Overdue 30+";"Overdue 1-30";"Due 0-7";"Due 8-15";"Due 16-30";"Due 31+"}(a formula, never typed labels);B24=SUMIF(db,A24#,fa);C24=COUNTIF(db,A24#);D24=B24#/$B$12. - Top suppliers —
A32:D32Supplier | Outstanding | Invoices | Overdue 30+;A33=TAKE(SORTBY(UNIQUE(sp),SUMIF(sp,UNIQUE(sp),fa),-1),10);B33=SUMIF(sp,A33#,fa);C33=COUNTIF(sp,A33#);D33=SUMIFS(fa,sp,A33#,dd,"<-30"). - Formats — one call per CONTIGUOUS range, never a comma-separated address:
#,##0.00onB11:B20, onB24:B29, onB33:B42, onD33:D42;#,##0onC11:C20, onC24:C29, onC33:C42;0.0%onD24:D29; wrap text onE11:E20. Bold rows 4, 10, 23, 32; column widths A 60, B 18, C 12, D 55, E 90. One clustered column chart onA23:B29titledOutstanding by due bucket, placed right of the tables. Deleteblitz_. ActivateAP_Intelligence. - End the operation by reading
AP_Intelligence!A5:C15and the top three rows of each detail block (AP_Detail!A3:H5,A32:H34,A61:H63,A90:H92,A119:H121) — the material for Op 6 and the reply.
Op 6 — AI commentary
Write E11:E15 in one block: two or three sentences per KPI in the user's language — what the number
is, why it matters, and the concrete next step — naming the largest supplier or invoice from the
detail rows you read. Say plainly when a KPI is zero (e.g. "no approved invoices fall due in the next
seven days, so the near-term payment pipeline is empty"). Never restate the definition column. Quote
amounts as they appear (already in the ledger currency); never invent a number you did not read.
Reply
Four to six lines in the user's language — report and sheet names are fine, function names, blitz_ and status names are never mentioned: the three ranked actions with their amounts, the total
outstanding, the no-rate note if not empty, then the offers, chosen by what is non-zero:
C11 > 0: "Want me to prepare the release of the invoice holds for your review? I'll pre-fill the release upload — nothing goes to Oracle without your confirmation." (→ br-ap-hold-release), and "or first a hold-by-hold view with reasons, aging and anomalies" (→ br-ap-holds-analysis).C14 > 0orC13 > 0: "I can plan the payment run for the approved invoices" (→ br-ap-payment-optimizer).- Always: "Ask me any payables question and I'll add it as a KPI card on the dashboard."
On yes, continue with that skill (Claude:
read_skill("<name>"); Copilot routes to it); each reuses the workbook and re-extracts only what it needs.
Follow-up questions → new KPI cards
A question the extracted data can answer becomes a card in the next free row of A16:E20 (then A21 onward, shifting nothing else): A = the question as asked, B = =SUMIFS(fa,<criteria>),
C = =COUNTIFS(<criteria>), D = the criteria in words, E = one sentence of commentary after reading
B:C. Add its drill-down as a further block on AP_Detail at {r} = 146, 175, ... with the same formula
shape. Available criteria columns: Days To Due / Due Date (timing), Approved Flag, On Hold, Invoice Status, Trading Partner, Invoice Currency Code, Pay Group, Payment Method, Payment Priority, Invoice Date, Functional Currency Amount (thresholds). Examples:
- "unapproved invoices over 10,000 due next month" →
af,"N",dd,">"&(EOMONTH(TODAY(),0)-TODAY()),dd,"<="&(EOMONTH(TODAY(),1)-TODAY()),fa,">10000" - "how much do we owe <supplier>" →
sp,"<supplier>"(use the exactTrading Partnertext fromAP_Raw).
A question the data cannot answer is routed, never guessed: hold names, reasons and who placed them
→ br-ap-holds-analysis; the PO and receipt matched to an invoice → br-run-reports with AP Invoices and Lines and Invoice Number=<n>; Display Level=Lines and Distributions (columns Po Number, Receipt Number); payments already made → AP Invoice Payments with Invoice Number=<n>;
supplier master data → AP Suppliers. Say which report you are running and why.
Actions and follow-ups
- Release a hold → br-ap-hold-release. Its download lists only user-releasable holds: a system
variance hold (
Line Variance,Dist Variance) never appears, because Oracle re-applies it on the next validation until the invoice is corrected. If the user asks to release one, say so and point to the fix — correct the lines or distributions in the Invoice Workbench and revalidate — instead of attempting a release. - Refresh / update the numbers → read
A16:E20(the follow-up cards) first, deleteAP_Raw,AP_DetailandAP_Intelligence, run Ops 1–6 again and re-create the follow-up cards from the questions you read. - A different Operating Unit → the same, with the new value; never merge two runs into one sheet.
Rules
- Formulas only; never type computed numbers or bucket labels into cells; the bucket list is a formula
array so
8-15-style text cannot turn into a date. - Get-or-create sheets (Claude:
getItemOrNullObject+load("isNullObject"), nevergetItemin try/catch; load a range, sync, read that same variable). Copilot: one edit action per Op. - Never activate
blitz_; delete it in Op 5. Never re-run a report that produced a data sheet. - Every range address is ONE contiguous block. A comma-separated multi-area address (
B11,B24) is rejected outright and the cell-by-cell recovery that follows is what turns a fast run into a slow one. Issue one call per block; several blocks in the same operation are free. - A rejected write is retried ONCE, on that one range, and never cell-by-cell. If the retry fails too, leave that range unformatted, finish the pass, and say so in the reply.
- Dynamic-array formulas (
FILTER,SORTBY,UNIQUE,TAKE,CHOOSECOLS,MINIFS) need Microsoft 365 Excel; on an older Excel every block shows#NAME?— say so and stop rather than rewriting them.