@mui/x-data-grid-premium 7.26.0 → 7.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/DataGridPremium/DataGridPremium.js +6 -0
  3. package/DataGridPremium/useDataGridPremiumComponent.js +1 -1
  4. package/esm/DataGridPremium/DataGridPremium.js +6 -0
  5. package/esm/DataGridPremium/useDataGridPremiumComponent.js +1 -1
  6. package/esm/hooks/features/clipboard/useGridClipboardImport.js +2 -2
  7. package/esm/hooks/features/export/index.js +1 -1
  8. package/esm/hooks/features/export/serializer/excelSerializer.js +69 -180
  9. package/esm/hooks/features/export/serializer/setupExcelExportWebWorker.js +53 -0
  10. package/esm/hooks/features/export/serializer/utils.js +93 -0
  11. package/esm/hooks/features/export/useGridExcelExport.js +11 -5
  12. package/esm/setupExcelExportWebWorker.js +1 -0
  13. package/esm/utils/releaseInfo.js +1 -1
  14. package/hooks/features/clipboard/useGridClipboardImport.js +2 -2
  15. package/hooks/features/export/index.d.ts +1 -1
  16. package/hooks/features/export/index.js +2 -2
  17. package/hooks/features/export/serializer/excelSerializer.d.ts +3 -31
  18. package/hooks/features/export/serializer/excelSerializer.js +74 -187
  19. package/hooks/features/export/serializer/setupExcelExportWebWorker.d.ts +2 -0
  20. package/hooks/features/export/serializer/setupExcelExportWebWorker.js +59 -0
  21. package/hooks/features/export/serializer/utils.d.ts +36 -0
  22. package/hooks/features/export/serializer/utils.js +106 -0
  23. package/hooks/features/export/useGridExcelExport.js +10 -3
  24. package/index.js +1 -1
  25. package/modern/DataGridPremium/DataGridPremium.js +6 -0
  26. package/modern/DataGridPremium/useDataGridPremiumComponent.js +1 -1
  27. package/modern/hooks/features/clipboard/useGridClipboardImport.js +2 -2
  28. package/modern/hooks/features/export/index.js +1 -1
  29. package/modern/hooks/features/export/serializer/excelSerializer.js +69 -180
  30. package/modern/hooks/features/export/serializer/setupExcelExportWebWorker.js +53 -0
  31. package/modern/hooks/features/export/serializer/utils.js +93 -0
  32. package/modern/hooks/features/export/useGridExcelExport.js +11 -5
  33. package/modern/index.js +1 -1
  34. package/modern/setupExcelExportWebWorker.js +1 -0
  35. package/modern/utils/releaseInfo.js +1 -1
  36. package/package.json +3 -3
  37. package/setupExcelExportWebWorker.d.ts +1 -0
  38. package/setupExcelExportWebWorker.js +12 -0
  39. package/utils/releaseInfo.js +1 -1
@@ -5,7 +5,7 @@ import { useGridApiMethod, useGridLogger, useGridApiOptionHandler } from '@mui/x
5
5
  import { useGridRegisterPipeProcessor, exportAs, getColumnsToExport, defaultGetRowsToExport } from '@mui/x-data-grid/internals';
6
6
  import { buildExcel, getDataForValueOptionsSheet, serializeColumns, serializeRowUnsafe } from "./serializer/excelSerializer.js";
7
7
  import { GridExcelExportMenuItem } from "../../../components/index.js";
8
-
8
+ import { jsx as _jsx } from "react/jsx-runtime";
9
9
  /**
10
10
  * @requires useGridColumns (state)
11
11
  * @requires useGridFilter (state)
@@ -13,7 +13,6 @@ import { GridExcelExportMenuItem } from "../../../components/index.js";
13
13
  * @requires useGridSelection (state)
14
14
  * @requires useGridParamsApi (method)
15
15
  */
