Repository navigation
PivotTables: Group Selection, time grouping, calculated items, timelines and filter menus (builds on #474, #498, #1189) - #1207
Herr-Enklo wants to merge 16 commits into
Conversation
… base item pivot.valueSettings accepts every Show Values As calculation: % of, % of Parent Row Total, % of Parent Column Total, % of Parent Total, Difference From, % Difference From, % Running Total In, Rank Smallest to Largest and Index, in addition to the existing % of Grand Total, % of Column Total, % of Row Total, Running Total In and Rank Largest to Smallest. The calculations that need one take a base field (a row or column field) and a base item (an item label, "(previous)" or "(next)"); Running Total and Rank now follow the base field instead of always using the first row field. pivot.fields reports the base field and item. XLSX: written and read as showDataAs with baseField and baseItem, and as the x14 pivotShowAs extension for the calculations that showDataAs cannot express.
pivot.group accepts by: range with start, end and interval (Excel's Starting at, Ending at and By), defaulting to the field's smallest and largest numbers in steps of 10. Each range becomes one item captioned "0-9" for whole-number steps or "0-2.5" otherwise; numbers below the start or above the end fall into "<start" and ">end" items, sorted first and last. Bounds must be finite with start no greater than end, the step positive, and the grouping is limited to 100,000 ranges. by: none removes the grouping, and a change of grouping clears the field's item selection. pivot.list and pivot.fields report the range; the field menu in the PivotTable Fields pane gains Group by Ranges of 10. XLSX: written as a fieldGroup on the base cache field with rangePr startNum, endNum and groupInterval and the group items, and read back; a range without a usable width is ungrouped with a warning.
New commands set a filter rule on a row or column field: - pivot.labelFilter compares each item's caption: equals, does not equal, begins with, ends with, contains (and their negations), greater than, less than, between and not between. The text comparisons take * and ? wildcards; numbers compare as numbers; case does not matter. - pivot.valueFilter compares each item's total of a value field (the first by default) with a number or a range. - pivot.top10 keeps the top or bottom items by a value field, counted as items, a percent of the total or a sum. - pivot.clearFilter clears a field's filters, or every field's; a report filter stays in its area, showing all items. Value and Top 10 filters apply within each parent item, and subtotals and grand totals count only the items shown. As in Excel without "Allow multiple filters per field", a field has one kind of filter at a time: a rule replaces the field's item selection and the reverse. A rule follows its field between rows and columns and is dropped when the field moves to the filters area; value rules follow a renamed value field and go with a removed one; regrouping a field clears its label filter. pivot.list and pivot.fields report each rule. The PivotTable Fields pane gains Top 10 Items, Bottom 10 Items and Clear Filter in a field's menu, and no longer lists a row or column field's filter in the Filters area. XLSX: written as the pivotTableDefinition <filters> (caption*, value*, count, percent and sum filter types with their AutoFilter conditions) and read back; date filters are skipped with a warning.
…op 10 filters) Brings storytold#474 and storytold#498 up to date with main (413 commits). Conflicts resolved keeping both sides: - engine/pivot.rs: main's column budget check (`data_cols_exceed_sheet`, refusing a report that can't fit before its column groups are allocated) now runs in the record loop after storytold#498's shared `add` closure; the data loop takes main's values-on-rows value index and storytold#474's Show Values As. - xlsx/pivot.rs: storytold#498's filter writer and reader next to main's `axis_fields_xml`; the read warning keeps only calculated items (values on rows and label/value filters are both supported now). - ui-egui/pivot_pane.rs: main's translated "Show as …" labels for all 15 Show Values As calculations. - Docs and the ROADMAP progress log keep both sides' entries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review of storytold#498 (neilcawse): on a real report a Top 15 filter whose items 14, 15 and 16 all had the same value showed 15 rows where Excel shows 16. Excel keeps every item tied with the last item a Top N (items) filter keeps; GridCraft now does the same, for Top and Bottom. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…elines Engine and model for the rest of Excel's PivotTable Analyze depth: - Grouping (PivotTable Analyze › Group). `pivot.group` takes several date and time levels at once (seconds, minutes, hours, days, months, quarters, years; one field entry per level, coarsest first), Starting at / Ending at for dates (values outside fall into `<date` and `>date` items) and Number of days (N-day spans from the first date, the last one cut at the end). Without parameters it opens the Grouping dialog for the field at the active cell. `pivot.groupSelection` gathers two or more selected items into `Group1`, `Group2`… of a new grouped field (`Region2`) placed just outside its base field; `pivot.ungroup` removes groups (the grouped field goes with its last one) or a date/number grouping. Captions follow Excel: `12 AM`, `:05`, `1/15/2026 - 1/21/2026`. - Calculated items (Calculations › Fields, Items & Sets). A formula over the items of one field (`=East+West`, `=Region[East]*1.1`, `'North East'`) runs on each item's summary for every combination of the other fields' items; the results count in subtotals and grand totals, as in Excel. Where items of two fields meet, the later one in solve order sets the value (`pivot.solveOrder`). `pivot.listFormulas` writes Excel's formula list sheet. Excel's restrictions are enforced both ways: no calculated items with date/number grouping, Average/StdDev/Var or a field twice in Values, and a field with calculated items stays in Rows or Columns. - Timelines (Insert › Filters › Timeline, PivotTable Analyze › Insert Timeline, and the Timeline tab's caption, Report Connections, styles, size and Show options). A timeline keeps its selection as whole periods of its level; connected PivotTables keep only records whose date falls in it. - The report now records which field and item each label cell shows (`Output::items`), so commands can act on the selected items. Behaviour was checked black-box against Excel 365 (captions, totals that include calculated items, restrictions, timeline defaults). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ribbon now shows Excel's two PivotTable tabs while the active cell is in a PivotTable report, and goes back to Home when it leaves. Every group follows Excel 365 in order and control type: Analyze has PivotTable (name, Options), Active Field, Group, Filter, Data, Actions, Calculations, Tools and Show; Design has Layout (Subtotals, Grand Totals, Report Layout, Blank Rows), PivotTable Style Options and the PivotTable Styles gallery. Existing pivot commands are wired where Excel has them; controls for features GridCraft doesn't have yet (slicers and timelines for PivotTables, calculated items, grouping dialogs, OLAP tools, blank rows...) stay visible, disabled, with the reason on hover. Each group is its own function in ribbon/pivot_tabs.rs, so a feature can be wired in where its control already sits. New pieces behind the controls: - pivot.clearAll and pivot.clearFilters (Actions > Clear): Clear All empties the PivotTable but keeps it, as Excel does, instead of deleting it. - pivot.showFieldList (UI): the Field List toggle hides the Fields pane. - Value Field Settings and Change PivotTable Data Source dialogs. - Key tips JT and JY. They are contextual: the matcher switches to a contextual tab only while it shows, so Table Design's JT letters keep working; xtask keytips accepts contextual tab targets and generates tests for the hidden case. - German labels in German Excel's wording (PivotTable-Analyse, Entwurf, ...), checked against the installed German Excel's own labels. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…on and calculated items - Date groupings write and read hours, minutes and seconds (`groupBy`), Starting at / Ending at set by hand (`autoStart="0"`, `autoEnd="0"` with the dates) and Number of days (`groupInterval`, with `1/5/2024 - 2/3/2024` group items cut at the end). - Group Selection fields are cache fields over their base field (`databaseField="0"`, `fieldGroup base` with `discretePr` mapping each base shared item to a group item); the base field names them with `<fieldGroup par>`. Reading turns such a field back into the model's groups. - Calculated items now load instead of being dropped with a warning: each is a shared item of its field after the data items, and its formula is a `calculatedItem` of the cache with a `pivotArea` pointing at that item. - A `fieldGroup` that only names a grouped field (`par` without `rangePr` or `discretePr`) no longer reads as an unsupported grouping. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ilters A timeline is saved the way Excel 2013+ stores one: a timeline part per sheet (`x15:timeline`: caption, level, selection level, scroll position, style and the Show options) listed in the sheet's `x15:timelineRefs`, a timeline cache per timeline (`timelineCacheDefinition`: the date field, its PivotTable by sheet id and name, the selected period and the data bounds) listed in the workbook's `x15:timelineCacheRefs` with its `NativeTimeline_` defined name, a `tsle:timeslicer` drawing frame with a fallback shape, and a `dateBetween` filter in the PivotTable that the cache's state names. The PivotTable's cache gets the `x14:pivotCacheDefinition` id the timeline cache refers to, and the timeline's field is written as dates. Reading puts it back together after every sheet is read: frames give the anchors, caches the field, selection and PivotTables (mapped by sheet id and name to the model's ids); the PivotTable's timeline filter and the cache's defined name are not read as a filter rule or a name. A timeline cache can only list PivotTables on one pivot cache, and GridCraft writes one pivot cache per PivotTable, so a timeline filtering several PivotTables is saved filtering the first of them (GridCraft's JSON keeps them all). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GETPIVOTDATA(data_field, pivot_table, [field1, item1], ...) reads a value
shown in a PivotTable report, with Excel's semantics, checked against Excel
365 on synthetic PivotTables:
- data_field is a value field's caption or its source field, case ignored;
pivot_table is any cell or range in the report (#REF! otherwise).
- Pairs name row, column or single-item report filter fields and one of
their shown items: numbers and dates (serials or DATE) match by value,
text matches an item's label. Fields left out stand for their total, or
for the one item the named items leave (Plums sells only in the West).
- Hidden, filtered and collapsed items, totals turned off and ambiguous
pairs give #REF!; an empty value cell in a cross tab is 0; Show Values As
results come back as shown.
Layering: the engine, which lays out reports, now records with each report
what every line and data column stands for (model PivotReport, a runtime
cache on the PivotTable that comparisons ignore). calc evaluates
GETPIVOTDATA from that index alone and depends on the report area, so
refreshes (full recalcs) and edits inside the report reach it. Reports of
PivotTables read from files are indexed on open when the recomputed report
matches the cells on the sheet. GETPIVOTDATA has no _xlfn prefix in files.
Generate GetPivotData (PivotTable Analyze > PivotTable > Options, and File
> Options > Formulas > Use GetPivotData functions for PivotTable
references) is an application setting, on by default: clicking, dragging
back to or arrowing onto a PivotTable value while typing a formula inserts
GETPIVOTDATA("Sum of Sales",$A$3,"Region","East") instead of the
reference, with the sheet when the PivotTable is elsewhere and DATE for
date items.
The PivotTable Analyze tab now uses the index too: Active Field shows the
active cell's field, Field Settings opens Value Field Settings, Expand and
Collapse Field and Ungroup act on it, and Select > Values selects the
value cells.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s and the timeline UI - Report field buttons: the Row Labels / Column Labels cells (each field's header in Outline and Tabular form, and each report filter) get Excel's dropdown button. Its menu has Select field (Compact form), Sort A to Z / Z to A, Clear Filter From, Label Filters ▸ (the 14 comparisons), Value Filters ▸ (8 comparisons and Top 10…) and the searchable item checklist. The Fields pane's field menus get the same two submenus. - Dialogs: Label Filter, Value Filter, Top 10 Filter, Grouping (Starting at, Ending at, By; for dates the seven levels and Number of days), Insert Calculated Item (Name, Formula, Fields, Items, Insert Item, Add/Modify, Delete), Calculated Item Solve Order, Insert Timelines and a timeline's Report Connections. They run the engine commands; errors keep them open. - Timelines are drawn on the sheet (caption, clear button, selection label, time level menu, period tiles under their year, scroll bar) in our own palette for the twelve styles. A click selects a period, Shift+click extends the selection, the caption row selects or drags the object, Delete removes it. Insert › Filters › Timeline sits after Slicer, and a selected timeline shows the Timeline tab: caption and Report Connections, Timeline Styles, Arrange (disabled), Size, and Show (Header, Selection Label, Scrollbar, Time Level). - German labels for all of it (Zeitachse, Beschriftungsfilter, Wertefilter, Top 10…, Gruppierung, Berechnetes Element einfügen…) and for the Fields pane; key tip NST for Insert › Timeline. - `pivot.fieldItems` (query) lists a field's items with whether its item selection shows them, for the checklist. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…gn tabs, GETPIVOTDATA Wires this branch's commands into the tabs' placeholders: - Group: Group Selection (`pivot.groupSelection`), Ungroup (`pivot.ungroup`, enabled on date/number-grouped and Group Selection fields) and Group Field (`pivot.group`, the Grouping dialog). - Filter: Insert Timeline (`pivot.insertTimeline`); Insert Slicer and Filter Connections stay disabled. - Calculations › Fields, Items, & Sets: Calculated Item…, Solve Order… and List Formulas next to Calculated Field…. - Value Field Settings offers all 15 Show Values As calculations (storytold#474) with a base field and base item; the Active Field's show-as key covers them. Merge resolutions: the PivotTable model and the report output keep both sides' fields (Group Selection fields, calculated items and the item cells here; the GETPIVOTDATA report index there); the GETPIVOTDATA index names a Group Selection field by its own name. Duplicate German labels keep the tabs' wording. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Checked in Excel 365: a field grouped by 30-day spans showed its items in text order (`11.11.2026 - 10.12.2026` first) because the pivot field carried `sortType="ascending"`, which Excel applies to group captions as text. Its group items are already in date order, so ascending date groups are now written without `sortType`, as Excel writes them, and a date-grouped field without one reads back as ascending. (storytold#1067 found and fixed the same for days.) A timeline's date field is only written as dates when nothing else needs its shared items (an ungrouped Rows or Columns field keeps them). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gaps.md item 8, the target-app, file-format and UI parity docs, the beta gates and the ROADMAP progress log cover Group Selection, time grouping, calculated items, timelines and the label/value filter menus, and record what Excel 365 does with the files: grouping round-trips, while saved calculated items and timeline selections are not picked up yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…uage The timeline drew its time level (MONTHS) and the empty-selection caption (All Periods) in English even with a German interface, although the level menu was already translated. Both now go through the language catalog: MONATE, Alle Zeiträume. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
I tested this PR at Filters behave as in Excel.
The difference from #498 is the tie at the Top N cut-off. Speeding Violations has a Top 15 with items tied at 15th place. Excel shows 19 rows; #498 shows 18, and which tied item it keeps changes from run to run (2 of 10 runs kept the other one). This PR shows all 19 every time. With 72b2a77 the item lists of all 11 filtered PivotTables match Excel's. The cells that still differ come from value sorting, captions and layout, which #722 covers. They are the same on One loss on save, without a warning. ELD-Unverified-Logs has a label filter on a field that isn't in any area: <filter fld="14" type="captionEqual" evalOrder="-1" id="3" stringValue1="1">It appears in A minor difference: No crashes, and each file opened and saved in 2 s or less. |
|
Thank you @Herr-Enklo. I will be more thorough in subsequent implementations! |
Retain supported label, value and Top 10 rules for fields outside Rows and Columns during XLSX load/save, without creating report-filter rows or buttons. Reactivate saved rules when the field returns to an axis, and remove them cleanly when filters or their referenced value fields are cleared. Add synthetic field-14 import, repeated round-trip, engine and UI regression tests. Update the affected PivotTable support documentation. Validation: cargo xtask ci passed all 8 gates; 1665 tests passed, with one existing timing-sensitive test ignored.
Builds on #474 and #498 by @prxnvt:
Their commits stay in the branch, brought up to date with main. #498's open review point is fixed: Top N keeps items tied at the cut-off.
Grouping (PivotTable Analyze › Group)
Region2withGroup1. Ungroup (Alt+Shift+Left) removes it.<1/1/2026/>6/30/2026items.fieldGroup,rangePr,groupItemsanddiscretePrare read and written. Date groups keep their chronological order in Excel.Calculated items
pivot.calculatedItem,pivot.solveOrder,pivot.listFormulas, plus the querypivot.fieldItems.calculatedItemsare loaded and saved. The reader no longer warns "calculated items … are not supported".Timelines
dateBetweenPivotTable filter are read and written.Filter menus
Checked in Excel 365
All checks ran black-box on synthetic files that were never saved.
f="1"it refuses the file, without it it loads none; 10 variants tried). It also doesn't apply a timeline's saved period on refresh (11 variants tried). GridCraft round-trips both correctly; gaps.md §8 documents this.Not included
Tests
pivot_timeline.rs.cargo xtask ci: all 8 steps pass (1658 tests).🤖 Generated with Claude Code