@achmadya-dev/mcp-excel-query 0.3.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 (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +123 -0
  3. package/dist/excel/cell.d.ts +12 -0
  4. package/dist/excel/cell.d.ts.map +1 -0
  5. package/dist/excel/cell.js +136 -0
  6. package/dist/excel/cell.js.map +1 -0
  7. package/dist/excel/date.d.ts +6 -0
  8. package/dist/excel/date.d.ts.map +1 -0
  9. package/dist/excel/date.js +132 -0
  10. package/dist/excel/date.js.map +1 -0
  11. package/dist/excel/excel.d.ts +29 -0
  12. package/dist/excel/excel.d.ts.map +1 -0
  13. package/dist/excel/excel.js +94 -0
  14. package/dist/excel/excel.js.map +1 -0
  15. package/dist/excel/range.d.ts +15 -0
  16. package/dist/excel/range.d.ts.map +1 -0
  17. package/dist/excel/range.js +70 -0
  18. package/dist/excel/range.js.map +1 -0
  19. package/dist/index.d.ts +3 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +44 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/tools/excel_copy_range.d.ts +2 -0
  24. package/dist/tools/excel_copy_range.d.ts.map +1 -0
  25. package/dist/tools/excel_copy_range.js +56 -0
  26. package/dist/tools/excel_copy_range.js.map +1 -0
  27. package/dist/tools/excel_copy_sheet.d.ts +2 -0
  28. package/dist/tools/excel_copy_sheet.d.ts.map +1 -0
  29. package/dist/tools/excel_copy_sheet.js +56 -0
  30. package/dist/tools/excel_copy_sheet.js.map +1 -0
  31. package/dist/tools/excel_create_file.d.ts +2 -0
  32. package/dist/tools/excel_create_file.d.ts.map +1 -0
  33. package/dist/tools/excel_create_file.js +31 -0
  34. package/dist/tools/excel_create_file.js.map +1 -0
  35. package/dist/tools/excel_create_table.d.ts +2 -0
  36. package/dist/tools/excel_create_table.d.ts.map +1 -0
  37. package/dist/tools/excel_create_table.js +73 -0
  38. package/dist/tools/excel_create_table.js.map +1 -0
  39. package/dist/tools/excel_delete_range.d.ts +2 -0
  40. package/dist/tools/excel_delete_range.d.ts.map +1 -0
  41. package/dist/tools/excel_delete_range.js +55 -0
  42. package/dist/tools/excel_delete_range.js.map +1 -0
  43. package/dist/tools/excel_delete_sheet.d.ts +2 -0
  44. package/dist/tools/excel_delete_sheet.d.ts.map +1 -0
  45. package/dist/tools/excel_delete_sheet.js +32 -0
  46. package/dist/tools/excel_delete_sheet.js.map +1 -0
  47. package/dist/tools/excel_format_range.d.ts +2 -0
  48. package/dist/tools/excel_format_range.d.ts.map +1 -0
  49. package/dist/tools/excel_format_range.js +157 -0
  50. package/dist/tools/excel_format_range.js.map +1 -0
  51. package/dist/tools/excel_get_metadata.d.ts +2 -0
  52. package/dist/tools/excel_get_metadata.d.ts.map +1 -0
  53. package/dist/tools/excel_get_metadata.js +71 -0
  54. package/dist/tools/excel_get_metadata.js.map +1 -0
  55. package/dist/tools/excel_insert_columns.d.ts +2 -0
  56. package/dist/tools/excel_insert_columns.d.ts.map +1 -0
  57. package/dist/tools/excel_insert_columns.js +44 -0
  58. package/dist/tools/excel_insert_columns.js.map +1 -0
  59. package/dist/tools/excel_insert_rows.d.ts +2 -0
  60. package/dist/tools/excel_insert_rows.d.ts.map +1 -0
  61. package/dist/tools/excel_insert_rows.js +39 -0
  62. package/dist/tools/excel_insert_rows.js.map +1 -0
  63. package/dist/tools/excel_read_sheet.d.ts +2 -0
  64. package/dist/tools/excel_read_sheet.d.ts.map +1 -0
  65. package/dist/tools/excel_read_sheet.js +147 -0
  66. package/dist/tools/excel_read_sheet.js.map +1 -0
  67. package/dist/tools/excel_rename_sheet.d.ts +2 -0
  68. package/dist/tools/excel_rename_sheet.d.ts.map +1 -0
  69. package/dist/tools/excel_rename_sheet.js +37 -0
  70. package/dist/tools/excel_rename_sheet.js.map +1 -0
  71. package/dist/tools/excel_set_data_validation.d.ts +2 -0
  72. package/dist/tools/excel_set_data_validation.d.ts.map +1 -0
  73. package/dist/tools/excel_set_data_validation.js +126 -0
  74. package/dist/tools/excel_set_data_validation.js.map +1 -0
  75. package/dist/tools/excel_set_dimensions.d.ts +2 -0
  76. package/dist/tools/excel_set_dimensions.d.ts.map +1 -0
  77. package/dist/tools/excel_set_dimensions.js +134 -0
  78. package/dist/tools/excel_set_dimensions.js.map +1 -0
  79. package/dist/tools/excel_set_sheet_visibility.d.ts +2 -0
  80. package/dist/tools/excel_set_sheet_visibility.d.ts.map +1 -0
  81. package/dist/tools/excel_set_sheet_visibility.js +39 -0
  82. package/dist/tools/excel_set_sheet_visibility.js.map +1 -0
  83. package/dist/tools/excel_unmerge_cells.d.ts +2 -0
  84. package/dist/tools/excel_unmerge_cells.d.ts.map +1 -0
  85. package/dist/tools/excel_unmerge_cells.js +42 -0
  86. package/dist/tools/excel_unmerge_cells.js.map +1 -0
  87. package/dist/tools/excel_write_range.d.ts +2 -0
  88. package/dist/tools/excel_write_range.d.ts.map +1 -0
  89. package/dist/tools/excel_write_range.js +156 -0
  90. package/dist/tools/excel_write_range.js.map +1 -0
  91. package/package.json +54 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 achmadya
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,123 @@
1
+ # @achmadya-dev/mcp-excel-query
2
+
3
+ MCP server for local `.xlsx` files over **stdio**. TypeScript + [ExcelJS](https://github.com/exceljs/exceljs). Read, write, format, and manage workbooks without Microsoft Excel installed.
4
+
5
+ ## Requirements
6
+
7
+ - Node.js **≥ 20**
8
+ - `.xlsx` files on the local filesystem (paths passed in tool arguments)
9
+
10
+ ## Install from npm
11
+
12
+ ```json
13
+ {
14
+ "mcpServers": {
15
+ "excel": {
16
+ "command": "npx",
17
+ "args": ["-y", "@achmadya-dev/mcp-excel-query"],
18
+ "env": {
19
+ "EXCEL_PAGING_CELLS_LIMIT": "4000"
20
+ }
21
+ }
22
+ }
23
+ }
24
+ ```
25
+
26
+ Or use `envFile` instead of inline `env`.
27
+
28
+ ## Develop from source
29
+
30
+ ```bash
31
+ cp .env.example .env
32
+ pnpm install
33
+ pnpm --filter @achmadya-dev/mcp-excel-query run build
34
+ ```
35
+
36
+ `.cursor/mcp.json`:
37
+
38
+ ```json
39
+ {
40
+ "mcpServers": {
41
+ "excel": {
42
+ "command": "node",
43
+ "args": ["${workspaceFolder}/packages/mcp-excel-query/dist/index.js"],
44
+ "envFile": "${workspaceFolder}/.env"
45
+ }
46
+ }
47
+ }
48
+ ```
49
+
50
+ Relevant `.env` key:
51
+
52
+ ```env
53
+ EXCEL_PAGING_CELLS_LIMIT=4000
54
+ ```
55
+
56
+ ## Environment variables
57
+
58
+ | Variable | Default | Description |
59
+ | -------------------------- | -------------------- | ------------------------------------------------------ |
60
+ | `EXCEL_PAGING_CELLS_LIMIT` | _(unset = no limit)_ | Max cells returned per read; prevents huge sheet dumps |
61
+
62
+ ## Tools (17)
63
+
64
+ | Tool | Use for |
65
+ | ---------------------------- | ---------------------------------------------------------------------------- |
66
+ | `excel_read_sheet` | Read rows, formulas (`showFormula`), styles, dates, merged cells, validation |
67
+ | `excel_get_metadata` | Sheet names, dimensions, date info |
68
+ | `excel_create_file` | New workbook + optional headers |
69
+ | `excel_write_range` | Bulk write, append, new sheet, single cell/formula, optional style |
70
+ | `excel_format_range` | Font, fill, border, alignment, numFmt, merge |
71
+ | `excel_copy_sheet` | Duplicate worksheet |
72
+ | `excel_rename_sheet` | Rename worksheet |
73
+ | `excel_delete_sheet` | Delete worksheet |
74
+ | `excel_copy_range` | Copy cells to another location |
75
+ | `excel_delete_range` | Delete range; `shiftDirection: up` or `left` |
76
+ | `excel_unmerge_cells` | Unmerge range |
77
+ | `excel_create_table` | Native Excel table |
78
+ | `excel_insert_rows` | Insert empty rows |
79
+ | `excel_insert_columns` | Insert empty columns |
80
+ | `excel_set_sheet_visibility` | Show, hide, or very-hide a sheet |
81
+ | `excel_set_data_validation` | Dropdown / validation rules on a range |
82
+ | `excel_set_dimensions` | Row height, column width, sheet defaults |
83
+
84
+ ### Common patterns
85
+
86
+ ```json
87
+ // Append rows
88
+ { "append": true, "values": [[1, "Alice", 25]] }
89
+
90
+ // Write formula to one cell
91
+ { "startCell": "D2", "values": [["=SUM(A2:C2)"]] }
92
+
93
+ // New blank sheet
94
+ { "newSheet": true, "sheetName": "Report" }
95
+
96
+ // Style one cell
97
+ { "startCell": "A1", "values": [["Title"]], "style": { "font": { "bold": true } } }
98
+
99
+ // Merge + format
100
+ { "startCell": "A1", "endCell": "C1", "mergeCells": true, "bold": true }
101
+
102
+ // Read dates using each cell's Excel numFmt
103
+ { "range": "H3:H10", "headerRow": 0, "dateFormat": "cell" }
104
+
105
+ // Hide a sheet
106
+ { "sheetName": "Archive", "state": "hidden" }
107
+
108
+ // Dropdown validation
109
+ { "startCell": "B2", "endCell": "B100", "type": "list", "formulae": ["\"Yes,No,Maybe\""] }
110
+ ```
111
+
112
+ ## Notes
113
+
114
+ - Formulas are stored, not evaluated server-side.
115
+ - `.xlsx` only (not `.xls` or `.csv`).
116
+
117
+ ## Package scripts
118
+
119
+ ```bash
120
+ pnpm run build
121
+ pnpm test
122
+ pnpm start
123
+ ```
@@ -0,0 +1,12 @@
1
+ import type ExcelJS from "exceljs";
2
+ export type CellValue = string | number | boolean | null;
3
+ export declare class Cell {
4
+ static readDisplay(cellValue: unknown, showFormula: boolean, opts?: {
5
+ dateFormat?: string;
6
+ cellNumFmt?: string;
7
+ }): CellValue | string;
8
+ static extractStyle(cell: ExcelJS.Cell): Record<string, unknown> | null;
9
+ static set(cell: ExcelJS.Cell, value: unknown): void;
10
+ static applyStyle(excelCell: ExcelJS.Cell, style: Record<string, unknown>): void;
11
+ }
12
+ //# sourceMappingURL=cell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cell.d.ts","sourceRoot":"","sources":["../../src/excel/cell.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAQnC,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AA8CzD,qBAAa,IAAI;IACf,MAAM,CAAC,WAAW,CAChB,SAAS,EAAE,OAAO,EAClB,WAAW,EAAE,OAAO,EACpB,IAAI,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAClD,SAAS,GAAG,MAAM;IAerB,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAYvE,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAmBpD,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAmDjF"}
@@ -0,0 +1,136 @@
1
+ import { extractDateFromCellValue, formatDateValue, parseDateValue, resolveDateFormat, } from "./date.js";
2
+ function toArgb(hex) {
3
+ const clean = hex.trim().replace(/^#/, "");
4
+ if (clean.length === 6) {
5
+ return { argb: "FF" + clean.toUpperCase() };
6
+ }
7
+ if (clean.length === 8) {
8
+ return { argb: clean.toUpperCase() };
9
+ }
10
+ return { argb: clean };
11
+ }
12
+ function getCleanValue(cellValue) {
13
+ if (cellValue === null || cellValue === undefined)
14
+ return null;
15
+ if (cellValue instanceof Date)
16
+ return cellValue.toISOString();
17
+ if (typeof cellValue === "object") {
18
+ if ("result" in cellValue) {
19
+ return getCleanValue(cellValue.result);
20
+ }
21
+ if ("richText" in cellValue && Array.isArray(cellValue.richText)) {
22
+ return cellValue.richText
23
+ .map((t) => t.text || "")
24
+ .join("");
25
+ }
26
+ if ("text" in cellValue) {
27
+ return String(cellValue.text);
28
+ }
29
+ return JSON.stringify(cellValue);
30
+ }
31
+ return cellValue;
32
+ }
33
+ function getFormula(cellValue) {
34
+ if (cellValue === null || cellValue === undefined)
35
+ return null;
36
+ if (typeof cellValue === "object" && "formula" in cellValue) {
37
+ const formula = cellValue.formula;
38
+ return formula.startsWith("=") ? formula : `=${formula}`;
39
+ }
40
+ if (typeof cellValue === "string" && cellValue.startsWith("=")) {
41
+ return cellValue;
42
+ }
43
+ return null;
44
+ }
45
+ export class Cell {
46
+ static readDisplay(cellValue, showFormula, opts) {
47
+ if (showFormula) {
48
+ const formula = getFormula(cellValue);
49
+ if (formula)
50
+ return formula;
51
+ }
52
+ const resolvedFormat = resolveDateFormat(opts?.dateFormat, opts?.cellNumFmt);
53
+ if (resolvedFormat) {
54
+ const date = extractDateFromCellValue(cellValue);
55
+ if (date)
56
+ return formatDateValue(date, resolvedFormat);
57
+ }
58
+ return getCleanValue(cellValue);
59
+ }
60
+ static extractStyle(cell) {
61
+ const style = {};
62
+ if (cell.font && Object.keys(cell.font).length > 0)
63
+ style.font = { ...cell.font };
64
+ if (cell.fill && Object.keys(cell.fill).length > 0)
65
+ style.fill = { ...cell.fill };
66
+ if (cell.alignment && Object.keys(cell.alignment).length > 0) {
67
+ style.alignment = { ...cell.alignment };
68
+ }
69
+ if (cell.border && Object.keys(cell.border).length > 0)
70
+ style.border = { ...cell.border };
71
+ if (cell.numFmt)
72
+ style.numFmt = cell.numFmt;
73
+ return Object.keys(style).length > 0 ? style : null;
74
+ }
75
+ static set(cell, value) {
76
+ if (value === null || value === undefined) {
77
+ cell.value = null;
78
+ return;
79
+ }
80
+ if (typeof value === "string" && value.startsWith("=")) {
81
+ cell.value = { formula: value.slice(1) };
82
+ return;
83
+ }
84
+ const parsedDate = parseDateValue(value);
85
+ if (parsedDate) {
86
+ cell.value = parsedDate;
87
+ return;
88
+ }
89
+ cell.value = value;
90
+ }
91
+ static applyStyle(excelCell, style) {
92
+ if (!style)
93
+ return;
94
+ if (style.font && typeof style.font === "object") {
95
+ const font = { ...style.font };
96
+ if (typeof font.color === "string") {
97
+ font.color = toArgb(font.color);
98
+ }
99
+ excelCell.font = font;
100
+ }
101
+ if (style.fill && typeof style.fill === "object") {
102
+ const fillSrc = style.fill;
103
+ const fill = {};
104
+ fill.type = fillSrc.type || "pattern";
105
+ fill.pattern = fillSrc.pattern || "solid";
106
+ if (typeof fillSrc.fgColor === "string") {
107
+ fill.fgColor = toArgb(fillSrc.fgColor);
108
+ }
109
+ if (typeof fillSrc.bgColor === "string") {
110
+ fill.bgColor = toArgb(fillSrc.bgColor);
111
+ }
112
+ excelCell.fill = fill;
113
+ }
114
+ if (style.alignment && typeof style.alignment === "object") {
115
+ excelCell.alignment = { ...style.alignment };
116
+ }
117
+ if (style.border && typeof style.border === "object") {
118
+ const border = {};
119
+ const sides = ["top", "left", "bottom", "right"];
120
+ const borderSrc = style.border;
121
+ for (const side of sides) {
122
+ if (borderSrc[side]) {
123
+ border[side] = {
124
+ style: borderSrc[side].style,
125
+ ...(borderSrc[side].color ? { color: toArgb(borderSrc[side].color) } : {}),
126
+ };
127
+ }
128
+ }
129
+ excelCell.border = border;
130
+ }
131
+ if (typeof style.numFmt === "string") {
132
+ excelCell.numFmt = style.numFmt;
133
+ }
134
+ }
135
+ }
136
+ //# sourceMappingURL=cell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cell.js","sourceRoot":"","sources":["../../src/excel/cell.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare function normalizeExcelNumFmt(numFmt: string): string;
2
+ export declare function parseDateValue(value: unknown): Date | null;
3
+ export declare function extractDateFromCellValue(cellValue: unknown): Date | null;
4
+ export declare function formatDateValue(date: Date, pattern: string): string;
5
+ export declare function resolveDateFormat(dateFormat: string | undefined, cellNumFmt?: string): string | undefined;
6
+ //# sourceMappingURL=date.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/excel/date.ts"],"names":[],"mappings":"AAgDA,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAyC1D;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAexE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAsBnE;AAED,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,UAAU,CAAC,EAAE,MAAM,GAClB,MAAM,GAAG,SAAS,CAMpB"}
@@ -0,0 +1,132 @@
1
+ const MONTH_SHORT = [
2
+ "Jan",
3
+ "Feb",
4
+ "Mar",
5
+ "Apr",
6
+ "May",
7
+ "Jun",
8
+ "Jul",
9
+ "Aug",
10
+ "Sep",
11
+ "Oct",
12
+ "Nov",
13
+ "Dec",
14
+ ];
15
+ const MONTH_FULL = [
16
+ "January",
17
+ "February",
18
+ "March",
19
+ "April",
20
+ "May",
21
+ "June",
22
+ "July",
23
+ "August",
24
+ "September",
25
+ "October",
26
+ "November",
27
+ "December",
28
+ ];
29
+ const MONTH_INDEX = Object.fromEntries(MONTH_SHORT.flatMap((m, i) => [
30
+ [m.toLowerCase(), i],
31
+ [MONTH_FULL[i].toLowerCase(), i],
32
+ ]));
33
+ const ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:?\d{2})?)?$/;
34
+ function excelSerialToDate(serial) {
35
+ if (!Number.isFinite(serial) || serial < 1 || serial >= 2958466)
36
+ return null;
37
+ const utcDays = Math.floor(serial - 25569);
38
+ const ms = utcDays * 86400 * 1000;
39
+ const date = new Date(ms);
40
+ return Number.isNaN(date.getTime()) ? null : date;
41
+ }
42
+ export function normalizeExcelNumFmt(numFmt) {
43
+ return numFmt.replace(/\\"/g, " ").replace(/"/g, "").replace(/\s+/g, " ").trim();
44
+ }
45
+ export function parseDateValue(value) {
46
+ if (value instanceof Date) {
47
+ return Number.isNaN(value.getTime()) ? null : value;
48
+ }
49
+ if (typeof value === "number") {
50
+ return excelSerialToDate(value);
51
+ }
52
+ if (typeof value !== "string")
53
+ return null;
54
+ const trimmed = value.trim();
55
+ if (!trimmed)
56
+ return null;
57
+ if (ISO_DATE_RE.test(trimmed)) {
58
+ const date = new Date(trimmed);
59
+ return Number.isNaN(date.getTime()) ? null : date;
60
+ }
61
+ const textDate = trimmed.match(/^(\d{1,2})\s+([A-Za-z]{3,9})\s+(\d{2,4})$/);
62
+ if (textDate) {
63
+ const day = parseInt(textDate[1], 10);
64
+ const month = MONTH_INDEX[textDate[2].toLowerCase()];
65
+ let year = parseInt(textDate[3], 10);
66
+ if (month === undefined)
67
+ return null;
68
+ if (year < 100)
69
+ year += 2000;
70
+ const date = new Date(year, month, day);
71
+ return Number.isNaN(date.getTime()) ? null : date;
72
+ }
73
+ const slashDate = trimmed.match(/^(\d{1,2})[/-](\d{1,2})[/-](\d{2,4})$/);
74
+ if (slashDate) {
75
+ const day = parseInt(slashDate[1], 10);
76
+ const month = parseInt(slashDate[2], 10) - 1;
77
+ let year = parseInt(slashDate[3], 10);
78
+ if (year < 100)
79
+ year += 2000;
80
+ const date = new Date(year, month, day);
81
+ return Number.isNaN(date.getTime()) ? null : date;
82
+ }
83
+ return null;
84
+ }
85
+ export function extractDateFromCellValue(cellValue) {
86
+ if (cellValue === null || cellValue === undefined)
87
+ return null;
88
+ if (cellValue instanceof Date) {
89
+ return Number.isNaN(cellValue.getTime()) ? null : cellValue;
90
+ }
91
+ if (typeof cellValue === "object" && "result" in cellValue) {
92
+ return extractDateFromCellValue(cellValue.result);
93
+ }
94
+ if (typeof cellValue === "number") {
95
+ return excelSerialToDate(cellValue);
96
+ }
97
+ if (typeof cellValue === "string") {
98
+ return parseDateValue(cellValue);
99
+ }
100
+ return null;
101
+ }
102
+ export function formatDateValue(date, pattern) {
103
+ const pad = (n, len = 2) => String(n).padStart(len, "0");
104
+ const replacements = [
105
+ ["yyyy", String(date.getFullYear())],
106
+ ["yy", String(date.getFullYear()).slice(-2)],
107
+ ["MMMM", MONTH_FULL[date.getMonth()]],
108
+ ["mmmm", MONTH_FULL[date.getMonth()]],
109
+ ["MMM", MONTH_SHORT[date.getMonth()]],
110
+ ["mmm", MONTH_SHORT[date.getMonth()]],
111
+ ["MM", pad(date.getMonth() + 1)],
112
+ ["dd", pad(date.getDate())],
113
+ ["HH", pad(date.getHours())],
114
+ ["hh", pad(date.getHours() % 12 || 12)],
115
+ ["mm", pad(date.getMinutes())],
116
+ ["ss", pad(date.getSeconds())],
117
+ ];
118
+ let result = normalizeExcelNumFmt(pattern);
119
+ for (const [token, value] of replacements) {
120
+ result = result.replaceAll(token, value);
121
+ }
122
+ return result;
123
+ }
124
+ export function resolveDateFormat(dateFormat, cellNumFmt) {
125
+ if (!dateFormat)
126
+ return undefined;
127
+ if (dateFormat === "cell") {
128
+ return cellNumFmt ? normalizeExcelNumFmt(cellNumFmt) : undefined;
129
+ }
130
+ return dateFormat;
131
+ }
132
+ //# sourceMappingURL=date.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date.js","sourceRoot":"","sources":["../../src/excel/date.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import ExcelJS from "exceljs";
2
+ import { type A1Bounds } from "./range.js";
3
+ export declare class Sheet {
4
+ private readonly worksheet;
5
+ constructor(worksheet: ExcelJS.Worksheet);
6
+ get name(): string;
7
+ get raw(): ExcelJS.Worksheet;
8
+ range(a1: string): A1Bounds;
9
+ range(start: string, end: string): A1Bounds;
10
+ }
11
+ export declare class Excel {
12
+ private readonly wb;
13
+ private readonly filePath;
14
+ private constructor();
15
+ static pagingLimit(): number;
16
+ static open(filePath: string): Promise<Excel>;
17
+ static create(filePath: string, opts?: {
18
+ sheetName?: string;
19
+ headers?: string[];
20
+ }): Excel;
21
+ get path(): string;
22
+ get workbook(): ExcelJS.Workbook;
23
+ save(): Promise<void>;
24
+ sheet(name?: string): Sheet;
25
+ addSheet(name: string): Sheet;
26
+ hasSheet(name: string): boolean;
27
+ removeSheet(name: string): void;
28
+ }
29
+ //# sourceMappingURL=excel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"excel.d.ts","sourceRoot":"","sources":["../../src/excel/excel.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAG9B,OAAO,EAAS,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAElD,qBAAa,KAAK;IACJ,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,OAAO,CAAC,SAAS;IAEzD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,GAAG,IAAI,OAAO,CAAC,SAAS,CAE3B;IAED,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ;IAC3B,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ;CAO5C;AAED,qBAAa,KAAK;IAEd,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAF3B,OAAO;IAKP,MAAM,CAAC,WAAW,IAAI,MAAM;WAOf,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IASnD,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,KAAK;IAiBzF,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAE/B;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK;IAQ3B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK;IAO7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI/B,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAUhC"}
@@ -0,0 +1,94 @@
1
+ import ExcelJS from "exceljs";
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ import { Range } from "./range.js";
5
+ export class Sheet {
6
+ worksheet;
7
+ constructor(worksheet) {
8
+ this.worksheet = worksheet;
9
+ }
10
+ get name() {
11
+ return this.worksheet.name;
12
+ }
13
+ get raw() {
14
+ return this.worksheet;
15
+ }
16
+ range(startOrA1, end) {
17
+ if (end !== undefined) {
18
+ return Range.between(startOrA1, end);
19
+ }
20
+ return Range.parse(startOrA1);
21
+ }
22
+ }
23
+ export class Excel {
24
+ wb;
25
+ filePath;
26
+ constructor(wb, filePath) {
27
+ this.wb = wb;
28
+ this.filePath = filePath;
29
+ }
30
+ static pagingLimit() {
31
+ const raw = process.env.EXCEL_PAGING_CELLS_LIMIT;
32
+ if (raw === undefined || raw === "")
33
+ return 4000;
34
+ const n = parseInt(raw, 10);
35
+ return Number.isFinite(n) && n > 0 ? n : 4000;
36
+ }
37
+ static async open(filePath) {
38
+ if (!fs.existsSync(filePath)) {
39
+ throw new Error(`File not found: ${filePath}`);
40
+ }
41
+ const workbook = new ExcelJS.Workbook();
42
+ await workbook.xlsx.readFile(filePath);
43
+ return new Excel(workbook, filePath);
44
+ }
45
+ static create(filePath, opts) {
46
+ const dir = path.dirname(filePath);
47
+ if (!fs.existsSync(dir)) {
48
+ fs.mkdirSync(dir, { recursive: true });
49
+ }
50
+ const workbook = new ExcelJS.Workbook();
51
+ const sheetName = opts?.sheetName ?? "Sheet1";
52
+ const worksheet = workbook.addWorksheet(sheetName);
53
+ if (opts?.headers && opts.headers.length > 0) {
54
+ worksheet.addRow(opts.headers);
55
+ }
56
+ return new Excel(workbook, filePath);
57
+ }
58
+ get path() {
59
+ return this.filePath;
60
+ }
61
+ get workbook() {
62
+ return this.wb;
63
+ }
64
+ async save() {
65
+ await this.wb.xlsx.writeFile(this.filePath);
66
+ }
67
+ sheet(name) {
68
+ const worksheet = name ? this.wb.getWorksheet(name) : this.wb.worksheets[0];
69
+ if (!worksheet) {
70
+ throw new Error(`Worksheet not found: "${name ?? "Index 0"}"`);
71
+ }
72
+ return new Sheet(worksheet);
73
+ }
74
+ addSheet(name) {
75
+ if (this.wb.getWorksheet(name)) {
76
+ throw new Error(`Worksheet already exists: "${name}"`);
77
+ }
78
+ return new Sheet(this.wb.addWorksheet(name));
79
+ }
80
+ hasSheet(name) {
81
+ return this.wb.getWorksheet(name) !== undefined;
82
+ }
83
+ removeSheet(name) {
84
+ if (this.wb.worksheets.length <= 1) {
85
+ throw new Error("Cannot delete the only worksheet in the workbook");
86
+ }
87
+ const worksheet = this.wb.getWorksheet(name);
88
+ if (!worksheet) {
89
+ throw new Error(`Worksheet not found: "${name}"`);
90
+ }
91
+ this.wb.removeWorksheet(worksheet.id);
92
+ }
93
+ }
94
+ //# sourceMappingURL=excel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"excel.js","sourceRoot":"","sources":["../../src/excel/excel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export type A1Bounds = {
2
+ startRow: number;
3
+ startCol: number;
4
+ endRow: number;
5
+ endCol: number;
6
+ };
7
+ export declare class Range {
8
+ static letterToCol(letter: string): number;
9
+ static colToLetter(col: number): string;
10
+ static address(row: number, col: number): string;
11
+ static toA1(bounds: A1Bounds): string;
12
+ static parse(rangeStr: string): A1Bounds;
13
+ static between(startCell: string, endCell?: string): A1Bounds;
14
+ }
15
+ //# sourceMappingURL=range.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"range.d.ts","sourceRoot":"","sources":["../../src/excel/range.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,qBAAa,KAAK;IAChB,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAY1C,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAWvC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM;IAIhD,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM;IAQrC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ;IAyBxC,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ;CAa9D"}