DashReporter· Getting started Open the app

Getting started

Two ways to read this.

In a hurry? The Quick start below is eight steps and about five minutes. It takes you from an empty page to a dashboard you can hand to someone else, and it is complete on its own.

Want to see what the thing is actually for? The Investigations that follow are nine short worked examples on the same sample data. Each one asks a real question, answers it, and teaches a technique you can point at your own data. They are independent — read one, read all nine, or skip them until you need one.

Read this beside the app, not instead of it

Every step is something to do rather than something to know. Put this guide in one window and DashReporter in another, side by side — the button at the top opens the app in a new tab, and most systems will tile two windows if you drag one to each edge of the screen.

Nothing you open leaves your machine. The file is read by your browser, the query engine runs in your browser, and nothing is written to browser storage. Watch the network tab while you work; it stays quiet.

Quick start

Open the sample data

Click Try it with sample data. That loads sales_actual.csv — about 58,000 order lines over 18 months — without downloading anything.

You can also drag your own CSV, TSV, Parquet or .drd file onto the page at any time. Each file gets its own tab.

Look at what it guessed

Click Edit model. Inference gets close and then gets things wrong, which is why the model is editable rather than hidden. On this file:

  • Order Date is M/d/yyyy H:mm:ss, a format most CSV sniffers do not parse. Without it there is no trend at all.
  • Order Number is a high-cardinality integer that is an identifier, not a quantity. Summed naively it produces a number in the trillions.
  • Discount Rate is a rate, so it wants AVG. Summed, it is meaningless.

One correction is worth making now, because two investigations depend on it: set Territory to level 2 so it sits under Region. The tool cannot infer that relationship — see the tangent — so it has to be declared. It only needs declaring once; the correction is saved into any .drd you export.

Why can't it work out that Territory belongs to Region?

Because it doesn't. Metro appears under North, South and East; Coastal under South and West. Knowing the territory does not tell you the region, so no amount of looking at the data reveals the relationship. That is a ragged hierarchy, and it is extremely common in real data — sales geographies name territories locally all the time.

The contrast is in the same file: every Sales Rep belongs to exactly one territory, so that relationship is discoverable, and the tool finds it unaided.

Category Level 1 / 2 / 3 are found automatically too, from their names.

Combine actuals with plan

Drag sales_budget.csv onto the page as well (or download it from the landing page), then click Combine sources…, tick both, and Combine.

Rows are stacked, not joined. That distinction matters more than it sounds: joining a fact table to a coarser plan multiplies rows and inflates every total, silently. Stacking cannot. A Source column records which file each row came from, and a measure missing from one file is simply null in those rows.

You now have Revenue and Budget Revenue as two measures on one dataset.

Build "Actual vs Budget"

On the combined tab: Edit modelDerived measures. Name it Actual vs Budget and build:

SUM (Revenue) - SUM (Budget Revenue)

Two things to notice. The aggregates are part of the formula rather than inherited from wherever else, so the measure prints what it computes and can't change under you. And if you switch the operator to /, both operands snap to SUM — a rate is the ratio of the totals, and a ratio of averages ignores order size. The naive path is the correct one.

Build something incoherent anyway and you get a warning, inline, at the point of choice. It never blocks you.

Explore

Break down by picks the dimension in the table.

  • Click a row to drill. Clicking South filters to South and moves the breakdown down a level to its territories.
  • Drag across rows to take several at once — the only way to build a multi-row selection, since the table narrows to whatever you pick.
  • The breadcrumb above the table is the way back. Click any level to return to it; that clears its filter and everything beneath it.
  • The chips along the top are every filter currently applied. Click one to remove it.
  • In the sidebar, ctrl-click a value to select only it — the fastest way to walk a dimension one value at a time while watching the trend redraw.

Change the shape of the chart

Four buttons next to the grain selector. How a chart is drawn is part of what it says:

formwhat it's for
linetrajectory and level — where a series went, how series compare
barsone period against the next, as discrete quantities
stackedthe total, and what makes it up
100%the mix, with the total deliberately removed

The last one is not decoration: composition shifting while the whole grows or shrinks is invisible in the other three.

Getting several bands on the chart at once

The trend draws one series per selected measure, not one per value of a dimension. To get a band per customer segment, make them measures: Edit modelPivot a measure across a dimensionRevenue across Customer Segment.

That mints one measure per value, and they behave like any other — bands on the trend, columns in the breakdown (a genuine cross-tab), a tile each. The slices replace the source in the selection, because the parts and the whole stacked together count everything twice.

Save a view and pin it

