@devmm/puredocs-excel-angular 1.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 TVE
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/dist/index.cjs ADDED
@@ -0,0 +1,193 @@
1
+ 'use strict';
2
+
3
+ var core = require('@angular/core');
4
+ var puredocsExcel = require('@devmm/puredocs-excel');
5
+
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __decorateClass = (decorators, target, key, kind) => {
8
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
9
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
10
+ if (decorator = decorators[i])
11
+ result = (decorator(result)) || result;
12
+ return result;
13
+ };
14
+ exports.ExcelService = class ExcelService {
15
+ // ── Read ────────────────────────────────────────────────────────────────────
16
+ /**
17
+ * Reads an Excel file from a browser File object.
18
+ *
19
+ * @example
20
+ * // In a component
21
+ * async onFileSelected(event: Event) {
22
+ * const file = (event.target as HTMLInputElement).files![0];
23
+ * const wb = await this.excel.readFile(file);
24
+ * const sheet = wb.worksheets[0];
25
+ * console.log(sheet.getCell('A1').getText());
26
+ * }
27
+ */
28
+ async readFile(file) {
29
+ const buffer = await file.arrayBuffer();
30
+ return puredocsExcel.Workbook.fromBuffer(buffer);
31
+ }
32
+ /**
33
+ * Reads an Excel file from an ArrayBuffer or Uint8Array.
34
+ * Useful when data comes from an HTTP response.
35
+ *
36
+ * @example
37
+ * const response = await fetch('/api/report.xlsx');
38
+ * const buffer = await response.arrayBuffer();
39
+ * const wb = await this.excel.readBuffer(buffer);
40
+ */
41
+ readBuffer(buffer) {
42
+ return puredocsExcel.Workbook.fromBuffer(buffer);
43
+ }
44
+ // ── Create ──────────────────────────────────────────────────────────────────
45
+ /**
46
+ * Creates a new empty workbook.
47
+ *
48
+ * @example
49
+ * const wb = this.excel.createWorkbook();
50
+ * const sheet = wb.addWorksheet('Report');
51
+ * sheet.getCell('A1').setValue('Hello');
52
+ */
53
+ createWorkbook() {
54
+ return puredocsExcel.Workbook.create();
55
+ }
56
+ /**
57
+ * Creates a workbook, applies a configuration callback, and returns it.
58
+ * Convenience method for building workbooks inline.
59
+ *
60
+ * @example
61
+ * const wb = this.excel.buildWorkbook(wb => {
62
+ * const sheet = wb.addWorksheet('Sales');
63
+ * sheet.getCell('A1').setValue('Total');
64
+ * sheet.getCell('B1').setValue(12345);
65
+ * });
66
+ */
67
+ buildWorkbook(configure) {
68
+ const wb = puredocsExcel.Workbook.create();
69
+ configure(wb);
70
+ return wb;
71
+ }
72
+ // ── Export ──────────────────────────────────────────────────────────────────
73
+ /**
74
+ * Serialises a workbook to a Uint8Array buffer.
75
+ * Use this when you want to upload the file via HTTP.
76
+ *
77
+ * @example
78
+ * const buffer = this.excel.toBuffer(workbook);
79
+ * await this.http.post('/api/upload', buffer, {
80
+ * headers: { 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }
81
+ * }).toPromise();
82
+ */
83
+ toBuffer(workbook) {
84
+ return workbook.saveAsBuffer();
85
+ }
86
+ /**
87
+ * Triggers a browser download of the workbook.
88
+ * Works in any modern browser via the Blob + anchor trick.
89
+ *
90
+ * @param workbook The workbook to download
91
+ * @param fileName Download filename (default: "export.xlsx")
92
+ *
93
+ * @example
94
+ * this.excel.download(workbook, 'monthly-report.xlsx');
95
+ */
96
+ download(workbook, fileName = "export.xlsx") {
97
+ const buffer = workbook.saveAsBuffer();
98
+ this.downloadBuffer(buffer, fileName);
99
+ }
100
+ /**
101
+ * Triggers a browser download from a raw Uint8Array buffer.
102
+ *
103
+ * @example
104
+ * const buffer = someExternalSource.getXlsxBuffer();
105
+ * this.excel.downloadBuffer(buffer, 'data.xlsx');
106
+ */
107
+ downloadBuffer(buffer, fileName = "export.xlsx") {
108
+ const blob = new Blob([buffer], {
109
+ type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
110
+ });
111
+ const url = URL.createObjectURL(blob);
112
+ const anchor = document.createElement("a");
113
+ anchor.href = url;
114
+ anchor.download = fileName;
115
+ anchor.style.display = "none";
116
+ document.body.appendChild(anchor);
117
+ anchor.click();
118
+ setTimeout(() => {
119
+ URL.revokeObjectURL(url);
120
+ document.body.removeChild(anchor);
121
+ }, 100);
122
+ }
123
+ /**
124
+ * Returns a Blob from a workbook (useful for FormData uploads).
125
+ *
126
+ * @example
127
+ * const blob = this.excel.toBlob(workbook);
128
+ * const formData = new FormData();
129
+ * formData.append('file', blob, 'report.xlsx');
130
+ * await this.http.post('/api/upload', formData).toPromise();
131
+ */
132
+ toBlob(workbook, fileName = "export.xlsx") {
133
+ const buffer = workbook.saveAsBuffer();
134
+ return new Blob([buffer], {
135
+ type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
136
+ });
137
+ }
138
+ // ── Convenience builders ────────────────────────────────────────────────────
139
+ /**
140
+ * Creates a simple single-sheet workbook from a 2D data array with optional headers.
141
+ * Suitable for quick table exports.
142
+ *
143
+ * @example
144
+ * const data = [
145
+ * ['Alice', 30, 'Engineer'],
146
+ * ['Bob', 25, 'Designer'],
147
+ * ];
148
+ * const headers = ['Name', 'Age', 'Role'];
149
+ * this.excel.download(
150
+ * this.excel.fromTable(data, { headers, sheetName: 'Staff' }),
151
+ * 'staff.xlsx',
152
+ * );
153
+ */
154
+ fromTable(rows, options) {
155
+ const wb = puredocsExcel.Workbook.create();
156
+ const sheet = wb.addWorksheet(options?.sheetName ?? "Sheet1");
157
+ let dataStartRow = 1;
158
+ if (options?.headers && options.headers.length > 0) {
159
+ options.headers.forEach((h, i) => sheet.getCell(1, i + 1).setValue(h));
160
+ if (options.headerStyle) {
161
+ const range = sheet.getRange(`A1:${colLetter(options.headers.length)}1`);
162
+ range.applyStyle(options.headerStyle);
163
+ }
164
+ dataStartRow = 2;
165
+ }
166
+ rows.forEach((row, rowIdx) => {
167
+ row.forEach((val, colIdx) => {
168
+ const cell = sheet.getCell(dataStartRow + rowIdx, colIdx + 1);
169
+ if (val === null || val === void 0) return;
170
+ if (typeof val === "string") cell.setValue(val);
171
+ else if (typeof val === "number") cell.setValue(val);
172
+ else if (typeof val === "boolean") cell.setValue(val);
173
+ else if (val instanceof Date) cell.setValue(val);
174
+ else cell.setValue(String(val));
175
+ });
176
+ });
177
+ return wb;
178
+ }
179
+ };
180
+ exports.ExcelService = __decorateClass([
181
+ core.Injectable({ providedIn: "root" })
182
+ ], exports.ExcelService);
183
+ function colLetter(col) {
184
+ let result = "";
185
+ while (col > 0) {
186
+ const rem = (col - 1) % 26;
187
+ result = String.fromCharCode(65 + rem) + result;
188
+ col = Math.floor((col - rem) / 26);
189
+ }
190
+ return result;
191
+ }
192
+ //# sourceMappingURL=index.cjs.map
193
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/excel.service.ts"],"names":["ExcelService","Workbook","Injectable"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Angular service for working with Excel files.\n * Wraps @devmm/puredocs-excel with Angular-idiomatic patterns:\n * - Injectable for DI\n * - Returns Observable where appropriate\n * - Handles browser download\n * - Signal-compatible (returns plain values, no Subjects needed)\n *\n * Port concept from TVE.PureDocs.Excel — adapts C# service pattern to Angular.\n */\nimport { Injectable } from '@angular/core';\nimport { Workbook, Worksheet, CellStyle } from '@devmm/puredocs-excel';\n\nexport interface ExcelReadOptions {\n /** If true, reads formula cached values. Default: true. */\n readCachedValues?: boolean;\n}\n\nexport interface ExcelWriteOptions {\n /** File name for download (browser only). Defaults to 'export.xlsx'. */\n fileName?: string;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class ExcelService {\n\n // ── Read ────────────────────────────────────────────────────────────────────\n\n /**\n * Reads an Excel file from a browser File object.\n *\n * @example\n * // In a component\n * async onFileSelected(event: Event) {\n * const file = (event.target as HTMLInputElement).files![0];\n * const wb = await this.excel.readFile(file);\n * const sheet = wb.worksheets[0];\n * console.log(sheet.getCell('A1').getText());\n * }\n */\n async readFile(file: File): Promise<Workbook> {\n const buffer = await file.arrayBuffer();\n return Workbook.fromBuffer(buffer);\n }\n\n /**\n * Reads an Excel file from an ArrayBuffer or Uint8Array.\n * Useful when data comes from an HTTP response.\n *\n * @example\n * const response = await fetch('/api/report.xlsx');\n * const buffer = await response.arrayBuffer();\n * const wb = await this.excel.readBuffer(buffer);\n */\n readBuffer(buffer: ArrayBuffer | Uint8Array): Workbook {\n return Workbook.fromBuffer(buffer);\n }\n\n // ── Create ──────────────────────────────────────────────────────────────────\n\n /**\n * Creates a new empty workbook.\n *\n * @example\n * const wb = this.excel.createWorkbook();\n * const sheet = wb.addWorksheet('Report');\n * sheet.getCell('A1').setValue('Hello');\n */\n createWorkbook(): Workbook {\n return Workbook.create();\n }\n\n /**\n * Creates a workbook, applies a configuration callback, and returns it.\n * Convenience method for building workbooks inline.\n *\n * @example\n * const wb = this.excel.buildWorkbook(wb => {\n * const sheet = wb.addWorksheet('Sales');\n * sheet.getCell('A1').setValue('Total');\n * sheet.getCell('B1').setValue(12345);\n * });\n */\n buildWorkbook(configure: (workbook: Workbook) => void): Workbook {\n const wb = Workbook.create();\n configure(wb);\n return wb;\n }\n\n // ── Export ──────────────────────────────────────────────────────────────────\n\n /**\n * Serialises a workbook to a Uint8Array buffer.\n * Use this when you want to upload the file via HTTP.\n *\n * @example\n * const buffer = this.excel.toBuffer(workbook);\n * await this.http.post('/api/upload', buffer, {\n * headers: { 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }\n * }).toPromise();\n */\n toBuffer(workbook: Workbook): Uint8Array {\n return workbook.saveAsBuffer();\n }\n\n /**\n * Triggers a browser download of the workbook.\n * Works in any modern browser via the Blob + anchor trick.\n *\n * @param workbook The workbook to download\n * @param fileName Download filename (default: \"export.xlsx\")\n *\n * @example\n * this.excel.download(workbook, 'monthly-report.xlsx');\n */\n download(workbook: Workbook, fileName = 'export.xlsx'): void {\n const buffer = workbook.saveAsBuffer();\n this.downloadBuffer(buffer, fileName);\n }\n\n /**\n * Triggers a browser download from a raw Uint8Array buffer.\n *\n * @example\n * const buffer = someExternalSource.getXlsxBuffer();\n * this.excel.downloadBuffer(buffer, 'data.xlsx');\n */\n downloadBuffer(buffer: Uint8Array, fileName = 'export.xlsx'): void {\n const blob = new Blob([buffer as BlobPart], {\n type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = fileName;\n anchor.style.display = 'none';\n document.body.appendChild(anchor);\n anchor.click();\n\n // Cleanup after a short delay to allow the download to start\n setTimeout(() => {\n URL.revokeObjectURL(url);\n document.body.removeChild(anchor);\n }, 100);\n }\n\n /**\n * Returns a Blob from a workbook (useful for FormData uploads).\n *\n * @example\n * const blob = this.excel.toBlob(workbook);\n * const formData = new FormData();\n * formData.append('file', blob, 'report.xlsx');\n * await this.http.post('/api/upload', formData).toPromise();\n */\n toBlob(workbook: Workbook, fileName = 'export.xlsx'): Blob {\n const buffer = workbook.saveAsBuffer();\n return new Blob([buffer as BlobPart], {\n type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n });\n }\n\n // ── Convenience builders ────────────────────────────────────────────────────\n\n /**\n * Creates a simple single-sheet workbook from a 2D data array with optional headers.\n * Suitable for quick table exports.\n *\n * @example\n * const data = [\n * ['Alice', 30, 'Engineer'],\n * ['Bob', 25, 'Designer'],\n * ];\n * const headers = ['Name', 'Age', 'Role'];\n * this.excel.download(\n * this.excel.fromTable(data, { headers, sheetName: 'Staff' }),\n * 'staff.xlsx',\n * );\n */\n fromTable(\n rows: unknown[][],\n options?: {\n headers?: string[];\n sheetName?: string;\n headerStyle?: (style: CellStyle) => void;\n },\n ): Workbook {\n const wb = Workbook.create();\n const sheet = wb.addWorksheet(options?.sheetName ?? 'Sheet1');\n\n let dataStartRow = 1;\n\n if (options?.headers && options.headers.length > 0) {\n options.headers.forEach((h, i) => sheet.getCell(1, i + 1).setValue(h));\n\n // Apply header style if provided\n if (options.headerStyle) {\n const range = sheet.getRange(`A1:${colLetter(options.headers.length)}1`);\n range.applyStyle(options.headerStyle);\n }\n\n dataStartRow = 2;\n }\n\n rows.forEach((row, rowIdx) => {\n row.forEach((val, colIdx) => {\n const cell = sheet.getCell(dataStartRow + rowIdx, colIdx + 1);\n if (val === null || val === undefined) return;\n if (typeof val === 'string') cell.setValue(val);\n else if (typeof val === 'number') cell.setValue(val);\n else if (typeof val === 'boolean') cell.setValue(val);\n else if (val instanceof Date) cell.setValue(val);\n else cell.setValue(String(val));\n });\n });\n\n return wb;\n }\n}\n\n// ── Helpers ────────────────────────────────────────────────────────────────────\n\n/** Converts a 1-based column index to a letter (A, B, … Z, AA …). */\nfunction colLetter(col: number): string {\n let result = '';\n while (col > 0) {\n const rem = (col - 1) % 26;\n result = String.fromCharCode(65 + rem) + result;\n col = Math.floor((col - rem) / 26);\n }\n return result;\n}\n"]}
@@ -0,0 +1,118 @@
1
+ import { Workbook, CellStyle } from '@devmm/puredocs-excel';
2
+
3
+ interface ExcelReadOptions {
4
+ /** If true, reads formula cached values. Default: true. */
5
+ readCachedValues?: boolean;
6
+ }
7
+ interface ExcelWriteOptions {
8
+ /** File name for download (browser only). Defaults to 'export.xlsx'. */
9
+ fileName?: string;
10
+ }
11
+ declare class ExcelService {
12
+ /**
13
+ * Reads an Excel file from a browser File object.
14
+ *
15
+ * @example
16
+ * // In a component
17
+ * async onFileSelected(event: Event) {
18
+ * const file = (event.target as HTMLInputElement).files![0];
19
+ * const wb = await this.excel.readFile(file);
20
+ * const sheet = wb.worksheets[0];
21
+ * console.log(sheet.getCell('A1').getText());
22
+ * }
23
+ */
24
+ readFile(file: File): Promise<Workbook>;
25
+ /**
26
+ * Reads an Excel file from an ArrayBuffer or Uint8Array.
27
+ * Useful when data comes from an HTTP response.
28
+ *
29
+ * @example
30
+ * const response = await fetch('/api/report.xlsx');
31
+ * const buffer = await response.arrayBuffer();
32
+ * const wb = await this.excel.readBuffer(buffer);
33
+ */
34
+ readBuffer(buffer: ArrayBuffer | Uint8Array): Workbook;
35
+ /**
36
+ * Creates a new empty workbook.
37
+ *
38
+ * @example
39
+ * const wb = this.excel.createWorkbook();
40
+ * const sheet = wb.addWorksheet('Report');
41
+ * sheet.getCell('A1').setValue('Hello');
42
+ */
43
+ createWorkbook(): Workbook;
44
+ /**
45
+ * Creates a workbook, applies a configuration callback, and returns it.
46
+ * Convenience method for building workbooks inline.
47
+ *
48
+ * @example
49
+ * const wb = this.excel.buildWorkbook(wb => {
50
+ * const sheet = wb.addWorksheet('Sales');
51
+ * sheet.getCell('A1').setValue('Total');
52
+ * sheet.getCell('B1').setValue(12345);
53
+ * });
54
+ */
55
+ buildWorkbook(configure: (workbook: Workbook) => void): Workbook;
56
+ /**
57
+ * Serialises a workbook to a Uint8Array buffer.
58
+ * Use this when you want to upload the file via HTTP.
59
+ *
60
+ * @example
61
+ * const buffer = this.excel.toBuffer(workbook);
62
+ * await this.http.post('/api/upload', buffer, {
63
+ * headers: { 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }
64
+ * }).toPromise();
65
+ */
66
+ toBuffer(workbook: Workbook): Uint8Array;
67
+ /**
68
+ * Triggers a browser download of the workbook.
69
+ * Works in any modern browser via the Blob + anchor trick.
70
+ *
71
+ * @param workbook The workbook to download
72
+ * @param fileName Download filename (default: "export.xlsx")
73
+ *
74
+ * @example
75
+ * this.excel.download(workbook, 'monthly-report.xlsx');
76
+ */
77
+ download(workbook: Workbook, fileName?: string): void;
78
+ /**
79
+ * Triggers a browser download from a raw Uint8Array buffer.
80
+ *
81
+ * @example
82
+ * const buffer = someExternalSource.getXlsxBuffer();
83
+ * this.excel.downloadBuffer(buffer, 'data.xlsx');
84
+ */
85
+ downloadBuffer(buffer: Uint8Array, fileName?: string): void;
86
+ /**
87
+ * Returns a Blob from a workbook (useful for FormData uploads).
88
+ *
89
+ * @example
90
+ * const blob = this.excel.toBlob(workbook);
91
+ * const formData = new FormData();
92
+ * formData.append('file', blob, 'report.xlsx');
93
+ * await this.http.post('/api/upload', formData).toPromise();
94
+ */
95
+ toBlob(workbook: Workbook, fileName?: string): Blob;
96
+ /**
97
+ * Creates a simple single-sheet workbook from a 2D data array with optional headers.
98
+ * Suitable for quick table exports.
99
+ *
100
+ * @example
101
+ * const data = [
102
+ * ['Alice', 30, 'Engineer'],
103
+ * ['Bob', 25, 'Designer'],
104
+ * ];
105
+ * const headers = ['Name', 'Age', 'Role'];
106
+ * this.excel.download(
107
+ * this.excel.fromTable(data, { headers, sheetName: 'Staff' }),
108
+ * 'staff.xlsx',
109
+ * );
110
+ */
111
+ fromTable(rows: unknown[][], options?: {
112
+ headers?: string[];
113
+ sheetName?: string;
114
+ headerStyle?: (style: CellStyle) => void;
115
+ }): Workbook;
116
+ }
117
+
118
+ export { type ExcelReadOptions, ExcelService, type ExcelWriteOptions };
@@ -0,0 +1,118 @@
1
+ import { Workbook, CellStyle } from '@devmm/puredocs-excel';
2
+
3
+ interface ExcelReadOptions {
4
+ /** If true, reads formula cached values. Default: true. */
5
+ readCachedValues?: boolean;
6
+ }
7
+ interface ExcelWriteOptions {
8
+ /** File name for download (browser only). Defaults to 'export.xlsx'. */
9
+ fileName?: string;
10
+ }
11
+ declare class ExcelService {
12
+ /**
13
+ * Reads an Excel file from a browser File object.
14
+ *
15
+ * @example
16
+ * // In a component
17
+ * async onFileSelected(event: Event) {
18
+ * const file = (event.target as HTMLInputElement).files![0];
19
+ * const wb = await this.excel.readFile(file);
20
+ * const sheet = wb.worksheets[0];
21
+ * console.log(sheet.getCell('A1').getText());
22
+ * }
23
+ */
24
+ readFile(file: File): Promise<Workbook>;
25
+ /**
26
+ * Reads an Excel file from an ArrayBuffer or Uint8Array.
27
+ * Useful when data comes from an HTTP response.
28
+ *
29
+ * @example
30
+ * const response = await fetch('/api/report.xlsx');
31
+ * const buffer = await response.arrayBuffer();
32
+ * const wb = await this.excel.readBuffer(buffer);
33
+ */
34
+ readBuffer(buffer: ArrayBuffer | Uint8Array): Workbook;
35
+ /**
36
+ * Creates a new empty workbook.
37
+ *
38
+ * @example
39
+ * const wb = this.excel.createWorkbook();
40
+ * const sheet = wb.addWorksheet('Report');
41
+ * sheet.getCell('A1').setValue('Hello');
42
+ */
43
+ createWorkbook(): Workbook;
44
+ /**
45
+ * Creates a workbook, applies a configuration callback, and returns it.
46
+ * Convenience method for building workbooks inline.
47
+ *
48
+ * @example
49
+ * const wb = this.excel.buildWorkbook(wb => {
50
+ * const sheet = wb.addWorksheet('Sales');
51
+ * sheet.getCell('A1').setValue('Total');
52
+ * sheet.getCell('B1').setValue(12345);
53
+ * });
54
+ */
55
+ buildWorkbook(configure: (workbook: Workbook) => void): Workbook;
56
+ /**
57
+ * Serialises a workbook to a Uint8Array buffer.
58
+ * Use this when you want to upload the file via HTTP.
59
+ *
60
+ * @example
61
+ * const buffer = this.excel.toBuffer(workbook);
62
+ * await this.http.post('/api/upload', buffer, {
63
+ * headers: { 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }
64
+ * }).toPromise();
65
+ */
66
+ toBuffer(workbook: Workbook): Uint8Array;
67
+ /**
68
+ * Triggers a browser download of the workbook.
69
+ * Works in any modern browser via the Blob + anchor trick.
70
+ *
71
+ * @param workbook The workbook to download
72
+ * @param fileName Download filename (default: "export.xlsx")
73
+ *
74
+ * @example
75
+ * this.excel.download(workbook, 'monthly-report.xlsx');
76
+ */
77
+ download(workbook: Workbook, fileName?: string): void;
78
+ /**
79
+ * Triggers a browser download from a raw Uint8Array buffer.
80
+ *
81
+ * @example
82
+ * const buffer = someExternalSource.getXlsxBuffer();
83
+ * this.excel.downloadBuffer(buffer, 'data.xlsx');
84
+ */
85
+ downloadBuffer(buffer: Uint8Array, fileName?: string): void;
86
+ /**
87
+ * Returns a Blob from a workbook (useful for FormData uploads).
88
+ *
89
+ * @example
90
+ * const blob = this.excel.toBlob(workbook);
91
+ * const formData = new FormData();
92
+ * formData.append('file', blob, 'report.xlsx');
93
+ * await this.http.post('/api/upload', formData).toPromise();
94
+ */
95
+ toBlob(workbook: Workbook, fileName?: string): Blob;
96
+ /**
97
+ * Creates a simple single-sheet workbook from a 2D data array with optional headers.
98
+ * Suitable for quick table exports.
99
+ *
100
+ * @example
101
+ * const data = [
102
+ * ['Alice', 30, 'Engineer'],
103
+ * ['Bob', 25, 'Designer'],
104
+ * ];
105
+ * const headers = ['Name', 'Age', 'Role'];
106
+ * this.excel.download(
107
+ * this.excel.fromTable(data, { headers, sheetName: 'Staff' }),
108
+ * 'staff.xlsx',
109
+ * );
110
+ */
111
+ fromTable(rows: unknown[][], options?: {
112
+ headers?: string[];
113
+ sheetName?: string;
114
+ headerStyle?: (style: CellStyle) => void;
115
+ }): Workbook;
116
+ }
117
+
118
+ export { type ExcelReadOptions, ExcelService, type ExcelWriteOptions };
package/dist/index.js ADDED
@@ -0,0 +1,193 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { Workbook } from '@devmm/puredocs-excel';
3
+
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __decorateClass = (decorators, target, key, kind) => {
6
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
7
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
8
+ if (decorator = decorators[i])
9
+ result = (decorator(result)) || result;
10
+ return result;
11
+ };
12
+ var ExcelService = class {
13
+ // ── Read ────────────────────────────────────────────────────────────────────
14
+ /**
15
+ * Reads an Excel file from a browser File object.
16
+ *
17
+ * @example
18
+ * // In a component
19
+ * async onFileSelected(event: Event) {
20
+ * const file = (event.target as HTMLInputElement).files![0];
21
+ * const wb = await this.excel.readFile(file);
22
+ * const sheet = wb.worksheets[0];
23
+ * console.log(sheet.getCell('A1').getText());
24
+ * }
25
+ */
26
+ async readFile(file) {
27
+ const buffer = await file.arrayBuffer();
28
+ return Workbook.fromBuffer(buffer);
29
+ }
30
+ /**
31
+ * Reads an Excel file from an ArrayBuffer or Uint8Array.
32
+ * Useful when data comes from an HTTP response.
33
+ *
34
+ * @example
35
+ * const response = await fetch('/api/report.xlsx');
36
+ * const buffer = await response.arrayBuffer();
37
+ * const wb = await this.excel.readBuffer(buffer);
38
+ */
39
+ readBuffer(buffer) {
40
+ return Workbook.fromBuffer(buffer);
41
+ }
42
+ // ── Create ──────────────────────────────────────────────────────────────────
43
+ /**
44
+ * Creates a new empty workbook.
45
+ *
46
+ * @example
47
+ * const wb = this.excel.createWorkbook();
48
+ * const sheet = wb.addWorksheet('Report');
49
+ * sheet.getCell('A1').setValue('Hello');
50
+ */
51
+ createWorkbook() {
52
+ return Workbook.create();
53
+ }
54
+ /**
55
+ * Creates a workbook, applies a configuration callback, and returns it.
56
+ * Convenience method for building workbooks inline.
57
+ *
58
+ * @example
59
+ * const wb = this.excel.buildWorkbook(wb => {
60
+ * const sheet = wb.addWorksheet('Sales');
61
+ * sheet.getCell('A1').setValue('Total');
62
+ * sheet.getCell('B1').setValue(12345);
63
+ * });
64
+ */
65
+ buildWorkbook(configure) {
66
+ const wb = Workbook.create();
67
+ configure(wb);
68
+ return wb;
69
+ }
70
+ // ── Export ──────────────────────────────────────────────────────────────────
71
+ /**
72
+ * Serialises a workbook to a Uint8Array buffer.
73
+ * Use this when you want to upload the file via HTTP.
74
+ *
75
+ * @example
76
+ * const buffer = this.excel.toBuffer(workbook);
77
+ * await this.http.post('/api/upload', buffer, {
78
+ * headers: { 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }
79
+ * }).toPromise();
80
+ */
81
+ toBuffer(workbook) {
82
+ return workbook.saveAsBuffer();
83
+ }
84
+ /**
85
+ * Triggers a browser download of the workbook.
86
+ * Works in any modern browser via the Blob + anchor trick.
87
+ *
88
+ * @param workbook The workbook to download
89
+ * @param fileName Download filename (default: "export.xlsx")
90
+ *
91
+ * @example
92
+ * this.excel.download(workbook, 'monthly-report.xlsx');
93
+ */
94
+ download(workbook, fileName = "export.xlsx") {
95
+ const buffer = workbook.saveAsBuffer();
96
+ this.downloadBuffer(buffer, fileName);
97
+ }
98
+ /**
99
+ * Triggers a browser download from a raw Uint8Array buffer.
100
+ *
101
+ * @example
102
+ * const buffer = someExternalSource.getXlsxBuffer();
103
+ * this.excel.downloadBuffer(buffer, 'data.xlsx');
104
+ */
105
+ downloadBuffer(buffer, fileName = "export.xlsx") {
106
+ const blob = new Blob([buffer], {
107
+ type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
108
+ });
109
+ const url = URL.createObjectURL(blob);
110
+ const anchor = document.createElement("a");
111
+ anchor.href = url;
112
+ anchor.download = fileName;
113
+ anchor.style.display = "none";
114
+ document.body.appendChild(anchor);
115
+ anchor.click();
116
+ setTimeout(() => {
117
+ URL.revokeObjectURL(url);
118
+ document.body.removeChild(anchor);
119
+ }, 100);
120
+ }
121
+ /**
122
+ * Returns a Blob from a workbook (useful for FormData uploads).
123
+ *
124
+ * @example
125
+ * const blob = this.excel.toBlob(workbook);
126
+ * const formData = new FormData();
127
+ * formData.append('file', blob, 'report.xlsx');
128
+ * await this.http.post('/api/upload', formData).toPromise();
129
+ */
130
+ toBlob(workbook, fileName = "export.xlsx") {
131
+ const buffer = workbook.saveAsBuffer();
132
+ return new Blob([buffer], {
133
+ type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
134
+ });
135
+ }
136
+ // ── Convenience builders ────────────────────────────────────────────────────
137
+ /**
138
+ * Creates a simple single-sheet workbook from a 2D data array with optional headers.
139
+ * Suitable for quick table exports.
140
+ *
141
+ * @example
142
+ * const data = [
143
+ * ['Alice', 30, 'Engineer'],
144
+ * ['Bob', 25, 'Designer'],
145
+ * ];
146
+ * const headers = ['Name', 'Age', 'Role'];
147
+ * this.excel.download(
148
+ * this.excel.fromTable(data, { headers, sheetName: 'Staff' }),
149
+ * 'staff.xlsx',
150
+ * );
151
+ */
152
+ fromTable(rows, options) {
153
+ const wb = Workbook.create();
154
+ const sheet = wb.addWorksheet(options?.sheetName ?? "Sheet1");
155
+ let dataStartRow = 1;
156
+ if (options?.headers && options.headers.length > 0) {
157
+ options.headers.forEach((h, i) => sheet.getCell(1, i + 1).setValue(h));
158
+ if (options.headerStyle) {
159
+ const range = sheet.getRange(`A1:${colLetter(options.headers.length)}1`);
160
+ range.applyStyle(options.headerStyle);
161
+ }
162
+ dataStartRow = 2;
163
+ }
164
+ rows.forEach((row, rowIdx) => {
165
+ row.forEach((val, colIdx) => {
166
+ const cell = sheet.getCell(dataStartRow + rowIdx, colIdx + 1);
167
+ if (val === null || val === void 0) return;
168
+ if (typeof val === "string") cell.setValue(val);
169
+ else if (typeof val === "number") cell.setValue(val);
170
+ else if (typeof val === "boolean") cell.setValue(val);
171
+ else if (val instanceof Date) cell.setValue(val);
172
+ else cell.setValue(String(val));
173
+ });
174
+ });
175
+ return wb;
176
+ }
177
+ };
178
+ ExcelService = __decorateClass([
179
+ Injectable({ providedIn: "root" })
180
+ ], ExcelService);
181
+ function colLetter(col) {
182
+ let result = "";
183
+ while (col > 0) {
184
+ const rem = (col - 1) % 26;
185
+ result = String.fromCharCode(65 + rem) + result;
186
+ col = Math.floor((col - rem) / 26);
187
+ }
188
+ return result;
189
+ }
190
+
191
+ export { ExcelService };
192
+ //# sourceMappingURL=index.js.map
193
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/excel.service.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Angular service for working with Excel files.\n * Wraps @devmm/puredocs-excel with Angular-idiomatic patterns:\n * - Injectable for DI\n * - Returns Observable where appropriate\n * - Handles browser download\n * - Signal-compatible (returns plain values, no Subjects needed)\n *\n * Port concept from TVE.PureDocs.Excel — adapts C# service pattern to Angular.\n */\nimport { Injectable } from '@angular/core';\nimport { Workbook, Worksheet, CellStyle } from '@devmm/puredocs-excel';\n\nexport interface ExcelReadOptions {\n /** If true, reads formula cached values. Default: true. */\n readCachedValues?: boolean;\n}\n\nexport interface ExcelWriteOptions {\n /** File name for download (browser only). Defaults to 'export.xlsx'. */\n fileName?: string;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class ExcelService {\n\n // ── Read ────────────────────────────────────────────────────────────────────\n\n /**\n * Reads an Excel file from a browser File object.\n *\n * @example\n * // In a component\n * async onFileSelected(event: Event) {\n * const file = (event.target as HTMLInputElement).files![0];\n * const wb = await this.excel.readFile(file);\n * const sheet = wb.worksheets[0];\n * console.log(sheet.getCell('A1').getText());\n * }\n */\n async readFile(file: File): Promise<Workbook> {\n const buffer = await file.arrayBuffer();\n return Workbook.fromBuffer(buffer);\n }\n\n /**\n * Reads an Excel file from an ArrayBuffer or Uint8Array.\n * Useful when data comes from an HTTP response.\n *\n * @example\n * const response = await fetch('/api/report.xlsx');\n * const buffer = await response.arrayBuffer();\n * const wb = await this.excel.readBuffer(buffer);\n */\n readBuffer(buffer: ArrayBuffer | Uint8Array): Workbook {\n return Workbook.fromBuffer(buffer);\n }\n\n // ── Create ──────────────────────────────────────────────────────────────────\n\n /**\n * Creates a new empty workbook.\n *\n * @example\n * const wb = this.excel.createWorkbook();\n * const sheet = wb.addWorksheet('Report');\n * sheet.getCell('A1').setValue('Hello');\n */\n createWorkbook(): Workbook {\n return Workbook.create();\n }\n\n /**\n * Creates a workbook, applies a configuration callback, and returns it.\n * Convenience method for building workbooks inline.\n *\n * @example\n * const wb = this.excel.buildWorkbook(wb => {\n * const sheet = wb.addWorksheet('Sales');\n * sheet.getCell('A1').setValue('Total');\n * sheet.getCell('B1').setValue(12345);\n * });\n */\n buildWorkbook(configure: (workbook: Workbook) => void): Workbook {\n const wb = Workbook.create();\n configure(wb);\n return wb;\n }\n\n // ── Export ──────────────────────────────────────────────────────────────────\n\n /**\n * Serialises a workbook to a Uint8Array buffer.\n * Use this when you want to upload the file via HTTP.\n *\n * @example\n * const buffer = this.excel.toBuffer(workbook);\n * await this.http.post('/api/upload', buffer, {\n * headers: { 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }\n * }).toPromise();\n */\n toBuffer(workbook: Workbook): Uint8Array {\n return workbook.saveAsBuffer();\n }\n\n /**\n * Triggers a browser download of the workbook.\n * Works in any modern browser via the Blob + anchor trick.\n *\n * @param workbook The workbook to download\n * @param fileName Download filename (default: \"export.xlsx\")\n *\n * @example\n * this.excel.download(workbook, 'monthly-report.xlsx');\n */\n download(workbook: Workbook, fileName = 'export.xlsx'): void {\n const buffer = workbook.saveAsBuffer();\n this.downloadBuffer(buffer, fileName);\n }\n\n /**\n * Triggers a browser download from a raw Uint8Array buffer.\n *\n * @example\n * const buffer = someExternalSource.getXlsxBuffer();\n * this.excel.downloadBuffer(buffer, 'data.xlsx');\n */\n downloadBuffer(buffer: Uint8Array, fileName = 'export.xlsx'): void {\n const blob = new Blob([buffer as BlobPart], {\n type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = fileName;\n anchor.style.display = 'none';\n document.body.appendChild(anchor);\n anchor.click();\n\n // Cleanup after a short delay to allow the download to start\n setTimeout(() => {\n URL.revokeObjectURL(url);\n document.body.removeChild(anchor);\n }, 100);\n }\n\n /**\n * Returns a Blob from a workbook (useful for FormData uploads).\n *\n * @example\n * const blob = this.excel.toBlob(workbook);\n * const formData = new FormData();\n * formData.append('file', blob, 'report.xlsx');\n * await this.http.post('/api/upload', formData).toPromise();\n */\n toBlob(workbook: Workbook, fileName = 'export.xlsx'): Blob {\n const buffer = workbook.saveAsBuffer();\n return new Blob([buffer as BlobPart], {\n type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n });\n }\n\n // ── Convenience builders ────────────────────────────────────────────────────\n\n /**\n * Creates a simple single-sheet workbook from a 2D data array with optional headers.\n * Suitable for quick table exports.\n *\n * @example\n * const data = [\n * ['Alice', 30, 'Engineer'],\n * ['Bob', 25, 'Designer'],\n * ];\n * const headers = ['Name', 'Age', 'Role'];\n * this.excel.download(\n * this.excel.fromTable(data, { headers, sheetName: 'Staff' }),\n * 'staff.xlsx',\n * );\n */\n fromTable(\n rows: unknown[][],\n options?: {\n headers?: string[];\n sheetName?: string;\n headerStyle?: (style: CellStyle) => void;\n },\n ): Workbook {\n const wb = Workbook.create();\n const sheet = wb.addWorksheet(options?.sheetName ?? 'Sheet1');\n\n let dataStartRow = 1;\n\n if (options?.headers && options.headers.length > 0) {\n options.headers.forEach((h, i) => sheet.getCell(1, i + 1).setValue(h));\n\n // Apply header style if provided\n if (options.headerStyle) {\n const range = sheet.getRange(`A1:${colLetter(options.headers.length)}1`);\n range.applyStyle(options.headerStyle);\n }\n\n dataStartRow = 2;\n }\n\n rows.forEach((row, rowIdx) => {\n row.forEach((val, colIdx) => {\n const cell = sheet.getCell(dataStartRow + rowIdx, colIdx + 1);\n if (val === null || val === undefined) return;\n if (typeof val === 'string') cell.setValue(val);\n else if (typeof val === 'number') cell.setValue(val);\n else if (typeof val === 'boolean') cell.setValue(val);\n else if (val instanceof Date) cell.setValue(val);\n else cell.setValue(String(val));\n });\n });\n\n return wb;\n }\n}\n\n// ── Helpers ────────────────────────────────────────────────────────────────────\n\n/** Converts a 1-based column index to a letter (A, B, … Z, AA …). */\nfunction colLetter(col: number): string {\n let result = '';\n while (col > 0) {\n const rem = (col - 1) % 26;\n result = String.fromCharCode(65 + rem) + result;\n col = Math.floor((col - rem) / 26);\n }\n return result;\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@devmm/puredocs-excel-angular",
3
+ "version": "1.0.0",
4
+ "description": "Angular service wrapper for @devmm/puredocs-excel",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "require": "./dist/index.cjs"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "sideEffects": false,
21
+ "peerDependencies": {
22
+ "@angular/common": ">=17.0.0",
23
+ "@angular/core": ">=17.0.0",
24
+ "@devmm/puredocs-excel": "1.0.0"
25
+ },
26
+ "devDependencies": {
27
+ "typescript": "^5.4.0",
28
+ "tsup": "^8.0.0",
29
+ "@devmm/puredocs-excel": "1.0.0"
30
+ },
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/quangtrungsoft/puredocs-excel.git",
34
+ "directory": "packages/angular"
35
+ },
36
+ "bugs": {
37
+ "url": "https://github.com/quangtrungsoft/puredocs-excel/issues"
38
+ },
39
+ "homepage": "https://github.com/quangtrungsoft/puredocs-excel/tree/main/packages/angular#readme",
40
+ "scripts": {
41
+ "build": "tsup",
42
+ "typecheck": "tsc --noEmit",
43
+ "clean": "rm -rf dist"
44
+ }
45
+ }