@sme.up/doc-alchemist 1.1.0-SNAPSHOT-20250623155458 → 1.1.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 (127) hide show
  1. package/README.md +278 -30
  2. package/dist/assets/gfx-data.d.ts +1 -0
  3. package/dist/assets/gfx-data.js +2 -0
  4. package/dist/assets/gfx-data.js.map +1 -0
  5. package/dist/converters/excel/commons.d.ts +35 -0
  6. package/dist/converters/excel/commons.js +216 -0
  7. package/dist/converters/excel/commons.js.map +1 -0
  8. package/dist/{src/excel/excel-generator.types.d.ts → converters/excel/excel-converter.types.d.ts} +1 -0
  9. package/dist/{src/excel/excel-generator.types.js → converters/excel/excel-converter.types.js} +4 -2
  10. package/dist/converters/excel/excel-converter.types.js.map +1 -0
  11. package/dist/{src/excel/matrix-generator.d.ts → converters/excel/matrix-converter.d.ts} +4 -2
  12. package/dist/{src/excel/matrix-generator.js → converters/excel/matrix-converter.js} +32 -17
  13. package/dist/converters/excel/matrix-converter.js.map +1 -0
  14. package/dist/{src/excel/tree-generator.d.ts → converters/excel/tree-converter.d.ts} +2 -2
  15. package/dist/{src/excel/tree-generator.js → converters/excel/tree-converter.js} +5 -5
  16. package/dist/converters/excel/tree-converter.js.map +1 -0
  17. package/dist/{src/excel/excel-generator.d.ts → converters/excel-converter.d.ts} +2 -1
  18. package/dist/{src/excel/excel-generator.js → converters/excel-converter.js} +4 -4
  19. package/dist/converters/excel-converter.js.map +1 -0
  20. package/dist/converters/images/charts-generator.d.ts +9 -0
  21. package/dist/converters/images/charts-generator.js +250 -0
  22. package/dist/converters/images/charts-generator.js.map +1 -0
  23. package/dist/converters/pdf/autotable-renderer.d.ts +3 -0
  24. package/dist/converters/pdf/autotable-renderer.js +89 -0
  25. package/dist/converters/pdf/autotable-renderer.js.map +1 -0
  26. package/dist/converters/pdf/cover-renderer.d.ts +1 -0
  27. package/dist/converters/pdf/cover-renderer.js +26 -0
  28. package/dist/converters/pdf/cover-renderer.js.map +1 -0
  29. package/dist/converters/pdf/formulas-helper.d.ts +40 -0
  30. package/dist/converters/pdf/formulas-helper.js +227 -0
  31. package/dist/converters/pdf/formulas-helper.js.map +1 -0
  32. package/dist/converters/pdf/matrix-converter.d.ts +16 -0
  33. package/dist/converters/pdf/matrix-converter.js +198 -0
  34. package/dist/converters/pdf/matrix-converter.js.map +1 -0
  35. package/dist/converters/pdf/pdf-converter.types.d.ts +12 -0
  36. package/dist/converters/pdf/pdf-converter.types.js +2 -0
  37. package/dist/converters/pdf/pdf-converter.types.js.map +1 -0
  38. package/dist/converters/pdf/sch-converter.d.ts +3 -0
  39. package/dist/converters/pdf/sch-converter.js +99 -0
  40. package/dist/converters/pdf/sch-converter.js.map +1 -0
  41. package/dist/converters/pdf-converter.d.ts +8 -0
  42. package/dist/converters/pdf-converter.js +44 -0
  43. package/dist/converters/pdf-converter.js.map +1 -0
  44. package/dist/index.d.ts +7 -4
  45. package/dist/index.js +4 -2
  46. package/dist/index.js.map +1 -1
  47. package/dist/types/component.d.ts +53 -0
  48. package/dist/types/component.js +53 -0
  49. package/dist/types/component.js.map +1 -0
  50. package/dist/types/data-structures/smeupDataStructure.d.ts +215 -0
  51. package/dist/types/data-structures/smeupDataStructure.js +99 -0
  52. package/dist/types/data-structures/smeupDataStructure.js.map +1 -0
  53. package/dist/types/data-structures/smeupDataTable.d.ts +116 -0
  54. package/dist/types/data-structures/smeupDataTable.js +43 -0
  55. package/dist/types/data-structures/smeupDataTable.js.map +1 -0
  56. package/dist/types/data-structures/smeupDataTree.d.ts +13 -0
  57. package/dist/types/data-structures/smeupDataTree.js +2 -0
  58. package/dist/types/data-structures/smeupDataTree.js.map +1 -0
  59. package/dist/types/data-structures/smeupSch.d.ts +72 -0
  60. package/dist/types/data-structures/smeupSch.js +11 -0
  61. package/dist/types/data-structures/smeupSch.js.map +1 -0
  62. package/dist/types/dynamism.d.ts +45 -0
  63. package/dist/types/dynamism.js +30 -0
  64. package/dist/types/dynamism.js.map +1 -0
  65. package/dist/types/general.d.ts +22 -0
  66. package/dist/types/general.js +24 -0
  67. package/dist/types/general.js.map +1 -0
  68. package/dist/types/helpers.d.ts +4 -0
  69. package/dist/types/helpers.js +6 -0
  70. package/dist/types/helpers.js.map +1 -0
  71. package/dist/{src/types → types}/index.d.ts +8 -2
  72. package/dist/{src/types → types}/index.js +1 -0
  73. package/dist/types/index.js.map +1 -0
  74. package/dist/utils/commons-utility.d.ts +59 -0
  75. package/dist/{src/utils/generator-utility.js → utils/commons-utility.js} +63 -10
  76. package/dist/utils/commons-utility.js.map +1 -0
  77. package/dist/utils/datastructure-utility.d.ts +2 -0
  78. package/dist/utils/datastructure-utility.js +5 -0
  79. package/dist/utils/datastructure-utility.js.map +1 -0
  80. package/dist/{src/utils → utils}/dates-utility.d.ts +9 -0
  81. package/dist/{src/utils → utils}/dates-utility.js +18 -0
  82. package/dist/utils/dates-utility.js.map +1 -0
  83. package/dist/utils/formatter-utility.d.ts +3 -0
  84. package/dist/utils/formatter-utility.js +36 -0
  85. package/dist/utils/formatter-utility.js.map +1 -0
  86. package/dist/{src/utils → utils}/math-utility.d.ts +1 -0
  87. package/dist/{src/utils → utils}/math-utility.js +10 -0
  88. package/dist/utils/math-utility.js.map +1 -0
  89. package/dist/utils/objects-utility.js.map +1 -0
  90. package/dist/utils/regex-utility.js.map +1 -0
  91. package/package.json +13 -11
  92. package/dist/assets/sample-data.d.ts +0 -48
  93. package/dist/assets/sample-data.js +0 -372
  94. package/dist/assets/sample-data.js.map +0 -1
  95. package/dist/debug.d.ts +0 -1
  96. package/dist/debug.js +0 -29
  97. package/dist/debug.js.map +0 -1
  98. package/dist/src/excel/commons.d.ts +0 -21
  99. package/dist/src/excel/commons.js +0 -120
  100. package/dist/src/excel/commons.js.map +0 -1
  101. package/dist/src/excel/excel-generator.js.map +0 -1
  102. package/dist/src/excel/excel-generator.types.js.map +0 -1
  103. package/dist/src/excel/matrix-generator.js.map +0 -1
  104. package/dist/src/excel/tree-generator.js.map +0 -1
  105. package/dist/src/index.d.ts +0 -1
  106. package/dist/src/index.js +0 -2
  107. package/dist/src/index.js.map +0 -1
  108. package/dist/src/pdf/pdf-generator.d.ts +0 -7
  109. package/dist/src/pdf/pdf-generator.js +0 -28
  110. package/dist/src/pdf/pdf-generator.js.map +0 -1
  111. package/dist/src/types/index.js.map +0 -1
  112. package/dist/src/utils/datastructure-utility.d.ts +0 -2
  113. package/dist/src/utils/datastructure-utility.js +0 -5
  114. package/dist/src/utils/datastructure-utility.js.map +0 -1
  115. package/dist/src/utils/dates-utility.js.map +0 -1
  116. package/dist/src/utils/generator-utility.d.ts +0 -34
  117. package/dist/src/utils/generator-utility.js.map +0 -1
  118. package/dist/src/utils/math-utility.js.map +0 -1
  119. package/dist/src/utils/objects-utility.js.map +0 -1
  120. package/dist/src/utils/regex-utility.js.map +0 -1
  121. package/dist/tests/excel-generator.test.d.ts +0 -1
  122. package/dist/tests/excel-generator.test.js +0 -406
  123. package/dist/tests/excel-generator.test.js.map +0 -1
  124. /package/dist/{src/utils → utils}/objects-utility.d.ts +0 -0
  125. /package/dist/{src/utils → utils}/objects-utility.js +0 -0
  126. /package/dist/{src/utils → utils}/regex-utility.d.ts +0 -0
  127. /package/dist/{src/utils → utils}/regex-utility.js +0 -0