Save view captures everything you navigated to: filters, date window, grain, breakdown, sort, which measures were on screen, and the chart form.

Then Pin it. Pinning nominates the view a .drd opens on. That's a choice about what you're handing over — sometimes the point of a file is the finding, sometimes it's the data with the filters left clean.

Save it, then drop it back

Generate report (PDF) prints a document: the filters in force, the totals, the trend, and a breakdown for every level of the drill path — not just the level on screen.

Save compiled data (.drd) writes your model, derived measures, saved views and the data into one file. It is columnar and compressed, so it is both smaller than the CSVs and dramatically faster to open — five million rows in about a second against roughly forty-two for raw CSV.

Now drag that .drd back onto the page. It opens on your pinned view, already there. That is the whole point of the format: hand someone the file and they arrive where you left off, which is the difference between sending a finding and sending a haystack.

That's the quick start. Everything below is optional.

Investigations

The sample data has nine things worth finding planted in it. Each one below is a worked example: the question, what to do, what you find, and the technique underneath.

They get harder. The first is a number sitting in plain sight; the last is an absence you can only reach by sorting for it.

Knowing when to stop

The hardest part of real analysis is not finding something odd, it is deciding a finding is finished. Each investigation ends with a stated conclusion for exactly that reason. A finding is done when you can say what it is, where it lives, and whether it is local or general — not when you run out of curiosity.

1. A gap you can only see against plan

Setup combined tab · filter Territory = Lakeside · break down by Channel · measures Revenue, Budget Revenue, Actual vs Budget.
Online actual 207,113 budget 316,137 variance -109,024 Retail actual 651,228 budget 352,205 variance 299,022 Wholesale actual 0 budget 1,182,956 variance -1,182,956
Finding

Lakeside does no wholesale business at all, against a plan of nearly 1.2 million. It is the only channel-and-territory combination in the entire file that exists in budget and not in actuals.

Technique · combining turns an absence into a number

In the actuals alone this is a row that isn't there — the hardest kind of thing to notice, because nothing draws your eye to a blank. Put the plan beside it and the same fact becomes the largest negative variance on the screen.

2. Is it behaviour, or is it policy?

Setup clear filters · measure Discount Rate (it should be AVG; fix it in the model if not) · break down by Region, then drill into East.
Region: South 9.5% North 7.8% West 9.5% East 18.0% East: Metro 9.5% Harbour 9.4% Valley 35.0%

Now check whether it is uniform inside Valley: break down by category, by channel, by customer segment, by sales rep. It is ~35% in every one. Switch the trend to month grain — it is flat across all eighteen, never below 34.2% or above 35.6%.

Finding

Valley discounts at roughly 35% against about 9.5% everywhere else, uniformly and without variation over time.

Technique · uniform across every sub-dimension means policy; concentrated means behaviour

If one rep or one product line were responsible, the average would be dragged by them and the rest of Valley would look normal. It isn't, so this is a rule someone set — a report that produces a phone call, not a coaching conversation.

3. A season, or a step change?

Setup clear filters · filter Category Level 3 = Hoses · measures Revenue, Budget Revenue · trend at month grain.
2024 82% 152% 104% 84% 88% 81% 104% 114% 96% 71% 99% 128% (of budget) 2025 40% 28% 22% 30% 15% 13%
Finding

Through 2024 hoses oscillate around plan, which is what a seasonal product does. At the start of 2025 the line steps down and never recovers, while budget climbs into spring on the seasonal assumption. It is company-wide — every territory sits between 15% and 37% of plan in the first half of 2025.

Technique · plan is what separates a season from a change

Actuals alone show a decline that could be winter. The budget expected the opposite, and that divergence is the signal. And check the scope before you attribute it: found inside a territory filter, this looks like a local problem. It isn't.

4. Look at the shape, not just the total

Setup clear filters · break down by Sales Rep · measures Revenue and Rows · sort by Revenue.

Abbott, Payton leads at about 1.7 million, more than double anyone else. Now look at Rows, and filter to Basin to compare like with like:

orders min median mean max Abbott, Payton 397 540.85 3,263.44 4,312.47 15,109.34 Pike, Jordan 1,507 51.00 288.31 394.18 1,419.48 Ives, Frankie 1,474 38.31 287.86 387.40 1,422.97
Finding

A quarter the order count, ten times the order size. Not one big deal — every order is large. Zero of their 397 orders fall below the other reps' median.

Technique · Rows beside a measure turns a total into a distribution

A tempting explanation is a data-entry error — someone adding a digit. That theory dies on the count: a fat finger is sporadic, and there is no normal part of this book.

