Pivots that go past the grid.
Workspace tables give you AG Grid's sorting, filtering and chart view, and BDOBB keeps all of that. Then it adds a report model: the same field as several measures, formulas that work on totals, Pages, two kinds of filter, and totals that refuse to guess. It all opens from a drawer on the table card, and a background worker does the maths.
Click a drawer tab.
Change a control.
Watch the report.
Each drawer is a vertical tab, the same way it appears in the app: Arrange stands at the left edge and the other seven line up on the right, Saved last. Labels and hint lines match the app word for word; the drawers are unchanged from v7.0.0 through v10.0.0. The sample is four quarters of made-up Actual and Budget figures for two tickers, in $m.
Eight drawers.
Each one adds something.
Each row says what Workspace's grid already does and what the drawer adds. Clicking a tab in the demo opens its row here, and each row has a button that opens its drawer in the demo.
Arrange Drag fields between lists · click a pill for actions
Four lists: Available, Row Groups, Column Groups and Data Columns. Order sets the hierarchy. Every pill has an action menu, so nothing depends on dragging. Pivot on switches between the report and the source rows without losing the definition.
Adds to Workspace: a saved report model that travels with the card, instead of a one-off grid state.
Categories Define report categories and their transformations
A category groups by a field's native values, or turns a date into Y, Q, M, or fiscal FY and FQ. Fiscal categories need each company's binding and never assume a December year end. Mixed fiscal calendars show a warning, because same-label periods can cover different dates.
Adds to Workspace: calendar and fiscal period grouping with a check that the periods line up.
Measures Choose aggregation for every data column
Nine aggregations: Sum, Mean, Median, Min, Max, First, Last, Count and Unique count. Nothing is summed until you choose. Duplicate a field and each copy keeps its own aggregation and label, so Revenue can show Sum and Max side by side. First and Last need a date category.
Adds to Workspace: independent measures on one field, and no silent default totals.
Pages Select the current report page
A Page selects a complete set of members from one category, such as Scenario = Actual. All, None, Previous page and Next page step through it. A Page can be promoted to a dashboard parameter group, so one control drives several reports.
Adds to Workspace: report pages, like a spreadsheet pivot's page field, linked to the dashboard.
Formulas Source and aggregate expressions
Source-row formulas such as [Revenue] / 1000 add a field to every record. Aggregate formulas such as SUM([Net income]) / SUM([Revenue]) work on totals, which is why a grand-total margin is a true ratio. IF, comparisons and the nine aggregation functions are available; invalid or ambiguous references stay visible as errors.
Adds to Workspace: calculated measures with a reference picker, bounded and validated before they run.
Category filters Keep selected category members
Tick the members a category keeps. Every total, subtotal and formula is recalculated from what remains, and the grand total never includes a member you removed.
Adds to Workspace: report-level member filters that sit alongside the grid's column filters.
Result filters Filter report groups by their results
Keep only the groups whose calculated result passes a test, such as Company where Net margin is greater than 30. Operators: Equals, Does not equal, Greater than, At least, Less than and At most. Surviving records are deduplicated, then totals are evaluated again.
Adds to Workspace: filtering on the answer, not just on the input.
Saved Model · Statement template
Model shows the saved definitions, warnings and repair, so a malformed import can be inspected rather than dropped. Statement template maps source facts to a version-pinned income statement, balance sheet or cash flow, and opens in the Statement view.
Adds to Workspace: a portable, inspectable model and financial-statement templates.
Change the data source.
Keep the pivot.
BDOBB reads the same backends your OpenBB widgets already use, including ones built on OpenBB's Open Data Platform (ODP). ODP gives every provider of a dataset one standard model: the same field names, percents normalised so 1% is 0.01, and missing values as null instead of placeholder text. A BDOBB report model points at those field names, not at a vendor. Switch the widget to another provider of the same model and your categories, measures, formulas and filters keep working, with nothing to rewrite.
What the source sends
ODP standard model EquityHistorical
The provider maps its own keys onto the standard names once, in its model. Every provider of this model returns these fields.
BDOBB report model Unchanged
Monthly last close, high, low and total volume by symbol, plus a range formula. The saved model only names standard fields, so it carries over as is.
Prices, quotes, options chains, statements, economic series: ODP ships standard models across market and economic datasets, so one report model can serve several providers.
Positions, holdings and transactions from your own backend follow the same rule. Define the model once in your ODP provider and every source behind it shares the field names your pivots use.
Fields a provider adds beyond the standard stay provider-specific. A measure built on one of those needs that provider. Without it, BDOBB marks the values unavailable instead of counting them as zero.
An opt-in Rust engine.
TypeScript stays the default.
BDOBB includes an opt-in Rust/WebAssembly calculation engine for the pivot. It moves the report model's calculations into a portable Rust core running in a WebAssembly worker, while the same table, drawers and styles stay in front of it. The foundation has shipped in the source since v7.0.0. Production builds still use the TypeScript engine; the Rust engine is selected explicitly for development and testing.
Saved pivot definitions and styles don't change. The WebAssembly worker passes all 41 recorded pivot traces in Chromium and WebKit, and in Safari on iPad.
The engine's contract already covers revisioned reads, bounded blocks, cancellation and recovery. Running pivots on the backend, and server-side (SSRM) tables, are still future work.
A benchmark will establish performance. It doesn't change which engine is active: TypeScript stays the default until the remaining testing is done.
One source.
Every view follows.
Make any table a source, then open linked tables and charts from its card menu. The source fetches and calculates once. Each linked view takes the source's current rows, or just the ones you select, so a chart always plots the same numbers as the table beside it.
| Select | Company › Quarter | Revenue | Net income | Margin |
|---|
| Company | Quarter | Revenue | Margin |
|---|
Illustrative sample, in $m: the same rows as the drawer demo above. Click a company row and one of its quarters to see the double-count guard.
- One fetch, many views. The source owns acquisition and calculation; linked tables and charts never ask the backend again.
- No second aggregation. A linked chart plots the source's output as it is, so its numbers match the table's.
- Linked tables can narrow further. Each one can add its own constraints on top of what the source passes on.
- Selections never double-count. A company row plus one of its quarters counts those records once. With nothing selected, the whole presented output flows through, and Select all includes rows scrolled out of view.
- Private stays private. Hidden private columns stay out of linked views, while the source's formulas can still use them.
- Warnings travel. If the source's data is incomplete, every linked table and chart says so too.
apps.json leaves them out.
Totals you can defend.
- No invented zeros. Missing records show as unavailable, never as 0 in a sum.
- Ratios of totals. A grand-total margin divides the totals, not the average of the margins above it.
- No guessed year ends. Fiscal periods need each company's year end, and mismatches are flagged.
- No licence to buy. The table and pivot are BDOBB's own, with a 500-column cap on generated pivots.
Pivot icon: “Pivot” by Matt Garbarino, from the Noun Project, licensed under CC BY 3.0. Cropped to the artwork and drawn in the text colour, the same way the BDOBB app uses it. The icon is not part of BDOBB's own artwork.