@origints/xlsx 0.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.
@@ -0,0 +1,212 @@
1
+ import { Cell as ExcelJSCell } from 'exceljs';
2
+ import { XlsxResult, XlsxPath, CellValue, ExtendedCellValue } from './xlsx-result';
3
+ /**
4
+ * Cell style information.
5
+ */
6
+ export interface CellStyle {
7
+ readonly font?: {
8
+ readonly name?: string;
9
+ readonly size?: number;
10
+ readonly bold?: boolean;
11
+ readonly italic?: boolean;
12
+ readonly underline?: boolean;
13
+ readonly strikethrough?: boolean;
14
+ readonly color?: string;
15
+ };
16
+ readonly fill?: {
17
+ readonly type?: string;
18
+ readonly color?: string;
19
+ };
20
+ readonly border?: {
21
+ readonly top?: boolean;
22
+ readonly bottom?: boolean;
23
+ readonly left?: boolean;
24
+ readonly right?: boolean;
25
+ };
26
+ readonly alignment?: {
27
+ readonly horizontal?: string;
28
+ readonly vertical?: string;
29
+ readonly wrapText?: boolean;
30
+ };
31
+ readonly numFmt?: string;
32
+ }
33
+ /**
34
+ * A segment of rich text with its formatting.
35
+ */
36
+ export interface RichTextSegment {
37
+ readonly text: string;
38
+ readonly bold?: boolean;
39
+ readonly italic?: boolean;
40
+ readonly underline?: boolean;
41
+ readonly strikethrough?: boolean;
42
+ readonly color?: string;
43
+ readonly size?: number;
44
+ readonly font?: string;
45
+ }
46
+ /**
47
+ * Rich text content with all formatting preserved.
48
+ */
49
+ export interface RichTextContent {
50
+ readonly segments: readonly RichTextSegment[];
51
+ readonly hyperlink?: string;
52
+ }
53
+ /**
54
+ * A wrapper around ExcelJS Cell with full metadata preservation.
55
+ *
56
+ * XlsxCell enables typed extraction of cell values while maintaining
57
+ * provenance information. Each cell knows its exact location in the
58
+ * workbook, allowing full traceability.
59
+ */
60
+ export declare class XlsxCell {
61
+ private readonly cell;
62
+ private readonly _path;
63
+ private readonly _sheetName;
64
+ private constructor();
65
+ /**
66
+ * Creates an XlsxCell from an ExcelJS cell.
67
+ * @internal
68
+ */
69
+ static fromExcelJS(cell: ExcelJSCell, sheetName: string, file?: string): XlsxCell;
70
+ /**
71
+ * Returns the cell address (e.g., "A1").
72
+ */
73
+ get address(): string;
74
+ /**
75
+ * Returns the 1-based row number.
76
+ */
77
+ get row(): number;
78
+ /**
79
+ * Returns the 1-based column number.
80
+ */
81
+ get col(): number;
82
+ /**
83
+ * Returns the column letter(s) (e.g., "A", "AA").
84
+ */
85
+ get colLetter(): string;
86
+ /**
87
+ * Returns the current path for lineage tracking.
88
+ */
89
+ get path(): XlsxPath;
90
+ /**
91
+ * Returns the sheet name this cell belongs to.
92
+ */
93
+ get sheetName(): string;
94
+ /**
95
+ * Returns the raw cell value.
96
+ */
97
+ value(): XlsxResult<CellValue>;
98
+ /**
99
+ * Returns the extended cell value (including formula info).
100
+ */
101
+ extendedValue(): XlsxResult<ExtendedCellValue>;
102
+ /**
103
+ * Extract value as a string.
104
+ */
105
+ string(): XlsxResult<string>;
106
+ /**
107
+ * Extract value as a number.
108
+ */
109
+ number(): XlsxResult<number>;
110
+ /**
111
+ * Extract value as a boolean.
112
+ */
113
+ boolean(): XlsxResult<boolean>;
114
+ /**
115
+ * Extract value as a Date.
116
+ */
117
+ date(): XlsxResult<Date>;
118
+ /**
119
+ * Get the formula if this cell contains one.
120
+ */
121
+ formula(): XlsxResult<string>;
122
+ /**
123
+ * Get the cell content as rich text with formatting preserved.
124
+ * Returns segments with their individual formatting properties.
125
+ */
126
+ richText(): XlsxResult<RichTextContent>;
127
+ /**
128
+ * Get the cell content as Markdown.
129
+ *
130
+ * Converts cell content including:
131
+ * - Bold text -> **text**
132
+ * - Italic text -> *text*
133
+ * - Strikethrough -> ~~text~~
134
+ * - Hyperlinks -> [text](url)
135
+ * - Rich text segments with mixed formatting
136
+ */
137
+ markdown(): XlsxResult<string>;
138
+ /**
139
+ * Check if the cell contains rich text (multiple formatted segments).
140
+ */
141
+ isRichText(): boolean;
142
+ /**
143
+ * Check if the cell is empty.
144
+ */
145
+ isEmpty(): boolean;
146
+ /**
147
+ * Check if the cell contains a formula.
148
+ */
149
+ isFormula(): boolean;
150
+ /**
151
+ * Check if the cell is part of a merged range.
152
+ */
153
+ isMerged(): boolean;
154
+ /**
155
+ * Check if this is the master cell of a merged range.
156
+ */
157
+ isMergedMaster(): boolean;
158
+ /**
159
+ * Check if the cell contains a string.
160
+ */
161
+ isString(): boolean;
162
+ /**
163
+ * Check if the cell contains a number.
164
+ */
165
+ isNumber(): boolean;
166
+ /**
167
+ * Check if the cell contains a boolean.
168
+ */
169
+ isBoolean(): boolean;
170
+ /**
171
+ * Check if the cell contains a date.
172
+ */
173
+ isDate(): boolean;
174
+ /**
175
+ * Check if the cell contains an error.
176
+ */
177
+ isError(): boolean;
178
+ /**
179
+ * Get the cell's style information.
180
+ */
181
+ style(): CellStyle;
182
+ /**
183
+ * Get the hyperlink URL if the cell contains one.
184
+ */
185
+ hyperlink(): XlsxResult<string>;
186
+ /**
187
+ * Get the comment/note if the cell has one.
188
+ */
189
+ comment(): XlsxResult<string>;
190
+ /**
191
+ * Get a cell offset from this one.
192
+ * @internal Used by navigation methods
193
+ */
194
+ getOffsetCell(rowDelta: number, colDelta: number, getCell: (row: number, col: number) => XlsxCell | undefined): XlsxResult<XlsxCell>;
195
+ /**
196
+ * Get the raw value, handling ExcelJS value types.
197
+ */
198
+ private getRawValue;
199
+ /**
200
+ * Get the resolved value (formula result or plain value).
201
+ */
202
+ private getResolvedValue;
203
+ /**
204
+ * Normalize a formula result value.
205
+ */
206
+ private normalizeResult;
207
+ /**
208
+ * Convert Excel date number to JavaScript Date.
209
+ * Excel dates are days since 1900-01-01 (with a leap year bug).
210
+ */
211
+ private excelDateToJS;
212
+ }
@@ -0,0 +1,203 @@
1
+ import { XlsxSheet } from './xlsx-sheet';
2
+ import { XlsxCell } from './xlsx-cell';
3
+ import { XlsxResult, XlsxPath } from './xlsx-result';
4
+ import { CellPredicate } from './xlsx-query';
5
+ /**
6
+ * Direction for cursor movement.
7
+ */
8
+ export type CursorDirection = 'right' | 'left' | 'down' | 'up';
9
+ /**
10
+ * Result of a grab operation.
11
+ */
12
+ export interface GrabResult {
13
+ readonly cells: XlsxCell[];
14
+ readonly cursor: XlsxCursor;
15
+ }
16
+ /**
17
+ * Result of a single grab operation.
18
+ */
19
+ export interface GrabOneResult {
20
+ readonly cell: XlsxCell;
21
+ readonly cursor: XlsxCursor;
22
+ }
23
+ /**
24
+ * An immutable cursor for navigating through cells in a sheet.
25
+ *
26
+ * XlsxCursor provides a fluent API for moving through cells,
27
+ * skipping cells based on predicates, and grabbing sequences
28
+ * of cells. Each operation returns a new cursor, maintaining
29
+ * immutability.
30
+ */
31
+ export declare class XlsxCursor {
32
+ private readonly sheet;
33
+ private readonly _row;
34
+ private readonly _col;
35
+ private readonly _direction;
36
+ private constructor();
37
+ /**
38
+ * Create a cursor from an address string.
39
+ * @internal
40
+ */
41
+ static create(sheet: XlsxSheet, address: string): XlsxCursor;
42
+ /**
43
+ * Create a cursor from row and column coordinates.
44
+ * @internal
45
+ */
46
+ static createAt(sheet: XlsxSheet, row: number, col: number): XlsxCursor;
47
+ /**
48
+ * Get the current row (1-based).
49
+ */
50
+ get row(): number;
51
+ /**
52
+ * Get the current column (1-based).
53
+ */
54
+ get col(): number;
55
+ /**
56
+ * Get the current address.
57
+ */
58
+ get address(): string;
59
+ /**
60
+ * Get the current column letter.
61
+ */
62
+ get colLetter(): string;
63
+ /**
64
+ * Get the current direction.
65
+ */
66
+ get direction(): CursorDirection;
67
+ /**
68
+ * Get the path for lineage tracking.
69
+ */
70
+ get path(): XlsxPath;
71
+ /**
72
+ * Move by a delta (returns new cursor).
73
+ */
74
+ move(rowDelta: number, colDelta: number): XlsxCursor;
75
+ /**
76
+ * Move to a specific address.
77
+ */
78
+ moveTo(address: string): XlsxCursor;
79
+ /**
80
+ * Move to a specific row.
81
+ */
82
+ moveToRow(row: number): XlsxCursor;
83
+ /**
84
+ * Move to a specific column.
85
+ */
86
+ moveToCol(col: number | string): XlsxCursor;
87
+ /**
88
+ * Move left by count cells.
89
+ */
90
+ left(count?: number): XlsxCursor;
91
+ /**
92
+ * Move right by count cells.
93
+ */
94
+ right(count?: number): XlsxCursor;
95
+ /**
96
+ * Move up by count cells.
97
+ */
98
+ up(count?: number): XlsxCursor;
99
+ /**
100
+ * Move down by count cells.
101
+ */
102
+ down(count?: number): XlsxCursor;
103
+ /**
104
+ * Set the current direction.
105
+ */
106
+ setDirection(direction: CursorDirection): XlsxCursor;
107
+ /**
108
+ * Move forward in the current direction.
109
+ */
110
+ forward(count?: number): XlsxCursor;
111
+ /**
112
+ * Move to the start of the current row.
113
+ */
114
+ startOfRow(): XlsxCursor;
115
+ /**
116
+ * Move to the start of the current column.
117
+ */
118
+ startOfCol(): XlsxCursor;
119
+ /**
120
+ * Skip empty cells in the current direction.
121
+ */
122
+ skipEmpty(): XlsxCursor;
123
+ /**
124
+ * Skip cells while the predicate is true.
125
+ */
126
+ skipWhile(predicate: CellPredicate): XlsxCursor;
127
+ /**
128
+ * Skip cells until the predicate is true.
129
+ */
130
+ skipUntil(predicate: CellPredicate): XlsxCursor;
131
+ /**
132
+ * Skip cells until a specific value is found.
133
+ */
134
+ skipToValue(value: unknown): XlsxCursor;
135
+ /**
136
+ * Skip a specific number of cells.
137
+ */
138
+ skip(count: number): XlsxCursor;
139
+ /**
140
+ * Grab the current cell and move forward.
141
+ */
142
+ grab(): XlsxResult<GrabOneResult>;
143
+ /**
144
+ * Grab n cells in the current direction.
145
+ */
146
+ grabN(count: number): XlsxResult<GrabResult>;
147
+ /**
148
+ * Grab cells while the predicate is true.
149
+ */
150
+ grabWhile(predicate: CellPredicate): XlsxResult<GrabResult>;
151
+ /**
152
+ * Grab cells until the predicate is true (not including the matching cell).
153
+ */
154
+ grabUntil(predicate: CellPredicate): XlsxResult<GrabResult>;
155
+ /**
156
+ * Grab the rest of the current row.
157
+ */
158
+ grabRow(): XlsxResult<GrabResult>;
159
+ /**
160
+ * Grab the rest of the current column.
161
+ */
162
+ grabCol(): XlsxResult<GrabResult>;
163
+ /**
164
+ * Grab non-empty cells in the current direction.
165
+ */
166
+ grabNonEmpty(): XlsxResult<GrabResult>;
167
+ /**
168
+ * Peek at the current cell without moving.
169
+ */
170
+ peek(): XlsxResult<XlsxCell>;
171
+ /**
172
+ * Peek at cells ahead without moving.
173
+ */
174
+ peekAhead(count: number): XlsxResult<XlsxCell[]>;
175
+ /**
176
+ * Peek at a cell at an offset without moving.
177
+ */
178
+ peekAt(rowDelta: number, colDelta: number): XlsxResult<XlsxCell>;
179
+ /**
180
+ * Get the cell at the current position.
181
+ */
182
+ cell(): XlsxResult<XlsxCell>;
183
+ /**
184
+ * Get the value of the current cell.
185
+ */
186
+ value(): XlsxResult<unknown>;
187
+ /**
188
+ * Check if the cursor is at a valid position with data.
189
+ */
190
+ isValid(): boolean;
191
+ /**
192
+ * Check if the current cell is empty.
193
+ */
194
+ isEmpty(): boolean;
195
+ /**
196
+ * Check if the current cell is non-empty.
197
+ */
198
+ isNotEmpty(): boolean;
199
+ /**
200
+ * Create a new cursor at the same position.
201
+ */
202
+ clone(): XlsxCursor;
203
+ }
@@ -0,0 +1,155 @@
1
+ import { XlsxCell } from './xlsx-cell';
2
+ import { CellValue } from './xlsx-result';
3
+ /**
4
+ * A predicate function for matching cells.
5
+ */
6
+ export type CellPredicate = (cell: XlsxCell) => boolean;
7
+ /**
8
+ * Built-in predicates for common cell matching scenarios.
9
+ */
10
+ export declare const predicates: {
11
+ /**
12
+ * Match cells with the exact value.
13
+ */
14
+ equals: (value: CellValue) => CellPredicate;
15
+ /**
16
+ * Match cells containing the specified text (case-insensitive by default).
17
+ */
18
+ contains: (text: string, caseSensitive?: boolean) => CellPredicate;
19
+ /**
20
+ * Match cells whose value matches the regex pattern.
21
+ */
22
+ matches: (pattern: RegExp) => CellPredicate;
23
+ /**
24
+ * Match cells whose string value starts with the prefix.
25
+ */
26
+ startsWith: (prefix: string, caseSensitive?: boolean) => CellPredicate;
27
+ /**
28
+ * Match cells whose string value ends with the suffix.
29
+ */
30
+ endsWith: (suffix: string, caseSensitive?: boolean) => CellPredicate;
31
+ /**
32
+ * Match cells containing a string value.
33
+ */
34
+ isString: () => CellPredicate;
35
+ /**
36
+ * Match cells containing a numeric value.
37
+ */
38
+ isNumber: () => CellPredicate;
39
+ /**
40
+ * Match cells containing a boolean value.
41
+ */
42
+ isBoolean: () => CellPredicate;
43
+ /**
44
+ * Match cells containing a date value.
45
+ */
46
+ isDate: () => CellPredicate;
47
+ /**
48
+ * Match empty cells.
49
+ */
50
+ isEmpty: () => CellPredicate;
51
+ /**
52
+ * Match non-empty cells.
53
+ */
54
+ isNotEmpty: () => CellPredicate;
55
+ /**
56
+ * Match cells containing a formula.
57
+ */
58
+ isFormula: () => CellPredicate;
59
+ /**
60
+ * Match cells containing an error.
61
+ */
62
+ isError: () => CellPredicate;
63
+ /**
64
+ * Match merged cells.
65
+ */
66
+ isMerged: () => CellPredicate;
67
+ /**
68
+ * Match cells with numeric value greater than n.
69
+ */
70
+ greaterThan: (n: number) => CellPredicate;
71
+ /**
72
+ * Match cells with numeric value greater than or equal to n.
73
+ */
74
+ greaterThanOrEqual: (n: number) => CellPredicate;
75
+ /**
76
+ * Match cells with numeric value less than n.
77
+ */
78
+ lessThan: (n: number) => CellPredicate;
79
+ /**
80
+ * Match cells with numeric value less than or equal to n.
81
+ */
82
+ lessThanOrEqual: (n: number) => CellPredicate;
83
+ /**
84
+ * Match cells with numeric value between min and max (inclusive).
85
+ */
86
+ between: (min: number, max: number) => CellPredicate;
87
+ /**
88
+ * Match cells with date before the specified date.
89
+ */
90
+ dateBefore: (date: Date) => CellPredicate;
91
+ /**
92
+ * Match cells with date after the specified date.
93
+ */
94
+ dateAfter: (date: Date) => CellPredicate;
95
+ /**
96
+ * Match cells with date between start and end (inclusive).
97
+ */
98
+ dateBetween: (start: Date, end: Date) => CellPredicate;
99
+ /**
100
+ * Match cells in the specified row.
101
+ */
102
+ inRow: (rowNum: number) => CellPredicate;
103
+ /**
104
+ * Match cells in the specified column.
105
+ */
106
+ inCol: (colNum: number) => CellPredicate;
107
+ /**
108
+ * Match cells in the specified column (by letter).
109
+ */
110
+ inColLetter: (colLetter: string) => CellPredicate;
111
+ /**
112
+ * Match cells that satisfy all predicates.
113
+ */
114
+ and: (...preds: CellPredicate[]) => CellPredicate;
115
+ /**
116
+ * Match cells that satisfy at least one predicate.
117
+ */
118
+ or: (...preds: CellPredicate[]) => CellPredicate;
119
+ /**
120
+ * Match cells that do not satisfy the predicate.
121
+ */
122
+ not: (pred: CellPredicate) => CellPredicate;
123
+ /**
124
+ * Match cells with bold font.
125
+ */
126
+ isBold: () => CellPredicate;
127
+ /**
128
+ * Match cells with italic font.
129
+ */
130
+ isItalic: () => CellPredicate;
131
+ /**
132
+ * Match cells with a hyperlink.
133
+ */
134
+ hasHyperlink: () => CellPredicate;
135
+ /**
136
+ * Match cells with a comment.
137
+ */
138
+ hasComment: () => CellPredicate;
139
+ /**
140
+ * Always match.
141
+ */
142
+ always: () => CellPredicate;
143
+ /**
144
+ * Never match.
145
+ */
146
+ never: () => CellPredicate;
147
+ /**
148
+ * Create a custom predicate from a function.
149
+ */
150
+ custom: (fn: (cell: XlsxCell) => boolean) => CellPredicate;
151
+ };
152
+ /**
153
+ * Type for the predicates object.
154
+ */
155
+ export type Predicates = typeof predicates;