16
- import { jsx as _jsx } from "react/jsx-runtime";
17
16
  export const useGridExcelExport = (apiRef, props) => {
18
17
  const logger = useGridLogger(apiRef, 'useGridExcelExport');
19
18
  const getDataAsExcel = React.useCallback((options = {}) => {
@@ -89,15 +88,22 @@ export const useGridExcelExport = (apiRef, props) => {
89
88
  const valueOptionsData = await getDataForValueOptionsSheet(exportedColumns, valueOptionsSheetName, apiRef.current);
90
89
  const serializedColumns = serializeColumns(exportedColumns, options.columnsStyles || {});
91
90
  apiRef.current.resetColSpan();
92
- const serializedRows = exportedRowIds.map(id => serializeRowUnsafe(id, exportedColumns, apiRef, valueOptionsData, {
93
- escapeFormulas: options.escapeFormulas ?? true
94
- }));
91
+ const serializedRows = [];
92
+ for (let i = 0; i < exportedRowIds.length; i += 1) {
93
+ const id = exportedRowIds[i];
94
+ const serializedRow = serializeRowUnsafe(id, exportedColumns, apiRef, valueOptionsData, {
95
+ escapeFormulas: options.escapeFormulas ?? true
96
+ });
97
+ serializedRows.push(serializedRow);
98
+ }
95
99
  apiRef.current.resetColSpan();
96
100
  const columnGroupPaths = exportedColumns.reduce((acc, column) => {
97
101
  acc[column.field] = apiRef.current.getColumnGroupPath(column.field);
98
102
  return acc;
99
103
  }, {});
100
104
  const message = {
105
+ // workers share the pub-sub channel namespace. Use this property to filter out messages.
106
+ namespace: 'mui-x-data-grid-export',
101
107
  serializedColumns,
102
108
  serializedRows,
103
109
  valueOptionsData,
@@ -0,0 +1 @@
1
+ export { setupExcelExportWebWorker } from "./hooks/features/export/serializer/setupExcelExportWebWorker.js";
@@ -1,6 +1,6 @@
1
1
  import { ponyfillGlobal } from '@mui/utils';
2
2
  export const getReleaseInfo = () => {
3
- const releaseInfo = "MTczODg4MjgwMDAwMA==";
3
+ const releaseInfo = "MTczOTc0NjgwMDAwMA==";
4
4
  if (process.env.NODE_ENV !== 'production') {
5
5
  // A simple hack to set the value in the test environment (has no build step).
6
6
  // eslint-disable-next-line no-useless-concat
@@ -263,7 +263,6 @@ const useGridClipboardImport = (apiRef, props) => {
263
263
  const onProcessRowUpdateError = props.onProcessRowUpdateError;
264
264
  const getRowId = props.getRowId;
265
265
  const enableClipboardPaste = !props.disableClipboardPaste;
266
- const rootEl = apiRef.current.rootElementRef?.current;
267
266
  const logger = (0, _internals.useGridLogger)(apiRef, 'useGridClipboardImport');
268
267
  const splitClipboardPastedText = props.splitClipboardPastedText;
269
268
  const {
@@ -286,6 +285,7 @@ const useGridClipboardImport = (apiRef, props) => {
286
285
  return;
287
286
  }
288
287
  }
288
+ const rootEl = apiRef.current.rootElementRef?.current;
289
289
  if (!rootEl) {
290
290
  return;
291
291
  }
@@ -326,7 +326,7 @@ const useGridClipboardImport = (apiRef, props) => {
326
326
  paginationMode
327
327
  });
328
328
  cellUpdater.applyUpdates();
329
- }, [apiRef, processRowUpdate, onProcessRowUpdateError, getRowId, enableClipboardPaste, rootEl, splitClipboardPastedText, pagination, paginationMode, onBeforeClipboardPasteStart, logger]);
329
+ }, [apiRef, processRowUpdate, onProcessRowUpdateError, getRowId, enableClipboardPaste, splitClipboardPastedText, pagination, paginationMode, onBeforeClipboardPasteStart, logger]);
330
330
  const checkIfCanStartEditing = React.useCallback((initialValue, {
331
331
  event
332
332
  }) => {
@@ -1,2 +1,2 @@
1
1
  export * from './gridExcelExportInterface';
2
- export { setupExcelExportWebWorker } from './serializer/excelSerializer';
2
+ export { setupExcelExportWebWorker } from './serializer/setupExcelExportWebWorker';
@@ -9,7 +9,7 @@ var _exportNames = {
9
9
  Object.defineProperty(exports, "setupExcelExportWebWorker", {
10
10
  enumerable: true,
11
11
  get: function () {
12
- return _excelSerializer.setupExcelExportWebWorker;
12
+ return _setupExcelExportWebWorker.setupExcelExportWebWorker;
13
13
  }
14
14
  });
15
15
  var _gridExcelExportInterface = require("./gridExcelExportInterface");
@@ -24,4 +24,4 @@ Object.keys(_gridExcelExportInterface).forEach(function (key) {
24
24
  }
25
25
  });
26
26
  });
27
- var _excelSerializer = require("./serializer/excelSerializer");
27
+ var _setupExcelExportWebWorker = require("./serializer/setupExcelExportWebWorker");
@@ -1,18 +1,11 @@
1
1
  import type * as Excel from 'exceljs';
2
2
  import { RefObject } from '@mui/x-internals/types';
3
3
  import { GridRowId, GridColDef } from '@mui/x-data-grid-pro';
4
- import { GridStateColDef, GridColumnGroupLookup } from '@mui/x-data-grid/internals';
4
+ import { GridStateColDef } from '@mui/x-data-grid/internals';
5
5
  import { ColumnsStylesInterface, GridExcelExportOptions } from '../gridExcelExportInterface';
6
6
  import { GridPrivateApiPremium } from '../../../../models/gridApiPremium';
7
- interface SerializedRow {
8
- row: Record<string, undefined | number | boolean | string | Date>;
9
- dataValidation: Record<string, Excel.DataValidation>;
10
- outlineLevel: number;
11
- mergedCells: {
12
- leftIndex: number;
13
- rightIndex: number;
14
- }[];
15
- }
7
+ import { SerializedColumns, SerializedRow, ValueOptionsData } from './utils';
8
+ export type { ExcelExportInitEvent } from './utils';
16
9
  /**
17
10
  * FIXME: This function mutates the colspan info, but colspan info assumes that the columns
18
11
  * passed to it are always consistent. In this case, the exported columns may differ from the
@@ -37,17 +30,7 @@ export declare const serializeColumn: (column: GridColDef, columnsStyles: Column
37
30
  fill?: Excel.Fill | undefined;
38
31
  };
39
32
  };
40
- type SerializedColumns = Array<{
41
- key: string;
42
- width: number;
43
- style: Partial<Excel.Style>;
44
- headerText: string;
45
- }>;
46
33
  export declare function serializeColumns(columns: GridStateColDef[], styles: ColumnsStylesInterface): SerializedColumns;
47
- type ValueOptionsData = Record<string, {
48
- values: (string | number)[];
49
- address: string;
50
- }>;
51
34
  export declare function getDataForValueOptionsSheet(columns: GridStateColDef[], valueOptionsSheetName: string, api: GridPrivateApiPremium): Promise<ValueOptionsData>;
52
35
  interface BuildExcelOptions extends Pick<GridExcelExportOptions, 'exceljsPreProcess' | 'exceljsPostProcess'>, Pick<Required<GridExcelExportOptions>, 'valueOptionsSheetName' | 'includeHeaders' | 'includeColumnGroupsHeaders' | 'escapeFormulas'> {
53
36
  columns: GridStateColDef[];
@@ -55,14 +38,3 @@ interface BuildExcelOptions extends Pick<GridExcelExportOptions, 'exceljsPreProc
55
38
  columnsStyles?: ColumnsStylesInterface;
56
39
  }
57
40
  export declare function buildExcel(options: BuildExcelOptions, apiRef: RefObject<GridPrivateApiPremium>): Promise<Excel.Workbook>;
58
- export interface ExcelExportInitEvent {
59
- serializedColumns: SerializedColumns;
60
- serializedRows: SerializedRow[];
61
- valueOptionsSheetName: string;
62
- columnGroupPaths: Record<string, string[]>;
63
- columnGroupDetails: GridColumnGroupLookup;
64
- valueOptionsData: ValueOptionsData;
65
- options: Omit<GridExcelExportOptions, 'exceljsPreProcess' | 'exceljsPostProcess' | 'columnsStyles' | 'valueOptionsSheetName'>;
66
- }
67
- export declare function setupExcelExportWebWorker(workerOptions?: Pick<GridExcelExportOptions, 'exceljsPostProcess' | 'exceljsPreProcess'>): void;
68
- export {};
@@ -9,33 +9,36 @@ exports.getDataForValueOptionsSheet = getDataForValueOptionsSheet;
9
9
  exports.serializeColumn = void 0;
10
10
  exports.serializeColumns = serializeColumns;
11
11
  exports.serializeRowUnsafe = void 0;
12
- exports.setupExcelExportWebWorker = setupExcelExportWebWorker;
13
12
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
14
- var _interopRequireWildcard2 = _interopRequireDefault(require("@babel/runtime/helpers/interopRequireWildcard"));
15
13
  var _xDataGridPro = require("@mui/x-data-grid-pro");
16
14
  var _internals = require("@mui/x-data-grid/internals");
17
15
  var _warning = require("@mui/x-internals/warning");
18
- const getExcelJs = async () => {
19
- const excelJsModule = await Promise.resolve().then(() => (0, _interopRequireWildcard2.default)(require('exceljs')));
20
- return excelJsModule.default ?? excelJsModule;
21
- };
22
- const getFormattedValueOptions = (colDef, row, valueOptions, api) => {
16
+ var _utils = require("./utils");
17
+ const getFormattedValueOptions = (colDef, row, valueOptions, api, callback) => {
23
18
  if (!colDef.valueOptions) {
24
- return [];
19
+ return;
25
20
  }
26
- let valueOptionsFormatted = valueOptions;
27
- if (colDef.valueFormatter) {
28
- valueOptionsFormatted = valueOptionsFormatted.map(option => {
21
+ const valueFormatter = colDef.valueFormatter;
22
+ for (let i = 0; i < valueOptions.length; i += 1) {
23
+ const option = valueOptions[i];
24
+ let value;
25
+ if (valueFormatter) {
29
26
  if (typeof option === 'object') {
30
- return option;
27
+ value = option.label;
28
+ } else {
29
+ value = String(colDef.valueFormatter(option, row, colDef, {
30
+ current: api
31
+ }));
31
32
  }
32
- return String(colDef.valueFormatter(option, row, colDef, {
33
- current: api
34
- }));
35
- });
33
+ } else {
34
+ value = typeof option === 'object' ? option.label : option;
35
+ }
36
+ callback(value, i);
36
37
  }
37
- return valueOptionsFormatted.map(option => typeof option === 'object' ? option.label : option);
38
38
  };
39
+ const commaRegex = /,/g;
40
+ const commaReplacement = 'CHAR(44)';
41
+
39
42
  /**
40
43
  * FIXME: This function mutates the colspan info, but colspan info assumes that the columns
41
44
  * passed to it are always consistent. In this case, the exported columns may differ from the
@@ -43,11 +46,15 @@ const getFormattedValueOptions = (colDef, row, valueOptions, api) => {
43
46
  * The caller of this function MUST call `resetColSpan()` before and after usage.
44
47
  */
45
48
  const serializeRowUnsafe = (id, columns, apiRef, defaultValueOptionsFormulae, options) => {
46
- const row = {};
49
+ const serializedRow = {};
47
50
  const dataValidation = {};
48
51
  const mergedCells = [];
49
- const firstCellParams = apiRef.current.getCellParams(id, columns[0].field);
50
- const outlineLevel = firstCellParams.rowNode.depth;
52
+ const row = apiRef.current.getRow(id);
53
+ const rowNode = apiRef.current.getRowNode(id);
54
+ if (!row || !rowNode) {
55
+ throw new Error(`No row with id #${id} found`);
56
+ }
57
+ const outlineLevel = rowNode.depth;
51
58
  const hasColSpan = (0, _internals.gridHasColSpanSelector)(apiRef);
52
59
  if (hasColSpan) {
53
60
  // `colSpan` is only calculated for rendered rows, so we need to calculate it during export for every row
@@ -69,25 +76,32 @@ const serializeRowUnsafe = (id, columns, apiRef, defaultValueOptionsFormulae, op
69
76
  rightIndex: colIndex + colSpanInfo.cellProps.colSpan
70
77
  });
71
78
  }
72
- const cellParams = apiRef.current.getCellParams(id, column.field);
73
79
  let cellValue;
74
- switch (cellParams.colDef.type) {
80
+ switch (column.type) {
75
81
  case 'singleSelect':
76
82
  {
77
- const castColumn = cellParams.colDef;
83
+ const castColumn = column;
78
84
  if (typeof castColumn.valueOptions === 'function') {
79
85
  // If value option depends on the row, set specific options to the cell
80
86
  // This dataValidation is buggy with LibreOffice and does not allow to have coma
81
87
  const valueOptions = castColumn.valueOptions({
82
88
  id,
83
89
  row,
84
- field: cellParams.field
90
+ field: column.field
91
+ });
92
+ let formulae = '"';
93
+ getFormattedValueOptions(castColumn, row, valueOptions, apiRef.current, (value, index) => {
94
+ const formatted = value.toString().replace(commaRegex, commaReplacement);
95
+ formulae += formatted;
96
+ if (index < valueOptions.length - 1) {
97
+ formulae += ',';
98
+ }
85
99
  });
86
- const formattedValueOptions = getFormattedValueOptions(castColumn, row, valueOptions, apiRef.current);
100
+ formulae += '"';
87
101
  dataValidation[castColumn.field] = {
88
102
  type: 'list',
89
103
  allowBlank: true,
90
- formulae: [`"${formattedValueOptions.map(x => x.toString().replaceAll(',', 'CHAR(44)')).join(',')}"`]
104
+ formulae: [formulae]
91
105
  };
92
106
  } else {
93
107
  const address = defaultValueOptionsFormulae[column.field].address;
@@ -99,22 +113,22 @@ const serializeRowUnsafe = (id, columns, apiRef, defaultValueOptionsFormulae, op
99
113
  formulae: [address]
100
114
  };
101
115
  }
102
- const formattedValue = apiRef.current.getCellParams(id, castColumn.field).formattedValue;
116
+ const formattedValue = apiRef.current.getRowFormattedValue(row, castColumn);
103
117
  if (process.env.NODE_ENV !== 'production') {
104
- if (String(cellParams.formattedValue) === '[object Object]') {
118
+ if (String(formattedValue) === '[object Object]') {
105
119
  (0, _warning.warnOnce)(['MUI X: When the value of a field is an object or a `renderCell` is provided, the Excel export might not display the value correctly.', 'You can provide a `valueFormatter` with a string representation to be used.']);
106
120
  }
107
121
  }
108
122
  if ((0, _internals.isObject)(formattedValue)) {
109
- row[castColumn.field] = formattedValue?.label;
123
+ serializedRow[castColumn.field] = formattedValue?.label;
110
124
  } else {
111
- row[castColumn.field] = formattedValue;
125
+ serializedRow[castColumn.field] = formattedValue;
112
126
  }
113
127
  break;
114
128
  }
115
129
  case 'boolean':
116
130
  case 'number':
117
- cellValue = apiRef.current.getCellParams(id, column.field).value;
131
+ cellValue = apiRef.current.getRowValue(row, column);
118
132
  break;
119
133
  case 'date':
120
134
  case 'dateTime':
@@ -122,21 +136,21 @@ const serializeRowUnsafe = (id, columns, apiRef, defaultValueOptionsFormulae, op
122
136
  // Excel does not do any timezone conversion, so we create a date using UTC instead of local timezone
123
137
  // Solution from: https://github.com/exceljs/exceljs/issues/486#issuecomment-432557582
124
138
  // About Date.UTC(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/UTC#exemples
125
- const value = apiRef.current.getCellParams(id, column.field).value;
139
+ const value = apiRef.current.getRowValue(row, column);
126
140
  // value may be `undefined` in auto-generated grouping rows
127
141
  if (!value) {
128
142
  break;
129
143
  }
130
144
  const utcDate = new Date(Date.UTC(value.getFullYear(), value.getMonth(), value.getDate(), value.getHours(), value.getMinutes(), value.getSeconds()));
131
- row[column.field] = utcDate;
145
+ serializedRow[column.field] = utcDate;
132
146
  break;
133
147
  }
134
148
  case 'actions':
135
149
  break;
136
150
  default:
137
- cellValue = apiRef.current.getCellParams(id, column.field).formattedValue;
151
+ cellValue = apiRef.current.getRowFormattedValue(row, column);
138
152
  if (process.env.NODE_ENV !== 'production') {
139
- if (String(cellParams.formattedValue) === '[object Object]') {
153
+ if (String(cellValue) === '[object Object]') {
140
154
  (0, _warning.warnOnce)(['MUI X: When the value of a field is an object or a `renderCell` is provided, the Excel export might not display the value correctly.', 'You can provide a `valueFormatter` with a string representation to be used.']);
141
155
  }
142
156
  }
@@ -149,11 +163,11 @@ const serializeRowUnsafe = (id, columns, apiRef, defaultValueOptionsFormulae, op
149
163
  }
150
164
  }
151
165
  if (typeof cellValue !== 'undefined') {
152
- row[column.field] = cellValue;
166
+ serializedRow[column.field] = cellValue;
153
167
  }
154
168
  });
155
169
  return {
156
- row,
170
+ row: serializedRow,
157
171
  dataValidation,
158
172
  outlineLevel,
159
173
  mergedCells
@@ -184,120 +198,39 @@ const serializeColumn = (column, columnsStyles) => {
184
198
  };
185
199
  };
186
200
  exports.serializeColumn = serializeColumn;
187
- const addColumnGroupingHeaders = (worksheet, columns, columnGroupPaths, columnGroupDetails) => {
188
- const maxDepth = Math.max(...columns.map(({
189
- key
190
- }) => columnGroupPaths[key]?.length ?? 0));
191
- if (maxDepth === 0) {
192
- return;
193
- }
194
- for (let rowIndex = 0; rowIndex < maxDepth; rowIndex += 1) {
195
- const row = columns.map(({
196
- key
197
- }) => {
198
- const groupingPath = columnGroupPaths[key];
199
- if (groupingPath.length <= rowIndex) {
200
- return {
201
- groupId: null,
202
- parents: groupingPath
203
- };
204
- }
205
- return (0, _extends2.default)({}, columnGroupDetails[groupingPath[rowIndex]], {
206
- parents: groupingPath.slice(0, rowIndex)
207
- });
208
- });
209
- const newRow = worksheet.addRow(row.map(group => group.groupId === null ? null : group?.headerName ?? group.groupId));
210
-
211
- // use `rowCount`, since worksheet can have additional rows added in `exceljsPreProcess`
212
- const lastRowIndex = newRow.worksheet.rowCount;
213
- let leftIndex = 0;
214
- let rightIndex = 1;
215
- while (rightIndex < columns.length) {
216
- const {
217
- groupId: leftGroupId,
218
- parents: leftParents
219
- } = row[leftIndex];
220
- const {
221
- groupId: rightGroupId,
222
- parents: rightParents
223
- } = row[rightIndex];
224
- const areInSameGroup = leftGroupId === rightGroupId && leftParents.length === rightParents.length && leftParents.every((leftParent, index) => rightParents[index] === leftParent);
225
- if (areInSameGroup) {
226
- rightIndex += 1;
227
- } else {
228
- if (rightIndex - leftIndex > 1) {
229
- worksheet.mergeCells(lastRowIndex, leftIndex + 1, lastRowIndex, rightIndex);
230
- }
231
- leftIndex = rightIndex;
232
- rightIndex += 1;
233
- }
234
- }
235
- if (rightIndex - leftIndex > 1) {
236
- worksheet.mergeCells(lastRowIndex, leftIndex + 1, lastRowIndex, rightIndex);
237
- }
238
- }
239
- };
240
201
  function serializeColumns(columns, styles) {
241
202
  return columns.map(column => serializeColumn(column, styles));
242
203
  }
243
204
  async function getDataForValueOptionsSheet(columns, valueOptionsSheetName, api) {
244
- const candidateColumns = columns.filter(column => (0, _internals.isSingleSelectColDef)(column) && Array.isArray(column.valueOptions));
245
-
246
205
  // Creates a temp worksheet to obtain the column letters
247
- const excelJS = await getExcelJs();
206
+ const excelJS = await (0, _utils.getExcelJs)();
248
207
  const workbook = new excelJS.Workbook();
249
208
  const worksheet = workbook.addWorksheet('Sheet1');
250
- worksheet.columns = candidateColumns.map(column => ({
251
- key: column.field
252
- }));
253
- return candidateColumns.reduce((acc, column) => {
254
- const singleSelectColumn = column;
255
- const formattedValueOptions = getFormattedValueOptions(singleSelectColumn, {}, singleSelectColumn.valueOptions, api);
209
+ const record = {};
210
+ const worksheetColumns = [];
211
+ for (let i = 0; i < columns.length; i += 1) {
212
+ const column = columns[i];
213
+ const isCandidateColumn = (0, _internals.isSingleSelectColDef)(column) && Array.isArray(column.valueOptions);
214
+ if (!isCandidateColumn) {
215
+ continue;
216
+ }
217
+ worksheetColumns.push({
218
+ key: column.field
219
+ });
220
+ worksheet.columns = worksheetColumns;
256
221
  const header = column.headerName ?? column.field;
257
- const values = [header, ...formattedValueOptions];
222
+ const values = [header];
223
+ getFormattedValueOptions(column, {}, column.valueOptions, api, value => {
224
+ values.push(value);
225
+ });
258
226
  const letter = worksheet.getColumn(column.field).letter;
259
227
  const address = `${valueOptionsSheetName}!$${letter}$2:$${letter}$${values.length}`;
260
- acc[column.field] = {
228
+ record[column.field] = {
261
229
  values,
262
230
  address
263
231
  };
264
- return acc;
265
- }, {});
266
- }
267
- function addSerializedRowToWorksheet(serializedRow, worksheet) {
268
- const {
269
- row,
270
- dataValidation,
271
- outlineLevel,
272
- mergedCells
273
- } = serializedRow;
274
- const newRow = worksheet.addRow(row);
275
- Object.keys(dataValidation).forEach(field => {
276
- newRow.getCell(field).dataValidation = (0, _extends2.default)({}, dataValidation[field]);
277
- });
278
- if (outlineLevel) {
279
- newRow.outlineLevel = outlineLevel;
280
232
  }
281
-
282
- // use `rowCount`, since worksheet can have additional rows added in `exceljsPreProcess`
283
- const lastRowIndex = newRow.worksheet.rowCount;
284
- mergedCells.forEach(mergedCell => {
285
- worksheet.mergeCells(lastRowIndex, mergedCell.leftIndex, lastRowIndex, mergedCell.rightIndex);
286
- });
287
- }
288
- async function createValueOptionsSheetIfNeeded(valueOptionsData, sheetName, workbook) {
289
- if (Object.keys(valueOptionsData).length === 0) {
290
- return;
291
- }
292
- const valueOptionsWorksheet = workbook.addWorksheet(sheetName);
293
- valueOptionsWorksheet.columns = Object.keys(valueOptionsData).map(key => ({
294
- key
295
- }));
296
- Object.entries(valueOptionsData).forEach(([field, {
297
- values
298
- }]) => {
299
- valueOptionsWorksheet.getColumn(field).values = values;
300
- });
233
+ return record;
301
234
  }
302
235
  async function buildExcel(options, apiRef) {
303
236
  const {
@@ -310,7 +243,7 @@ async function buildExcel(options, apiRef) {
310
243
  exceljsPostProcess,
311
244
  columnsStyles = {}
312
245
  } = options;
313
- const excelJS = await getExcelJs();
246
+ const excelJS = await (0, _utils.getExcelJs)();
314
247
  const workbook = new excelJS.Workbook();
315
248
  const worksheet = workbook.addWorksheet('Sheet1');
316
249
  const serializedColumns = serializeColumns(columns, columnsStyles);
@@ -326,17 +259,17 @@ async function buildExcel(options, apiRef) {
326
259
  acc[column.field] = apiRef.current.getColumnGroupPath(column.field);
327
260
  return acc;
328
261
  }, {});
329
- addColumnGroupingHeaders(worksheet, serializedColumns, columnGroupPaths, apiRef.current.getAllGroupDetails());
262
+ (0, _utils.addColumnGroupingHeaders)(worksheet, serializedColumns, columnGroupPaths, apiRef.current.getAllGroupDetails());
330
263
  }
331
264
  if (includeHeaders) {
332
265
  worksheet.addRow(columns.map(column => column.headerName ?? column.field));
333
266
  }
334
267
  const valueOptionsData = await getDataForValueOptionsSheet(columns, valueOptionsSheetName, apiRef.current);
335
- createValueOptionsSheetIfNeeded(valueOptionsData, valueOptionsSheetName, workbook);
268
+ (0, _utils.createValueOptionsSheetIfNeeded)(valueOptionsData, valueOptionsSheetName, workbook);
336
269
  apiRef.current.resetColSpan();
337
270
  rowIds.forEach(id => {
338
271
  const serializedRow = serializeRowUnsafe(id, columns, apiRef, valueOptionsData, options);
339
- addSerializedRowToWorksheet(serializedRow, worksheet);
272
+ (0, _utils.addSerializedRowToWorksheet)(serializedRow, worksheet);
340
273
  });
341
274
  apiRef.current.resetColSpan();
342
275
  if (exceljsPostProcess) {
@@ -346,50 +279,4 @@ async function buildExcel(options, apiRef) {
346
279
  });
347
280
  }
348
281
  return workbook;
349
- }
350
- function setupExcelExportWebWorker(workerOptions = {}) {
351
- // eslint-disable-next-line no-restricted-globals
352
- addEventListener('message', async event => {
353
- const {
354
- serializedColumns,
355
- serializedRows,
356
- options,
357
- valueOptionsSheetName,
358
- valueOptionsData,
359
- columnGroupDetails,
360
- columnGroupPaths
361
- } = event.data;
362
- const {
363
- exceljsPostProcess,
364
- exceljsPreProcess
365
- } = workerOptions;
366
- const excelJS = await getExcelJs();
367
- const workbook = new excelJS.Workbook();
368
- const worksheet = workbook.addWorksheet('Sheet1');
369
- worksheet.columns = serializedColumns;
370
- if (exceljsPreProcess) {
371
- await exceljsPreProcess({
372
- workbook,
373
- worksheet
374
- });
375
- }
376
- if (options.includeColumnGroupsHeaders) {
377
- addColumnGroupingHeaders(worksheet, serializedColumns, columnGroupPaths, columnGroupDetails);
378
- }
379
- const includeHeaders = options.includeHeaders ?? true;
380
- if (includeHeaders) {
381
- worksheet.addRow(serializedColumns.map(column => column.headerText));
382
- }
383
- createValueOptionsSheetIfNeeded(valueOptionsData, valueOptionsSheetName, workbook);
384
- serializedRows.forEach(serializedRow => {
385
- addSerializedRowToWorksheet(serializedRow, worksheet);
386
- });
387
- if (exceljsPostProcess) {
388
- await exceljsPostProcess({
389
- workbook,
390
- worksheet
391
- });
392
- }
393
- postMessage(await workbook.xlsx.writeBuffer());
394
- });
395
282
  }
@@ -0,0 +1,2 @@
1
+ import type { GridExcelExportOptions } from '../gridExcelExportInterface';
2
+ export declare function setupExcelExportWebWorker(workerOptions?: Pick<GridExcelExportOptions, 'exceljsPostProcess' | 'exceljsPreProcess'>): void;
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.setupExcelExportWebWorker = setupExcelExportWebWorker;
7
+ var _utils = require("./utils");
8
+ function setupExcelExportWebWorker(workerOptions = {}) {
9
+ // eslint-disable-next-line no-restricted-globals
10
+ addEventListener('message', async event => {
11
+ const {
12
+ namespace,
13
+ serializedColumns,
14
+ serializedRows,
15
+ options,
16
+ valueOptionsSheetName,
17
+ valueOptionsData,
18
+ columnGroupDetails,
19
+ columnGroupPaths
20
+ } = event.data;
21
+
22
+ // workers share the pub-sub channel namespace. Use this property to filter out messages.
23
+ if (namespace !== 'mui-x-data-grid-export') {
24
+ return;
25
+ }
26
+ const {
27
+ exceljsPostProcess,
28
+ exceljsPreProcess
29
+ } = workerOptions;
30
+ const excelJS = await (0, _utils.getExcelJs)();
31
+ const workbook = new excelJS.Workbook();
32
+ const worksheet = workbook.addWorksheet('Sheet1');
33
+ worksheet.columns = serializedColumns;
34
+ if (exceljsPreProcess) {
35
+ await exceljsPreProcess({
36
+ workbook,
37
+ worksheet
38
+ });
39
+ }
40
+ if (options.includeColumnGroupsHeaders) {
41
+ (0, _utils.addColumnGroupingHeaders)(worksheet, serializedColumns, columnGroupPaths, columnGroupDetails);
42
+ }
43
+ const includeHeaders = options.includeHeaders ?? true;
44
+ if (includeHeaders) {
45
+ worksheet.addRow(serializedColumns.map(column => column.headerText));
46
+ }
47
+ (0, _utils.createValueOptionsSheetIfNeeded)(valueOptionsData, valueOptionsSheetName, workbook);
48
+ serializedRows.forEach(serializedRow => {
49
+ (0, _utils.addSerializedRowToWorksheet)(serializedRow, worksheet);
50
+ });
51
+ if (exceljsPostProcess) {
52
+ await exceljsPostProcess({
53
+ workbook,
54
+ worksheet
55
+ });
56
+ }
57
+ postMessage(await workbook.xlsx.writeBuffer());
58
+ });
59
+ }
@@ -0,0 +1,36 @@
1
+ import type * as Excel from 'exceljs';
2
+ import type { GridColumnGroupLookup } from '@mui/x-data-grid/internals';
3
+ import type { GridExcelExportOptions } from '../gridExcelExportInterface';
4
+ export declare const getExcelJs: () => Promise<typeof Excel>;
5
+ export interface SerializedRow {
6
+ row: Record<string, undefined | number | boolean | string | Date>;
7
+ dataValidation: Record<string, Excel.DataValidation>;
8
+ outlineLevel: number;
9
+ mergedCells: {
10
+ leftIndex: number;
11
+ rightIndex: number;
12
+ }[];
13
+ }
14
+ export declare const addColumnGroupingHeaders: (worksheet: Excel.Worksheet, columns: SerializedColumns, columnGroupPaths: Record<string, string[]>, columnGroupDetails: GridColumnGroupLookup) => void;
15
+ export type SerializedColumns = Array<{
16
+ key: string;
17
+ width: number;
18
+ style: Partial<Excel.Style>;
19
+ headerText: string;
20
+ }>;
21
+ export type ValueOptionsData = Record<string, {
22
+ values: (string | number)[];
23
+ address: string;
24
+ }>;
25
+ export declare function addSerializedRowToWorksheet(serializedRow: SerializedRow, worksheet: Excel.Worksheet): void;
26
+ export declare function createValueOptionsSheetIfNeeded(valueOptionsData: ValueOptionsData, sheetName: string, workbook: Excel.Workbook): Promise<void>;
27
+ export interface ExcelExportInitEvent {
28
+ namespace?: string;
29
+ serializedColumns: SerializedColumns;
30
+ serializedRows: SerializedRow[];
31
+ valueOptionsSheetName: string;
32
+ columnGroupPaths: Record<string, string[]>;
33
+ columnGroupDetails: GridColumnGroupLookup;
34
+ valueOptionsData: ValueOptionsData;
35
+ options: Omit<GridExcelExportOptions, 'exceljsPreProcess' | 'exceljsPostProcess' | 'columnsStyles' | 'valueOptionsSheetName'>;
36
+ }