@@ -0,0 +1,40 @@
1
+ import { WebupManagerData } from "../../types/index.js";
2
+ import { CellValueProps } from "./pdf-converter.types.js";
3
+ import ExcelJS from "exceljs";
4
+ /**
5
+ * Handles the calculation of Excel-like SUBTOTAL formulas for a given cell and range.
6
+ *
7
+ * Supports various SUBTOTAL types such as SUM, AVERAGE, COUNTA, MAX, and MIN.
8
+ * The function extracts the relevant range from the worksheet, computes the result
9
+ * based on the subtotal type, and formats the output as needed (including date and number formatting).
10
+ *
11
+ * @param cell - The ExcelJS cell object where the formula is applied.
12
+ * @param worksheet - The ExcelJS worksheet containing the data range.
13
+ * @param webupManagerData - Additional data/context used for formatting numbers and dates.
14
+ * @param subtotalMatch - The RegExp match array containing the parsed SUBTOTAL formula components:
15
+ * - [1]: The subtotal type (e.g., 1 for AVERAGE, 3 for COUNTA, 4 for MAX, 5 for MIN, 9 for SUM).
16
+ * - [2]: The start cell reference of the range.
17
+ * - [3]: The end cell reference of the range.
18
+ * @returns An object containing the computed value and its type ("number" or "string").
19
+ */
20
+ export declare const handleSubtotalFormula: (cell: ExcelJS.Cell, worksheet: ExcelJS.Worksheet, webupManagerData: WebupManagerData, subtotalMatch: RegExpMatchArray) => CellValueProps;
21
+ /**
22
+ * Evaluates a standard Excel formula from a given cell by replacing cell references
23
+ * with their actual values from the worksheet and then computing the result.
24
+ *
25
+ * - Replaces cell references (e.g., "A1") in the formula with their corresponding values.
26
+ * - Handles different cell value types: number, string, formula result, and date.
27
+ * - Evaluates the resulting formula string using a safe function context.
28
+ * - Applies number formatting if the result is numeric and a format is specified.
29
+ * - Returns the computed value and its type ("number" or "string").
30
+ *
31
+ * @param cell - The ExcelJS cell containing the formula to evaluate.
32
+ * @param worksheet - The ExcelJS worksheet object for resolving cell references.
33
+ * @param webupManagerData - Additional data used for number formatting.
34
+ * @returns An object containing the evaluated value and its type.
35
+ */
36
+ export declare const evaluateStandardFormula: (cell: ExcelJS.Cell, worksheet: ExcelJS.Worksheet, webupManagerData: WebupManagerData) => CellValueProps;
37
+ /**
38
+ * Extracts and formats the value of a given ExcelJS cell based on its type.
39
+ */
40
+ export declare const getCellValueData: (cell: ExcelJS.Cell, worksheet: ExcelJS.Worksheet, webupManagerData: WebupManagerData) => CellValueProps;
@@ -0,0 +1,227 @@
1
+ import { getCellsFromRange } from "../excel/commons.js";
2
+ import { areAllValuesDates } from "../../utils/dates-utility.js";
3
+ import { formatDate, formatNumber } from "../../utils/formatter-utility.js";
4
+ import ExcelJS from "exceljs";
5
+ import { calculateExpression } from "../../utils/math-utility.js";
6
+ /**
7
+ * Handles the calculation of Excel-like SUBTOTAL formulas for a given cell and range.
8
+ *
9
+ * Supports various SUBTOTAL types such as SUM, AVERAGE, COUNTA, MAX, and MIN.
10
+ * The function extracts the relevant range from the worksheet, computes the result
11
+ * based on the subtotal type, and formats the output as needed (including date and number formatting).
12
+ *
13
+ * @param cell - The ExcelJS cell object where the formula is applied.
14
+ * @param worksheet - The ExcelJS worksheet containing the data range.
15
+ * @param webupManagerData - Additional data/context used for formatting numbers and dates.
16
+ * @param subtotalMatch - The RegExp match array containing the parsed SUBTOTAL formula components:
17
+ * - [1]: The subtotal type (e.g., 1 for AVERAGE, 3 for COUNTA, 4 for MAX, 5 for MIN, 9 for SUM).
18
+ * - [2]: The start cell reference of the range.
19
+ * - [3]: The end cell reference of the range.
20
+ * @returns An object containing the computed value and its type ("number" or "string").
21
+ */
22
+ export const handleSubtotalFormula = (cell, worksheet, webupManagerData, subtotalMatch) => {
23
+ const subtotalType = parseInt(subtotalMatch[1], 10);
24
+ const startRef = subtotalMatch[2];
25
+ const endRef = subtotalMatch[3];
26
+ const cells = getCellsFromRange(worksheet, startRef, endRef).filter(cell => cell.type !== ExcelJS.ValueType.Formula);
27
+ let result;
28
+ const areAllDates = areAllValuesDates(cells);
29
+ switch (subtotalType) {
30
+ case 3: // COUNTA
31
+ result = cells.length;
32
+ break;
33
+ case 9: // SUM
34
+ result = cells.reduce((sum, cell) => {
35
+ const n = typeof cell.value === "number"
36
+ ? cell.value
37
+ : typeof cell.value === "string"
38
+ ? parseFloat(cell.value)
39
+ : NaN;
40
+ return !isNaN(n)
41
+ ? (typeof sum === "number"
42
+ ? sum
43
+ : typeof sum === "string"
44
+ ? parseFloat(sum)
45
+ : 0) + n
46
+ : sum;
47
+ }, 0);
48
+ break;
49
+ case 4: // MAX
50
+ result = cells.length
51
+ ? Math.max(...cells.map(cell => {
52
+ if (cell.type === ExcelJS.ValueType.Date) {
53
+ return cell.value instanceof Date
54
+ ? cell.value.getTime()
55
+ : -Infinity;
56
+ }
57
+ return typeof cell.value === "number"
58
+ ? cell.value
59
+ : (typeof cell.value === "string"
60
+ ? parseFloat(cell.value)
61
+ : -Infinity) || -Infinity;
62
+ }))
63
+ : "";
64
+ break;
65
+ case 5: // MIN
66
+ result = cells.length
67
+ ? Math.min(...cells.map(cell => {
68
+ if (cell.type === ExcelJS.ValueType.Date) {
69
+ return cell.value instanceof Date
70
+ ? cell.value.getTime()
71
+ : Infinity;
72
+ }
73
+ return typeof cell.value === "number"
74
+ ? cell.value
75
+ : (typeof cell.value === "string"
76
+ ? parseFloat(cell.value)
77
+ : Infinity) || Infinity;
78
+ }))
79
+ : "";
80
+ break;
81
+ case 1: {
82
+ // AVERAGE
83
+ const nums = cells
84
+ .map(cell => typeof cell.value === "number"
85
+ ? cell.value
86
+ : typeof cell.value === "string"
87
+ ? parseFloat(cell.value)
88
+ : NaN)
89
+ .filter(v => !isNaN(v));
90
+ result = nums.length ? nums.reduce((a, b) => a + b, 0) / nums.length : "";
91
+ break;
92
+ }
93
+ default: {
94
+ if (cell.result != null && typeof cell.result !== "object") {
95
+ result = cell.result;
96
+ }
97
+ else {
98
+ result =
99
+ cell.text ||
100
+ (typeof cell.value === "string" || typeof cell.value === "number"
101
+ ? cell.value
102
+ : "") ||
103
+ "";
104
+ }
105
+ break;
106
+ }
107
+ }
108
+ if (areAllDates) {
109
+ return {
110
+ value: result,
111
+ text: formatDate(new Date(result), webupManagerData),
112
+ type: "date",
113
+ };
114
+ }
115
+ else if (typeof result === "number" && cell.numFmt) {
116
+ return {
117
+ value: result,
118
+ text: formatNumber(result, cell.numFmt, webupManagerData),
119
+ type: "number",
120
+ };
121
+ }
122
+ return {
123
+ value: result,
124
+ text: result.toString(),
125
+ type: typeof result === "number" ? "number" : "string",
126
+ };
127
+ };
128
+ /**
129
+ * Evaluates a standard Excel formula from a given cell by replacing cell references
130
+ * with their actual values from the worksheet and then computing the result.
131
+ *
132
+ * - Replaces cell references (e.g., "A1") in the formula with their corresponding values.
133
+ * - Handles different cell value types: number, string, formula result, and date.
134
+ * - Evaluates the resulting formula string using a safe function context.
135
+ * - Applies number formatting if the result is numeric and a format is specified.
136
+ * - Returns the computed value and its type ("number" or "string").
137
+ *
138
+ * @param cell - The ExcelJS cell containing the formula to evaluate.
139
+ * @param worksheet - The ExcelJS worksheet object for resolving cell references.
140
+ * @param webupManagerData - Additional data used for number formatting.
141
+ * @returns An object containing the evaluated value and its type.
142
+ */
143
+ export const evaluateStandardFormula = (cell, worksheet, webupManagerData) => {
144
+ const formula = cell.formula;
145
+ const formulaWithSolvedVariables = formula.replace(/([A-Z]+\d+)/g, ref => {
146
+ try {
147
+ const refCell = worksheet.getCell(ref);
148
+ if (refCell) {
149
+ if (refCell.type === ExcelJS.ValueType.Number) {
150
+ return refCell.value?.toString() ?? "0";
151
+ }
152
+ else if (refCell.type === ExcelJS.ValueType.String) {
153
+ // If the cell contains text, return as is (no quotes) for JS compatibility
154
+ return refCell.value?.toString() ?? "";
155
+ }
156
+ else if (refCell.type === ExcelJS.ValueType.Formula) {
157
+ return getCellValueData(refCell, worksheet, webupManagerData).value.toString();
158
+ }
159
+ else if (refCell.type === ExcelJS.ValueType.Date &&
160
+ refCell.value instanceof Date) {
161
+ return refCell.value.getTime().toString();
162
+ }
163
+ else {
164
+ return refCell.value?.toString() ?? "0";
165
+ }
166
+ }
167
+ }
168
+ catch {
169
+ return "0";
170
+ }
171
+ return "0";
172
+ });
173
+ const result = calculateExpression(formulaWithSolvedVariables);
174
+ // If the result is a number and a format is specified, apply it
175
+ if (typeof result === "number" && cell.numFmt) {
176
+ return {
177
+ value: result,
178
+ text: formatNumber(result, cell.numFmt, webupManagerData),
179
+ type: "number",
180
+ };
181
+ }
182
+ return {
183
+ value: result,
184
+ text: result != null ? result.toString() : cell.formula,
185
+ type: typeof result === "number" ? "number" : "string",
186
+ };
187
+ };
188
+ /**
189
+ * Extracts and formats the value of a given ExcelJS cell based on its type.
190
+ */
191
+ export const getCellValueData = (cell, worksheet, webupManagerData) => {
192
+ if (cell.type === ExcelJS.ValueType.Formula &&
193
+ typeof cell.formula === "string") {
194
+ const subtotalMatch = cell.formula.match(/^SUBTOTAL\((\d+)\s*,\s*([A-Z]+\d+):([A-Z]+\d+)\)/i);
195
+ if (subtotalMatch) {
196
+ return handleSubtotalFormula(cell, worksheet, webupManagerData, subtotalMatch);
197
+ }
198
+ else {
199
+ return evaluateStandardFormula(cell, worksheet, webupManagerData);
200
+ }
201
+ }
202
+ else if (cell.type === ExcelJS.ValueType.Date &&
203
+ cell.value instanceof Date) {
204
+ return {
205
+ value: cell.value,
206
+ text: formatDate(cell.value, webupManagerData),
207
+ type: "date",
208
+ };
209
+ }
210
+ else if (cell.type === ExcelJS.ValueType.Number) {
211
+ return {
212
+ value: cell.value,
213
+ text: formatNumber(cell.value, cell.numFmt ?? 0, webupManagerData),
214
+ type: "number",
215
+ };
216
+ }
217
+ else {
218
+ // Fallback to text or value if available, otherwise empty string
219
+ const value = cell?.text || cell?.value?.toString() || "";
220
+ return {
221
+ value: value,
222
+ text: value,
223
+ type: "string",
224
+ };
225
+ }
226
+ };
227
+ //# sourceMappingURL=formulas-helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formulas-helper.js","sourceRoot":"","sources":["../../../src/converters/pdf/formulas-helper.ts"],"names":[],"mappings":"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","sourcesContent":["import { getCellsFromRange } from \"../excel/commons.js\";\nimport { WebupManagerData } from \"../../types/index.js\";\nimport { areAllValuesDates } from \"../../utils/dates-utility.js\";\nimport { formatDate, formatNumber } from \"../../utils/formatter-utility.js\";\nimport { CellValueProps } from \"./pdf-converter.types.js\";\nimport ExcelJS from \"exceljs\";\nimport { calculateExpression } from \"../../utils/math-utility.js\";\n\n/**\n * Handles the calculation of Excel-like SUBTOTAL formulas for a given cell and range.\n *\n * Supports various SUBTOTAL types such as SUM, AVERAGE, COUNTA, MAX, and MIN.\n * The function extracts the relevant range from the worksheet, computes the result\n * based on the subtotal type, and formats the output as needed (including date and number formatting).\n *\n * @param cell - The ExcelJS cell object where the formula is applied.\n * @param worksheet - The ExcelJS worksheet containing the data range.\n * @param webupManagerData - Additional data/context used for formatting numbers and dates.\n * @param subtotalMatch - The RegExp match array containing the parsed SUBTOTAL formula components:\n * - [1]: The subtotal type (e.g., 1 for AVERAGE, 3 for COUNTA, 4 for MAX, 5 for MIN, 9 for SUM).\n * - [2]: The start cell reference of the range.\n * - [3]: The end cell reference of the range.\n * @returns An object containing the computed value and its type (\"number\" or \"string\").\n */\nexport const handleSubtotalFormula = (\n cell: ExcelJS.Cell,\n worksheet: ExcelJS.Worksheet,\n webupManagerData: WebupManagerData,\n subtotalMatch: RegExpMatchArray,\n): CellValueProps => {\n const subtotalType = parseInt(subtotalMatch[1], 10);\n const startRef = subtotalMatch[2];\n const endRef = subtotalMatch[3];\n const cells = getCellsFromRange(worksheet, startRef, endRef).filter(\n cell => cell.type !== ExcelJS.ValueType.Formula,\n );\n let result: number | string | \"\";\n const areAllDates = areAllValuesDates(cells);\n switch (subtotalType) {\n case 3: // COUNTA\n result = cells.length;\n break;\n case 9: // SUM\n result = cells.reduce((sum, cell) => {\n const n =\n typeof cell.value === \"number\"\n ? cell.value\n : typeof cell.value === \"string\"\n ? parseFloat(cell.value)\n : NaN;\n return !isNaN(n)\n ? (typeof sum === \"number\"\n ? sum\n : typeof sum === \"string\"\n ? parseFloat(sum)\n : 0) + n\n : sum;\n }, 0);\n break;\n case 4: // MAX\n result = cells.length\n ? Math.max(\n ...cells.map(cell => {\n if (cell.type === ExcelJS.ValueType.Date) {\n return cell.value instanceof Date\n ? cell.value.getTime()\n : -Infinity;\n }\n return typeof cell.value === \"number\"\n ? cell.value\n : (typeof cell.value === \"string\"\n ? parseFloat(cell.value)\n : -Infinity) || -Infinity;\n }),\n )\n : \"\";\n break;\n case 5: // MIN\n result = cells.length\n ? Math.min(\n ...cells.map(cell => {\n if (cell.type === ExcelJS.ValueType.Date) {\n return cell.value instanceof Date\n ? cell.value.getTime()\n : Infinity;\n }\n return typeof cell.value === \"number\"\n ? cell.value\n : (typeof cell.value === \"string\"\n ? parseFloat(cell.value)\n : Infinity) || Infinity;\n }),\n )\n : \"\";\n break;\n case 1: {\n // AVERAGE\n const nums = cells\n .map(cell =>\n typeof cell.value === \"number\"\n ? cell.value\n : typeof cell.value === \"string\"\n ? parseFloat(cell.value)\n : NaN,\n )\n .filter(v => !isNaN(v));\n result = nums.length ? nums.reduce((a, b) => a + b, 0) / nums.length : \"\";\n break;\n }\n default: {\n if (cell.result != null && typeof cell.result !== \"object\") {\n result = cell.result;\n } else {\n result =\n cell.text ||\n (typeof cell.value === \"string\" || typeof cell.value === \"number\"\n ? cell.value\n : \"\") ||\n \"\";\n }\n break;\n }\n }\n\n if (areAllDates) {\n return {\n value: result,\n text: formatDate(new Date(result), webupManagerData),\n type: \"date\",\n };\n } else if (typeof result === \"number\" && cell.numFmt) {\n return {\n value: result,\n text: formatNumber(result, cell.numFmt, webupManagerData),\n type: \"number\",\n };\n }\n return {\n value: result,\n text: result.toString(),\n type: typeof result === \"number\" ? \"number\" : \"string\",\n };\n};\n\n/**\n * Evaluates a standard Excel formula from a given cell by replacing cell references\n * with their actual values from the worksheet and then computing the result.\n *\n * - Replaces cell references (e.g., \"A1\") in the formula with their corresponding values.\n * - Handles different cell value types: number, string, formula result, and date.\n * - Evaluates the resulting formula string using a safe function context.\n * - Applies number formatting if the result is numeric and a format is specified.\n * - Returns the computed value and its type (\"number\" or \"string\").\n *\n * @param cell - The ExcelJS cell containing the formula to evaluate.\n * @param worksheet - The ExcelJS worksheet object for resolving cell references.\n * @param webupManagerData - Additional data used for number formatting.\n * @returns An object containing the evaluated value and its type.\n */\nexport const evaluateStandardFormula = (\n cell: ExcelJS.Cell,\n worksheet: ExcelJS.Worksheet,\n webupManagerData: WebupManagerData,\n): CellValueProps => {\n const formula = cell.formula;\n const formulaWithSolvedVariables = formula.replace(/([A-Z]+\\d+)/g, ref => {\n try {\n const refCell = worksheet.getCell(ref);\n if (refCell) {\n if (refCell.type === ExcelJS.ValueType.Number) {\n return refCell.value?.toString() ?? \"0\";\n } else if (refCell.type === ExcelJS.ValueType.String) {\n // If the cell contains text, return as is (no quotes) for JS compatibility\n return refCell.value?.toString() ?? \"\";\n } else if (refCell.type === ExcelJS.ValueType.Formula) {\n return getCellValueData(\n refCell,\n worksheet,\n webupManagerData,\n ).value.toString();\n } else if (\n refCell.type === ExcelJS.ValueType.Date &&\n refCell.value instanceof Date\n ) {\n return refCell.value.getTime().toString();\n } else {\n return refCell.value?.toString() ?? \"0\";\n }\n }\n } catch {\n return \"0\";\n }\n return \"0\";\n });\n const result = calculateExpression(formulaWithSolvedVariables);\n // If the result is a number and a format is specified, apply it\n if (typeof result === \"number\" && cell.numFmt) {\n return {\n value: result,\n text: formatNumber(result, cell.numFmt, webupManagerData),\n type: \"number\",\n };\n }\n return {\n value: result,\n text: result != null ? result.toString() : cell.formula,\n type: typeof result === \"number\" ? \"number\" : \"string\",\n };\n};\n\n/**\n * Extracts and formats the value of a given ExcelJS cell based on its type.\n */\nexport const getCellValueData = (\n cell: ExcelJS.Cell,\n worksheet: ExcelJS.Worksheet,\n webupManagerData: WebupManagerData,\n): CellValueProps => {\n if (\n cell.type === ExcelJS.ValueType.Formula &&\n typeof cell.formula === \"string\"\n ) {\n const subtotalMatch = cell.formula.match(\n /^SUBTOTAL\\((\\d+)\\s*,\\s*([A-Z]+\\d+):([A-Z]+\\d+)\\)/i,\n );\n if (subtotalMatch) {\n return handleSubtotalFormula(\n cell,\n worksheet,\n webupManagerData,\n subtotalMatch,\n );\n } else {\n return evaluateStandardFormula(cell, worksheet, webupManagerData);\n }\n } else if (\n cell.type === ExcelJS.ValueType.Date &&\n cell.value instanceof Date\n ) {\n return {\n value: cell.value,\n text: formatDate(cell.value, webupManagerData),\n type: \"date\",\n };\n } else if (cell.type === ExcelJS.ValueType.Number) {\n return {\n value: cell.value as number,\n text: formatNumber(\n cell.value as number,\n cell.numFmt ?? 0,\n webupManagerData,\n ),\n type: \"number\",\n };\n } else {\n // Fallback to text or value if available, otherwise empty string\n const value = cell?.text || cell?.value?.toString() || \"\";\n return {\n value: value,\n text: value,\n type: \"string\",\n };\n }\n};\n"]}
@@ -0,0 +1,16 @@
1
+ import * as jsPDFModule from "jspdf";
2
+ import ExcelJS from "exceljs";
3
+ import { WebupManagerData } from "../../index.js";
4
+ /**
5
+ * Converts an ExcelJS worksheet into a PDF document using jsPDF and autoTable.
6
+ *
7
+ * This function extracts visible headers and data from the provided worksheet,
8
+ * applies cell styles, simulates Excel cell overflow, and calculates the optimal
9
+ * font size for the table. It then generates a PDF document with the formatted
10
+ * table and returns the resulting jsPDF instance.
11
+ *
12
+ * @param worksheet - The ExcelJS worksheet to convert to PDF.
13
+ * @param webupManagerData - Additional data required for extracting worksheet content.
14
+ * @returns A Promise that resolves to a jsPDF document containing the worksheet data as a table.
15
+ */
16
+ export declare const dataTableToPdfDoc: (worksheet: ExcelJS.Worksheet, webupManagerData: WebupManagerData) => Promise<jsPDFModule.jsPDF>;
@@ -0,0 +1,198 @@
1
+ import * as jsPDFModule from "jspdf";
2
+ import autoTable from "jspdf-autotable";
3
+ import { convertColorToRgb } from "../../utils/commons-utility.js";
4
+ import { logoBase64 } from "../../assets/gfx-data.js";
5
+ import { getCellValueData } from "./formulas-helper.js";
6
+ import { getAutoTableOptions } from "./autotable-renderer.js";
7
+ /**
8
+ * Converts an ExcelJS worksheet into a PDF document using jsPDF and autoTable.
9
+ *
10
+ * This function extracts visible headers and data from the provided worksheet,
11
+ * applies cell styles, simulates Excel cell overflow, and calculates the optimal
12
+ * font size for the table. It then generates a PDF document with the formatted
13
+ * table and returns the resulting jsPDF instance.
14
+ *
15
+ * @param worksheet - The ExcelJS worksheet to convert to PDF.
16
+ * @param webupManagerData - Additional data required for extracting worksheet content.
17
+ * @returns A Promise that resolves to a jsPDF document containing the worksheet data as a table.
18
+ */
19
+ export const dataTableToPdfDoc = async (worksheet, webupManagerData) => {
20
+ const doc = new jsPDFModule.jsPDF({ orientation: "landscape" });
21
+ doc.setFont("helvetica", "normal");
22
+ doc.setFontSize(10);
23
+ // Extract headers and column indexes
24
+ const { visibleHeaders, visibleColumnIndexes } = extractVisibleHeadersAndIndexes(worksheet);
25
+ // Extract data and cell styles separately
26
+ const data = extractData(worksheet, visibleColumnIndexes, webupManagerData);
27
+ const cellStyles = extractStyles(worksheet, visibleColumnIndexes, data);
28
+ // Post-process data to simulate Excel overflow
29
+ postProcessExcelOverflow(data, cellStyles);
30
+ // Calculate optimal font size based on data
31
+ const pageWidth = doc.internal.pageSize.getWidth();
32
+ const optimalFontSize = calculateOptimalFontSize(data, visibleHeaders, pageWidth);
33
+ autoTable(doc, getAutoTableOptions(visibleHeaders, data, optimalFontSize, cellStyles, logoBase64));
34
+ return doc;
35
+ };
36
+ // Function to calculate the optimal font size
37
+ const calculateOptimalFontSize = (data, visibleHeaders, pageWidth) => {
38
+ const maxSamples = Math.min(100, data.length); // Analyze max 100 rows
39
+ const availableWidth = pageWidth - 20; // Margins
40
+ const numColumns = visibleHeaders.length;
41
+ // If there are few columns, we can allow a larger font size
42
+ if (numColumns <= 3) {
43
+ return 10;
44
+ }
45
+ // Calculate more accurate statistics per column
46
+ const columnStats = visibleHeaders.map((header, colIndex) => {
47
+ const lengths = [header.length];
48
+ // Collect all cell lengths for this column
49
+ for (let rowIndex = 0; rowIndex < maxSamples; rowIndex++) {
50
+ if (data[rowIndex] && data[rowIndex][colIndex]) {
51
+ const cellLength = data[rowIndex][colIndex].text.replace(/\u00A0/g, " ").length;
52
+ lengths.push(cellLength);
53
+ }
54
+ }
55
+ lengths.sort((a, b) => a - b);
56
+ // Use the 90th percentile instead of the maximum to be less conservative
57
+ const percentile90Index = Math.floor(lengths.length * 0.9);
58
+ const effectiveWidth = lengths[percentile90Index] || lengths[lengths.length - 1];
59
+ // The average length to balance very long columns with short ones
60
+ const avgLength = lengths.reduce((sum, len) => sum + len, 0) / lengths.length;
61
+ return {
62
+ max: Math.max(...lengths),
63
+ p90: effectiveWidth,
64
+ avg: avgLength,
65
+ min: Math.min(...lengths),
66
+ };
67
+ });
68
+ // Use a mixed strategy: combine 90th percentile with weighted average
69
+ const estimatedColumnWidths = columnStats.map(stats => {
70
+ // Weight the average more than the 90th percentile to be less pessimistic
71
+ const weightedWidth = stats.avg * 0.7 + stats.p90 * 0.3;
72
+ return Math.max(weightedWidth, 3); // Minimum width of 3 characters
73
+ });
74
+ // Try different font sizes starting from the largest
75
+ for (let testFontSize = 10; testFontSize >= 4; testFontSize -= 0.5) {
76
+ // More optimistic factor based on font size
77
+ const charWidthFactor = testFontSize >= 8 ? 3.2 : testFontSize >= 6 ? 2.8 : 2.5;
78
+ const estimatedTotalWidth = estimatedColumnWidths.reduce((sum, width) => sum + width * charWidthFactor, 0);
79
+ // Add a margin for columns (space between columns)
80
+ const totalWidthWithMargins = estimatedTotalWidth + numColumns * 10; // 10px between columns
81
+ if (totalWidthWithMargins <= availableWidth) {
82
+ return testFontSize;
83
+ }
84
+ }
85
+ return 4; // Minimum font size if nothing fits
86
+ };
87
+ /**
88
+ * Extracts visible headers and their column indexes from the worksheet (ignoring hidden columns).
89
+ */
90
+ const extractVisibleHeadersAndIndexes = (worksheet) => {
91
+ const headerRow = worksheet.getRow(1);
92
+ const visibleHeaders = [];
93
+ const visibleColumnIndexes = [];
94
+ headerRow.eachCell({ includeEmpty: true }, (cell, colNumber) => {
95
+ const column = worksheet.getColumn(colNumber);
96
+ if (!column.hidden) {
97
+ visibleHeaders.push(cell?.toString() ?? "");
98
+ visibleColumnIndexes.push(colNumber);
99
+ }
100
+ });
101
+ return { visibleHeaders, visibleColumnIndexes };
102
+ };
103
+ /**
104
+ * Extracts the data from the worksheet for the given visible columns, formatting dates and preserving spaces.
105
+ */
106
+ const extractData = (worksheet, visibleColumnIndexes, webupManagerData) => {
107
+ const data = [];
108
+ worksheet.eachRow((row, rowIndex) => {
109
+ if (rowIndex === 1)
110
+ return; // Skip header
111
+ const rowData = [];
112
+ visibleColumnIndexes.forEach(colIdx => {
113
+ const cell = row.getCell(colIdx);
114
+ const cellValue = getCellValueData(cell, worksheet, webupManagerData);
115
+ // Preserve spaces by replacing them with non-breaking spaces
116
+ cellValue.text = cellValue.text.replace(/ /g, "\u00A0");
117
+ rowData.push(cellValue);
118
+ });
119
+ data.push(rowData);
120
+ });
121
+ return data;
122
+ };
123
+ /**
124
+ * Extracts the cell styles (font, color, fill) for the given visible columns from the worksheet.
125
+ */
126
+ const extractStyles = (worksheet, visibleColumnIndexes, rawData) => {
127
+ const cellStyles = [];
128
+ worksheet.eachRow((row, rowIndex) => {
129
+ if (rowIndex === 1)
130
+ return; // Skip header
131
+ const rowStyles = [];
132
+ visibleColumnIndexes.forEach((colIdx, index) => {
133
+ const cell = row.getCell(colIdx);
134
+ const cellStyle = {};
135
+ // Font
136
+ if (cell.font) {
137
+ if (cell.font.bold && cell.font.italic) {
138
+ cellStyle.fontStyle = "bolditalic";
139
+ }
140
+ else if (cell.font.bold) {
141
+ cellStyle.fontStyle = "bold";
142
+ }
143
+ else if (cell.font.italic) {
144
+ cellStyle.fontStyle = "italic";
145
+ }
146
+ else {
147
+ cellStyle.fontStyle = "normal";
148
+ }
149
+ if (cell.font.color?.argb) {
150
+ const color = cell.font.color.argb;
151
+ const [r, g, b] = convertColorToRgb(color);
152
+ if (!isNaN(r) && !isNaN(g) && !isNaN(b)) {
153
+ cellStyle.textColor = [r, g, b];
154
+ }
155
+ }
156
+ }
157
+ // Fill (background color)
158
+ if (cell.fill &&
159
+ cell.fill.type === "pattern" &&
160
+ cell.fill.fgColor?.argb) {
161
+ const color = cell.fill.fgColor.argb;
162
+ const [r, g, b] = convertColorToRgb(color);
163
+ if (!isNaN(r) && !isNaN(g) && !isNaN(b)) {
164
+ cellStyle.fillColor = [r, g, b];
165
+ }
166
+ }
167
+ // Align right if the cell is numeric
168
+ if (rawData[rowIndex - 2][index].type === "number") {
169
+ cellStyle.halign = "right";
170
+ }
171
+ rowStyles.push(cellStyle);
172
+ });
173
+ cellStyles.push(rowStyles);
174
+ });
175
+ return cellStyles;
176
+ };
177
+ /**
178
+ * Post-processes the data and cell styles to simulate Excel's text overflow behavior.
179
+ * If a cell has long text and the next cell is empty, the width is set to auto.
180
+ */
181
+ const postProcessExcelOverflow = (data, cellStyles) => {
182
+ for (let rowIndex = 0; rowIndex < data.length; rowIndex++) {
183
+ for (let colIndex = 0; colIndex < data[rowIndex].length - 1; colIndex++) {
184
+ const currentCell = data[rowIndex][colIndex];
185
+ const nextCell = data[rowIndex][colIndex + 1];
186
+ // If the current cell has long text and the next one is empty or only spaces
187
+ if (currentCell &&
188
+ currentCell.text.length > 15 &&
189
+ (!nextCell || nextCell.text.trim() === "")) {
190
+ // Extend the width of the current cell
191
+ if (!cellStyles[rowIndex][colIndex].cellWidth) {
192
+ cellStyles[rowIndex][colIndex].cellWidth = "auto";
193
+ }
194
+ }
195
+ }
196
+ }
197
+ };
198
+ //# sourceMappingURL=matrix-converter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matrix-converter.js","sourceRoot":"","sources":["../../../src/converters/pdf/matrix-converter.ts"],"names":[],"mappings":"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","sourcesContent":["import * as jsPDFModule from \"jspdf\";\nimport ExcelJS from \"exceljs\";\nimport autoTable from \"jspdf-autotable\";\nimport { WebupManagerData } from \"../../index.js\";\nimport { CellStyleData, CellValueProps } from \"./pdf-converter.types.js\";\nimport { convertColorToRgb } from \"../../utils/commons-utility.js\";\nimport { logoBase64 } from \"../../assets/gfx-data.js\";\nimport { getCellValueData } from \"./formulas-helper.js\";\nimport { getAutoTableOptions } from \"./autotable-renderer.js\";\n\n/**\n * Converts an ExcelJS worksheet into a PDF document using jsPDF and autoTable.\n *\n * This function extracts visible headers and data from the provided worksheet,\n * applies cell styles, simulates Excel cell overflow, and calculates the optimal\n * font size for the table. It then generates a PDF document with the formatted\n * table and returns the resulting jsPDF instance.\n *\n * @param worksheet - The ExcelJS worksheet to convert to PDF.\n * @param webupManagerData - Additional data required for extracting worksheet content.\n * @returns A Promise that resolves to a jsPDF document containing the worksheet data as a table.\n */\nexport const dataTableToPdfDoc = async (\n worksheet: ExcelJS.Worksheet,\n webupManagerData: WebupManagerData,\n): Promise<jsPDFModule.jsPDF> => {\n const doc = new jsPDFModule.jsPDF({ orientation: \"landscape\" });\n doc.setFont(\"helvetica\", \"normal\");\n doc.setFontSize(10);\n\n // Extract headers and column indexes\n const { visibleHeaders, visibleColumnIndexes } =\n extractVisibleHeadersAndIndexes(worksheet);\n\n // Extract data and cell styles separately\n const data = extractData(worksheet, visibleColumnIndexes, webupManagerData);\n const cellStyles = extractStyles(worksheet, visibleColumnIndexes, data);\n\n // Post-process data to simulate Excel overflow\n postProcessExcelOverflow(data, cellStyles);\n\n // Calculate optimal font size based on data\n const pageWidth = doc.internal.pageSize.getWidth();\n const optimalFontSize = calculateOptimalFontSize(\n data,\n visibleHeaders,\n pageWidth,\n );\n\n autoTable(\n doc,\n getAutoTableOptions(\n visibleHeaders,\n data,\n optimalFontSize,\n cellStyles,\n logoBase64,\n ),\n );\n\n return doc;\n};\n\n// Function to calculate the optimal font size\nconst calculateOptimalFontSize = (\n data: CellValueProps[][],\n visibleHeaders: string[],\n pageWidth: number,\n): number => {\n const maxSamples = Math.min(100, data.length); // Analyze max 100 rows\n const availableWidth = pageWidth - 20; // Margins\n const numColumns = visibleHeaders.length;\n\n // If there are few columns, we can allow a larger font size\n if (numColumns <= 3) {\n return 10;\n }\n\n // Calculate more accurate statistics per column\n const columnStats = visibleHeaders.map((header, colIndex) => {\n const lengths: number[] = [header.length];\n\n // Collect all cell lengths for this column\n for (let rowIndex = 0; rowIndex < maxSamples; rowIndex++) {\n if (data[rowIndex] && data[rowIndex][colIndex]) {\n const cellLength = data[rowIndex][colIndex].text.replace(\n /\\u00A0/g,\n \" \",\n ).length;\n lengths.push(cellLength);\n }\n }\n\n lengths.sort((a, b) => a - b);\n\n // Use the 90th percentile instead of the maximum to be less conservative\n const percentile90Index = Math.floor(lengths.length * 0.9);\n const effectiveWidth =\n lengths[percentile90Index] || lengths[lengths.length - 1];\n\n // The average length to balance very long columns with short ones\n const avgLength =\n lengths.reduce((sum, len) => sum + len, 0) / lengths.length;\n\n return {\n max: Math.max(...lengths),\n p90: effectiveWidth,\n avg: avgLength,\n min: Math.min(...lengths),\n };\n });\n\n // Use a mixed strategy: combine 90th percentile with weighted average\n const estimatedColumnWidths = columnStats.map(stats => {\n // Weight the average more than the 90th percentile to be less pessimistic\n const weightedWidth = stats.avg * 0.7 + stats.p90 * 0.3;\n return Math.max(weightedWidth, 3); // Minimum width of 3 characters\n });\n\n // Try different font sizes starting from the largest\n for (let testFontSize = 10; testFontSize >= 4; testFontSize -= 0.5) {\n // More optimistic factor based on font size\n const charWidthFactor =\n testFontSize >= 8 ? 3.2 : testFontSize >= 6 ? 2.8 : 2.5;\n\n const estimatedTotalWidth = estimatedColumnWidths.reduce(\n (sum, width) => sum + width * charWidthFactor,\n 0,\n );\n\n // Add a margin for columns (space between columns)\n const totalWidthWithMargins = estimatedTotalWidth + numColumns * 10; // 10px between columns\n\n if (totalWidthWithMargins <= availableWidth) {\n return testFontSize;\n }\n }\n\n return 4; // Minimum font size if nothing fits\n};\n\n/**\n * Extracts visible headers and their column indexes from the worksheet (ignoring hidden columns).\n */\nconst extractVisibleHeadersAndIndexes = (\n worksheet: ExcelJS.Worksheet,\n): { visibleHeaders: string[]; visibleColumnIndexes: number[] } => {\n const headerRow = worksheet.getRow(1);\n const visibleHeaders: string[] = [];\n const visibleColumnIndexes: number[] = [];\n headerRow.eachCell({ includeEmpty: true }, (cell, colNumber) => {\n const column = worksheet.getColumn(colNumber);\n if (!column.hidden) {\n visibleHeaders.push(cell?.toString() ?? \"\");\n visibleColumnIndexes.push(colNumber);\n }\n });\n return { visibleHeaders, visibleColumnIndexes };\n};\n\n/**\n * Extracts the data from the worksheet for the given visible columns, formatting dates and preserving spaces.\n */\nconst extractData = (\n worksheet: ExcelJS.Worksheet,\n visibleColumnIndexes: number[],\n webupManagerData: WebupManagerData,\n): CellValueProps[][] => {\n const data: CellValueProps[][] = [];\n worksheet.eachRow((row, rowIndex) => {\n if (rowIndex === 1) return; // Skip header\n const rowData: CellValueProps[] = [];\n visibleColumnIndexes.forEach(colIdx => {\n const cell = row.getCell(colIdx);\n const cellValue = getCellValueData(cell, worksheet, webupManagerData);\n // Preserve spaces by replacing them with non-breaking spaces\n cellValue.text = cellValue.text.replace(/ /g, \"\\u00A0\");\n rowData.push(cellValue);\n });\n data.push(rowData);\n });\n return data;\n};\n\n/**\n * Extracts the cell styles (font, color, fill) for the given visible columns from the worksheet.\n */\nconst extractStyles = (\n worksheet: ExcelJS.Worksheet,\n visibleColumnIndexes: number[],\n rawData: CellValueProps[][],\n): CellStyleData[][] => {\n const cellStyles: CellStyleData[][] = [];\n worksheet.eachRow((row, rowIndex) => {\n if (rowIndex === 1) return; // Skip header\n const rowStyles: CellStyleData[] = [];\n visibleColumnIndexes.forEach((colIdx, index) => {\n const cell = row.getCell(colIdx);\n const cellStyle: CellStyleData = {};\n // Font\n if (cell.font) {\n if (cell.font.bold && cell.font.italic) {\n cellStyle.fontStyle = \"bolditalic\";\n } else if (cell.font.bold) {\n cellStyle.fontStyle = \"bold\";\n } else if (cell.font.italic) {\n cellStyle.fontStyle = \"italic\";\n } else {\n cellStyle.fontStyle = \"normal\";\n }\n if (cell.font.color?.argb) {\n const color = cell.font.color.argb;\n const [r, g, b] = convertColorToRgb(color);\n if (!isNaN(r) && !isNaN(g) && !isNaN(b)) {\n cellStyle.textColor = [r, g, b];\n }\n }\n }\n // Fill (background color)\n if (\n cell.fill &&\n cell.fill.type === \"pattern\" &&\n cell.fill.fgColor?.argb\n ) {\n const color = cell.fill.fgColor.argb;\n const [r, g, b] = convertColorToRgb(color);\n if (!isNaN(r) && !isNaN(g) && !isNaN(b)) {\n cellStyle.fillColor = [r, g, b];\n }\n }\n // Align right if the cell is numeric\n if (rawData[rowIndex - 2][index].type === \"number\") {\n cellStyle.halign = \"right\";\n }\n\n rowStyles.push(cellStyle);\n });\n cellStyles.push(rowStyles);\n });\n return cellStyles;\n};\n\n/**\n * Post-processes the data and cell styles to simulate Excel's text overflow behavior.\n * If a cell has long text and the next cell is empty, the width is set to auto.\n */\nconst postProcessExcelOverflow = (\n data: CellValueProps[][],\n cellStyles: CellStyleData[][],\n) => {\n for (let rowIndex = 0; rowIndex < data.length; rowIndex++) {\n for (let colIndex = 0; colIndex < data[rowIndex].length - 1; colIndex++) {\n const currentCell = data[rowIndex][colIndex];\n const nextCell = data[rowIndex][colIndex + 1];\n\n // If the current cell has long text and the next one is empty or only spaces\n if (\n currentCell &&\n currentCell.text.length > 15 &&\n (!nextCell || nextCell.text.trim() === \"\")\n ) {\n // Extend the width of the current cell\n if (!cellStyles[rowIndex][colIndex].cellWidth) {\n cellStyles[rowIndex][colIndex].cellWidth = \"auto\";\n }\n }\n }\n }\n};\n"]}
@@ -0,0 +1,12 @@
1
+ export interface CellStyleData {
2
+ fontStyle?: "normal" | "bold" | "italic" | "bolditalic";
3
+ textColor?: [number, number, number];
4
+ fillColor?: [number, number, number];
5
+ cellWidth?: string;
6
+ halign?: "left" | "right" | "center";
7
+ }
8
+ export interface CellValueProps {
9
+ value: string | number | Date;
10
+ text: string;
11
+ type: "string" | "number" | "date";
12
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pdf-converter.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pdf-converter.types.js","sourceRoot":"","sources":["../../../src/converters/pdf/pdf-converter.types.ts"],"names":[],"mappings":"","sourcesContent":["export interface CellStyleData {\n fontStyle?: \"normal\" | \"bold\" | \"italic\" | \"bolditalic\";\n textColor?: [number, number, number];\n fillColor?: [number, number, number];\n cellWidth?: string;\n halign?: \"left\" | \"right\" | \"center\";\n}\n\nexport interface CellValueProps {\n // The raw value of the cell, can be string, number, Date\n value: string | number | Date;\n // Formatted representation of the value\n text: string;\n type: \"string\" | \"number\" | \"date\";\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import * as jsPDFModule from "jspdf";
2
+ import { SmeupSch } from "../../types/data-structures/smeupSch.js";
3
+ export declare const schedaToPdfDoc: (sch: SmeupSch) => Promise<jsPDFModule.jsPDF>;