@sme.up/doc-alchemist 1.8.1 → 1.8.3
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.
- package/dist/converters/excel/commons.d.ts +23 -0
- package/dist/converters/excel/commons.js +53 -1
- package/dist/converters/excel/commons.js.map +1 -1
- package/dist/converters/excel/matrix-converter.d.ts +8 -0
- package/dist/converters/excel/matrix-converter.js +145 -30
- package/dist/converters/excel/matrix-converter.js.map +1 -1
- package/dist/converters/excel/tree-converter.js +2 -0
- package/dist/converters/excel/tree-converter.js.map +1 -1
- package/dist/converters/pdf/jspdf/matrix-converter.js +3 -3
- package/dist/converters/pdf/jspdf/matrix-converter.js.map +1 -1
- package/dist/utils/commons-utility.js +2 -1
- package/dist/utils/commons-utility.js.map +1 -1
- package/dist/{converters/pdf/jspdf/formulas-helper.d.ts → utils/excel-formulas-helper.d.ts} +24 -17
- package/dist/{converters/pdf/jspdf/formulas-helper.js → utils/excel-formulas-helper.js} +83 -29
- package/dist/utils/excel-formulas-helper.js.map +1 -0
- package/package.json +1 -1
- package/dist/converters/pdf/jspdf/formulas-helper.js.map +0 -1
|
@@ -10,6 +10,10 @@ export declare const initializeWorksheet: (workbook: ExcelJS.Workbook, title?: s
|
|
|
10
10
|
export declare const setHeaderStyling: (worksheet: Worksheet, headersRow?: number, background?: boolean) => void;
|
|
11
11
|
export declare const addFooterTotalsRow: (worksheet: ExcelJS.Worksheet, columns: SmeupDataColumn[], props: GenericObject, webupManagerData: WebupManagerData) => void;
|
|
12
12
|
export declare const getExcelColumnLetter: (index: number) => string;
|
|
13
|
+
/**
|
|
14
|
+
* Converts an Excel column letter (e.g. "A", "Z", "AA", "AB") to its 1-based column number.
|
|
15
|
+
*/
|
|
16
|
+
export declare const columnLetterToNumber: (letter: string) => number;
|
|
13
17
|
/**
|
|
14
18
|
* Returns the formula used in the footer to add Totals at the end of the table
|
|
15
19
|
* @param totalOperation string
|
|
@@ -42,3 +46,22 @@ export declare const groupedCellFormatAttributes: {
|
|
|
42
46
|
};
|
|
43
47
|
export declare const isGroupedCell: (cell: ExcelJS.Cell) => boolean;
|
|
44
48
|
export declare const normalizeSheetName: (name: string) => string;
|
|
49
|
+
/**
|
|
50
|
+
* Returns the actual number of active columns in the worksheet.
|
|
51
|
+
* Useful because ExcelJS, after removing columns with spliceColumns,
|
|
52
|
+
* does not correctly update the columnCount property and leaves empty columns
|
|
53
|
+
* in the worksheet.columns array.
|
|
54
|
+
* Only columns that exist and have a key (col.key) are counted.
|
|
55
|
+
*
|
|
56
|
+
* @param worksheet - The ExcelJS worksheet to analyze
|
|
57
|
+
* @returns {number} - The number of columns that are actually present and active
|
|
58
|
+
*/
|
|
59
|
+
export declare const getRealColumnsCount: (worksheet: ExcelJS.Worksheet) => number;
|
|
60
|
+
/**
|
|
61
|
+
* Resolves formulas and values in the worksheet.
|
|
62
|
+
* Calculates last row formula first to avoid multiple calculations of the same formula for each row in the group.
|
|
63
|
+
* Then resolves formulas in all other rows.
|
|
64
|
+
* @param worksheet
|
|
65
|
+
* @param webupManagerData
|
|
66
|
+
*/
|
|
67
|
+
export declare const resolveWorksheetFormulas: (worksheet: ExcelJS.Worksheet, webupManagerData: WebupManagerData) => void;
|
|
@@ -3,12 +3,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.normalizeSheetName = exports.isGroupedCell = exports.groupedCellFormatAttributes = exports.getCellsFromRange = exports.getDistinctCount = exports.smeupFormulaToExcelValue = exports.smeupFormulaToExcelFormula = exports.getTotalFormula = exports.getExcelColumnLetter = exports.addFooterTotalsRow = exports.setHeaderStyling = exports.initializeWorksheet = void 0;
|
|
6
|
+
exports.resolveWorksheetFormulas = exports.getRealColumnsCount = exports.normalizeSheetName = exports.isGroupedCell = exports.groupedCellFormatAttributes = exports.getCellsFromRange = exports.getDistinctCount = exports.smeupFormulaToExcelValue = exports.smeupFormulaToExcelFormula = exports.getTotalFormula = exports.columnLetterToNumber = exports.getExcelColumnLetter = exports.addFooterTotalsRow = exports.setHeaderStyling = exports.initializeWorksheet = void 0;
|
|
7
7
|
const exceljs_1 = __importDefault(require("exceljs"));
|
|
8
8
|
const excel_converter_types_1 = require("./excel-converter.types");
|
|
9
9
|
const objects_utility_1 = require("../../utils/objects-utility");
|
|
10
10
|
const matrix_converter_1 = require("./matrix-converter");
|
|
11
11
|
const math_utility_1 = require("../../utils/math-utility");
|
|
12
|
+
const excel_formulas_helper_1 = require("../../utils/excel-formulas-helper");
|
|
12
13
|
const { ValueType } = exceljs_1.default;
|
|
13
14
|
/**
|
|
14
15
|
* Adds creator, creation date to the workbook and creates a sheet
|
|
@@ -87,6 +88,17 @@ const getExcelColumnLetter = (index) => {
|
|
|
87
88
|
return columnLetter;
|
|
88
89
|
};
|
|
89
90
|
exports.getExcelColumnLetter = getExcelColumnLetter;
|
|
91
|
+
/**
|
|
92
|
+
* Converts an Excel column letter (e.g. "A", "Z", "AA", "AB") to its 1-based column number.
|
|
93
|
+
*/
|
|
94
|
+
const columnLetterToNumber = (letter) => {
|
|
95
|
+
let result = 0;
|
|
96
|
+
for (const char of letter.toUpperCase()) {
|
|
97
|
+
result = result * 26 + char.charCodeAt(0) - 64;
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
};
|
|
101
|
+
exports.columnLetterToNumber = columnLetterToNumber;
|
|
90
102
|
/**
|
|
91
103
|
* Returns the formula used in the footer to add Totals at the end of the table
|
|
92
104
|
* @param totalOperation string
|
|
@@ -261,4 +273,44 @@ const normalizeSheetName = (name) => {
|
|
|
261
273
|
return normalized;
|
|
262
274
|
};
|
|
263
275
|
exports.normalizeSheetName = normalizeSheetName;
|
|
276
|
+
/**
|
|
277
|
+
* Returns the actual number of active columns in the worksheet.
|
|
278
|
+
* Useful because ExcelJS, after removing columns with spliceColumns,
|
|
279
|
+
* does not correctly update the columnCount property and leaves empty columns
|
|
280
|
+
* in the worksheet.columns array.
|
|
281
|
+
* Only columns that exist and have a key (col.key) are counted.
|
|
282
|
+
*
|
|
283
|
+
* @param worksheet - The ExcelJS worksheet to analyze
|
|
284
|
+
* @returns {number} - The number of columns that are actually present and active
|
|
285
|
+
*/
|
|
286
|
+
const getRealColumnsCount = (worksheet) => {
|
|
287
|
+
return worksheet.columns.filter(col => !!col && col.key).length;
|
|
288
|
+
};
|
|
289
|
+
exports.getRealColumnsCount = getRealColumnsCount;
|
|
290
|
+
/**
|
|
291
|
+
* Resolves formulas and values in the worksheet.
|
|
292
|
+
* Calculates last row formula first to avoid multiple calculations of the same formula for each row in the group.
|
|
293
|
+
* Then resolves formulas in all other rows.
|
|
294
|
+
* @param worksheet
|
|
295
|
+
* @param webupManagerData
|
|
296
|
+
*/
|
|
297
|
+
const resolveWorksheetFormulas = (worksheet, webupManagerData) => {
|
|
298
|
+
// Resolve last row formulas
|
|
299
|
+
worksheet.lastRow?.eachCell((cell, _) => {
|
|
300
|
+
if (cell.formula && !cell.formula.includes("SUBTOTAL")) {
|
|
301
|
+
cell.value = (0, excel_formulas_helper_1.getSanitizedCellValue)(cell, worksheet, webupManagerData);
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
// Resolve formulas in all other outlined rows
|
|
305
|
+
worksheet.eachRow((row, _) => {
|
|
306
|
+
if (row !== worksheet.lastRow) {
|
|
307
|
+
row.eachCell((cell, _) => {
|
|
308
|
+
if (cell.formula && !cell.formula.includes("SUBTOTAL")) {
|
|
309
|
+
cell.value = (0, excel_formulas_helper_1.getSanitizedCellValue)(cell, worksheet, webupManagerData);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
};
|
|
315
|
+
exports.resolveWorksheetFormulas = resolveWorksheetFormulas;
|
|
264
316
|
//# sourceMappingURL=commons.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commons.js","sourceRoot":"","sources":["../../../src/converters/excel/commons.ts"],"names":[],"mappings":"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","sourcesContent":["import ExcelJS, { Alignment, Fill, Worksheet } from \"exceljs\";\nimport {\n allowedTotals,\n footerStyleFill,\n headerStyleFill,\n} from \"./excel-converter.types\";\nimport { GenericObject, WebupManagerData } from \"../../types/index\";\nimport { objectsIsDate } from \"../../utils/objects-utility\";\nimport { getExcelNumFormatForGroupedRow } from \"./matrix-converter\";\nimport {\n SmeupDataCell,\n SmeupDataColumn,\n} from \"../../types/data-structures/smeupDataTable\";\nimport { calculateExpression } from \"../../utils/math-utility\";\nconst { ValueType } = ExcelJS;\n\n/**\n * Adds creator, creation date to the workbook and creates a sheet\n * @param workbook\n * @returns void\n */\nexport const initializeWorksheet = (\n workbook: ExcelJS.Workbook,\n title?: string,\n) => {\n workbook.creator = \"/doc-alchemist - dataTable excel generator\";\n workbook.created = new Date();\n\n const worksheet = workbook.addWorksheet(\n title && title !== \"\" ? title : \"Export\",\n );\n return worksheet;\n};\n\nexport const setHeaderStyling = (\n worksheet: Worksheet,\n headersRow: number = 1,\n background = false,\n): void => {\n const headerRow = worksheet.getRow(headersRow);\n for (let col = 1; col <= worksheet.columns.length; col++) {\n const cell = headerRow.getCell(col);\n cell.font = { bold: true };\n cell.alignment = {\n horizontal: \"center\",\n vertical: \"middle\",\n wrapText: true,\n };\n cell.fill = {\n type: \"pattern\",\n pattern: \"solid\",\n fgColor: { argb: \"FFE0E0E0\" }, // note the \"FF\" alpha prefix\n };\n if (background) {\n const cell = headerRow.getCell(col);\n cell.fill = headerStyleFill;\n }\n }\n};\n\nexport const addFooterTotalsRow = (\n worksheet: ExcelJS.Worksheet,\n columns: SmeupDataColumn[],\n props: GenericObject,\n webupManagerData: WebupManagerData,\n) => {\n if (!props?.totals || typeof props.totals !== \"object\") {\n return;\n }\n\n const totals = props.totals as Record<string, string>;\n\n // Set footer total formulas\n const footerRowData = columns.map((column, columnIndex) => {\n const totalOperation: string = totals[column.name];\n if (!totalOperation) return;\n\n const formula = getTotalFormula(\n worksheet,\n totalOperation,\n columnIndex + 1, // from base 0 to base 1\n worksheet.rowCount,\n columns,\n totalOperation.startsWith(\"MATH\"),\n );\n\n return formula ? { formula: formula, type: ValueType.Formula } : \" \";\n });\n const footerRow = worksheet.addRow(footerRowData);\n\n // Format excel footer cells\n footerRow.font = { bold: true };\n footerRow.alignment = { horizontal: \"right\" };\n columns.map((column, index) => {\n const exceljsCell = footerRow.getCell(index + 1); // Convert base 0 index to base 1\n exceljsCell.fill = footerStyleFill;\n\n if (\n column.obj &&\n objectsIsDate(column.obj) &&\n (exceljsCell.formula?.startsWith(allowedTotals.Min) ||\n exceljsCell.formula?.startsWith(allowedTotals.Max))\n ) {\n const dateFormat =\n webupManagerData.datesLocale === \"it\" ? \"dd/mm/yyyy\" : \"mm/dd/yyyy\";\n exceljsCell.numFmt = dateFormat;\n return;\n }\n\n exceljsCell.numFmt = getExcelNumFormatForGroupedRow(column, totals);\n });\n};\n\nexport const getExcelColumnLetter = (index: number): string => {\n let columnLetter = \"\";\n while (index > 0) {\n index--; // Excel columns are 1-based, but calculations work better with 0-based\n columnLetter = String.fromCharCode((index % 26) + 65) + columnLetter;\n index = Math.floor(index / 26);\n }\n return columnLetter;\n};\n\n/**\n * Returns the formula used in the footer to add Totals at the end of the table\n * @param totalOperation string\n * @param colIndex string\n * @param rowNumber number\n * @returns\n */\nexport const getTotalFormula = (\n worksheet: ExcelJS.Worksheet,\n totalOperation: string,\n colIndex: number,\n rowNumber: number,\n filteredColumns: SmeupDataColumn[],\n isSmeupFormula: boolean,\n): string => {\n const startRow = 2;\n const columnExcelLetter = getExcelColumnLetter(colIndex);\n\n if (isSmeupFormula) {\n return smeupFormulaToExcelFormula(\n totalOperation,\n rowNumber,\n filteredColumns,\n );\n }\n\n if (!allowedTotals[totalOperation]) {\n console.warn(\n `Total operation [' ${totalOperation} '] is not supported`,\n \"exportUtils.ts\",\n );\n return \"\";\n }\n\n if (totalOperation === \"Distinct\") {\n return getDistinctCount(\n `${columnExcelLetter}${startRow}:${columnExcelLetter}${rowNumber}`,\n worksheet,\n );\n } else {\n return `${allowedTotals[totalOperation]}${columnExcelLetter}${startRow}:${columnExcelLetter}${rowNumber})`;\n }\n};\n\nexport const smeupFormulaToExcelFormula = (\n formula: string,\n rowNumber: number,\n filteredColumns: SmeupDataColumn[],\n): string => {\n const result = formula\n .replace(\"MATH\", \"\")\n .replace(/\\[([^\\]]+)\\]/g, (_, key) => {\n const columnIndex =\n filteredColumns.findIndex(col => col.name === key) + 1;\n const columnLetter = getExcelColumnLetter(columnIndex);\n return columnLetter && columnIndex\n ? `${columnLetter}${rowNumber + 1}`\n : key;\n })\n .replaceAll(\",\", \".\"); // Replace eventual , to . => The excel accepted decimal separator\n return result;\n};\n\nexport const smeupFormulaToExcelValue = (\n column: SmeupDataColumn,\n filteredColumns: SmeupDataColumn[],\n cells: Record<string, SmeupDataCell>,\n): string => {\n let resultValue: string | number = \"\";\n if (!column.formula) {\n return \"\";\n }\n const result = column.formula\n .replace(\"MATH\", \"\")\n .replace(/\\[([^\\]]+)\\]/g, (match, key) => {\n const columnIndex = filteredColumns.findIndex(col => col.name === key);\n return columnIndex >= 0\n ? (cells[key]?.value ?? \"\")\n : match === \"[SUM]\"\n ? match\n : key;\n });\n try {\n if (result === \"[SUM]\") {\n resultValue = applySUMFormula(column, filteredColumns, cells);\n } else {\n resultValue = calculateExpression(result);\n }\n } catch {\n resultValue = result; // If the formula fails, return the original formula\n }\n return resultValue.toString();\n};\n\nconst applySUMFormula = (\n column: SmeupDataColumn,\n filteredColumns: SmeupDataColumn[],\n cells: Record<string, SmeupDataCell>,\n): number => {\n let resultValue: number = 0;\n resultValue = 0;\n const index = filteredColumns.findIndex(col => col.name === column.name);\n filteredColumns.slice(0, index).forEach(col => {\n if (col.obj && col.obj.t === \"NR\") {\n let cellValue = 0;\n if (col.formula) {\n cellValue = Number(\n smeupFormulaToExcelValue(col, filteredColumns, cells),\n );\n } else {\n cellValue = Number(cells[col.name]?.value);\n }\n if (!isNaN(cellValue)) {\n resultValue = (resultValue as number) + cellValue;\n }\n }\n });\n return resultValue;\n};\n\nexport const getDistinctCount = (\n range: string,\n worksheet: ExcelJS.Worksheet,\n): string => {\n const column = range.split(\":\")[0].replace(/[0-9]/g, \"\"); // Extract column letter\n const startRow = parseInt(range.split(\":\")[0].replace(/\\D/g, \"\"), 10);\n const endRow = parseInt(range.split(\":\")[1].replace(/\\D/g, \"\"), 10);\n\n // Create a set to store unique values\n const uniqueValues = new Set<string>();\n\n for (let rowIndex = startRow; rowIndex <= endRow; rowIndex++) {\n const cell = worksheet.getCell(`${column}${rowIndex}`);\n if (cell.formula) continue;\n const cellValue = cell.value;\n if (cellValue !== null && cellValue !== undefined) {\n uniqueValues.add(cellValue.toString());\n }\n }\n\n return uniqueValues.size.toString();\n};\n\n/**\n * Estrae tutte le celle (ExcelJS.Cell) da un intervallo rettangolare specificato in un worksheet ExcelJS.\n *\n * L'intervallo è definito dai riferimenti di cella iniziale e finale (es. \"A1\" a \"C3\").\n * Restituisce le celle in ordine riga-major.\n *\n * @param worksheet - Il worksheet ExcelJS da cui estrarre le celle.\n * @param startRef - Il riferimento della cella iniziale (es. \"A1\").\n * @param endRef - Il riferimento della cella finale (es. \"C3\").\n * @returns Un array di ExcelJS.Cell dall'intervallo specificato, in ordine riga-major.\n */\nexport const getCellsFromRange = (\n worksheet: ExcelJS.Worksheet,\n startRef: string,\n endRef: string,\n): ExcelJS.Cell[] => {\n const parseCellRef = (ref: string) => {\n const match = ref.match(/^([A-Z]+)(\\d+)$/i);\n if (!match) return null;\n const col = match[1].toUpperCase();\n const row = parseInt(match[2], 10);\n return { col, row };\n };\n const colToIndex = (col: string) => {\n let idx = 0;\n for (let i = 0; i < col.length; i++) {\n idx = idx * 26 + (col.charCodeAt(i) - 64);\n }\n return idx;\n };\n const start = parseCellRef(startRef);\n const end = parseCellRef(endRef);\n if (!start || !end) return [];\n const cells: ExcelJS.Cell[] = [];\n for (let r = start.row; r <= end.row; r++) {\n for (let c = colToIndex(start.col); c <= colToIndex(end.col); c++) {\n const cell = worksheet.getRow(r).getCell(c);\n cells.push(cell);\n }\n }\n return cells;\n};\n\nexport const groupedCellFormatAttributes = {\n font: { bold: true },\n alignment: { horizontal: \"left\" } as Partial<Alignment>,\n fill: {\n type: \"pattern\",\n pattern: \"solid\",\n fgColor: { argb: \"FFF4F4F4\" },\n } as Fill,\n};\n\nexport const isGroupedCell = (cell: ExcelJS.Cell): boolean => {\n return (\n JSON.stringify({\n font: cell.font,\n alignment: cell.alignment,\n fill: cell.fill,\n }) === JSON.stringify(groupedCellFormatAttributes)\n );\n};\n\nexport const normalizeSheetName = (name: string): string => {\n let normalized = name.replace(/[:\\\\/?*[\\]]/g, \"_\");\n normalized = normalized.replace(/^'+|'+$/g, \"\");\n normalized = normalized.slice(0, 31);\n if (!normalized.trim()) {\n normalized = \"Sheet\";\n }\n return normalized;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"commons.js","sourceRoot":"","sources":["../../../src/converters/excel/commons.ts"],"names":[],"mappings":"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","sourcesContent":["import ExcelJS, { Alignment, Fill, Worksheet } from \"exceljs\";\nimport {\n allowedTotals,\n footerStyleFill,\n headerStyleFill,\n} from \"./excel-converter.types\";\nimport { GenericObject, WebupManagerData } from \"../../types/index\";\nimport { objectsIsDate } from \"../../utils/objects-utility\";\nimport { getExcelNumFormatForGroupedRow } from \"./matrix-converter\";\nimport {\n SmeupDataCell,\n SmeupDataColumn,\n} from \"../../types/data-structures/smeupDataTable\";\nimport { calculateExpression } from \"../../utils/math-utility\";\nimport { getSanitizedCellValue } from \"../../utils/excel-formulas-helper\";\nconst { ValueType } = ExcelJS;\n\n/**\n * Adds creator, creation date to the workbook and creates a sheet\n * @param workbook\n * @returns void\n */\nexport const initializeWorksheet = (\n workbook: ExcelJS.Workbook,\n title?: string,\n) => {\n workbook.creator = \"/doc-alchemist - dataTable excel generator\";\n workbook.created = new Date();\n\n const worksheet = workbook.addWorksheet(\n title && title !== \"\" ? title : \"Export\",\n );\n return worksheet;\n};\n\nexport const setHeaderStyling = (\n worksheet: Worksheet,\n headersRow: number = 1,\n background = false,\n): void => {\n const headerRow = worksheet.getRow(headersRow);\n for (let col = 1; col <= worksheet.columns.length; col++) {\n const cell = headerRow.getCell(col);\n cell.font = { bold: true };\n cell.alignment = {\n horizontal: \"center\",\n vertical: \"middle\",\n wrapText: true,\n };\n cell.fill = {\n type: \"pattern\",\n pattern: \"solid\",\n fgColor: { argb: \"FFE0E0E0\" }, // note the \"FF\" alpha prefix\n };\n if (background) {\n const cell = headerRow.getCell(col);\n cell.fill = headerStyleFill;\n }\n }\n};\n\nexport const addFooterTotalsRow = (\n worksheet: ExcelJS.Worksheet,\n columns: SmeupDataColumn[],\n props: GenericObject,\n webupManagerData: WebupManagerData,\n) => {\n if (!props?.totals || typeof props.totals !== \"object\") {\n return;\n }\n\n const totals = props.totals as Record<string, string>;\n\n // Set footer total formulas\n const footerRowData = columns.map((column, columnIndex) => {\n const totalOperation: string = totals[column.name];\n if (!totalOperation) return;\n\n const formula = getTotalFormula(\n worksheet,\n totalOperation,\n columnIndex + 1, // from base 0 to base 1\n worksheet.rowCount,\n columns,\n totalOperation.startsWith(\"MATH\"),\n );\n\n return formula ? { formula: formula, type: ValueType.Formula } : \" \";\n });\n const footerRow = worksheet.addRow(footerRowData);\n\n // Format excel footer cells\n footerRow.font = { bold: true };\n footerRow.alignment = { horizontal: \"right\" };\n columns.map((column, index) => {\n const exceljsCell = footerRow.getCell(index + 1); // Convert base 0 index to base 1\n exceljsCell.fill = footerStyleFill;\n\n if (\n column.obj &&\n objectsIsDate(column.obj) &&\n (exceljsCell.formula?.startsWith(allowedTotals.Min) ||\n exceljsCell.formula?.startsWith(allowedTotals.Max))\n ) {\n const dateFormat =\n webupManagerData.datesLocale === \"it\" ? \"dd/mm/yyyy\" : \"mm/dd/yyyy\";\n exceljsCell.numFmt = dateFormat;\n return;\n }\n\n exceljsCell.numFmt = getExcelNumFormatForGroupedRow(column, totals);\n });\n};\n\nexport const getExcelColumnLetter = (index: number): string => {\n let columnLetter = \"\";\n while (index > 0) {\n index--; // Excel columns are 1-based, but calculations work better with 0-based\n columnLetter = String.fromCharCode((index % 26) + 65) + columnLetter;\n index = Math.floor(index / 26);\n }\n return columnLetter;\n};\n\n/**\n * Converts an Excel column letter (e.g. \"A\", \"Z\", \"AA\", \"AB\") to its 1-based column number.\n */\nexport const columnLetterToNumber = (letter: string): number => {\n let result = 0;\n for (const char of letter.toUpperCase()) {\n result = result * 26 + char.charCodeAt(0) - 64;\n }\n return result;\n};\n\n/**\n * Returns the formula used in the footer to add Totals at the end of the table\n * @param totalOperation string\n * @param colIndex string\n * @param rowNumber number\n * @returns\n */\nexport const getTotalFormula = (\n worksheet: ExcelJS.Worksheet,\n totalOperation: string,\n colIndex: number,\n rowNumber: number,\n filteredColumns: SmeupDataColumn[],\n isSmeupFormula: boolean,\n): string => {\n const startRow = 2;\n const columnExcelLetter = getExcelColumnLetter(colIndex);\n\n if (isSmeupFormula) {\n return smeupFormulaToExcelFormula(\n totalOperation,\n rowNumber,\n filteredColumns,\n );\n }\n\n if (!allowedTotals[totalOperation]) {\n console.warn(\n `Total operation [' ${totalOperation} '] is not supported`,\n \"exportUtils.ts\",\n );\n return \"\";\n }\n\n if (totalOperation === \"Distinct\") {\n return getDistinctCount(\n `${columnExcelLetter}${startRow}:${columnExcelLetter}${rowNumber}`,\n worksheet,\n );\n } else {\n return `${allowedTotals[totalOperation]}${columnExcelLetter}${startRow}:${columnExcelLetter}${rowNumber})`;\n }\n};\n\nexport const smeupFormulaToExcelFormula = (\n formula: string,\n rowNumber: number,\n filteredColumns: SmeupDataColumn[],\n): string => {\n const result = formula\n .replace(\"MATH\", \"\")\n .replace(/\\[([^\\]]+)\\]/g, (_, key) => {\n const columnIndex =\n filteredColumns.findIndex(col => col.name === key) + 1;\n const columnLetter = getExcelColumnLetter(columnIndex);\n return columnLetter && columnIndex\n ? `${columnLetter}${rowNumber + 1}`\n : key;\n })\n .replaceAll(\",\", \".\"); // Replace eventual , to . => The excel accepted decimal separator\n return result;\n};\n\nexport const smeupFormulaToExcelValue = (\n column: SmeupDataColumn,\n filteredColumns: SmeupDataColumn[],\n cells: Record<string, SmeupDataCell>,\n): string => {\n let resultValue: string | number = \"\";\n if (!column.formula) {\n return \"\";\n }\n const result = column.formula\n .replace(\"MATH\", \"\")\n .replace(/\\[([^\\]]+)\\]/g, (match, key) => {\n const columnIndex = filteredColumns.findIndex(col => col.name === key);\n return columnIndex >= 0\n ? (cells[key]?.value ?? \"\")\n : match === \"[SUM]\"\n ? match\n : key;\n });\n try {\n if (result === \"[SUM]\") {\n resultValue = applySUMFormula(column, filteredColumns, cells);\n } else {\n resultValue = calculateExpression(result);\n }\n } catch {\n resultValue = result; // If the formula fails, return the original formula\n }\n return resultValue.toString();\n};\n\nconst applySUMFormula = (\n column: SmeupDataColumn,\n filteredColumns: SmeupDataColumn[],\n cells: Record<string, SmeupDataCell>,\n): number => {\n let resultValue: number = 0;\n resultValue = 0;\n const index = filteredColumns.findIndex(col => col.name === column.name);\n filteredColumns.slice(0, index).forEach(col => {\n if (col.obj && col.obj.t === \"NR\") {\n let cellValue = 0;\n if (col.formula) {\n cellValue = Number(\n smeupFormulaToExcelValue(col, filteredColumns, cells),\n );\n } else {\n cellValue = Number(cells[col.name]?.value);\n }\n if (!isNaN(cellValue)) {\n resultValue = (resultValue as number) + cellValue;\n }\n }\n });\n return resultValue;\n};\n\nexport const getDistinctCount = (\n range: string,\n worksheet: ExcelJS.Worksheet,\n): string => {\n const column = range.split(\":\")[0].replace(/[0-9]/g, \"\"); // Extract column letter\n const startRow = parseInt(range.split(\":\")[0].replace(/\\D/g, \"\"), 10);\n const endRow = parseInt(range.split(\":\")[1].replace(/\\D/g, \"\"), 10);\n\n // Create a set to store unique values\n const uniqueValues = new Set<string>();\n\n for (let rowIndex = startRow; rowIndex <= endRow; rowIndex++) {\n const cell = worksheet.getCell(`${column}${rowIndex}`);\n if (cell.formula) continue;\n const cellValue = cell.value;\n if (cellValue !== null && cellValue !== undefined) {\n uniqueValues.add(cellValue.toString());\n }\n }\n\n return uniqueValues.size.toString();\n};\n\n/**\n * Estrae tutte le celle (ExcelJS.Cell) da un intervallo rettangolare specificato in un worksheet ExcelJS.\n *\n * L'intervallo è definito dai riferimenti di cella iniziale e finale (es. \"A1\" a \"C3\").\n * Restituisce le celle in ordine riga-major.\n *\n * @param worksheet - Il worksheet ExcelJS da cui estrarre le celle.\n * @param startRef - Il riferimento della cella iniziale (es. \"A1\").\n * @param endRef - Il riferimento della cella finale (es. \"C3\").\n * @returns Un array di ExcelJS.Cell dall'intervallo specificato, in ordine riga-major.\n */\nexport const getCellsFromRange = (\n worksheet: ExcelJS.Worksheet,\n startRef: string,\n endRef: string,\n): ExcelJS.Cell[] => {\n const parseCellRef = (ref: string) => {\n const match = ref.match(/^([A-Z]+)(\\d+)$/i);\n if (!match) return null;\n const col = match[1].toUpperCase();\n const row = parseInt(match[2], 10);\n return { col, row };\n };\n const colToIndex = (col: string) => {\n let idx = 0;\n for (let i = 0; i < col.length; i++) {\n idx = idx * 26 + (col.charCodeAt(i) - 64);\n }\n return idx;\n };\n const start = parseCellRef(startRef);\n const end = parseCellRef(endRef);\n if (!start || !end) return [];\n const cells: ExcelJS.Cell[] = [];\n for (let r = start.row; r <= end.row; r++) {\n for (let c = colToIndex(start.col); c <= colToIndex(end.col); c++) {\n const cell = worksheet.getRow(r).getCell(c);\n cells.push(cell);\n }\n }\n return cells;\n};\n\nexport const groupedCellFormatAttributes = {\n font: { bold: true },\n alignment: { horizontal: \"left\" } as Partial<Alignment>,\n fill: {\n type: \"pattern\",\n pattern: \"solid\",\n fgColor: { argb: \"FFF4F4F4\" },\n } as Fill,\n};\n\nexport const isGroupedCell = (cell: ExcelJS.Cell): boolean => {\n return (\n JSON.stringify({\n font: cell.font,\n alignment: cell.alignment,\n fill: cell.fill,\n }) === JSON.stringify(groupedCellFormatAttributes)\n );\n};\n\nexport const normalizeSheetName = (name: string): string => {\n let normalized = name.replace(/[:\\\\/?*[\\]]/g, \"_\");\n normalized = normalized.replace(/^'+|'+$/g, \"\");\n normalized = normalized.slice(0, 31);\n if (!normalized.trim()) {\n normalized = \"Sheet\";\n }\n return normalized;\n};\n\n/**\n * Returns the actual number of active columns in the worksheet.\n * Useful because ExcelJS, after removing columns with spliceColumns,\n * does not correctly update the columnCount property and leaves empty columns\n * in the worksheet.columns array.\n * Only columns that exist and have a key (col.key) are counted.\n *\n * @param worksheet - The ExcelJS worksheet to analyze\n * @returns {number} - The number of columns that are actually present and active\n */\nexport const getRealColumnsCount = (worksheet: ExcelJS.Worksheet): number => {\n return worksheet.columns.filter(col => !!col && col.key).length;\n};\n\n/**\n * Resolves formulas and values in the worksheet.\n * Calculates last row formula first to avoid multiple calculations of the same formula for each row in the group.\n * Then resolves formulas in all other rows.\n * @param worksheet\n * @param webupManagerData\n */\nexport const resolveWorksheetFormulas = (\n worksheet: ExcelJS.Worksheet,\n webupManagerData: WebupManagerData,\n): void => {\n // Resolve last row formulas\n worksheet.lastRow?.eachCell((cell, _) => {\n if (cell.formula && !cell.formula.includes(\"SUBTOTAL\")) {\n cell.value = getSanitizedCellValue(cell, worksheet, webupManagerData);\n }\n });\n\n // Resolve formulas in all other outlined rows\n worksheet.eachRow((row, _) => {\n if (row !== worksheet.lastRow) {\n row.eachCell((cell, _) => {\n if (cell.formula && !cell.formula.includes(\"SUBTOTAL\")) {\n cell.value = getSanitizedCellValue(cell, worksheet, webupManagerData);\n }\n });\n }\n });\n};\n"]}
|
|
@@ -9,3 +9,11 @@ export declare const dataTableToExcelWorkbook: (component: {
|
|
|
9
9
|
export declare const addStyleToExceljsRow: (exceljsRow: ExcelJS.Row, columns: SmeupDataColumn[], row: SmeupDataRow | SmeupDataNode) => void;
|
|
10
10
|
export declare const getExcelNumFormatForGroupedRow: (column: SmeupDataColumn, totals: Record<string, string>) => string;
|
|
11
11
|
export declare const getExcelNumFormat: (cellDecimals: number, cellIntegers: number) => string;
|
|
12
|
+
/**
|
|
13
|
+
* Filters columns when the first visible column has a total applied
|
|
14
|
+
* @param columns - The columns to filter
|
|
15
|
+
* @param unfilteredColumns - The unfiltered columns to determine the index
|
|
16
|
+
* @param props - Component props containing totals configuration
|
|
17
|
+
* @returns The filtered columns
|
|
18
|
+
*/
|
|
19
|
+
export declare const filterColumnsWhenFirstVisibleHasTotal: (columns: SmeupDataColumn[], props: GenericObject) => SmeupDataColumn[];
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getExcelNumFormat = exports.getExcelNumFormatForGroupedRow = exports.addStyleToExceljsRow = exports.dataTableToExcelWorkbook = void 0;
|
|
6
|
+
exports.filterColumnsWhenFirstVisibleHasTotal = exports.getExcelNumFormat = exports.getExcelNumFormatForGroupedRow = exports.addStyleToExceljsRow = exports.dataTableToExcelWorkbook = void 0;
|
|
7
7
|
const exceljs_1 = __importDefault(require("exceljs"));
|
|
8
8
|
const commons_utility_1 = require("../../utils/commons-utility");
|
|
9
9
|
const excel_converter_types_1 = require("./excel-converter.types");
|
|
@@ -20,7 +20,13 @@ const dataTableToExcelWorkbook = (component, fileFormat, webupManagerData, sheet
|
|
|
20
20
|
// Visible attribute is used only to determine if the column is visible,
|
|
21
21
|
// ant not to determine if the group is active
|
|
22
22
|
const activeGroups = groupsArray.map((group) => group.column);
|
|
23
|
-
|
|
23
|
+
let filteredColumns = (0, commons_utility_1.getFilteredColumns)(smeupDataTable.columns, props, groupsArray);
|
|
24
|
+
// If there is a totalization on a column that matches the first visible column
|
|
25
|
+
// filter out all hidden columns that precede the column.
|
|
26
|
+
// This is necessary to avoid issues with formulas on grouped rows, due to the change
|
|
27
|
+
// that hides columns instead of removing them so some total formulas can be resolved programmatically,
|
|
28
|
+
// see resolveWorksheetFormulas function, and only after, removed.
|
|
29
|
+
filteredColumns = (0, exports.filterColumnsWhenFirstVisibleHasTotal)(filteredColumns, props);
|
|
24
30
|
const maxColumnValueLength = {};
|
|
25
31
|
// Determines the initial row of the data by checking if title is valid
|
|
26
32
|
const documentInitialRow = title
|
|
@@ -31,19 +37,7 @@ const dataTableToExcelWorkbook = (component, fileFormat, webupManagerData, sheet
|
|
|
31
37
|
setDataTableHeaderRow(worksheet, filteredColumns, maxColumnValueLength);
|
|
32
38
|
// Insert title (header row automatically pushes down other rows)
|
|
33
39
|
if (title) {
|
|
34
|
-
worksheet
|
|
35
|
-
// Insert empty row for better spacing
|
|
36
|
-
worksheet.insertRow(2, "");
|
|
37
|
-
const firstCol = 1;
|
|
38
|
-
const lastCol = worksheet.columnCount; // this is the actual column length
|
|
39
|
-
// Merge all cells in the new title row
|
|
40
|
-
worksheet.mergeCells(1, firstCol, 2, lastCol);
|
|
41
|
-
// Assign the value to the merged area
|
|
42
|
-
worksheet.getRow(1).getCell(firstCol).value = title;
|
|
43
|
-
// Style
|
|
44
|
-
const row = worksheet.getRow(1);
|
|
45
|
-
row.font = { bold: true, size: 14 };
|
|
46
|
-
row.alignment = { horizontal: "center", vertical: "middle" };
|
|
40
|
+
insertTitleRow(worksheet);
|
|
47
41
|
}
|
|
48
42
|
// Filter and sort rows (if filters are available)
|
|
49
43
|
const rows = (0, commons_utility_1.filterRows)(smeupDataTable, smeupDataTable.columns, props?.filters, webupManagerData);
|
|
@@ -79,11 +73,22 @@ const dataTableToExcelWorkbook = (component, fileFormat, webupManagerData, sheet
|
|
|
79
73
|
col.width = 10 * 1.1; // Default width
|
|
80
74
|
}
|
|
81
75
|
});
|
|
76
|
+
// Resolve formulas and values for grouped rows and totals before removing hidden columns
|
|
77
|
+
(0, commons_1.resolveWorksheetFormulas)(worksheet, webupManagerData);
|
|
78
|
+
// Remove hidden columns
|
|
79
|
+
removeHiddenColumns(worksheet);
|
|
80
|
+
// Iitle is set at the end due to issues with spliceColumns
|
|
81
|
+
// and merged cells
|
|
82
|
+
if (title) {
|
|
83
|
+
updateTitleRow(worksheet, title);
|
|
84
|
+
}
|
|
82
85
|
// Apply filter to column headers
|
|
83
|
-
// TODO: look if it breaks groupings
|
|
84
86
|
worksheet.autoFilter = {
|
|
85
87
|
from: { row: documentInitialRow, column: 1 },
|
|
86
|
-
to: {
|
|
88
|
+
to: {
|
|
89
|
+
row: rowNumber,
|
|
90
|
+
column: (0, commons_1.getRealColumnsCount)(worksheet),
|
|
91
|
+
},
|
|
87
92
|
};
|
|
88
93
|
// Forces full calculation when the workbook is opened
|
|
89
94
|
workbook.calcProperties = {
|
|
@@ -107,11 +112,87 @@ const setDataTableHeaderRow = (worksheet, filteredColumns, maxValueLengthMap) =>
|
|
|
107
112
|
return {
|
|
108
113
|
header: col.title,
|
|
109
114
|
key: col.name,
|
|
110
|
-
width: maxValueLengthMap[col.name],
|
|
115
|
+
width: maxValueLengthMap[col.name],
|
|
116
|
+
hidden: (0, datastructure_utility_1.isColumnHidden)(col), // Set the width to the updated value
|
|
111
117
|
};
|
|
112
118
|
});
|
|
113
119
|
(0, commons_1.setHeaderStyling)(worksheet);
|
|
114
120
|
};
|
|
121
|
+
/**
|
|
122
|
+
* Inserts empty rows at the top of the worksheet for the title section
|
|
123
|
+
* @param worksheet - The worksheet to insert rows into
|
|
124
|
+
*/
|
|
125
|
+
const insertTitleRow = (worksheet) => {
|
|
126
|
+
worksheet.insertRow(1, "");
|
|
127
|
+
// Insert empty row for better spacing
|
|
128
|
+
worksheet.insertRow(2, "");
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Updates the title row with content, merges cells, and applies styling
|
|
132
|
+
* Merges cells across all columns and applies bold font with center alignment
|
|
133
|
+
* @param worksheet - The worksheet containing the title rows
|
|
134
|
+
* @param title - The title text to display in the merged cells
|
|
135
|
+
*/
|
|
136
|
+
const updateTitleRow = (worksheet, title) => {
|
|
137
|
+
const firstCol = 1;
|
|
138
|
+
const lastCol = (0, commons_1.getRealColumnsCount)(worksheet);
|
|
139
|
+
// Merge all cells in the new title row
|
|
140
|
+
worksheet.mergeCells(1, firstCol, 2, lastCol);
|
|
141
|
+
// Assign the value to the merged area
|
|
142
|
+
worksheet.getRow(1).getCell(firstCol).value = title;
|
|
143
|
+
// Style
|
|
144
|
+
const row = worksheet.getRow(1);
|
|
145
|
+
row.font = { bold: true, size: 14 };
|
|
146
|
+
row.alignment = { horizontal: "center", vertical: "middle" };
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Given a formula string, shifts all column-letter references inside SUBTOTAL(...)
|
|
150
|
+
* expressions that fall after than removedColNumber by decrementing them by one.
|
|
151
|
+
* Handles simple ranges like SUBTOTAL(9,C2:C5) and compound expressions
|
|
152
|
+
* like `"Label" & SUBTOTAL(9,C2:C5)`.
|
|
153
|
+
*/
|
|
154
|
+
const shiftSubtotalColumnReferences = (formula, removedColNumber) => {
|
|
155
|
+
return formula.replace(/SUBTOTAL\([^)]+\)/g, subtotalMatch => subtotalMatch.replace(/([A-Z]+)(\d+)/g, (_, colLetter, rowNum) => {
|
|
156
|
+
const colNum = (0, commons_1.columnLetterToNumber)(colLetter);
|
|
157
|
+
return colNum > removedColNumber
|
|
158
|
+
? (0, commons_1.getExcelColumnLetter)(colNum - 1) + rowNum
|
|
159
|
+
: colLetter + rowNum;
|
|
160
|
+
}));
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* Scans every cell in the worksheet and, for cells whose formula contains
|
|
164
|
+
* SUBTOTAL, decrements any column references that point past removedColNumber.
|
|
165
|
+
* Must be called before spliceColumns so that formulas stay consistent.
|
|
166
|
+
*/
|
|
167
|
+
const updateSubtotalFormulasBeforeColumnRemoval = (worksheet, removedColNumber) => {
|
|
168
|
+
worksheet.eachRow(row => {
|
|
169
|
+
row.eachCell(cell => {
|
|
170
|
+
if (cell.formula?.includes("SUBTOTAL")) {
|
|
171
|
+
cell.value = {
|
|
172
|
+
formula: shiftSubtotalColumnReferences(cell.formula, removedColNumber),
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
/**
|
|
179
|
+
* Removes all hidden columns from the worksheet.
|
|
180
|
+
* Before each removal, updates any SUBTOTAL formulas in the sheet so that
|
|
181
|
+
* column references past the deleted column are decremented accordingly.
|
|
182
|
+
* @param worksheet
|
|
183
|
+
*/
|
|
184
|
+
const removeHiddenColumns = (worksheet) => {
|
|
185
|
+
const hiddenColumnKeys = worksheet.columns
|
|
186
|
+
.filter(col => col.hidden)
|
|
187
|
+
.map(col => col.key);
|
|
188
|
+
hiddenColumnKeys.forEach(colKey => {
|
|
189
|
+
if (colKey) {
|
|
190
|
+
const colNumber = worksheet.getColumn(colKey).number;
|
|
191
|
+
updateSubtotalFormulasBeforeColumnRemoval(worksheet, colNumber);
|
|
192
|
+
worksheet.spliceColumns(colNumber, 1);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
};
|
|
115
196
|
const insertDataTableGroupedRows = (worksheet, rows, groups, filteredColumns, unfilteredColumns, rowNumber, fileFormat, webupManagerData, currentOutlineLevel = 1, maxColumnValueLength, totals) => {
|
|
116
197
|
if (!groups.length) {
|
|
117
198
|
return insertDataTableRows(worksheet, rows, unfilteredColumns, filteredColumns, rowNumber, fileFormat, webupManagerData, maxColumnValueLength);
|
|
@@ -129,8 +210,8 @@ const insertDataTableGroupedRows = (worksheet, rows, groups, filteredColumns, un
|
|
|
129
210
|
const indentation = " ".repeat((currentOutlineLevel - 1) * 8);
|
|
130
211
|
// Insert header row
|
|
131
212
|
const headerRow = worksheet.addRow([]);
|
|
132
|
-
headerRow.getCell(1)
|
|
133
|
-
|
|
213
|
+
const headerCell = headerRow.getCell(1);
|
|
214
|
+
headerCell.value = `${indentation}▼${columnTitles[currentGroup]?.replace(/\n/g, " ")} - ${groupValue}`;
|
|
134
215
|
const headerRowNumber = ++rowNumber;
|
|
135
216
|
rowNumber = insertDataTableGroupedRows(worksheet, groupedRows, remainingGroups, filteredColumns, unfilteredColumns, rowNumber, fileFormat, webupManagerData, currentOutlineLevel + 1, maxColumnValueLength, totals);
|
|
136
217
|
const lastDataRow = rowNumber;
|
|
@@ -144,6 +225,7 @@ const insertDataTableGroupedRows = (worksheet, rows, groups, filteredColumns, un
|
|
|
144
225
|
const totalFormula = totals[col.name];
|
|
145
226
|
if (totalFormula) {
|
|
146
227
|
cell.alignment = { horizontal: "right" };
|
|
228
|
+
const cellValue = cell.value;
|
|
147
229
|
cell.value = totalFormula.startsWith("MATH")
|
|
148
230
|
? {
|
|
149
231
|
formula: (0, commons_1.smeupFormulaToExcelFormula)(totalFormula.replace("MATH", ""), headerRowNumber - 1, filteredColumns),
|
|
@@ -151,6 +233,10 @@ const insertDataTableGroupedRows = (worksheet, rows, groups, filteredColumns, un
|
|
|
151
233
|
: {
|
|
152
234
|
formula: getSubGroupTotalFormula(worksheet, totalFormula, colIndex + 1, headerRowNumber + 1, lastDataRow),
|
|
153
235
|
};
|
|
236
|
+
if (cellValue) {
|
|
237
|
+
cell.value = { formula: `"${cellValue} - Tot: " & ${cell.formula}` };
|
|
238
|
+
cell.alignment = { horizontal: "left" };
|
|
239
|
+
}
|
|
154
240
|
}
|
|
155
241
|
}
|
|
156
242
|
}
|
|
@@ -270,6 +356,25 @@ exports.getExcelNumFormat = getExcelNumFormat;
|
|
|
270
356
|
const decorateHeaderRow = (headerCell) => {
|
|
271
357
|
Object.assign(headerCell, commons_1.groupedCellFormatAttributes);
|
|
272
358
|
};
|
|
359
|
+
/**
|
|
360
|
+
* Filters columns when the first visible column has a total applied
|
|
361
|
+
* @param columns - The columns to filter
|
|
362
|
+
* @param unfilteredColumns - The unfiltered columns to determine the index
|
|
363
|
+
* @param props - Component props containing totals configuration
|
|
364
|
+
* @returns The filtered columns
|
|
365
|
+
*/
|
|
366
|
+
const filterColumnsWhenFirstVisibleHasTotal = (columns, props) => {
|
|
367
|
+
const firstVisibleColumnName = columns.find(col => !(0, datastructure_utility_1.isColumnHidden)(col))?.name;
|
|
368
|
+
if (!firstVisibleColumnName ||
|
|
369
|
+
!props?.totals ||
|
|
370
|
+
typeof props.totals !== "object" ||
|
|
371
|
+
!(firstVisibleColumnName in props.totals)) {
|
|
372
|
+
return columns;
|
|
373
|
+
}
|
|
374
|
+
const firstVisibleColumnIndex = columns.findIndex(col => col.name === firstVisibleColumnName);
|
|
375
|
+
return columns.filter((_, index) => index >= firstVisibleColumnIndex);
|
|
376
|
+
};
|
|
377
|
+
exports.filterColumnsWhenFirstVisibleHasTotal = filterColumnsWhenFirstVisibleHasTotal;
|
|
273
378
|
const getSubGroupTotalFormula = (worksheet, totalOperation, colIndex, firstDataRow, lastDataRow) => {
|
|
274
379
|
const columnExcelLetter = (0, commons_1.getExcelColumnLetter)(colIndex);
|
|
275
380
|
if (!excel_converter_types_1.allowedTotals[totalOperation]) {
|
|
@@ -308,19 +413,29 @@ const getFirstVisibleColumn = (worksheet) => {
|
|
|
308
413
|
const applyDataTableOutlineLevels = (worksheet) => {
|
|
309
414
|
let lastOutlineLevel = 0;
|
|
310
415
|
worksheet.eachRow((row, rowIndex) => {
|
|
311
|
-
if (rowIndex
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
416
|
+
if (rowIndex === 1)
|
|
417
|
+
return;
|
|
418
|
+
const firstCell = row.getCell(1);
|
|
419
|
+
const cellStr = firstCell.formula?.toString() ?? firstCell.value?.toString() ?? "";
|
|
420
|
+
const isHeader = cellStr.includes("▼");
|
|
421
|
+
if (isHeader) {
|
|
422
|
+
const cleanStr = cellStr.replace("▼", "");
|
|
423
|
+
if (firstCell.formula) {
|
|
424
|
+
firstCell.value = { formula: cleanStr };
|
|
320
425
|
}
|
|
321
426
|
else {
|
|
322
|
-
|
|
427
|
+
firstCell.value = cleanStr;
|
|
323
428
|
}
|
|
429
|
+
// Replace double quotes with empty chars because they can
|
|
430
|
+
// be included in formulas causing issues with
|
|
431
|
+
// the regex and the outline level calculation
|
|
432
|
+
const leadingSpaces = cleanStr.replace(/"/g, "").match(/^ */)?.[0].length || 0;
|
|
433
|
+
const outlineLevel = Math.floor(leadingSpaces / 8) + 1;
|
|
434
|
+
row.outlineLevel = outlineLevel - 1;
|
|
435
|
+
lastOutlineLevel = outlineLevel;
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
row.outlineLevel = lastOutlineLevel;
|
|
324
439
|
}
|
|
325
440
|
});
|
|
326
441
|
};
|