Finance does not want a dashboard. It wants a workbook — with its own columns, its own formulas, its own commentary — that is correct on the first working day of the month. Qrly ships a full spreadsheet engine bound directly to your database, where a refresh updates the data and leaves everything you built around it exactly where it was.
A spreadsheet report is a stored workbook, a real formula engine and a live connection to your data. Take any one away and it stops being useful.
Plenty of tools give you a grid. The difference is what happens when you type an equals sign.
A1 references, ranges, whole-column references, cross-sheet references and named ranges — the vocabulary anyone who has used a spreadsheet already has. Workbook-aware functions such as ROW, INDIRECT and OFFSET behave as they should, which is what makes patterns copied from an existing model actually work rather than nearly work.
Evaluation is lazy where Excel is lazy: IF and IFERROR do not evaluate the branch they are not taking, so a guard around a division or a lookup does what a guard is supposed to do.
Circular references are detected and reported as #CIRC! rather than hanging the tab or silently producing a number. The complete Excel error set is implemented — #DIV/0!, #N/A, #NAME?, #NULL!, #NUM!, #REF!, #VALUE!, #CIRC! and #SPILL! — so errors propagate the way the person building the model expects them to.
Excel number formats and date serials are supported, which matters more than it sounds: a date that is secretly a string is the single most common reason a migrated model gives a different answer.
The function library covers the usual surface, and then explicitly overrides the ones where a naive implementation and Excel disagree: UNIQUE, SUBTOTAL and AGGREGATE, GROUPBY, TEXTBEFORE and TEXTAFTER, WRAPCOLS, PERCENTOF and the REGEX* family.
Those are the functions people notice. SUBTOTAL that ignores hidden rows, UNIQUE that spills correctly, TEXTAFTER that handles the delimiter-not-found case the way Excel does — get them wrong and every number downstream is wrong with them.
Dynamic-array spilling is supported, with #SPILL! when the spill range is blocked — so modern array formulas behave rather than collapsing to their first cell.
Inserting and deleting rows and columns rewrites every dependent formula across the workbook. This is the least glamorous feature on the page and the one whose absence ruins a spreadsheet fastest: a grid where inserting a row breaks forty formulas is a grid nobody will maintain.
Muscle memory is a feature requirement. Anything that behaves differently from Excel here is a bug report waiting to be filed.
Formatting is where a spreadsheet feels finished or unfinished. There is no clever way to do it — you either ship the controls or you do not.
One click for the thing you want ninety per cent of the time, and a proper editor for the other ten.
Duplicates, unique values, top ten, bottom ten, above and below average, negatives in red, errors, blanks, dates today, dates in the last seven days, dates this month, a colour scale, data bars, and arrow, traffic-light and rating icon sets.
These exist because they are the rules people actually apply, and because making someone build "highlight duplicates" out of a custom formula is a small, daily insult.
The full dialog offers four rule types. Colour scales can be two- or three-colour; data bars take a bar colour; icon sets can be driven by percent, percentile or absolute number, with reverse order and custom thresholds.
Cell rules cover comparisons, between, text tests, duplicate, unique, top or bottom N or per cent, above and below average, empty, error, and an extensive date-period set.
Any rule can be a custom formula, evaluated by the same engine that evaluates the sheet. If you can express the condition as a formula, you can format on it — including conditions that read other columns, other sheets or named ranges.
That is what keeps the preset list from being a ceiling.
Matching cells can take a text colour, a fill, bold, italic, underline and strikethrough — the same styling vocabulary as manual formatting, so a conditionally formatted sheet and a hand-formatted one look like they belong to the same document.
Which matters when the workbook leaves the building as an XLSX attachment on a board pack.
This is the part that makes it a BI feature rather than a toy. A block is a rectangle of the sheet owned by a query, with an anchor cell, an optional header row, a maximum row count and a set of key columns.
Every BI tool can dump a result set into a grid. The question is what happens the second time.
A naive refresh writes the new result into the same rectangle, cell by cell, by position. That is fine on day one, when the block is all there is. It stops being fine the moment someone inserts a margin column beside it, adds a commentary row, or writes a note next to a specific customer — because on the next refresh the query returns its columns in a different order, or one fewer, or the rows come back sorted differently, and everything that was carefully placed is now beside the wrong record.
The predictable result is that people stop refreshing. They copy the block into a new tab, do their work there, and the "live" report becomes a manual one within two months. Qrly addresses this by addressing source columns by name, not by offset.
The spreadsheet assistant works one-shot or as a multi-turn chat, and it can only propose operations from a fixed whitelist: setCells, setRange, addSheet, format and clearRange. It cannot invent an operation, and it is capped at 400 context cells and 200 operations per reply.
The cap is not only about cost. An assistant permitted to rewrite an unbounded region of a financial model is a category of accident you do not want available.
What comes back is a preview draft, with an explanation of what it intends to do and a count of the cells it would affect. You apply it or you discard it.
Preview-before-apply is the same trust boundary Qrly uses for schema authoring: the model proposes a structured change, a human reads it, and only then does anything happen to the document.
XLSX export carries all sheets with real formulas and styles mapped to Excel, so the recipient gets a working model rather than a picture of one. CSV exports a single sheet as evaluated values, and JSON and XML are available for anything downstream that wants structure.
Formulas surviving the export is what makes the workbook forwardable. An accountant who receives values-only has received a screenshot with extra steps.
Exports are rendered server-side. The file a scheduled subscription emails to a distribution list is byte-identical to the file a read-only viewer downloads from the report page.
That removes an entire class of argument — the one that starts with two people comparing the version they each received and discovering the numbers do not agree.
It is Qrly's own tokenizer, parser and evaluator, running in the browser. It handles A1 references, ranges, whole columns, cross-sheet references and named ranges; lazy IF and IFERROR; cycle detection reported as #CIRC!; Excel number formats and date serials; workbook-aware functions such as ROW, INDIRECT and OFFSET; dynamic-array spilling; and the full Excel error set.
Roughly 500 worksheet functions are implemented, with Excel-correct overrides for UNIQUE, SUBTOTAL and AGGREGATE, GROUPBY, TEXTBEFORE and TEXTAFTER, WRAPCOLS, PERCENTOF and the REGEX family, within Excel's own limits of column XFD and 1,048,576 rows.
They survive. Data blocks address source columns by name rather than by offset, so columns and rows you inserted inside a block are preserved and never written over. A source column that disappears is cleared in place rather than shifting everything left, new source columns append past the block, and key columns return each record to the row it was on before.
Stale cells that Qrly itself wrote are removed; untagged cells you wrote are never touched. Each refresh reports rows and columns written, columns and rows kept, columns dropped and rows skipped.
From one of four binding kinds, per block: QUESTION binds a saved question; VISUAL stores QQL that is recompiled on every run so it follows the connection's dialect; SQL is ad-hoc raw SQL authored in Monaco with schema completion; and AI takes a natural-language prompt, resolves it to SQL once, and refreshes as plain SQL thereafter.
Each binding sets its sheet, anchor cell, whether headers are included, a max row count and its key columns.
No. An AI binding resolves the natural-language prompt to SQL once. From then on the block refreshes as plain SQL, so scheduled refreshes and subscriptions never spend tokens — and never risk the model returning a different query than it did last month.
Yes. XLSX export carries all sheets with real formulas and styles mapped to Excel. CSV exports a single sheet with evaluated values, and JSON and XML are also available.
All formats are rendered server-side, so the bytes a subscription emails out are the same bytes a read-only viewer downloads.
Not without you seeing it first. The assistant works one-shot or as a multi-turn chat and can only propose operations from a whitelist — setCells, setRange, addSheet, format and clearRange — capped at 400 context cells and 200 operations per reply.
What comes back is a preview draft with an explanation and an affected-cell count, which you apply or discard.
A real formula engine, bound to your database, where a refresh updates the data and leaves your work alone.