Skip to content

v3.0.0

Choose a tag to compare

@GabrielMarquezMatte GabrielMarquezMatte released this 04 Sep 03:02
· 75 commits to master since this release
ecd0ae9

⚠️ Breaking changes

  • IExcelRecordMap<T>.ConfigureExcelRecordMap is now generic in the row writer.
    Old: static abstract void ConfigureExcelRecordMap(ExcelRecordMapBuilder<T> builder);
    New: static abstract void ConfigureExcelRecordMap<TRow>(ExcelRecordMapBuilder<T, TRow> builder) where TRow : IRowWriter;

    This lets the mapped record-writer path compile each column's write action against the concrete row writer (XlsxRowWriter, XlsbRowWriter, ...) instead of dispatching through the IRowWriter interface on every cell — the same optimization the reflection-based writer already had via its per-TRow plan.

    Who's affected: only hand-written IExcelRecordMap<T> implementations. If your types use [ExcelSerializable] (the source generator), nothing to do — just recompile. A hand-written implementation needs updating:

    // before
    public static void ConfigureExcelRecordMap(ExcelRecordMapBuilder<MyRecord> builder) { ... }
    
    // after
    public static void ConfigureExcelRecordMap<TRow>(ExcelRecordMapBuilder<MyRecord, TRow> builder)
        where TRow : IRowWriter
    { ... }

New: encrypted OOXML writing

  • Excel.EncryptPackage / EncryptPackageAsync: encrypt an OOXML package into an agile-encrypted CFB container (file and stream overloads). Pairs with the encryption reading support shipped in v2.3.0 — round-tripping a password-protected workbook no longer needs a third-party tool.
  • Underlying pieces now public/available: agile EncryptionInfo descriptor serialization, the write direction of agile key derivation, and an OLE compound writer generalized to N streams with mini-FAT support.

New: ADO.NET access

  • ExcelDataReader implements IDataReader, giving Excel/CSV data a standard IDataReader surface (GetValue, GetSchemaTable, GetOrdinal, typed GetXxx accessors, etc.) for code that expects one — DataTables, data-binding, existing ADO.NET pipelines.
  • ExcelRowReaderExtensions.Sheets() / ExcelSheet: enumerate a workbook's sheets (index + name) without opening each one.

New: native bindings parity

  • Python: SheetWriter, a streaming write handle — write_row with type inference, in-memory streaming, and columnar writing. Encrypted writing wired into the native bindings.
  • Rust: Workbook::rows, a zero-allocation lending row cursor, and Workbook::read_all_decoded for an RAII row set.
  • C++: the same Workbook::rows buffer-reusing cursor and read_all_decoded counterparts.
  • ExcelReader.Arrow: RecordBatch write support (previously read-only).

Fixes

  • XLSB integers are ~2x smaller. Numeric cells with an integral value in [-2^29, 2^29) now encode as the 4-byte BrtCellRk (fInt) form instead of always paying for the 8-byte BrtCellReal — matching what Excel itself emits for a sheet of integers.
  • XlsbRowWriter.Write<T> overflow errors now name the type. A caller-defined IUtf8SpanFormattable that overflows to ±Infinity during numeric conversion previously surfaced a bare "non-finite value" error; it now names the source type, matching the message you already got for a non-numeric value.
  • Corrupt mini-stream sectors fail loudly. ReadMiniStream now throws InvalidDataException for an out-of-bounds mini-sector slice instead of letting the read overflow silently.
  • Fixed a NativeAOT startup crash affecting the Python wheel and C/C++/Rust bindings. The native library no longer pins IlcInstructionSet=native. That setting baked the build machine's CPU features into the binary as a hard requirement; because the binary is built on one machine and consumed on another (CI runner, or an end user's machine after installing the wheel), a CPU-feature mismatch made the process abort at startup with "The required instruction sets are not supported by the current CPU." — intermittently in CI, and potentially for any user whose CPU lacked whatever the build host happened to have (e.g. AVX-512). Vectorized code paths still light up at runtime on capable CPUs via Vector128/256.IsHardwareAccelerated checks, which are unaffected by this change.
  • Data integrity checks strengthened; mapped-record-writer benchmarks added for the new ExcelRecordMapBuilder<T, TRow> path.
  • Dependency bumps: dorny/paths-filter 3→4, analyzer packages.

Compatibility

  • Reading is unaffected — no breaking changes to any parser, reader, or the generated IExcelRowMap<T> side.
  • .NET 8 and .NET 10 both supported, as before.