From 66c04e192d95258c2f6c4ecee5761be01ce89e7d Mon Sep 17 00:00:00 2001 From: Brian Hung Date: Wed, 11 Jun 2025 18:31:42 -0700 Subject: [PATCH 1/2] feat: add import & export for xlsx and icalc --- Cargo.lock | 243 +---------------------------------- bindings/wasm/Cargo.toml | 1 + bindings/wasm/README.pkg.md | 20 ++- bindings/wasm/src/lib.rs | 40 ++++++ bindings/wasm/tests/test.mjs | 47 +++++++ xlsx/Cargo.toml | 4 +- xlsx/src/import/mod.rs | 7 + xlsx/tests/test.rs | 14 +- 8 files changed, 134 insertions(+), 242 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cbcdd9932..ef60f4aeb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,17 +8,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - [[package]] name = "aho-corasick" version = "1.1.3" @@ -55,12 +44,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - [[package]] name = "bitcode" version = "0.6.3" @@ -91,15 +74,6 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - [[package]] name = "bumpalo" version = "3.15.4" @@ -118,36 +92,11 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" -[[package]] -name = "bzip2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" -dependencies = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - [[package]] name = "cc" version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" -dependencies = [ - "jobserver", - "libc", -] [[package]] name = "cfg-if" @@ -190,16 +139,6 @@ dependencies = [ "phf_codegen", ] -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -210,12 +149,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - [[package]] name = "convert_case" version = "0.6.0" @@ -231,15 +164,6 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" -[[package]] -name = "cpufeatures" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] - [[package]] name = "crc32fast" version = "1.4.0" @@ -255,16 +179,6 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - [[package]] name = "csv" version = "1.3.0" @@ -305,17 +219,6 @@ dependencies = [ "powerfmt", ] -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", - "subtle", -] - [[package]] name = "either" version = "1.10.0" @@ -332,16 +235,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "getrandom" version = "0.2.13" @@ -365,15 +258,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - [[package]] name = "iana-time-zone" version = "0.1.60" @@ -403,27 +287,20 @@ version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - [[package]] name = "ironcalc" version = "0.5.0" dependencies = [ "bitcode", "chrono", + "flate2", "ironcalc_base", "itertools", "roxmltree", "serde", "serde_json", "thiserror", + "time", "uuid", "zip", ] @@ -472,15 +349,6 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" -[[package]] -name = "jobserver" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" -dependencies = [ - "libc", -] - [[package]] name = "js-sys" version = "0.3.69" @@ -625,29 +493,6 @@ dependencies = [ "regex", ] -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core", - "subtle", -] - -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest", - "hmac", - "password-hash", - "sha2", -] - [[package]] name = "phf" version = "0.11.2" @@ -686,12 +531,6 @@ dependencies = [ "siphasher", ] -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - [[package]] name = "portable-atomic" version = "1.7.0" @@ -932,40 +771,12 @@ dependencies = [ "serde", ] -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "siphasher" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" -[[package]] -name = "subtle" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" - [[package]] name = "syn" version = "2.0.77" @@ -1010,6 +821,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", + "js-sys", "num-conv", "powerfmt", "serde", @@ -1022,12 +834,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - [[package]] name = "unicode-ident" version = "1.0.12" @@ -1056,12 +862,6 @@ dependencies = [ "serde", ] -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -1072,6 +872,7 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" name = "wasm" version = "0.5.0" dependencies = [ + "ironcalc", "ironcalc_base", "serde", "serde-wasm-bindgen", @@ -1252,45 +1053,9 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" dependencies = [ - "aes", "byteorder", - "bzip2", - "constant_time_eq", "crc32fast", "crossbeam-utils", "flate2", - "hmac", - "pbkdf2", - "sha1", "time", - "zstd", -] - -[[package]] -name = "zstd" -version = "0.11.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" -dependencies = [ - "cc", - "pkg-config", ] diff --git a/bindings/wasm/Cargo.toml b/bindings/wasm/Cargo.toml index 231521091..9ec795465 100644 --- a/bindings/wasm/Cargo.toml +++ b/bindings/wasm/Cargo.toml @@ -14,6 +14,7 @@ crate-type = ["cdylib"] # Uses `../ironcalc/base` when used locally, and uses # the inicated version from crates.io when published. # https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#multiple-locations +ironcalc = { path = "../../xlsx", version = "0.5.0" } ironcalc_base = { path = "../../base", version = "0.5", features = ["use_regex_lite"] } serde = { version = "1.0", features = ["derive"] } wasm-bindgen = "0.2.92" diff --git a/bindings/wasm/README.pkg.md b/bindings/wasm/README.pkg.md index 8e62d0ec5..126db7171 100644 --- a/bindings/wasm/README.pkg.md +++ b/bindings/wasm/README.pkg.md @@ -1,6 +1,6 @@ # IronCalc Web bindings -This package contains web bindings for IronCalc. Note that it does not contain the xlsx writer and reader, only the engine. +This package contains web bindings for IronCalc. It exposes the engine and helper functions to import or export workbooks as XLSX or IronCalc (icalc) byte arrays, but it does not bundle a full XLSX reader. ## Usage @@ -31,3 +31,21 @@ function compute() { compute(); ``` + +### Importing and exporting bytes + +The `Model` class provides helpers to load or save workbooks as raw byte arrays. + +```ts +// create a new workbook and export as XLSX bytes +const model = new Model('Workbook1', 'en', 'UTC'); +model.setUserInput(0, 1, 1, '42'); +const xlsxBytes = model.saveToXlsx(); + +// load from those bytes +const roundTripped = Model.fromXlsxBytes(xlsxBytes, 'Workbook1', 'en', 'UTC'); + +// same helpers exist for IronCalc's internal format +const icalcBytes = model.saveToIcalc(); +const restored = Model.fromIcalcBytes(icalcBytes); +``` diff --git a/bindings/wasm/src/lib.rs b/bindings/wasm/src/lib.rs index 5767a2edf..fbc33b7da 100644 --- a/bindings/wasm/src/lib.rs +++ b/bindings/wasm/src/lib.rs @@ -4,11 +4,15 @@ use wasm_bindgen::{ JsValue, }; +use ironcalc::{ + base::Model as BaseWorkbookModel, export::save_xlsx_to_writer, import::load_from_xlsx_bytes, +}; use ironcalc_base::{ expressions::{lexer::util::get_tokens as tokenizer, types::Area, utils::number_to_column}, types::{CellType, Style}, BorderArea, ClipboardData, UserModel as BaseModel, }; +use std::io::{BufWriter, Cursor}; fn to_js_error(error: String) -> JsError { JsError::new(&error.to_string()) @@ -55,6 +59,27 @@ impl Model { Ok(Model { model }) } + #[wasm_bindgen(js_name = "fromICalcBytes")] + pub fn from_icalc_bytes(bytes: &[u8]) -> Result { + let model = BaseModel::from_bytes(bytes).map_err(to_js_error)?; + Ok(Model { model }) + } + + #[wasm_bindgen(js_name = "fromXLSXBytes")] + pub fn from_xlsx_bytes( + bytes: &[u8], + name: &str, + locale: &str, + timezone: &str, + ) -> Result { + let workbook = load_from_xlsx_bytes(bytes, name, locale, timezone) + .map_err(|e| to_js_error(e.to_string()))?; + let base_model = + BaseWorkbookModel::from_workbook(workbook).map_err(|e| to_js_error(e.to_string()))?; + let user_model = BaseModel::from_model(base_model); + Ok(Model { model: user_model }) + } + pub fn undo(&mut self) -> Result<(), JsError> { self.model.undo().map_err(to_js_error) } @@ -579,6 +604,21 @@ impl Model { self.model.to_bytes() } + #[wasm_bindgen(js_name = "saveToICalc")] + pub fn save_to_icalc(&self) -> Vec { + self.model.to_bytes() + } + + #[wasm_bindgen(js_name = "saveToXLSX")] + pub fn save_to_xlsx(&self) -> Result, JsError> { + let mut buffer: Vec = Vec::new(); + let cursor = Cursor::new(&mut buffer); + let writer = BufWriter::new(cursor); + save_xlsx_to_writer(self.model.get_model(), writer) + .map_err(|e| JsError::new(&e.to_string()))?; + Ok(buffer) + } + #[wasm_bindgen(js_name = "getName")] pub fn get_name(&self) -> String { self.model.get_name() diff --git a/bindings/wasm/tests/test.mjs b/bindings/wasm/tests/test.mjs index 374669966..c3ab1d471 100644 --- a/bindings/wasm/tests/test.mjs +++ b/bindings/wasm/tests/test.mjs @@ -130,5 +130,52 @@ test("autofill", () => { assert.strictEqual(result, "23"); }); +test('saveToXLSX returns data', () => { + const model = new Model('Workbook1', 'en', 'UTC'); + const bytes = model.saveToXLSX(); + assert.ok(bytes instanceof Uint8Array); + assert.ok(bytes.length > 0); +}); +test('saveToICalc returns data', () => { + const model = new Model('Workbook1', 'en', 'UTC'); + const bytes = model.saveToICalc(); + assert.ok(bytes instanceof Uint8Array); + assert.ok(bytes.length > 0); +}); + +test('fromICalcBytes loads model', () => { + const model = new Model('Workbook1', 'en', 'UTC'); + model.setUserInput(0, 1, 1, '42'); + const bytes = model.saveToICalc(); + const m2 = Model.fromICalcBytes(bytes); + assert.strictEqual(m2.getCellContent(0, 1, 1), '42'); +}); +test('fromXLSXBytes loads model', () => { + const model = new Model('Workbook1', 'en', 'UTC'); + model.setUserInput(0, 1, 1, '5'); + const bytes = model.saveToXLSX(); + const m2 = Model.fromXLSXBytes(bytes, 'Workbook1', 'en', 'UTC'); + assert.strictEqual(m2.getCellContent(0, 1, 1), '5'); +}); + +test('roundtrip via xlsx bytes', () => { + const m1 = new Model('Workbook1', 'en', 'UTC'); + m1.setUserInput(0, 1, 1, '7'); + m1.setUserInput(0, 1, 2, '=A1*3'); + const bytes = m1.saveToXLSX(); + const m2 = Model.fromXLSXBytes(bytes, 'Workbook1', 'en', 'UTC'); + m2.evaluate(); + assert.strictEqual(m2.getFormattedCellValue(0, 1, 2), '21'); +}); + +test('roundtrip via icalc bytes', () => { + const m1 = new Model('Workbook1', 'en', 'UTC'); + m1.setUserInput(0, 1, 1, '9'); + m1.setUserInput(0, 1, 2, '=A1*4'); + const bytes = m1.saveToICalc(); + const m2 = Model.fromICalcBytes(bytes); + m2.evaluate(); + assert.strictEqual(m2.getFormattedCellValue(0, 1, 2), '36'); +}); diff --git a/xlsx/Cargo.toml b/xlsx/Cargo.toml index 713d3bbe1..79d7549c6 100644 --- a/xlsx/Cargo.toml +++ b/xlsx/Cargo.toml @@ -12,7 +12,9 @@ readme = "README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -zip = "0.6" +zip = { version = "0.6.6", default-features = false, features = ["deflate", "time"] } +flate2 = { version = "1.0", default-features = false, features = ["rust_backend"] } +time = { version = "0.3", features = ["wasm-bindgen"] } roxmltree = "0.19" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/xlsx/src/import/mod.rs b/xlsx/src/import/mod.rs index 7ca509eeb..feaaef804 100644 --- a/xlsx/src/import/mod.rs +++ b/xlsx/src/import/mod.rs @@ -153,3 +153,10 @@ pub fn load_from_icalc(file_name: &str) -> Result { .map_err(|e| XlsxError::IO(format!("Failed to decode file: {}", e)))?; Model::from_workbook(workbook).map_err(XlsxError::Workbook) } + +/// Loads a [`Model`] from the bytes of an `ic` file. +pub fn load_from_icalc_bytes(bytes: &[u8]) -> Result { + let workbook: Workbook = bitcode::decode(bytes) + .map_err(|e| XlsxError::IO(format!("Failed to decode file: {}", e)))?; + Model::from_workbook(workbook).map_err(XlsxError::Workbook) +} diff --git a/xlsx/tests/test.rs b/xlsx/tests/test.rs index 0845da5c0..376bbcdde 100644 --- a/xlsx/tests/test.rs +++ b/xlsx/tests/test.rs @@ -7,7 +7,9 @@ use uuid::Uuid; use ironcalc::compare::{test_file, test_load_and_saving}; use ironcalc::export::save_to_xlsx; -use ironcalc::import::{load_from_icalc, load_from_xlsx, load_from_xlsx_bytes}; +use ironcalc::import::{ + load_from_icalc, load_from_icalc_bytes, load_from_xlsx, load_from_xlsx_bytes, +}; use ironcalc_base::types::{HorizontalAlignment, VerticalAlignment}; use ironcalc_base::{Model, UserModel}; @@ -62,6 +64,16 @@ fn test_load_from_xlsx_bytes() { assert_eq!(workbook.views[&0].sheet, 7); } +#[test] +fn test_load_from_icalc_bytes() { + let mut file = fs::File::open("tests/example.ic").unwrap(); + let mut bytes = Vec::new(); + file.read_to_end(&mut bytes).unwrap(); + let model = load_from_icalc_bytes(&bytes).unwrap(); + let model_from_file = load_from_icalc("tests/example.ic").unwrap(); + assert_eq!(model.workbook, model_from_file.workbook); +} + #[test] fn no_grid() { let model = load_from_xlsx("tests/NoGrid.xlsx", "en", "UTC").unwrap(); From 4905f609abefcb96c80968a0bc5d9be6434b8561 Mon Sep 17 00:00:00 2001 From: Brian Hung Date: Wed, 11 Jun 2025 18:38:00 -0700 Subject: [PATCH 2/2] update readme for wasm bindings --- bindings/wasm/README.md | 3 +-- bindings/wasm/README.pkg.md | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bindings/wasm/README.md b/bindings/wasm/README.md index b54082e32..fc0b21159 100644 --- a/bindings/wasm/README.md +++ b/bindings/wasm/README.md @@ -1,7 +1,6 @@ # IronCalc Web bindings -This crate is used to build the web bindings for IronCalc. -Note that it does not contain the xlsx writer and reader, only the engine. +This package contains web bindings for IronCalc. It exposes the engine and helper functions to import or export workbooks as XLSX or IronCalc (icalc) byte arrays. The built-in XLSX support focuses on core spreadsheet features like cell values, formulas, and styling. https://www.npmjs.com/package/@ironcalc/wasm?activeTab=readme diff --git a/bindings/wasm/README.pkg.md b/bindings/wasm/README.pkg.md index 126db7171..e26a45301 100644 --- a/bindings/wasm/README.pkg.md +++ b/bindings/wasm/README.pkg.md @@ -1,6 +1,6 @@ # IronCalc Web bindings -This package contains web bindings for IronCalc. It exposes the engine and helper functions to import or export workbooks as XLSX or IronCalc (icalc) byte arrays, but it does not bundle a full XLSX reader. +This package contains web bindings for IronCalc. It exposes the engine and helper functions to import or export workbooks as XLSX or IronCalc (icalc) byte arrays. The built-in XLSX support focuses on core spreadsheet features like cell values, formulas, and styling. ## Usage @@ -49,3 +49,4 @@ const roundTripped = Model.fromXlsxBytes(xlsxBytes, 'Workbook1', 'en', 'UTC'); const icalcBytes = model.saveToIcalc(); const restored = Model.fromIcalcBytes(icalcBytes); ``` +