Repository navigation
Conversation
…labels model::pivot_source resolves a PivotTable's source (a table without its totals row, a range, or a defined name, sheet-scoped or chained), names its columns (trimmed, repeats numbered) and labels its items (column format, date groups, (blank)). The engine's reports call it instead of their own copies, so file writers can state the same columns and items. PivotTable::axis_field replaces the engine's page-field grouping lookup, and numfmt's Formatted::plain replaces the display code's inline fill handling. Column headers are now read as values even while Show Formulas is on, and a repeat-fill in a number format shows as one space in item labels.
Number item labels keep the report's text with a repeat fill left out (as before this branch), so stored page selections such as " $120 " under an accounting format still match. item_label reads an array's first element once and calls a nested array (blank), as the item's value and key do, without recursing. MONTHS is private, and ItemLabels is left out until the file writer that uses it lands.
# Conflicts: # crates/numfmt/src/tests.rs # docs/architecture.md
…unscanned Round 1 review fixes for the shared pivot source module. - item_label took a numfmt::NumberFormat, which a file writer in the xlsx crate cannot name (the layers check bars xlsx -> numfmt). It now takes pivot_source::ItemFormat, built from a code string. - make_item parsed the column format uncached for every record (text and blank ones too), so a multi-megabyte code from a file made a report take seconds per thousand records. It uses the engine's format cache again, and a code over 4 x the character limit is General without being copied or scanned, as the grid shows it. - headers parse each style's format once, not once per column, with the same cap. - A header holding an array inside an array is read one level deep, as an item is, instead of formatting the inner value. - The header unit test used a trailing fill that trims away, so it could not tell plain() from text; it now uses a leading one. - Formatted::plain's doc said labels use it; item labels keep text.
Round 2 review fixes, correcting round 1's make_item change. - Round 1 had make_item look its column's format up in the format cache for every record: a global lock and a hash of the code per record, text and blank ones included, which main never paid for them. The report now builds each filter, row and column field's ItemFormat once, and distinct_labels does the same for its column; FieldItems::intern and make_item take the parsed format. - item_label's doc says callers pass each record as its cell's first element, as the report does; the engine comment said the opposite. - A test pins that a header is read one array level deep, as items are.
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
This is groundwork for OpenDocument Spreadsheet (ODS) support. It contains no ODS code. It moves the code that reads a PivotTable's source out of the engine and into the model, so that a future ODS reader and writer can use the same code as the engine's report.
Why ODS needs this
ODS stores a PivotTable (
table:data-pilot-table) by naming things the report shows:table:source-cell-range), as resolved from a table, a range or a defined name;table:source-field-name);table:selected-page,table:data-pilot-member).The names an ODS file holds therefore have to match the names the report computes. Otherwise a saved filter selects nothing, or a field points at a column that doesn't exist. Until now that logic lived only in
gridcraft-engine(L5). A file format crate cannot depend on the engine. The layers check limitsxlsxtocore,formula,mathandmodel, and an ODS reader and writer would sit at the same level. An earlier ODS draft kept its own copy of the logic, and that copy had already drifted from the engine's. Moving the logic into the model gives the engine and a file writer one copy to call.What changes
gridcraft_model::pivot_source:resolve: a table without its totals row, a range (whole columns or rows cut to the used range), or a defined name, sheet-scoped or chained, followed up to 4 levels.headers: column names, trimmed, with repeats numbered (Amount,Amount2). An empty header is an error. Each style's format is parsed once.column_format,date_group_itemanditem_label.ItemFormat: an opaque, pre-parsed number format for item labels. A crate without anumfmtdependency, such as a file format crate, can build one from a code string and callitem_label. A code too long to be valid is General without being scanned, as the grid shows it.pivot.rs,pivot/items.rs,pivot/compute.rs): calls these functions instead of its own copies. The report parses each filter, row and column field's item format once per report instead of once per record. The page-field grouping lookup uses the newPivotTable::axis_field.numfmt::Formatted::plain: the formatted text with a repeat fill shown as one space.engine::display::value_text_asand the pivot headers use it.gridcraft-modelnow depends ongridcraft-numfmt(L2 → L0, whichcargo xtask layersallows).gridcraft-xlsxreaches numfmt only transitively, and the FormatDep rule (no direct xlsx → numfmt dependency) still holds. This is for the reviewer to decide on.docs/architecture.md: the model row, timestamp line and revision history are updated.User-visible behaviour
=formulatext, while Show Formulas is on. Onmain, a formula header with Show Formulas on became a field named after the formula. Test:headers_read_values_while_formulas_show.main, without the repeat fill. Under an accounting format a label stays" $120 ", so storedselectedandcollapsed_itemslabels and subtotal captions still match. Test:accounting_items_keep_their_labels_without_the_fill, which fails if the label goes throughplain().(blank)as an item, and no header name, with no recursion. Nothing that calc produces should reach this. Tests:array_items_agree_in_value_key_and_labeland the model unit tests.mainalready has, so that the shared module keeps it:table_source_leaves_out_its_totals_row,sheet_scoped_and_chained_names_resolve,repeated_and_padded_headers_keep_their_fieldsandformatted_page_items_are_chosen_by_their_labels.Testing
Run locally on macOS (aarch64) after merging current
main:cargo xtask ci: fmt, clippy (-D warnings), i18n-report, assets, layers, wasm, parity and keytips pass.cargo test --workspace --lib --bins --tests --no-fail-fast: everything passes except two tests that this PR does not touch:gridcraft-ui-egui --test arabic_editingcaret_after_typing_arabic_is_drawn_at_its_left_endalso fails on an unmodifiedmaincheckout on this machine.gridcraft-math --test gatepathological_source_at_the_cap_finishes_in_bounded_timeexceeds its wall-clock budget when the machine is under heavy load. It passes when run on its own.CRAFT_FONTS_DIRset to the craft-fonts commit that CI pins. Without it, two tests fail for lack of glyphs, as they do onmain.cargo test --workspace --docpasses.Review rounds
The branch went through three rounds of review, with fixes, before this PR:
item_labeltook anumfmt::NumberFormat, which a file format crate can't name. It now takesItemFormat.plain()fromtext.These were considered and left as they are:
headershas no byte limit. That limit predates this PR, since the engine caps cells, not bytes.Overlap
#1684 changes whether source headers are trimmed. Whichever PR lands second should apply that change in
pivot_source::headers.Left out
ItemLabels, which the ODS PR adds.filter_button, which is in another split.cmd/pivot/*.Summary by CodeRabbit