diff --git a/src/types/pivotTables/PivotFormat.ts b/src/types/pivotTables/PivotFormat.ts index 182e511..68b6a00 100644 --- a/src/types/pivotTables/PivotFormat.ts +++ b/src/types/pivotTables/PivotFormat.ts @@ -1,4 +1,4 @@ -import type { Style } from '../styles/index.ts'; +import type { integer } from '../integer.ts'; import type { PivotArea } from './PivotArea.ts'; /** @@ -8,7 +8,7 @@ import type { PivotArea } from './PivotArea.ts'; * format targets with an action indicating whether formatting is applied or blanked. * * Formats are the durable representation of user formatting on pivot output: a consumer - * re-resolves each format's area against the current layout and overlays its {@link style} on + * re-resolves each format's area against the current layout and overlays its differential style on * every repaint, so the formatting follows the targeted region (an item's data cells, the grand * total row, ...) when the pivot reshapes, rather than sticking to cell coordinates. * @@ -24,9 +24,11 @@ export type PivotFormat = { /** The pivot table region this format applies to. */ pivotArea: PivotArea; /** - * The formatting to overlay on the area's cells. Only the properties present apply; everything - * else on a cell is left as-is (the differential-format semantics of OOXML's `dxf`). - * Absent for `action: 'blank'`. + * Index of the differential style to overlay on the area's cells, into + * {@link Workbook.diffStyles}. Only the properties present in that style apply; everything else + * on a cell is left as-is. Absent for `action: 'blank'`. + * + * @see {@link Workbook.diffStyles} */ - style?: Style; + diffStyleId?: integer; }; diff --git a/src/types/pivotTables/PivotTable.ts b/src/types/pivotTables/PivotTable.ts index c2805da..9e4fa14 100644 --- a/src/types/pivotTables/PivotTable.ts +++ b/src/types/pivotTables/PivotTable.ts @@ -92,9 +92,9 @@ export type PivotTable = { /** Presentation style for the pivot table. */ style?: PivotTableStyle; /** - * Custom formatting applied to specific regions of the pivot table. Each format carries its - * differential style inline (see {@link PivotFormat.style}); there is no separate dxf table - * in JSF. + * Custom formatting applied to specific regions of the pivot table. Each format references a + * shared differential style by index (see {@link PivotFormat.diffStyleId} and + * {@link Workbook.diffStyles}). */ formats?: PivotFormat[]; // conditionalFormats is omitted for now: the conditional formatting model is not finalized. diff --git a/src/types/pivotTables/PivotTableStyle.ts b/src/types/pivotTables/PivotTableStyle.ts index 5593618..5c115fd 100644 --- a/src/types/pivotTables/PivotTableStyle.ts +++ b/src/types/pivotTables/PivotTableStyle.ts @@ -7,14 +7,17 @@ import type { PivotTableStyleName } from './PivotTableStyleName.ts'; */ export type PivotTableStyle = { /** - * The name of the pivot table style (e.g. `"PivotStyleMedium9"`). + * The name of the pivot table style: either one of the built-in style names + * (e.g. `"PivotStyleMedium9"`, see {@link PivotTableStyleName}) or the name of a + * workbook-defined style (see {@link Workbook.tableStyles}). * * If the value is null or omitted the table should not be rendered with any special styling (note - * that this only applies if the style object itself is present). + * that this only applies if the style object itself is present). A name that is neither a + * built-in style name nor defined in the workbook should be treated the same way. * * @default null */ - name?: PivotTableStyleName | null; + name?: PivotTableStyleName | string | null; /** * Whether row header formatting should be applied. * diff --git a/src/types/tables/TableStyle.ts b/src/types/tables/TableStyle.ts index 60f3b8a..e2d1270 100644 --- a/src/types/tables/TableStyle.ts +++ b/src/types/tables/TableStyle.ts @@ -8,13 +8,16 @@ import type { TableStyleName } from './TableStyleName.ts'; */ export type TableStyle = { /** - * The name of the table style to use with this table. + * The name of the table style to use with this table: either one of the built-in style names + * ({@link TableStyleName}) or the name of a workbook-defined style (see + * {@link Workbook.tableStyles}). * * If the value is null or omitted the table should not be rendered with any special styling (note - * that this only applies if the style object itself is present). + * that this only applies if the style object itself is present). A name that is neither a + * built-in style name nor defined in the workbook should be treated the same way. * @default null */ - name?: TableStyleName | null; + name?: TableStyleName | string | null; /** * Whether row stripe formatting should be applied. * diff --git a/src/types/tables/TableStyleDefinition.ts b/src/types/tables/TableStyleDefinition.ts new file mode 100644 index 0000000..d991f20 --- /dev/null +++ b/src/types/tables/TableStyleDefinition.ts @@ -0,0 +1,31 @@ +import type { TableStyleElement } from './TableStyleElement.ts'; + +/** + * A workbook-defined (custom) style for tables and/or pivot tables. + * + * Definitions live in {@link Workbook.tableStyles} and are referenced by name from + * {@link TableStyle.name} and {@link PivotTableStyle.name}, the same way built-in style + * names are referenced. + * + * A definition only describes the regions it lists; regions without an element get no + * formatting from the style. Regions overlap (e.g. a header-row cell is also part of the + * whole table), in which case the more specific region's formatting wins, property by + * property. + * + * @group Workbooks + */ +export type TableStyleDefinition = { + /** + * The name of the style, as referenced from tables and pivot tables. Must match the + * definition's key in {@link Workbook.tableStyles}. + */ + name: string; + /** + * Whether this style may be applied to pivot tables, regular tables, or both. + * + * @default "all" + */ + table?: 'table' | 'pivot' | 'all'; + /** The formatting of each table region that this style defines. */ + elements?: TableStyleElement[]; +}; diff --git a/src/types/tables/TableStyleElement.ts b/src/types/tables/TableStyleElement.ts new file mode 100644 index 0000000..503c57f --- /dev/null +++ b/src/types/tables/TableStyleElement.ts @@ -0,0 +1,29 @@ +import type { integer } from '../integer.ts'; +import type { TableStyleElementType } from './TableStyleElementType.ts'; + +/** + * The formatting of one region of a table or pivot table, within a + * {@link TableStyleDefinition}. + * + * @group Workbooks + */ +export type TableStyleElement = { + /** The table region this element's formatting applies to. */ + type: TableStyleElementType; + /** + * The number of consecutive rows or columns in each stripe band. Only meaningful for the + * four stripe element types. + * + * @default 1 + */ + size?: integer; + /** + * Index of the differential style to overlay on the region's cells, into + * {@link Workbook.diffStyles}. Only the properties present in that style apply; everything else + * on a cell is left as-is. An element without a `diffStyleId` has no visual effect (a stripe + * element may still carry a meaningful {@link size}). + * + * @see {@link Workbook.diffStyles} + */ + diffStyleId?: integer; +}; diff --git a/src/types/tables/TableStyleElementType.ts b/src/types/tables/TableStyleElementType.ts new file mode 100644 index 0000000..5269a45 --- /dev/null +++ b/src/types/tables/TableStyleElementType.ts @@ -0,0 +1,71 @@ +/** + * The region of a table or pivot table that a {@link TableStyleElement} applies to. + * + * Some regions only occur in tables (e.g. `totalRow`), others only in pivot tables (e.g. + * `pageFieldLabels`, the subheading and subtotal regions); a style definition usable for + * both kinds of table may include elements for both. + * + * The `Kind` column below indicates which kind of table each region applies to. + * + * | Value | Kind | Region + * |--------------------------|-------|----------------------------------------------------------- + * | `wholeTable` | both | The entire table. + * | `headerRow` | both | The header row. + * | `totalRow` | table | The totals row. + * | `firstColumn` | both | The first column. + * | `lastColumn` | both | The last column. + * | `firstRowStripe` | both | Odd row stripes (the first, third, … band of rows). + * | `secondRowStripe` | both | Even row stripes (the second, fourth, … band of rows). + * | `firstColumnStripe` | both | Odd column stripes (the first, third, … band of columns). + * | `secondColumnStripe` | both | Even column stripes (the second, fourth, … band of columns). + * | `firstHeaderCell` | table | The first cell of the header row. + * | `lastHeaderCell` | table | The last cell of the header row. + * | `firstTotalCell` | table | The first cell of the totals row. + * | `lastTotalCell` | table | The last cell of the totals row. + * | `firstSubtotalColumn` | pivot | First-level subtotal columns. + * | `secondSubtotalColumn` | pivot | Second-level subtotal columns. + * | `thirdSubtotalColumn` | pivot | Third-level subtotal columns. + * | `firstSubtotalRow` | pivot | First-level subtotal rows. + * | `secondSubtotalRow` | pivot | Second-level subtotal rows. + * | `thirdSubtotalRow` | pivot | Third-level subtotal rows. + * | `blankRow` | pivot | Blank rows. + * | `firstColumnSubheading` | pivot | First-level column subheadings. + * | `secondColumnSubheading` | pivot | Second-level column subheadings. + * | `thirdColumnSubheading` | pivot | Third-level column subheadings. + * | `firstRowSubheading` | pivot | First-level row subheadings. + * | `secondRowSubheading` | pivot | Second-level row subheadings. + * | `thirdRowSubheading` | pivot | Third-level row subheadings. + * | `pageFieldLabels` | pivot | Page field label cells (the filter-field name cells). + * | `pageFieldValues` | pivot | Page field value cells (the filter-field selection cells). + * + * @group Workbooks + */ +export type TableStyleElementType = + 'wholeTable' | + 'headerRow' | + 'totalRow' | + 'firstColumn' | + 'lastColumn' | + 'firstRowStripe' | + 'secondRowStripe' | + 'firstColumnStripe' | + 'secondColumnStripe' | + 'firstHeaderCell' | + 'lastHeaderCell' | + 'firstTotalCell' | + 'lastTotalCell' | + 'firstSubtotalColumn' | + 'secondSubtotalColumn' | + 'thirdSubtotalColumn' | + 'firstSubtotalRow' | + 'secondSubtotalRow' | + 'thirdSubtotalRow' | + 'blankRow' | + 'firstColumnSubheading' | + 'secondColumnSubheading' | + 'thirdColumnSubheading' | + 'firstRowSubheading' | + 'secondRowSubheading' | + 'thirdRowSubheading' | + 'pageFieldLabels' | + 'pageFieldValues'; diff --git a/src/types/tables/index.ts b/src/types/tables/index.ts index f09df54..d32c703 100644 --- a/src/types/tables/index.ts +++ b/src/types/tables/index.ts @@ -2,4 +2,7 @@ export type * from './Table.ts'; export type * from './TableColumn.ts'; export type * from './TableColumnDataType.ts'; export type * from './TableStyle.ts'; +export type * from './TableStyleDefinition.ts'; +export type * from './TableStyleElement.ts'; +export type * from './TableStyleElementType.ts'; export type * from './TableStyleName.ts'; diff --git a/src/types/workbooks/Workbook.ts b/src/types/workbooks/Workbook.ts index df81daa..7565fc3 100644 --- a/src/types/workbooks/Workbook.ts +++ b/src/types/workbooks/Workbook.ts @@ -3,7 +3,7 @@ import type { DefinedName } from '../DefinedName.ts'; import type { External } from '../External.ts'; import type { NamedStyle } from '../styles/index.ts'; import type { Style } from '../styles/index.ts'; -import type { Table } from '../tables/index.ts'; +import type { Table, TableStyleDefinition } from '../tables/index.ts'; import type { Theme } from '../themes/index.ts'; import type { PivotTable } from '../pivotTables/index.ts'; import type { Worksheet } from '../worksheets/index.ts'; @@ -31,8 +31,32 @@ export type Workbook = { calculationProperties?: CalcProps; /** Styles for cells in the workbook. */ styles?: Style[]; + /** + * Differential styles: partial style overrides referenced by index from features that overlay + * formatting on top of a cell's own style rather than replacing it (pivot table formats, custom + * table styles, and future dynamic/conditional styles). + * + * This is the differential-overlay analog of {@link Workbook.styles}: where {@link Cell.s} + * indexes a complete cell style in `styles`, an overlay's `diffStyleId` indexes a partial + * override here. Only the properties present in an entry apply; everything else on the target + * cell is left as-is. + * + * Each entry reuses the {@link Style} type (already all-optional), but is interpreted + * differentially: an absent property means "leave unchanged", not "use the default". + * + * @see {@link PivotFormat.diffStyleId} + */ + diffStyles?: Style[]; /** Named cell style definitions (e.g. "Normal", "Heading 1"), keyed by style name. */ namedStyles?: Record; + /** + * Workbook-defined (custom) table and pivot table style definitions, keyed by style name. + * + * Tables and pivot tables reference these definitions by name, through + * {@link TableStyle.name} and {@link PivotTableStyle.name}, the same way they reference + * the built-in style names. + */ + tableStyles?: Record; /** External cells referenced by the workbook. An external cell is a cell in another workbook. */ externals?: External[]; /**