NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
crates.io · #2791 most downloaded on crates.io
An Excel/OpenDocument Spreadsheet reader and deserializer in pure Rust
Last release 2 months ago
27 Jul 2026
Ships fairly regularly
a new release about every 4 weeks
Nearly every release is documented
notes for 60 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
10 years old
82 releases · first in 2016
Fixed a regression in 0.36.0 that broke Strict OOXML (ISO/IEC 29500) _rels/.rels links.
Fixed a regression in 0.36.0 that broke Strict OOXML (ISO/IEC 29500)
_rels/.rels links.
Fixed XLS string handling to preserve empty strings instead of discarding
them. PR #679.
Fixed XLSB workbook parsing to consume the body of unhandled workbook-global
records. A leftover body was misread as the next record id, which either
silently dropped the worksheet or panicked from an empty buffer. PR #675.
Full Changelog: v0.36.0...v0.36.1
One column per quarter.
For historical reasons the XLSX methods for accessing merged cells were duplicated. This change introduces a cleaner API, deprecates the older methods…
Added an XLSX streaming API for cell and formula records, including shared
formula metadata. There are two new APIs:
XlsxCellReader::next_cell_with_formula() and
XlsxCellReader::next_cell_with_formula_metadata(). Previously it required 2
separate reads to get similar information. PR #654.
Added a per-sheet, lazy XLSX API to read worksheet hyperlinks:
Xlsx::hyperlinks_by_sheet_name() and Xlsx::hyperlinks_by_sheet_id(). Each
hyperlink reports its anchor range (Dimensions), external target
(URL/file/mailto), optional internal location, displayed text, and optional
tooltip. PR #659.
Extended the picture feature to also extract cell position information and
the raw image data, and to handle newer Excel 365 style embedded images.
PR #652.
Added support for reading XLSX rich string (rstring) records. Issue #655.
Updated dependencies and the minimum supported Rust version (MSRV) for
release 0.36.0:
atoi_simd: 0.17 → 0.18. PR #672zip: 7.0 → 8.6. This raises the MSRV from 1.83 to 1.88. PR #672quick-xml: 0.39 → 0.41, to address advisories RUSTSEC-2026-0194 andPerformance improvements:
Refactored and unified the merged-cell handling APIs. For historical reasons
the XLSX methods for accessing merged cells were duplicated. This change
introduces a cleaner API, deprecates the older methods, and aligns the XLS
merged-cell handling with the new XLSX APIs. Issue #536.
Made XLSX package path resolution more robust for non-standard package
layouts. Issue #638.
Changed XLSX <t> text handling in shared strings and inline strings to trim
leading and trailing ASCII whitespace (space, tab, CR, LF) unless the element
carries xml:space="preserve". See PR #671 and PR #673.
Fixed XLSX shared-formula cell-name replacement to be more precise for defined
names. PR #664.
Fixed XLSX custom number-format detection to treat the * (fill/repeat)
operator as escaping the character that follows it. PR #667.
Improved the XLS error message when a file is too small to be a valid
workbook. PR #670.
* fill operator in custom number format detection by @greymoth-jp in #667Full Changelog: v0.35.0...v0.36.0
Added has_1904_epoch() method to Xls/Xlsx/Xlsb structs to allow the user to determine which date epoch is in use by Excel. PR #630 .
Added has_1904_epoch() method to Xls/Xlsx/Xlsb structs to allow the user to
determine which date epoch is in use by Excel. PR #630.
Made RowDeserializer public to allow a custom DeserializeSeed.
PR #635.
Added deserialization examples. PR #649.
Performance improvements:
Fixed issue with redundant <v> value in inlineStr XLSX cells. Issue #633.
Fixed issue when processing XLSX files to ignore namespace prefix when reading
relation ids. Previously accepted only r: and relationships: prefixes.
Issue #634.
Fixed XLSX issue where rich text <r> elements were ignored after initial
plain <t> elements. Issue #636.
Fixed XLS issue where date format was ignored for formula values.
Issue #640.
Fixed XLSX shared formula expansion corrupting function names. The
replace_cell_names() function treated LOG10 as a cell reference (column
LOG, row 10). Issue #644.
Fixed XLSX inlineStr issue for elements that contain CDATA. Issue #648.
Fixed panic when parsing formulas in XLS BIFF5 workbooks.The parse_formula
function decoded the non-3D PtgRef, PtgArea, PtgRefErr, and PtgAreaErr tokens
assuming BIFF8 sizes. PR #643.
Fixed XLS panic with unsupported formula functions. Handle unsupported XLS
function ids as formula parse errors instead of indexing past the function
table. Issue #646.
<v> cell value parsing by @alexander-beedie in #622Full Changelog: v0.34.0...v0.35.0
Added has_1904_epoch() method to Xls/Xlsx/Xlsb structs to allow the user to
determine which date epoch is in use by Excel. PR #630.
Made RowDeserializer public to allow a custom DeserializeSeed.
PR #635.
Added deserialization examples. PR #649.
Performance improvements:
Fixed issue with redundant <v> value in inlineStr XLSX cells. Issue #633.
Fixed issue when processing XLSX files to ignore namespace prefix when reading
relation ids. Previously accepted only r: and relationships: prefixes.
Issue #634.
Fixed XLSX issue where rich text <r> elements were ignored after initial
plain <t> elements. Issue #636.
Fixed XLS issue where date format was ignored for formula values. Issue #640.
Fixed XLSX shared formula expansion corrupting function names. The
replace_cell_names() function treated LOG10 as a cell reference (column
LOG, row 10). Issue #644.
Fixed XLSX inlineStr issue for elements that contain CDATA. Issue #648.
Fixed panic when parsing formulas in XLS BIFF5 workbooks.The parse_formula
function decoded the non-3D PtgRef, PtgArea, PtgRefErr, and PtgAreaErr tokens
assuming BIFF8 sizes. PR #643.
Fixed XLS panic with unsupported formula functions. Handle unsupported XLS function ids as formula parse errors instead of indexing past the function table. Issue #646.
Updated benchmarking to uses the criterion.rs crate. This removed the requirement for using +nightly for cargo bench . PR #620 .
Updated benchmarking to uses the criterion.rs crate. This removed the
requirement for using +nightly for cargo bench. PR #620.
Updated dependencies for release 0.34.0:
quick-xml: 0.38 -> 0.39. PR #617Refactored CFB to resolve special case in the caller of fn get_chain.
PR #615.
Performance improvements:
Fixed capitalized workbook/book stream handling in XLS files. PR #618.
Fixed issue where BIFF5 Lbl and ExternSheet records were incorrectly
parsed as BIFF8. PR #613.
Fixed VBA check_variable_record to handle optional records. PR #614.
Fixed premature error when BIFF version is not Biff8 in XLS files. PR #619.
Fixed issue where XLSX cells with an empty <v/> value returned a string with
index 0 instead of an Empty value. Issue #607.
Fixed millisecond rounding issue where 1000 milliseconds weren't rounded up to
the next second. Issue #602, PR #605.
fast_float2 used at all float-parsing call sites by @alexander-beedie in #608xls sector chain reads by @alexander-beedie in #609Full Changelog: v0.33.0...v0.34.0
Updated benchmarking to uses the criterion.rs crate. This removed the
requirement for using +nightly for cargo bench. PR #620.
Updated dependencies for release 0.34.0:
quick-xml: 0.38 -> 0.39. PR #617Refactored CFB to resolve special case in the caller of fn get_chain.
PR #615.
Performance improvements:
Fixed capitalized workbook/book stream handling in XLS files. PR #618.
Fixed issue where BIFF5 Lbl and ExternSheet records were incorrectly
parsed as BIFF8. PR #613.
Fixed VBA check_variable_record to handle optional records. PR #614.
Fixed premature error when BIFF version is not Biff8 in XLS files. PR #619.
Fixed issue where XLSX cells with an empty <v/> value returned a string with
index 0 instead of an Empty value. Issue #607.
Fixed millisecond rounding issue where 1000 milliseconds weren't rounded up to the next second. Issue #602, PR #605.
Added support for reading data from Pivot Tables, which involves reading data from the internal Pivot Cache. PR #559 .
Update dependencies for release 0.33.0:
zip: 4.2.0 -> 7.0.atoi_simd: 0.16 -> 0.17Fixed potential memory exhaustion issue in ODS files that could be triggered
via repeated empty rows/columns.
The fix adds limits to prevent memory exhaustion from malicious ODS files that
declare billions of repeated cells via table:number-rows-repeated and
table:number-columns-repeated attributes.
The change adds the following protection layers:
MAX_COLUMNS (16,384).MAX_ROWS (1,048,576).MAX_CELLS (100 million) in get_range().These limits match XLSX's existing row/column limits and prevent a 7KB
malicious file from attempting to allocate memory for 17+ billion cells.
When MAX_CELLS is exceeded, return OdsError::CellLimitExceeded instead
of silently returning an empty range. This ensures callers are properly
informed of truncation rather than receiving silent data loss.
Fixed an issue where XLSX files with tables that had the internal insertRow
attribute set returned a Dimensions object where the end row was less than
the start row. This caused an assert/panic when trying to create a Range
object to return the table range. Issue #589.
Fixed an issue with XLSX files where worksheet tables used the unusual, but
valid, absolute reference system like "/xl/tables/table1.xml" instead of the
common Excel generated relative system "../tables/table1.xml". Issue #587.
Full Changelog: v0.32.0...v0.33.0
Fixed out-of-memory vulnerabilities in XLS file parsing by bounding allocations.
Refactored VBA reading functions to be on-demand for better performance.
Simplified vba_project() function return type from Option<Result<T>> to
Result<Option<T>> for more idiomatic error handling. This is a breaking
change.
Fixed out-of-memory vulnerabilities in XLS file parsing by bounding
allocations.
Fixed and extended support for XLSX shared formulas with handling of ranges,
absolute references, and column/row ranges in XLSX files.
Fixed XLSX issue with missing shared string sub-elements. Also improved error
messages for shared string parsing issues.
Fixed acceptance of XLS XLUnicodeRichExtendedString records without reserved
tags.
Fixed various edge cases in XLS handling that could lead to parsing errors.
Full Changelog: v0.31.0...v0.32.0
Upgraded quick-xml to v0.38. This was a significant change in quick-xml relative to v0.37 and required changes in calamine to entity handling. It also
Upgraded quick-xml to v0.38. This was a significant change in quick-xml
relative to v0.37 and required changes in calamine to entity handling. It
also fixes EOL handling which may lead to regressions in calamine
applications if they expected to see "\r\n" in strings instead of the
correct (for XML and Excel) "\n".
For most users these will be inconsequential changes but please take note
before upgrading production code.
Renamed the "dates" feature flag to "chrono" since there is now some
native date handling features without "chrono". The "chrono" flag is more
specific and accurate. The "dates" flag is still supported as before for
backward compatibility.
This change also made some datatype methods related to date/times available in
the "default" feature set. They were previously hidden unnecessarily behind
the "dates/"chrono" flag.
ExcelDateTime to convert the inner serialFixed issue where Excel xlsx shared formula failed if it contained Unicode
characters. Issue #553.
Fixed issue where Excel XML escapes in strings weren't unescaped. For example
"_x000D_" -> "\r". Issue #469.
Full Changelog: v0.30.1...v0.31.0
Added Debug and Clone to Table for easier debugging. PR #547 .
Debug and Clone to Table for easier debugging. PR #547.SST record had an incorrect#[derive(Debug, Clone)] on Table by @lukapeschke in #547Full Changelog: v0.30.0...v0.30.1
Added Debug and Clone to Table for easier debugging. PR #547.
Fixed issue Issue #548 for xls files where the SST record had an incorrect
number of unique strings.
Unpinned the zip.rs dependency from v4.2.0 to allow cargo to choose the correct version for the user's rustc version.
Unpinned the zip.rs dependency from v4.2.0 to allow cargo to choose the
correct version for the user's rustc version.
The Rust MSRV was bumped to v1.75.0 (which it should have been for for
zip.rs compatibility in previous releases).
See the discussion at Issue #527.
Full Changelog: v0.29.0...v0.30.0
Add additional documentation and examples for the Range , Cell , XlsxError and Table structs, and Xlsx Table and Merge methods. Issue #459
Range, Cell, XlsxErrorTable structs, and Xlsx Table and Merge methods. Issue #459Pin zip.rs to v4.2.0.
The current latest release of zip.rs, v4.3.0, requires a MSRV of v1.85.0.
This release pins zip.rs to v4.2.0 to allow users to maintain a MSRV of
v1.73.0 for at least one more release. It is likely that calamine v0.30.0 or
later will move back to the latest zip.rs v4.x and require rustc v1.85.0.
Xlsx::from_sparse() and also ensured that theRange of cells would be in row-column order. PR #524.Full Changelog: v0.28.0...v0.29.0
### Changed - Bump zip to 4.0.
(xls): add one more Error variant related to formatting.
Error variant related to formatting.Sparse cells expect 0 index rows, even when using header_row.
header_row.Ability to merge cells from xls and xlsx.
header_row config.docs.rs build.Add is_error and get_error methods to the DataType trait.
is_error and get_error methods to the DataType trait.Range::headers method.Dimensions methods.OnceLock instead of once_cell crate (MSRV: 1.71).Introduce a DataType trait implemented by both Data and DataRef.
DataType trait implemented by both Data and DataRef.Data and DataType now return Some(0{.0}) and Some(1{.0}) rather than
None when .as_i64 or .as_f64 is used on a Bool value.is_x methods for date and time variants.DataType enum to Data and DataTypeRef to DataRef._rels files.worksheet_formula not returning all formula.
worksheet_formula not returning all formula.New DataTypeRef available from worksheet_range_ref to reduce memory usage.
DataTypeRef available from worksheet_range_ref to reduce memory usage.Spelling of formula error type.
Range::get.Add support of sheet type and visibility.
de_opt_f64 example.Formula with string not displaying properly.
Bump MSRV to 1.60.0 due to log dependencies.
Support PROJECTCOMPATVERSION in vba.
r attribute.PROJECTCOMPATVERSION in vba.(all) parse format/style information to infer cell as datetime.
### Fixed - Wrong range len calculation. - Date precision.
Always return sheet names in lexicographic order (BTreeMap).
BTreeMap).Improve conversions from raw data to primitives.
Use chunks_exact instead of chunks where possible.
chunks_exact instead of chunks where possible.u32::MAX.to_u32, read_slice safe and sound.Add deserialize_with example in README.
deserialize_with example in README.Make Metadata.sheets (and Reader.sheet_names) always return names in workbook order.
Metadata.sheets (and Reader.sheet_names) always return names in
workbook order.Deprecate failure and impl std::Error for all errors.
std::error::Error for all errors.dates feature to enrich DataType with date conversions functions.### Added - Update dependencies.
### Fixed - Wrong bound comparisons.
### Added - Improve deserializer. - Bump dependencies.
Add several new convenient fn to DataType.
DataType.Range::range fn to get sub-ranges.Range::cells iterator.DoubleEndedIterator when possible.Range::get fn (similar to slice's).size_hint impl in iterators.ExactSizeIterator.Consider empty cell as empty str if deserializing to str or String.
Xls - allow sectors ending after eof (truncate them!).
Codepage/encoding_rs for codepage mapping.
encoding_rs for codepage mapping.Serde map do not stop at first empty value.
Do not return map keys for empty cells. Fixes not working #[serde(default)].
#[serde(default)].Add a RangeDeserializerBuilder::with_headers fn to improve serde deserializer.
RangeDeserializerBuilder::with_headers fn to improve serde deserializer.Ods, support *text:s* and *text:p*.
### Fixed - Support MulRk for xls files.
MulRk for xls files.Properly parse richtext ods files.
Ods: display sheet names in order.
Handle 'covered cells' which are behind merge-cells in ODS.
Boolean detection and missing repeated cells in ODS.
Possibility of index out of bound in get_value and eventually in Index<(usize, usize)>.
get_value and eventually in Index<(usize, usize)>.Have Range start/end return None if the range is actually empty.
start/end return None if the range is actually empty.Range::get_value return an Option if the index is out of range.Make Range::from_sparse public.
Range::from_sparse public.Migrate from error-chain to failure.
encoding_rs and zip).### Added - Update dependencies.
### Added - Add serde deserialization.
Update dependencies, in particular quick-xml 0.9.1.
Add a bound check when decoding cfb.
### Changed - Bump dependencies. - Ignore .bk files.
### Changed - Bump dependencies.
Update to quick-xml 0.7.3 and encoding_rs 0.6.6.
encoding_rs 0.6.6.Implement Display for DataType and CellTypeError.
Display for DataType and CellTypeError.CellType alias trait.### Changed - Update to quick-xml 0.7.1.
Your coding agent can read these notes before it upgrades. Set up the MCP server →