5. One customer type that only buys one way

Setup clear filters · Edit modelPivot a measure across a dimensionRevenue across Channel · break down by Customer Segment.
Consumer Online 17.8% Retail 22.3% Wholesale 59.9% Contract Online 17.5% Retail 23.1% Wholesale 59.4% Trade Online 17.7% Retail 22.5% Wholesale 59.8% Public Sector Online 0.0% Retail 0.0% Wholesale 100.0%
Finding

Public Sector — the largest segment at 37.8% of all revenue — buys through wholesale exclusively.

Technique · pivot to make a cross-tab

Pivoting one measure across a dimension gives you one measure per value, so a breakdown by anything else becomes a matrix. Three rows that look alike and one that doesn't is a pattern you can see in a second and would never find by drilling into segments one at a time.

Bonus: this also explains investigation 1 from the other side. Lakeside has no wholesale, and Public Sector only buys wholesale — so Lakeside has no Public Sector either. Two findings, one intersection.

6. Growing against a flat background

Setup clear filters · measure Units · break down by Territory · ctrl-click each territory in the sidebar in turn, watching the trend redraw.

Overall the trend is flat and uniform. Highland alone starts low in early 2024 and climbs steadily through to the end of the data.

Finding

Highland is growing against a background that isn't.

Technique · ctrl-click to walk a dimension one value at a time

Comparing eighteen-month shapes across nine territories is not something a single chart does well. Soloing each in turn and watching the same axes redraw makes an odd one obvious.

7. A specialist, not a lean

Setup clear filters · break down by Sales Rep · sort by Revenue ascending to find the small books · filter to Naylor, Indigo · break down by Category Level 3.
Finding

Indigo Naylor sells power tools. Only power tools — not mostly, exclusively.

Technique · "exclusively" and "mostly" are different findings

Every top seller has a category they lead in; that is ordinary. A rep with exactly one line is not. Check the whole breakdown, not just the top row.

Be careful with the story you attach: their revenue peaks in March and April, which looks like spring tool demand — but total company revenue peaks in March and April too. On a book of a few thousand a month, that is the season showing through, not evidence about them.

8. Hunting the axis a spike lives on

Setup clear filters · filter Category Level 3 = Cookware · trend at month grain.

March 2025 roughly doubles: 237,605 against about 120,000 either side. Now find which dimension it belongs to. Break down by Customer Segment and switch the chart to 100% — the mix does not move. Break down by Channel — all three channels roughly double together. Break down by Sales Rep and drag across the top four rows to select them all at once.

Those four reps are all in one territory: Foothills.

Finding

A single enormous month in cookware, in one territory, spread evenly across every channel and segment within it.

Technique · rule out axes with 100%, then locate on the one that's left

A spike that is mix-neutral across a dimension did not come from that dimension. Working through segment and channel that way costs two clicks each and eliminates them properly, rather than leaving you suspecting them.

9. Someone who stopped

Setup clear filters · break down by Sales Rep · tick Edges in the measures panel · click the Last header to sort ascending.
Ellery, Gray first 2024-01-02 last 2024-08-31 526 rows
Finding

One rep in the file stops mid-period and never comes back. Nobody joins.

Technique · sort instead of scroll

"Who left?" is not an aggregate question and no measure answers it. With four hundred reps you cannot eyeball it, and filtering to each in turn is hopeless. First and last dates turn it into a sort, and Rows beside them separates someone who left from someone who was always too small to notice.

Two mistakes worth making once

Both of these cost real time during the investigation that produced this tutorial. Neither is a bug — in both cases the chart was correct and the conclusion it invited was false.

The month that looks like a slump

Break down Units by month and February dips, in both years, in every region and category.

It is the calendar. February has 28 days against 31. Units per day is flat straight through, and the 2024 dip is shallower than 2025's only because 2024 was a leap year.

The tell was there in the observation itself: "consistent across every region and category". A real February effect would be concentrated somewhere. A pattern that appears uniformly in every slice usually belongs to the axis, not the data.

The filter you forgot was on

Halfway through investigation 8, a filter from an earlier search was still applied. Cookware looked like it had no wholesale spike and an online one instead — because the filter was Territory = Lakeside, which has no wholesale at all, and the remaining online figures were 2 to 10 orders a month.

The chips along the top of the screen were saying Territory: Lakeside the whole time.

Two habits worth building:

Where next

Open your own file. The techniques transfer directly:

And when you find something, save the view, pin it, and send the .drd. The person who opens it lands exactly where you were standing.

Open DashReporter in a new tab ↗ · or go back to the tab you already have it in