diff --git a/demos/aurelia/src/examples/slickgrid/example55.ts b/demos/aurelia/src/examples/slickgrid/example55.ts index a3b78c1cf..863c39149 100644 --- a/demos/aurelia/src/examples/slickgrid/example55.ts +++ b/demos/aurelia/src/examples/slickgrid/example55.ts @@ -48,6 +48,11 @@ export class Example55 { enableTextSelectionOnCells: true, enableVariableRowHeight: true, externalResources: [new ExcelExportService()], + excelExportOptions: { + // export variable row height will also be reflected in the export + // but it can be disabled by setting `includeVariableRowHeight` to false + // includeVariableRowHeight: false, // export all rows at default height + }, rowHeight: 40, gridHeight: 560, gridWidth: 1080, diff --git a/demos/aurelia/src/examples/slickgrid/example56.ts b/demos/aurelia/src/examples/slickgrid/example56.ts index c3771056a..f150136e6 100644 --- a/demos/aurelia/src/examples/slickgrid/example56.ts +++ b/demos/aurelia/src/examples/slickgrid/example56.ts @@ -62,6 +62,11 @@ export class Example56 { enableTextSelectionOnCells: true, enableVariableRowHeight: true, externalResources: [new ExcelExportService()], + excelExportOptions: { + // export variable row height will also be reflected in the export + // but it can be disabled by setting `includeVariableRowHeight` to false + // includeVariableRowHeight: false, // export all rows at default height + }, rowHeight: 40, frozenRow: 2, gridHeight: 560, diff --git a/demos/react/src/examples/slickgrid/Example55.tsx b/demos/react/src/examples/slickgrid/Example55.tsx index dca3ffe08..5ab7ac488 100644 --- a/demos/react/src/examples/slickgrid/Example55.tsx +++ b/demos/react/src/examples/slickgrid/Example55.tsx @@ -46,6 +46,11 @@ const Example55: React.FC = () => { enableTextSelectionOnCells: true, enableVariableRowHeight: true, externalResources: [new ExcelExportService()], + excelExportOptions: { + // export variable row height will also be reflected in the export + // but it can be disabled by setting `includeVariableRowHeight` to false + // includeVariableRowHeight: false, // export all rows at default height + }, rowHeight: 40, gridHeight: 560, gridWidth: 1080, diff --git a/demos/react/src/examples/slickgrid/Example56.tsx b/demos/react/src/examples/slickgrid/Example56.tsx index 5310a25a2..ea25ccc69 100644 --- a/demos/react/src/examples/slickgrid/Example56.tsx +++ b/demos/react/src/examples/slickgrid/Example56.tsx @@ -61,6 +61,11 @@ const Example56: React.FC = () => { enableTextSelectionOnCells: true, enableVariableRowHeight: true, externalResources: [new ExcelExportService()], + excelExportOptions: { + // export variable row height will also be reflected in the export + // but it can be disabled by setting `includeVariableRowHeight` to false + // includeVariableRowHeight: false, // export all rows at default height + }, rowHeight: 40, frozenRow: 2, gridHeight: 560, diff --git a/demos/vanilla/src/examples/example44.ts b/demos/vanilla/src/examples/example44.ts index f4977903a..048782236 100644 --- a/demos/vanilla/src/examples/example44.ts +++ b/demos/vanilla/src/examples/example44.ts @@ -53,6 +53,11 @@ export default class Example44 { enableTextSelectionOnCells: true, enableVariableRowHeight: true, externalResources: [new ExcelExportService()], + excelExportOptions: { + // export variable row height will also be reflected in the export + // but it can be disabled by setting `includeVariableRowHeight` to false + // includeVariableRowHeight: false, // export all rows at default height + }, rowHeight: 40, gridHeight: 560, gridWidth: 1080, diff --git a/demos/vanilla/src/examples/example45.ts b/demos/vanilla/src/examples/example45.ts index b33c8fe76..55a2b030a 100644 --- a/demos/vanilla/src/examples/example45.ts +++ b/demos/vanilla/src/examples/example45.ts @@ -68,6 +68,11 @@ export default class Example45 { enableTextSelectionOnCells: true, enableVariableRowHeight: true, externalResources: [new ExcelExportService()], + excelExportOptions: { + // export variable row height will also be reflected in the export + // but it can be disabled by setting `includeVariableRowHeight` to false + // includeVariableRowHeight: false, // export all rows at default height + }, rowHeight: 40, frozenRow: 2, gridHeight: 560, diff --git a/demos/vue/src/components/Example55.vue b/demos/vue/src/components/Example55.vue index e60fc4f6d..f9842fe15 100644 --- a/demos/vue/src/components/Example55.vue +++ b/demos/vue/src/components/Example55.vue @@ -45,6 +45,11 @@ function defineGrid() { enableTextSelectionOnCells: true, enableVariableRowHeight: true, externalResources: [new ExcelExportService()], + excelExportOptions: { + // export variable row height will also be reflected in the export + // but it can be disabled by setting `includeVariableRowHeight` to false + // includeVariableRowHeight: false, // export all rows at default height + }, rowHeight: 40, gridHeight: 560, gridWidth: 1080, diff --git a/demos/vue/src/components/Example56.vue b/demos/vue/src/components/Example56.vue index a995a84b7..e54092649 100644 --- a/demos/vue/src/components/Example56.vue +++ b/demos/vue/src/components/Example56.vue @@ -60,6 +60,11 @@ function defineGrid() { enableVariableRowHeight: true, rowHeight: 40, externalResources: [new ExcelExportService()], + excelExportOptions: { + // export variable row height will also be reflected in the export + // but it can be disabled by setting `includeVariableRowHeight` to false + // includeVariableRowHeight: false, // export all rows at default height + }, frozenRow: 2, gridHeight: 560, gridWidth: 1080, diff --git a/docs/grid-functionalities/export-to-excel.md b/docs/grid-functionalities/export-to-excel.md index 5f104404b..f78d7e1a4 100644 --- a/docs/grid-functionalities/export-to-excel.md +++ b/docs/grid-functionalities/export-to-excel.md @@ -9,6 +9,7 @@ - [Provide Custom Header Title](#provide-a-custom-header-title) - [Export from Button Click](#export-from-a-button-click-event) - [Show Loading Process Spinner](#show-loading-process-spinner) +- [Variable Row Height](#variable-row-height) - [Large Dataset Performance](#large-dataset-performance) - [UI Sample](#ui-sample) @@ -250,6 +251,17 @@ export class MyExample() { } ``` +### Variable Row Height +When `enableVariableRowHeight: true` is set in your grid options, Excel export automatically reflects each row's individual pixel height, converted to Excel points (px × 0.75). This is enabled by default whenever variable row height is active. + +To opt out, set `includeVariableRowHeight: false` in your `excelExportOptions`: + +```ts +excelExportOptions: { + includeVariableRowHeight: false, // export all rows at default height +} +``` + ### Large Dataset Performance For large datasets and formatter-heavy exports, you can improve responsiveness by enabling the DataView formatted cache. diff --git a/docs/grid-functionalities/export-to-pdf.md b/docs/grid-functionalities/export-to-pdf.md index 33a66a94d..daf6ce6a2 100644 --- a/docs/grid-functionalities/export-to-pdf.md +++ b/docs/grid-functionalities/export-to-pdf.md @@ -8,6 +8,7 @@ - [AutoTable Options Callback](#autotable-options-callback) - [Export from Button Click](#export-from-a-button-click-event) - [Show Loading Process Spinner](#show-loading-process-spinner) +- [Variable Row Height](#variable-row-height) - [Large Dataset Performance](#large-dataset-performance) - [UI Sample](#ui-sample) @@ -222,6 +223,17 @@ export class MyExample { } ``` +### Variable Row Height +When `enableVariableRowHeight: true` is set in your grid options, PDF export automatically reflects each row's individual pixel height, converted to PDF points (px × 0.75). When using `jspdf-autotable`, `minCellHeight` is set per cell; the manual fallback uses the per-row height directly. + +To opt out, set `includeVariableRowHeight: false` in your `pdfExportOptions`: + +```ts +pdfExportOptions: { + includeVariableRowHeight: false, // export all rows at default height +} +``` + ### Large Dataset Performance For large datasets and formatter-heavy exports, you can improve responsiveness by enabling the DataView formatted cache. diff --git a/docs/grid-functionalities/variable-row-height.md b/docs/grid-functionalities/variable-row-height.md index e4940d852..eb46b4384 100644 --- a/docs/grid-functionalities/variable-row-height.md +++ b/docs/grid-functionalities/variable-row-height.md @@ -4,6 +4,7 @@ - [Using rowHeightProvider](#using-rowheightprovider) - [Using Item Metadata Height Fallback](#using-item-metadata-height-fallback) - [Runtime Updates](#runtime-updates) +- [Export Integration](#export-integration) ### Introduction By default, SlickGrid uses the grid option `rowHeight` for every row. Variable row height is opt-in and only active when `enableVariableRowHeight` grid option is set to `true`. @@ -74,3 +75,23 @@ this.sgb?.slickGrid?.invalidateRowHeights?.(); ``` Use `invalidateRowHeights()` after any change that can alter computed row height. + +### Export Integration +When `enableVariableRowHeight: true`, both Excel and PDF exports automatically reflect the per-row heights. + +- **Excel**: row heights are written via `setRowInstructions`, converting pixels to points (px × 0.75). +- **PDF**: when using `jspdf-autotable`, `minCellHeight` is set per cell; the manual fallback uses the per-row height directly. + +Set `includeVariableRowHeight: false` in `excelExportOptions` or `pdfExportOptions` to skip row height export and use uniform row heights instead: + +```ts +const gridOptions: GridOption = { + enableVariableRowHeight: true, + excelExportOptions: { + includeVariableRowHeight: false, // skip variable heights in Excel export + }, + pdfExportOptions: { + includeVariableRowHeight: false, // skip variable heights in PDF export + }, +}; +``` diff --git a/frameworks/angular-slickgrid/docs/grid-functionalities/export-to-excel.md b/frameworks/angular-slickgrid/docs/grid-functionalities/export-to-excel.md index 308bd273f..c7f7a1774 100644 --- a/frameworks/angular-slickgrid/docs/grid-functionalities/export-to-excel.md +++ b/frameworks/angular-slickgrid/docs/grid-functionalities/export-to-excel.md @@ -9,6 +9,7 @@ - [Provide Custom Header Title](#provide-a-custom-header-title) - [Export from Button Click](#export-from-a-button-click-event) - [Show Loading Process Spinner](#show-loading-process-spinner) +- [Variable Row Height](#variable-row-height) - [Large Dataset Performance](#large-dataset-performance) - [UI Sample](#ui-sample) @@ -257,7 +258,19 @@ export class MyComponent() implements OnInit { } ``` +### Variable Row Height +When `enableVariableRowHeight: true`, the Excel export automatically reflects per-row heights, converting pixel heights to Excel points (px × 0.75). Set `includeVariableRowHeight: false` in `excelExportOptions` to skip this and use uniform row heights: +```ts +gridOptions = { + enableVariableRowHeight: true, + excelExportOptions: { + includeVariableRowHeight: false, // export all rows at default height + }, +}; +``` + +### Large Dataset Performance For a combined sorting + export strategy, see [Large Dataset Performance Guide](../developer-guides/large-dataset-performance.md). ```ts diff --git a/frameworks/angular-slickgrid/docs/grid-functionalities/export-to-pdf.md b/frameworks/angular-slickgrid/docs/grid-functionalities/export-to-pdf.md index c64dff08a..120178de6 100644 --- a/frameworks/angular-slickgrid/docs/grid-functionalities/export-to-pdf.md +++ b/frameworks/angular-slickgrid/docs/grid-functionalities/export-to-pdf.md @@ -8,6 +8,7 @@ - [AutoTable Options Callback](#autotable-options-callback) - [Export from Button Click](#export-from-button-click) - [Show Loading Process Spinner](#show-loading-process-spinner) +- [Variable Row Height](#variable-row-height) - [Large Dataset Performance](#large-dataset-performance) - [UI Sample](#ui-sample) @@ -223,7 +224,19 @@ export class MyExample { } ``` +### Variable Row Height +When `enableVariableRowHeight: true`, the PDF export automatically reflects per-row heights (px × 0.75 → pt). With `jspdf-autotable`, `minCellHeight` is set per row; the manual fallback uses the per-row height directly. Set `includeVariableRowHeight: false` in `pdfExportOptions` to skip this: +```ts +gridOptions = { + enableVariableRowHeight: true, + pdfExportOptions: { + includeVariableRowHeight: false, // export all rows at default height + }, +}; +``` + +### Large Dataset Performance For a combined sorting + export strategy, see [Large Dataset Performance Guide](../developer-guides/large-dataset-performance.md). ```ts diff --git a/frameworks/angular-slickgrid/docs/grid-functionalities/variable-row-height.md b/frameworks/angular-slickgrid/docs/grid-functionalities/variable-row-height.md index 606a24ed2..999877dac 100644 --- a/frameworks/angular-slickgrid/docs/grid-functionalities/variable-row-height.md +++ b/frameworks/angular-slickgrid/docs/grid-functionalities/variable-row-height.md @@ -4,6 +4,7 @@ - [Using rowHeightProvider](#using-rowheightprovider) - [Using Item Metadata Height Fallback](#using-item-metadata-height-fallback) - [Runtime Updates](#runtime-updates) +- [Export Integration](#export-integration) ### Introduction By default, SlickGrid uses the grid option `rowHeight` for every row. Variable row height is opt-in and only active when `enableVariableRowHeight` grid option is set to `true`. @@ -71,3 +72,23 @@ this.angularGrid?.slickGrid?.invalidateRowHeights?.(); ``` > Use `(onAngularGridCreated)` event in your view template to get a reference to `this.angularGrid?.slickGrid` (see [Grid and DataView events](../events/grid-dataview-events.md) for more info) + +### Export Integration +When `enableVariableRowHeight: true`, both Excel and PDF exports automatically reflect the per-row heights. + +- **Excel**: row heights are written via `setRowInstructions`, converting pixels to points (px × 0.75). +- **PDF**: when using `jspdf-autotable`, `minCellHeight` is set per cell; the manual fallback uses the per-row height directly. + +Set `includeVariableRowHeight: false` in `excelExportOptions` or `pdfExportOptions` to skip row height export and use uniform row heights instead: + +```ts +gridOptions: GridOption = { + enableVariableRowHeight: true, + excelExportOptions: { + includeVariableRowHeight: false, // skip variable heights in Excel export + }, + pdfExportOptions: { + includeVariableRowHeight: false, // skip variable heights in PDF export + }, +}; +``` diff --git a/frameworks/angular-slickgrid/src/demos/examples/example55.component.ts b/frameworks/angular-slickgrid/src/demos/examples/example55.component.ts index 3bfc07be8..09b5adcbb 100644 --- a/frameworks/angular-slickgrid/src/demos/examples/example55.component.ts +++ b/frameworks/angular-slickgrid/src/demos/examples/example55.component.ts @@ -51,6 +51,11 @@ export class Example55Component implements OnInit { enableTextSelectionOnCells: true, enableVariableRowHeight: true, externalResources: [new ExcelExportService()], + excelExportOptions: { + // export variable row height will also be reflected in the export + // but it can be disabled by setting `includeVariableRowHeight` to false + // includeVariableRowHeight: false, // export all rows at default height + }, rowHeight: 40, gridHeight: 560, gridWidth: 1080, diff --git a/frameworks/angular-slickgrid/src/demos/examples/example56.component.ts b/frameworks/angular-slickgrid/src/demos/examples/example56.component.ts index 767f045d6..703bf367c 100644 --- a/frameworks/angular-slickgrid/src/demos/examples/example56.component.ts +++ b/frameworks/angular-slickgrid/src/demos/examples/example56.component.ts @@ -65,6 +65,11 @@ export class Example56Component implements OnInit { enableTextSelectionOnCells: true, enableVariableRowHeight: true, externalResources: [new ExcelExportService()], + excelExportOptions: { + // export variable row height will also be reflected in the export + // but it can be disabled by setting `includeVariableRowHeight` to false + // includeVariableRowHeight: false, // export all rows at default height + }, rowHeight: 40, frozenRow: 2, gridHeight: 560, diff --git a/frameworks/aurelia-slickgrid/docs/grid-functionalities/export-to-excel.md b/frameworks/aurelia-slickgrid/docs/grid-functionalities/export-to-excel.md index 5c981376a..a679335df 100644 --- a/frameworks/aurelia-slickgrid/docs/grid-functionalities/export-to-excel.md +++ b/frameworks/aurelia-slickgrid/docs/grid-functionalities/export-to-excel.md @@ -9,6 +9,7 @@ - [Provide Custom Header Title](#provide-a-custom-header-title) - [Export from Button Click](#export-from-a-button-click-event) - [Show Loading Process Spinner](#show-loading-process-spinner) +- [Variable Row Height](#variable-row-height) - [Large Dataset Performance](#large-dataset-performance) - [UI Sample](#ui-sample) @@ -245,7 +246,19 @@ If you have lots of data, you might want to show a spinner telling the user that ``` +### Variable Row Height +When `enableVariableRowHeight: true`, the Excel export automatically reflects per-row heights, converting pixel heights to Excel points (px × 0.75). Set `includeVariableRowHeight: false` in `excelExportOptions` to skip this and use uniform row heights: +```ts +gridOptions = { + enableVariableRowHeight: true, + excelExportOptions: { + includeVariableRowHeight: false, // export all rows at default height + }, +}; +``` + +### Large Dataset Performance For a combined sorting + export strategy, see [Large Dataset Performance Guide](../developer-guides/large-dataset-performance.md). ```ts diff --git a/frameworks/aurelia-slickgrid/docs/grid-functionalities/export-to-pdf.md b/frameworks/aurelia-slickgrid/docs/grid-functionalities/export-to-pdf.md index 49b52d86c..8e278a364 100644 --- a/frameworks/aurelia-slickgrid/docs/grid-functionalities/export-to-pdf.md +++ b/frameworks/aurelia-slickgrid/docs/grid-functionalities/export-to-pdf.md @@ -8,6 +8,7 @@ - [AutoTable Options Callback](#autotable-options-callback) - [Export from Button Click](#export-from-button-click) - [Show Loading Process Spinner](#show-loading-process-spinner) +- [Variable Row Height](#variable-row-height) - [Large Dataset Performance](#large-dataset-performance) - [UI Sample](#ui-sample) @@ -223,7 +224,19 @@ export class MyExample { } ``` +### Variable Row Height +When `enableVariableRowHeight: true`, the PDF export automatically reflects per-row heights (px × 0.75 → pt). With `jspdf-autotable`, `minCellHeight` is set per row; the manual fallback uses the per-row height directly. Set `includeVariableRowHeight: false` in `pdfExportOptions` to skip this: +```ts +gridOptions = { + enableVariableRowHeight: true, + pdfExportOptions: { + includeVariableRowHeight: false, // export all rows at default height + }, +}; +``` + +### Large Dataset Performance For a combined sorting + export strategy, see [Large Dataset Performance Guide](../developer-guides/large-dataset-performance.md). ```ts diff --git a/frameworks/aurelia-slickgrid/docs/grid-functionalities/variable-row-height.md b/frameworks/aurelia-slickgrid/docs/grid-functionalities/variable-row-height.md index fef2aca30..5cc650df0 100644 --- a/frameworks/aurelia-slickgrid/docs/grid-functionalities/variable-row-height.md +++ b/frameworks/aurelia-slickgrid/docs/grid-functionalities/variable-row-height.md @@ -4,6 +4,7 @@ - [Using rowHeightProvider](#using-rowheightprovider) - [Using Item Metadata Height Fallback](#using-item-metadata-height-fallback) - [Runtime Updates](#runtime-updates) +- [Export Integration](#export-integration) ### Introduction By default, SlickGrid uses the grid option `rowHeight` for every row. Variable row height is opt-in and only active when `enableVariableRowHeight` grid option is set to `true`. @@ -70,4 +71,24 @@ After any change that impacts row height, call: this.aureliaGrid?.slickGrid?.invalidateRowHeights?.(); ``` -> Use `on-aurelia-grid-created.trigger` event in your view template to get a reference to `this.aureliaGrid?.slickGrid` (see [Grid and DataView events](../events/grid-dataview-events.md) for more info) \ No newline at end of file +> Use `on-aurelia-grid-created.trigger` event in your view template to get a reference to `this.aureliaGrid?.slickGrid` (see [Grid and DataView events](../events/grid-dataview-events.md) for more info) + +### Export Integration +When `enableVariableRowHeight: true`, both Excel and PDF exports automatically reflect the per-row heights. + +- **Excel**: row heights are written via `setRowInstructions`, converting pixels to points (px × 0.75). +- **PDF**: when using `jspdf-autotable`, `minCellHeight` is set per cell; the manual fallback uses the per-row height directly. + +Set `includeVariableRowHeight: false` in `excelExportOptions` or `pdfExportOptions` to skip row height export and use uniform row heights instead: + +```ts +gridOptions: GridOption = { + enableVariableRowHeight: true, + excelExportOptions: { + includeVariableRowHeight: false, // skip variable heights in Excel export + }, + pdfExportOptions: { + includeVariableRowHeight: false, // skip variable heights in PDF export + }, +}; +``` \ No newline at end of file diff --git a/frameworks/slickgrid-react/docs/grid-functionalities/export-to-excel.md b/frameworks/slickgrid-react/docs/grid-functionalities/export-to-excel.md index 8b3558ea6..709d0f0e4 100644 --- a/frameworks/slickgrid-react/docs/grid-functionalities/export-to-excel.md +++ b/frameworks/slickgrid-react/docs/grid-functionalities/export-to-excel.md @@ -9,6 +9,7 @@ - [Provide Custom Header Title](#provide-a-custom-header-title) - [Export from Button Click](#export-from-a-button-click-event) - [Show Loading Process Spinner](#show-loading-process-spinner) +- [Variable Row Height](#variable-row-height) - [Large Dataset Performance](#large-dataset-performance) - [UI Sample](#ui-sample) @@ -271,7 +272,19 @@ return !options ? null : ( ); ``` +### Variable Row Height +When `enableVariableRowHeight: true`, the Excel export automatically reflects per-row heights, converting pixel heights to Excel points (px × 0.75). Set `includeVariableRowHeight: false` in `excelExportOptions` to skip this and use uniform row heights: +```ts +gridOptions = { + enableVariableRowHeight: true, + excelExportOptions: { + includeVariableRowHeight: false, // export all rows at default height + }, +}; +``` + +### Large Dataset Performance For a combined sorting + export strategy, see [Large Dataset Performance Guide](../developer-guides/large-dataset-performance.md). ```ts diff --git a/frameworks/slickgrid-react/docs/grid-functionalities/export-to-pdf.md b/frameworks/slickgrid-react/docs/grid-functionalities/export-to-pdf.md index 841bb64af..0727c178d 100644 --- a/frameworks/slickgrid-react/docs/grid-functionalities/export-to-pdf.md +++ b/frameworks/slickgrid-react/docs/grid-functionalities/export-to-pdf.md @@ -8,6 +8,7 @@ - [AutoTable Options Callback](#autotable-options-callback) - [Export from Button Click](#export-from-button-click) - [Show Loading Process Spinner](#show-loading-process-spinner) +- [Variable Row Height](#variable-row-height) - [Large Dataset Performance](#large-dataset-performance) - [UI Sample](#ui-sample) @@ -232,7 +233,19 @@ return !options ? null : ( ); ``` +### Variable Row Height +When `enableVariableRowHeight: true`, the PDF export automatically reflects per-row heights (px × 0.75 → pt). With `jspdf-autotable`, `minCellHeight` is set per row; the manual fallback uses the per-row height directly. Set `includeVariableRowHeight: false` in `pdfExportOptions` to skip this: +```ts +gridOptions = { + enableVariableRowHeight: true, + pdfExportOptions: { + includeVariableRowHeight: false, // export all rows at default height + }, +}; +``` + +### Large Dataset Performance For a combined sorting + export strategy, see [Large Dataset Performance Guide](../developer-guides/large-dataset-performance.md). ```ts diff --git a/frameworks/slickgrid-react/docs/grid-functionalities/variable-row-height.md b/frameworks/slickgrid-react/docs/grid-functionalities/variable-row-height.md index 1628e5984..c6f04a054 100644 --- a/frameworks/slickgrid-react/docs/grid-functionalities/variable-row-height.md +++ b/frameworks/slickgrid-react/docs/grid-functionalities/variable-row-height.md @@ -4,6 +4,7 @@ - [Using rowHeightProvider](#using-rowheightprovider) - [Using Item Metadata Height Fallback](#using-item-metadata-height-fallback) - [Runtime Updates](#runtime-updates) +- [Export Integration](#export-integration) ### Introduction By default, SlickGrid uses the grid option `rowHeight` for every row. Variable row height is opt-in and only active when `enableVariableRowHeight` grid option is set to `true`. @@ -68,4 +69,24 @@ After any change that impacts row height, call: reactGridRef.current?.slickGrid?.invalidateRowHeights?.(); ``` -> Use `onReactGridCreated` event in your view template to get a reference to `reactGridRef.current?.slickGrid` (see [Grid and DataView events](../events/grid-dataview-events.md) for more info) \ No newline at end of file +> Use `onReactGridCreated` event in your view template to get a reference to `reactGridRef.current?.slickGrid` (see [Grid and DataView events](../events/grid-dataview-events.md) for more info) + +### Export Integration +When `enableVariableRowHeight: true`, both Excel and PDF exports automatically reflect the per-row heights. + +- **Excel**: row heights are written via `setRowInstructions`, converting pixels to points (px × 0.75). +- **PDF**: when using `jspdf-autotable`, `minCellHeight` is set per cell; the manual fallback uses the per-row height directly. + +Set `includeVariableRowHeight: false` in `excelExportOptions` or `pdfExportOptions` to skip row height export and use uniform row heights instead: + +```tsx +const gridOptions: GridOption = { + enableVariableRowHeight: true, + excelExportOptions: { + includeVariableRowHeight: false, // skip variable heights in Excel export + }, + pdfExportOptions: { + includeVariableRowHeight: false, // skip variable heights in PDF export + }, +}; +``` \ No newline at end of file diff --git a/frameworks/slickgrid-vue/docs/grid-functionalities/export-to-excel.md b/frameworks/slickgrid-vue/docs/grid-functionalities/export-to-excel.md index 697237a51..f4e685c65 100644 --- a/frameworks/slickgrid-vue/docs/grid-functionalities/export-to-excel.md +++ b/frameworks/slickgrid-vue/docs/grid-functionalities/export-to-excel.md @@ -9,6 +9,7 @@ - [Provide Custom Header Title](#provide-a-custom-header-title) - [Export from Button Click](#export-from-a-button-click-event) - [Show Loading Process Spinner](#show-loading-process-spinner) +- [Variable Row Height](#variable-row-height) - [Large Dataset Performance](#large-dataset-performance) - [UI Sample](#ui-sample) @@ -296,7 +297,19 @@ If you have lots of data, you might want to show a spinner telling the user that ``` +### Variable Row Height +When `enableVariableRowHeight: true`, the Excel export automatically reflects per-row heights, converting pixel heights to Excel points (px × 0.75). Set `includeVariableRowHeight: false` in `excelExportOptions` to skip this and use uniform row heights: +```ts +gridOptions = { + enableVariableRowHeight: true, + excelExportOptions: { + includeVariableRowHeight: false, // export all rows at default height + }, +}; +``` + +### Large Dataset Performance For a combined sorting + export strategy, see [Large Dataset Performance Guide](../developer-guides/large-dataset-performance.md). ```ts diff --git a/frameworks/slickgrid-vue/docs/grid-functionalities/export-to-pdf.md b/frameworks/slickgrid-vue/docs/grid-functionalities/export-to-pdf.md index 0064b8f62..f4579ec58 100644 --- a/frameworks/slickgrid-vue/docs/grid-functionalities/export-to-pdf.md +++ b/frameworks/slickgrid-vue/docs/grid-functionalities/export-to-pdf.md @@ -8,6 +8,7 @@ - [AutoTable Options Callback](#autotable-options-callback) - [Export from Button Click](#export-from-a-button-click-event) - [Show Loading Process Spinner](#show-loading-process-spinner) +- [Variable Row Height](#variable-row-height) - [Large Dataset Performance](#large-dataset-performance) - [UI Sample](#ui-sample) @@ -236,7 +237,19 @@ You can subscribe to `onBeforeExportToPdf` and `onAfterExportToPdf` events to sh ``` +### Variable Row Height +When `enableVariableRowHeight: true`, the PDF export automatically reflects per-row heights (px × 0.75 → pt). With `jspdf-autotable`, `minCellHeight` is set per row; the manual fallback uses the per-row height directly. Set `includeVariableRowHeight: false` in `pdfExportOptions` to skip this: +```ts +gridOptions = { + enableVariableRowHeight: true, + pdfExportOptions: { + includeVariableRowHeight: false, // export all rows at default height + }, +}; +``` + +### Large Dataset Performance For a combined sorting + export strategy, see [Large Dataset Performance Guide](../developer-guides/large-dataset-performance.md). ```ts diff --git a/frameworks/slickgrid-vue/docs/grid-functionalities/variable-row-height.md b/frameworks/slickgrid-vue/docs/grid-functionalities/variable-row-height.md index a8532b627..de9e6117b 100644 --- a/frameworks/slickgrid-vue/docs/grid-functionalities/variable-row-height.md +++ b/frameworks/slickgrid-vue/docs/grid-functionalities/variable-row-height.md @@ -4,6 +4,7 @@ - [Using rowHeightProvider](#using-rowheightprovider) - [Using Item Metadata Height Fallback](#using-item-metadata-height-fallback) - [Runtime Updates](#runtime-updates) +- [Export Integration](#export-integration) ### Introduction By default, SlickGrid uses the grid option `rowHeight` for every row. Variable row height is opt-in and only active when `enableVariableRowHeight` grid option is set to `true`. @@ -70,4 +71,24 @@ After any change that impacts row height, call: vueGrid.slickGrid?.invalidateRowHeights?.(); ``` -> Use `@onVueGridCreated` event in your view template to get a reference to `vueGrid.slickGrid` (see [Grid and DataView events](../events/grid-dataview-events.md) for more info) \ No newline at end of file +> Use `@onVueGridCreated` event in your view template to get a reference to `vueGrid.slickGrid` (see [Grid and DataView events](../events/grid-dataview-events.md) for more info) + +### Export Integration +When `enableVariableRowHeight: true`, both Excel and PDF exports automatically reflect the per-row heights. + +- **Excel**: row heights are written via `setRowInstructions`, converting pixels to points (px × 0.75). +- **PDF**: when using `jspdf-autotable`, `minCellHeight` is set per cell; the manual fallback uses the per-row height directly. + +Set `includeVariableRowHeight: false` in `excelExportOptions` or `pdfExportOptions` to skip row height export and use uniform row heights instead: + +```ts +const gridOptions: GridOption = { + enableVariableRowHeight: true, + excelExportOptions: { + includeVariableRowHeight: false, // skip variable heights in Excel export + }, + pdfExportOptions: { + includeVariableRowHeight: false, // skip variable heights in PDF export + }, +}; +``` \ No newline at end of file diff --git a/packages/common/src/interfaces/excelExportOption.interface.ts b/packages/common/src/interfaces/excelExportOption.interface.ts index d7146c9f6..a0e13566c 100644 --- a/packages/common/src/interfaces/excelExportOption.interface.ts +++ b/packages/common/src/interfaces/excelExportOption.interface.ts @@ -62,6 +62,13 @@ export interface ExcelExportOption { */ useStreamingExport?: boolean; + /** + * When true (default), export row heights to Excel when enableVariableRowHeight is active. + * Set to false to ignore variable row heights and export all rows at default height. + * Heights are converted from pixels to Excel points (72 DPI) for proper rendering. + */ + includeVariableRowHeight?: boolean; + /** Add a Custom Excel Header on first row of the Excel Sheet */ customExcelHeader?: (workbook: Workbook, sheet: Worksheet) => void; } diff --git a/packages/common/src/interfaces/pdfExportOption.interface.ts b/packages/common/src/interfaces/pdfExportOption.interface.ts index 86a973615..d94ec6517 100644 --- a/packages/common/src/interfaces/pdfExportOption.interface.ts +++ b/packages/common/src/interfaces/pdfExportOption.interface.ts @@ -78,6 +78,13 @@ export interface PdfExportOption { */ width?: number; + /** + * When true (default), export row heights to PDF when enableVariableRowHeight is active. + * Set to false to ignore variable row heights and export all rows at default height. + * Heights are converted from pixels to PDF points (72 DPI): pixels * 0.75. + */ + includeVariableRowHeight?: boolean; + /** * Optional callback to customize the jsPDF-AutoTable options before the table is rendered. * Receives the fully-built AutoTable options object and must return the (possibly mutated) options. diff --git a/packages/excel-export/src/excelExport.helpers.spec.ts b/packages/excel-export/src/excelExport.helpers.spec.ts index 26103c624..478564dfa 100644 --- a/packages/excel-export/src/excelExport.helpers.spec.ts +++ b/packages/excel-export/src/excelExport.helpers.spec.ts @@ -41,7 +41,7 @@ describe('ExcelExportService Helpers', () => { it('efficientYield fallback uses setTimeout', async () => { (globalThis as any).scheduler = undefined; - const spy = vi.spyOn(global, 'setTimeout'); + const spy = vi.spyOn(globalThis, 'setTimeout'); await (service as any).efficientYield(); expect(spy).toHaveBeenCalled(); }); diff --git a/packages/excel-export/src/excelExport.service.spec.ts b/packages/excel-export/src/excelExport.service.spec.ts index e2ee4f7df..67c58c4b5 100644 --- a/packages/excel-export/src/excelExport.service.spec.ts +++ b/packages/excel-export/src/excelExport.service.spec.ts @@ -45,8 +45,8 @@ const pubSubServiceStub = { // URL object is not supported in JSDOM, we can simply mock it const createObjectMock = vi.fn(); -(global as any).URL.createObjectURL = createObjectMock; -(global as any).URL.revokeObjectURL = vi.fn(); +(globalThis as any).URL.createObjectURL = createObjectMock; +(globalThis as any).URL.revokeObjectURL = vi.fn(); const myBoldHtmlFormatter: Formatter = (_row, _cell, value) => (value !== null ? { text: `${value}` } : (null as any)); const myUppercaseFormatter: Formatter = (_row, _cell, value) => (value ? { text: value.toUpperCase() } : (null as any)); @@ -91,6 +91,7 @@ const gridStub = { getVisibleColumns: vi.fn(), getGrouping: vi.fn(), getParentRowSpanByCell: vi.fn(), + getRowHeight: vi.fn(), } as unknown as SlickGrid; describe('ExcelExportService', () => { @@ -1984,7 +1985,7 @@ describe('ExcelExportService', () => { vi.spyOn(dataViewStub, 'getGrouping').mockReturnValue([]); const pubSubSpy = vi.spyOn(pubSubServiceStub, 'publish'); - const setTimeoutSpy = vi.spyOn(global, 'setTimeout'); + const setTimeoutSpy = vi.spyOn(globalThis, 'setTimeout'); service.init(gridStub, container); @@ -1997,7 +1998,7 @@ describe('ExcelExportService', () => { // Should yield based on simplified frequency (500 for 2000 rows) // With 2000 rows and frequency of 500, we expect 4 yields: at 500, 1000, 1500, 2000 - const yieldCalls = setTimeoutSpy.mock.calls.filter((call) => call[1] === 0); + const yieldCalls = setTimeoutSpy.mock.calls.filter((call: any[]) => call[1] === 0); expect(yieldCalls.length).toBeGreaterThanOrEqual(1); // Simplified yielding strategy expect(pubSubSpy).not.toHaveBeenCalledWith('onExcelExportProgress', expect.anything()); @@ -2104,7 +2105,7 @@ describe('ExcelExportService', () => { vi.spyOn(dataViewStub, 'getItem').mockImplementation((index) => mockData[index]); vi.spyOn(dataViewStub, 'getGrouping').mockReturnValue([]); - const setTimeoutSpy = vi.spyOn(global, 'setTimeout'); + const setTimeoutSpy = vi.spyOn(globalThis, 'setTimeout'); service.init(gridStub, container); @@ -2117,7 +2118,7 @@ describe('ExcelExportService', () => { // Should yield based on simplified frequency (1000 for 5000 rows) // With 5000 rows and frequency of 1000, we expect yields at 1000,2000,3000,4000 - const yieldCalls = setTimeoutSpy.mock.calls.filter((call) => call[1] === 0); + const yieldCalls = setTimeoutSpy.mock.calls.filter((call: any[]) => call[1] === 0); expect(yieldCalls.length).toBeGreaterThanOrEqual(4); }); }); @@ -2596,7 +2597,7 @@ describe('ExcelExportService', () => { it('efficientYield should fallback to setTimeout when scheduler is unavailable', async () => { (globalThis as any).scheduler = undefined; - const setTimeoutSpy = vi.spyOn(global, 'setTimeout'); + const setTimeoutSpy = vi.spyOn(globalThis, 'setTimeout'); service.init(gridStub, container); await (service as any).efficientYield(); expect(setTimeoutSpy).toHaveBeenCalled(); @@ -2643,6 +2644,102 @@ describe('ExcelExportService', () => { const out = (service as any).readGroupedTotalRows([col], { groupTotals: { sum: 42 } }, 0); expect(out).toEqual(expect.arrayContaining(['', 'Total 42'])); }); + + describe('Variable Row Height', () => { + it('exportToExcel should call applyVariableRowHeights when variable row height is enabled', async () => { + const mockGridOptionWithVarHeight = { ...mockGridOptions, enableVariableRowHeight: true } as GridOption; + vi.spyOn(gridStub, 'getOptions').mockReturnValue(mockGridOptionWithVarHeight); + vi.spyOn(gridStub, 'getRowHeight').mockReturnValue(40); + vi.spyOn(gridStub, 'getVisibleColumns').mockReturnValue([{ id: 'id', field: 'id', name: 'ID', width: 100 }] as Column[]); + vi.spyOn(dataViewStub, 'getGrouping').mockReturnValue([]); + vi.spyOn(dataViewStub, 'getLength').mockReturnValue(1); + vi.spyOn(dataViewStub, 'getItem').mockReturnValueOnce({ id: 1 }); + + const applyVariableRowHeightsSpy = vi.spyOn(service as any, 'applyVariableRowHeights'); + + service.init(gridStub, container); + const result = await service.exportToExcel({ filename: 'export', useStreamingExport: false, includeVariableRowHeight: true }); + + expect(result).toBe(true); + expect(applyVariableRowHeightsSpy).toHaveBeenCalledTimes(1); + }); + + it('exportToExcel should not call applyVariableRowHeights when includeVariableRowHeight is false', async () => { + const mockGridOptionWithVarHeight = { ...mockGridOptions, enableVariableRowHeight: true } as GridOption; + vi.spyOn(gridStub, 'getOptions').mockReturnValue(mockGridOptionWithVarHeight); + vi.spyOn(gridStub, 'getRowHeight').mockReturnValue(40); + vi.spyOn(gridStub, 'getVisibleColumns').mockReturnValue([{ id: 'id', field: 'id', name: 'ID', width: 100 }] as Column[]); + vi.spyOn(dataViewStub, 'getGrouping').mockReturnValue([]); + vi.spyOn(dataViewStub, 'getLength').mockReturnValue(1); + vi.spyOn(dataViewStub, 'getItem').mockReturnValueOnce({ id: 1 }); + + const applyVariableRowHeightsSpy = vi.spyOn(service as any, 'applyVariableRowHeights'); + + service.init(gridStub, container); + const result = await service.exportToExcel({ filename: 'export', useStreamingExport: false, includeVariableRowHeight: false }); + + expect(result).toBe(true); + expect(applyVariableRowHeightsSpy).not.toHaveBeenCalled(); + }); + + it('applyVariableRowHeights should set row heights when enableVariableRowHeight is true', () => { + const mockGridOptionWithVarHeight = { ...mockGridOptions, enableVariableRowHeight: true } as GridOption; + vi.spyOn(gridStub, 'getOptions').mockReturnValue(mockGridOptionWithVarHeight); + vi.spyOn(gridStub, 'getRowHeight').mockReturnValueOnce(40).mockReturnValueOnce(50).mockReturnValueOnce(60); + vi.spyOn(dataViewStub, 'getLength').mockReturnValue(3); + + const setRowInstructionsSpy = vi.fn(); + (service as any)._sheet = { setRowInstructions: setRowInstructionsSpy }; + (service as any)._excelExportOptions = { includeVariableRowHeight: true }; + (service as any)._hasColumnTitlePreHeader = false; + + service.init(gridStub, container); + (service as any).applyVariableRowHeights(); + + // Excel row starts at 2 (1 for header, +1 for 0-based index) + // 40px * 0.75 = 30pt, 50px * 0.75 = 37.5pt, 60px * 0.75 = 45pt + expect(setRowInstructionsSpy).toHaveBeenCalledWith(2, { height: 30 }); + expect(setRowInstructionsSpy).toHaveBeenCalledWith(3, { height: 37.5 }); + expect(setRowInstructionsSpy).toHaveBeenCalledWith(4, { height: 45 }); + expect(setRowInstructionsSpy).toHaveBeenCalledTimes(3); + }); + + it('applyVariableRowHeights should offset row numbers when hasColumnTitlePreHeader is true', () => { + const mockGridOptionWithVarHeight = { ...mockGridOptions, enableVariableRowHeight: true } as GridOption; + vi.spyOn(gridStub, 'getOptions').mockReturnValue(mockGridOptionWithVarHeight); + vi.spyOn(gridStub, 'getRowHeight').mockReturnValue(40); + vi.spyOn(dataViewStub, 'getLength').mockReturnValue(1); + + const setRowInstructionsSpy = vi.fn(); + (service as any)._sheet = { setRowInstructions: setRowInstructionsSpy }; + (service as any)._excelExportOptions = { includeVariableRowHeight: true }; + (service as any)._hasColumnTitlePreHeader = true; + + service.init(gridStub, container); + (service as any).applyVariableRowHeights(); + + // Excel row starts at 3 (1 for pre-header, 1 for header, +1 for 0-based index) + expect(setRowInstructionsSpy).toHaveBeenCalledWith(3, { height: 30 }); + }); + + it('should convert pixel heights to Excel points correctly (72 DPI)', () => { + const mockGridOptionWithVarHeight = { ...mockGridOptions, enableVariableRowHeight: true } as GridOption; + vi.spyOn(gridStub, 'getOptions').mockReturnValue(mockGridOptionWithVarHeight); + vi.spyOn(gridStub, 'getRowHeight').mockReturnValue(40); + vi.spyOn(dataViewStub, 'getLength').mockReturnValue(1); + + const setRowInstructionsSpy = vi.fn(); + (service as any)._sheet = { setRowInstructions: setRowInstructionsSpy }; + (service as any)._excelExportOptions = { includeVariableRowHeight: true }; + (service as any)._hasColumnTitlePreHeader = false; + + service.init(gridStub, container); + (service as any).applyVariableRowHeights(); + + // 40px * 0.75 = 30pt + expect(setRowInstructionsSpy).toHaveBeenCalledWith(2, { height: 30 }); + }); + }); }); describe('without Translater Service', () => { diff --git a/packages/excel-export/src/excelExport.service.ts b/packages/excel-export/src/excelExport.service.ts index 20776a34f..f6f102638 100644 --- a/packages/excel-export/src/excelExport.service.ts +++ b/packages/excel-export/src/excelExport.service.ts @@ -210,6 +210,12 @@ export class ExcelExportService implements ExternalResource, BaseExcelExportServ } this._sheet.setData(finalOutput); + + // Apply variable row heights if enabled + if (this._gridOptions.enableVariableRowHeight && this._excelExportOptions.includeVariableRowHeight !== false) { + this.applyVariableRowHeights(); + } + this._workbook.addWorksheet(this._sheet); // MIME type could be undefined, if that's the case we'll detect the type by its file extension @@ -650,6 +656,23 @@ export class ExcelExportService implements ExternalResource, BaseExcelExportServ }); } + /** + * Apply variable row heights from grid to Excel sheet when enableVariableRowHeight is enabled. + * Converts pixel heights to Excel points (72 DPI) using formula: pixels * (72/96) = pixels * 0.75 + */ + protected applyVariableRowHeights(): void { + const lineCount = this._dataView.getLength(); + const headerRowOffset = this._hasColumnTitlePreHeader ? 3 : 2; // Offset for pre-header + header rows + + for (let row = 0; row < lineCount; row++) { + const pixelHeight = this._grid.getRowHeight(row); + const excelRowNumber = row + headerRowOffset; + // Convert pixels to Excel points: 72 DPI / 96 DPI = 0.75 + const excelHeight = Math.round(pixelHeight * 0.75 * 100) / 100; // Round to 2 decimal places + this._sheet.setRowInstructions(excelRowNumber, { height: excelHeight }); + } + } + /** * Get the data of a regular row (a row without grouping) * @param {Array} columns - column definitions diff --git a/packages/pdf-export/src/pdfExport.service.spec.ts b/packages/pdf-export/src/pdfExport.service.spec.ts index 053643208..a7ba7c538 100644 --- a/packages/pdf-export/src/pdfExport.service.spec.ts +++ b/packages/pdf-export/src/pdfExport.service.spec.ts @@ -968,6 +968,103 @@ describe('PdfExportService', () => { }); }); + describe('Variable Row Height', () => { + async function createVarHeightService(getRowHeightFn: (row: number) => number) { + vi.resetModules(); + let capturedDidParseCell: ((data: any) => void) | undefined; + const autoTableSpy = vi.fn((opts: any) => { + capturedDidParseCell = opts.didParseCell; + }); + function jsPDFMockVarHeight(this: any) { + this.save = vi.fn(); + this.setFontSize = vi.fn(); + this.getTextWidth = vi.fn((txt: string) => txt.length * 6); + this.internal = { pageSize: { getWidth: () => 595.28, getHeight: () => 841.89 } }; + this.setFillColor = vi.fn(); + this.setTextColor = vi.fn(); + this.rect = vi.fn(); + this.text = vi.fn(); + this.addPage = vi.fn(); + this.autoTable = autoTableSpy; + } + vi.doMock('jspdf', () => ({ __esModule: true, default: jsPDFMockVarHeight })); + const { PdfExportService: Svc } = await import('./pdfExport.service.js'); + const dataViewStub = { + getGrouping: () => [], + getLength: () => 2, + getItem: (idx: number) => ({ id: idx, title: `Task ${idx}` }), + getItemMetadata: vi.fn().mockReturnValue({}), + }; + const gridStub = { + getVisibleColumns: () => [{ id: 'title', field: 'title', name: 'Title', width: 100 }], + getOptions: () => ({ enableVariableRowHeight: true }), + getData: () => dataViewStub, + getRowHeight: getRowHeightFn, + }; + const pubSubService = { publish: vi.fn() }; + const container = { get: () => pubSubService }; + return { Svc, gridStub, container, autoTableSpy, getDidParseCell: () => capturedDidParseCell }; + } + + afterEach(() => { + vi.resetModules(); + }); + + it('should set minCellHeight via didParseCell for body cells (px to pt: px * 0.75)', async () => { + const { Svc, gridStub, container, getDidParseCell } = await createVarHeightService(() => 50); + const service = new Svc(); + service.init(gridStub as any, container as any); + await service.exportToPdf({ filename: 'var-height' }); + + const didParseCell = getDidParseCell(); + expect(didParseCell).toBeDefined(); + + const cell: any = { styles: {} }; + didParseCell!({ section: 'body', row: { index: 0 }, column: { index: 0 }, cell }); + // 50px * 0.75 = 37.5pt + expect(cell.styles.minCellHeight).toBe(37.5); + }); + + it('should NOT set minCellHeight for head cells', async () => { + const { Svc, gridStub, container, getDidParseCell } = await createVarHeightService(() => 50); + const service = new Svc(); + service.init(gridStub as any, container as any); + await service.exportToPdf({ filename: 'var-height-head' }); + + const cell: any = { styles: {} }; + getDidParseCell()!({ section: 'head', row: { index: 0 }, column: { index: 0 }, cell }); + expect(cell.styles.minCellHeight).toBeUndefined(); + }); + + it('should NOT set minCellHeight when includeVariableRowHeight is false', async () => { + const { Svc, gridStub, container, getDidParseCell } = await createVarHeightService(() => 50); + const service = new Svc(); + service.init(gridStub as any, container as any); + await service.exportToPdf({ filename: 'var-height-disabled', includeVariableRowHeight: false }); + + const cell: any = { styles: {} }; + getDidParseCell()!({ section: 'body', row: { index: 0 }, column: { index: 0 }, cell }); + expect(cell.styles.minCellHeight).toBeUndefined(); + }); + + it('should use per-row heights from getRowHeight', async () => { + const heights = [40, 60]; + const { Svc, gridStub, container, getDidParseCell } = await createVarHeightService((row) => heights[row]); + const service = new Svc(); + service.init(gridStub as any, container as any); + await service.exportToPdf({ filename: 'var-height-per-row' }); + + const cell0: any = { styles: {} }; + const cell1: any = { styles: {} }; + const fn = getDidParseCell()!; + fn({ section: 'body', row: { index: 0 }, column: { index: 0 }, cell: cell0 }); + fn({ section: 'body', row: { index: 1 }, column: { index: 0 }, cell: cell1 }); + // 40px * 0.75 = 30pt, 60px * 0.75 = 45pt + expect(cell0.styles.minCellHeight).toBe(30); + expect(cell1.styles.minCellHeight).toBe(45); + }); + }); + describe('without Translater Service', () => { beforeEach(() => { translateService = undefined as any; diff --git a/packages/pdf-export/src/pdfExport.service.ts b/packages/pdf-export/src/pdfExport.service.ts index f43eb3ae6..4ac04fe92 100644 --- a/packages/pdf-export/src/pdfExport.service.ts +++ b/packages/pdf-export/src/pdfExport.service.ts @@ -259,6 +259,14 @@ export class PdfExportService implements ExternalResource, BasePdfExportService if (data.section === 'head' && isColumnHeaderRow && headerAlignMap[data.column.index]) { data.cell.styles.halign = headerAlignMap[data.column.index]; } + // Apply variable row height as minCellHeight (px → pt: pixels * 0.75) + if ( + data.section === 'body' && + this._gridOptions.enableVariableRowHeight && + this._exportOptions.includeVariableRowHeight !== false + ) { + data.cell.styles.minCellHeight = this._grid.getRowHeight(data.row.index) * 0.75; + } }, alternateRowStyles: { fillColor: this._exportOptions.alternateRowColor!, @@ -284,8 +292,10 @@ export class PdfExportService implements ExternalResource, BasePdfExportService const pageHeight = doc.internal.pageSize.getHeight(); const pageWidth = doc.internal.pageSize.getWidth(); const bottomMargin = 40; - const rowHeight = 18; + const defaultRowHeight = 18; const margin = 40; + const useVariableRowHeight = + this._gridOptions.enableVariableRowHeight && this._exportOptions.includeVariableRowHeight !== false; // Dynamically calculate table width based on page width and margins const tableWidth = pageWidth - margin * 2; const colCount = headers.length; @@ -351,6 +361,8 @@ export class PdfExportService implements ExternalResource, BasePdfExportService y = this._drawHeaderRow(doc, y, headers, colWidths, margin, headerTextOffset, headerBackgroundOffset, headerAligns); doc.setFontSize(this._exportOptions.fontSize || 10); data.forEach((row, rowIdx) => { + // px → pt: pixels * 0.75; fall back to default when not in variable-height mode + const rowHeight = useVariableRowHeight ? Math.round(this._grid.getRowHeight(rowIdx) * 0.75 * 100) / 100 : defaultRowHeight; // Check for page break before drawing row if (y + rowHeight + bottomMargin > pageHeight) { doc.addPage();