@ricsam/excel-to-formula-engine 0.0.0 → 0.1.1

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/README.md CHANGED
@@ -1,45 +1,179 @@
1
- # @ricsam/excel-to-formula-engine
2
-
3
- ## ⚠️ IMPORTANT NOTICE ⚠️
4
-
5
- **This package is created solely for the purpose of setting up OIDC (OpenID Connect) trusted publishing with npm.**
6
-
7
- This is **NOT** a functional package and contains **NO** code or functionality beyond the OIDC setup configuration.
8
-
9
- ## Purpose
10
-
11
- This package exists to:
12
- 1. Configure OIDC trusted publishing for the package name `@ricsam/excel-to-formula-engine`
13
- 2. Enable secure, token-less publishing from CI/CD workflows
14
- 3. Establish provenance for packages published under this name
15
-
16
- ## What is OIDC Trusted Publishing?
17
-
18
- OIDC trusted publishing allows package maintainers to publish packages directly from their CI/CD workflows without needing to manage npm access tokens. Instead, it uses OpenID Connect to establish trust between the CI/CD provider (like GitHub Actions) and npm.
19
-
20
- ## Setup Instructions
21
-
22
- To properly configure OIDC trusted publishing for this package:
23
-
24
- 1. Go to [npmjs.com](https://www.npmjs.com/) and navigate to your package settings
25
- 2. Configure the trusted publisher (e.g., GitHub Actions)
26
- 3. Specify the repository and workflow that should be allowed to publish
27
- 4. Use the configured workflow to publish your actual package
28
-
29
- ## DO NOT USE THIS PACKAGE
30
-
31
- This package is a placeholder for OIDC configuration only. It:
32
- - Contains no executable code
33
- - Provides no functionality
34
- - Should not be installed as a dependency
35
- - Exists only for administrative purposes
36
-
37
- ## More Information
38
-
39
- For more details about npm's trusted publishing feature, see:
40
- - [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
41
- - [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
42
-
43
- ---
44
-
45
- **Maintained for OIDC setup purposes only**
1
+ # excel-to-formula-engine
2
+
3
+ Convert an Excel `.xlsx` file into [`@ricsam/formula-engine`](https://github.com/ricsam/formula-engine)
4
+ `WorkbookData`, in the browser.
5
+
6
+ ```ts
7
+ import { excelToFormulaEngine } from "@ricsam/excel-to-formula-engine";
8
+
9
+ const data = await excelToFormulaEngine(blob);
10
+ engine.addWorkbook({ workbookName: "Budget", data });
11
+ ```
12
+
13
+ Pure TypeScript — no WASM, no native toolchain, no server round trip. An `.xlsx`
14
+ is a ZIP of XML, so it unzips with [fflate](https://github.com/101arrowz/fflate)
15
+ and parses with [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser).
16
+ Ships as ESM and CJS with type declarations; ~48 kB per bundle, dependencies
17
+ external.
18
+
19
+ ## Install
20
+
21
+ ```bash
22
+ bun add @ricsam/excel-to-formula-engine @ricsam/formula-engine
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ `excelToFormulaEngine` accepts a `Blob` or `File` straight from a file input, or
28
+ raw bytes as an `ArrayBuffer` / `Uint8Array`.
29
+
30
+ ```ts
31
+ import { FormulaEngine } from "@ricsam/formula-engine";
32
+ import { excelToFormulaEngine } from "@ricsam/excel-to-formula-engine";
33
+
34
+ input.addEventListener("change", async () => {
35
+ const file = input.files?.[0];
36
+ if (!file) return;
37
+
38
+ const data = await excelToFormulaEngine(file);
39
+
40
+ const engine = FormulaEngine.buildEmpty();
41
+ engine.addWorkbook({ workbookName: file.name, data });
42
+
43
+ // Formulas are live — the engine recalculates them.
44
+ engine.getCellValue({
45
+ workbookName: file.name,
46
+ sheetName: "Data",
47
+ rowIndex: 4,
48
+ colIndex: 3,
49
+ });
50
+ });
51
+ ```
52
+
53
+ The whole workbook loads as a single undo step, so one `Ctrl-Z` reverts an
54
+ import.
55
+
56
+ ### Diagnostics
57
+
58
+ Anything that could not be translated is reported rather than silently dropped.
59
+ `excelToFormulaEngineDetailed` returns the diagnostics beside the data; they are
60
+ also stored in `data.workbookMetadata.diagnostics`.
61
+
62
+ ```ts
63
+ const { data, diagnostics } = await excelToFormulaEngineDetailed(file);
64
+
65
+ for (const diagnostic of diagnostics) {
66
+ console.warn(
67
+ `[${diagnostic.code}] ${diagnostic.sheetName}!${diagnostic.cellReference}`,
68
+ diagnostic.message
69
+ );
70
+ }
71
+ ```
72
+
73
+ ### Options
74
+
75
+ ```ts
76
+ await excelToFormulaEngine(file, {
77
+ sheets: ["Summary"], // import only these sheets
78
+ styles: false, // skip fills, fonts, borders
79
+ conditionalFormatting: false, // skip conditional formatting
80
+ tables: false, // skip Excel tables
81
+ definedNames: false, // skip defined names
82
+ cellMetadata: false, // skip number formats and hyperlinks
83
+ convertDates: false, // keep date serials as raw numbers
84
+ });
85
+ ```
86
+
87
+ ## What gets translated
88
+
89
+ | Excel | Engine | Notes |
90
+ | --- | --- | --- |
91
+ | Cell values | Cell content | Strings, numbers, booleans and error values keep their type. |
92
+ | Formulas | Formulas | Kept as formulas, not as Excel's cached results — the engine recalculates. |
93
+ | Shared formulas | Expanded formulas | Excel stores one formula per group; each member gets its references offset. |
94
+ | Sheet order | Sheet order | Array order becomes tab order. |
95
+ | Cross-sheet references | Unchanged | `Data!D5` parses identically. |
96
+ | Excel tables | Tables | Structured references (`Sales[Amount]`) work. Tables without a header row are skipped. |
97
+ | Defined names | Named expressions | Sheet-scoped names stay sheet-scoped. Built-ins like `_xlnm.Print_Area` are skipped. |
98
+ | Fills, fonts, borders | `CellStyle` | Theme and indexed colours are resolved, including tints. |
99
+ | Conditional formatting | Conditional styles | `cellIs`, `expression`, text rules and colour scales. See below. |
100
+ | Dates | ISO strings | The engine has no date type, so `45306` becomes `"2024-01-15"`. |
101
+ | Number formats, hyperlinks | Cell metadata | Stored for your UI; the engine does not interpret them. |
102
+ | Merges, frozen panes, column widths, hidden sheets | Sheet metadata | Same — stored for your UI to apply. |
103
+
104
+ ### Formulas the engine cannot evaluate
105
+
106
+ The engine implements around 40 functions. A formula using anything else — an
107
+ Excel file will often reach for `VLOOKUP`, `TEXT`, `ROUND` or `SUMPRODUCT` — is
108
+ **imported unchanged** and evaluates to `#NAME?`, with a warning diagnostic
109
+ naming the function and the cell.
110
+
111
+ This keeps the author's intent visible and editable in the cell, rather than
112
+ replacing it with a frozen copy of whatever Excel last calculated. Everything
113
+ needed to do the opposite is in the diagnostics if you prefer that trade.
114
+
115
+ ### Conditional formatting
116
+
117
+ Excel's rule catalogue is much larger than the engine's, which has a formula
118
+ rule and a two-stop gradient. These map across:
119
+
120
+ - `cellIs` with every operator, including `between` / `notBetween`
121
+ - `expression` (custom formula rules)
122
+ - `containsText`, `notContainsText`, `beginsWith`, `endsWith`
123
+ - `containsBlanks`, `notContainsBlanks`
124
+ - `colorScale` → gradient (a three-colour scale loses its midpoint, with an
125
+ `info` diagnostic)
126
+
127
+ Data bars, icon sets, `top10`, `aboveAverage` and duplicate rules are reported
128
+ as `unsupported-conditional-format` and skipped.
129
+
130
+ ### Not imported
131
+
132
+ Charts, images, shapes, pivot tables, macros, data validation, sparklines,
133
+ comments, and cell protection. The engine has no representation for them.
134
+ Password-protected and legacy `.xls` files are rejected with a clear error.
135
+
136
+ ## Demo
137
+
138
+ ```bash
139
+ bun run demo:serve
140
+ ```
141
+
142
+ Opens a page at <http://localhost:4321> where you can drop in a workbook and see
143
+ it recalculated live. `demo/sample.xlsx` is there to try.
144
+
145
+ ## Development
146
+
147
+ ```bash
148
+ bun install
149
+ bun run fixtures # generate .xlsx test fixtures with ExcelJS
150
+ bun run test # regenerates fixtures, then runs the suite
151
+ bun run typecheck
152
+ bun run build # emit dist/ (ESM, CJS and .d.ts)
153
+ ```
154
+
155
+ Fixtures are written by ExcelJS rather than hand-rolled XML, so the tests run
156
+ against real OOXML — shared strings, shared formulas, style indirection, table
157
+ parts and conditional formatting blocks as a spreadsheet application emits them.
158
+ They are generated rather than committed, so `bun run test` builds them first.
159
+
160
+ ## Releasing
161
+
162
+ Releases go out from `main` through [changesets](https://github.com/changesets/changesets)
163
+ and npm [trusted publishing](https://docs.npmjs.com/trusted-publishers), so no
164
+ npm token is stored in the repository — the publish job mints a short-lived
165
+ OIDC token instead.
166
+
167
+ ```bash
168
+ bunx changeset # describe the change; pick patch / minor / major
169
+ bunx changeset version # fold pending changesets into package.json + CHANGELOG
170
+ git commit -am "Release x.y.z"
171
+ git push origin main # .github/workflows/publish.yml builds, tests, publishes
172
+ ```
173
+
174
+ `changeset publish` only publishes when the version in `package.json` is not
175
+ already on npm, so pushing unrelated commits to `main` is safe.
176
+
177
+ ## License
178
+
179
+ ISC