Lesath validates spreadsheet packages against a documented subset. Unknown parts, unsupported XML, and features outside that subset produce errors. There is no option to import a workbook while silently dropping its content.
On this page
Supported content
| Content | XLSX | ODS |
|---|---|---|
| Multiple ordered sheets with names | Supported | Supported |
| Sparse cells | Supported | Supported |
| Plain strings | Inline strings; scalar string caches | Unstyled strings with matching display text |
| Finite numbers and booleans | Supported | Supported |
| Formula text with a cached scalar | = prefix |
of:= prefix |
| Repeated blank rows and cells | Not used by the writer | Supported |
Formula text can round-trip within its format, but Lesath never evaluates it. Cross-format formula export is rejected. See the formula guide.
Unsupported features
The subset excludes styles and formatting, rich text, date/time value types, merged cells, comments, charts, images, macros, validations, protection, hyperlinks, named ranges, external links, embedded objects, signatures, and encryption. Shared strings and shared formulas are outside the XLSX subset. ODS populated rows or cells with repetition attributes are rejected.
Many files generated by Excel or LibreOffice contain default style or metadata parts, even when their visible cells look simple. Such files may be rejected. Lesath does not promise round trips for general office files or implement the whole XLSX or ODS specification.
XLSX numbers have no date inference. A numeric date serial with no unsupported
style remains a number. Do not treat it as a Date or Time automatically.
String whitespace
XLSX inline strings preserve leading and trailing whitespace, repeated
spaces, tabs, and line breaks through xml:space="preserve" where needed.
ODS rejects strings with leading or trailing ASCII spaces, consecutive ASCII
spaces, tabs, carriage returns, or line feeds. These require text:s, tab,
or line-break markup that Lesath does not support. The restriction applies
to both imported strings and exported values, including formula caches.
An empty string and a single interior space are supported.
Workbook limits
| Limit | Maximum |
|---|---|
| Sheets per workbook | 200 |
| Populated cells across all sheets | 100,000 |
| Row coordinate | 1,048,576 |
| Column coordinate | 16,384 |
| Integer magnitude | 999,999,999,999,999 (15 digits) |
| String cell length | 32,767 UTF-16 code units |
| Sheet name length | 31 characters |
Floats must be finite. Ruby strings must be convertible to valid UTF-8 and cannot contain disallowed XML control characters. An emoji may occupy two UTF-16 code units, so the string limit is not a simple character count.
Package limits
| ZIP constraint | Maximum or rule |
|---|---|
| Entries | 256 |
| Uncompressed bytes per part | 20 MiB |
| Total uncompressed bytes | 50 MiB |
| Advertised compression ratio | 1,000:1 |
| Paths | No absolute paths, parent traversal, backslashes, or NUL bytes |
| Entries | No duplicate names or encrypted entries |
| XML | No DTD or entity declarations |
The generated ZIP is checked against the same package limits before the target path is created. Highly repetitive data can exceed the compression ratio limit even when it stays below the cell and byte limits.
Output paths must not already exist. Choose a new filename when saving edits; Lesath does not offer an overwrite flag.
Errors
| Exception | Common causes | What to do |
|---|---|---|
Lesath::UnsupportedFeature |
Unsupported parts, styles, XML, formula conversion, or ODS whitespace | Use a supported file or explicitly transform data before export |
Lesath::InvalidPackage |
Invalid or missing package structure, malformed XML, DTDs, or ZIP limits | Check the source file and package size |
Lesath::Error |
Unknown sheet, invalid value or coordinate, workbook limits, empty workbook, or existing target | Correct the workbook or choose a new output path |
ArgumentError |
Unknown file extension or format | Pass format: :xlsx or format: :ods |
UnsupportedFeature and InvalidPackage inherit from Lesath::Error. Catch
the specific exceptions first if you want to give different messages:
begin
book = Lesath.read("input.xlsx")
Lesath.write(book, "output.xlsx")
rescue Lesath::UnsupportedFeature => error
warn "Unsupported spreadsheet content: #{error.message}"
rescue Lesath::InvalidPackage => error
warn "Invalid spreadsheet package: #{error.message}"
rescue Lesath::Error => error
warn "Workbook error: #{error.message}"
end
Filesystem failures during export, such as a missing parent directory or
insufficient write permissions, can raise Ruby SystemCallError subclasses.
Handle these where your application manages output files.
Rukbat integration
Rukbat::Workbook is not directly accepted. Lesath has its own workbook model,
and Rukbat formatting, comments, and formula semantics need an explicit
adapter and loss policy. CSV remains the broader interchange path until
such an adapter exists.
The design rationale and source standards are documented in ADR 001.