Zig 0.17.0

xlsx

On this page:

  • spider.xlsx: Excel .xlsx files, written and read — opt-in with -Dxlsx=true (see modules/xlsx/README.md).

spider.xlsx

Public API — pure-Zig writing and reading of Excel .xlsx files. No C, no dependency besides std, no global state, no temporary files.

Writing: build a Workbook, add sheets, set cells, then get the file as bytes or write it to any std.Io.Writer:

zig
const wb = try xlsx.Workbook.init(allocator);
defer wb.deinit();
const sheet = try wb.addSheet("Results");
try sheet.setRow(0, 0, &.{ .{ .text = "Option" }, .{ .text = "Votes" } }, .{ .bold = true });
try sheet.setRow(1, 0, &.{ .{ .text = "Yes" }, .int(12) }, .{});
const bytes = try wb.toOwnedSlice(allocator);

Reading: open the bytes of a file with limits and iterate the rows of a sheet, typed, in bounded memory:

zig
const book = try xlsx.Reader.open(allocator, bytes, .{});
defer book.deinit();
const rows = try book.rows(0, .{});
defer rows.deinit();
while (try rows.next()) |row| { … }

Written: several sheets; text, numbers, booleans, dates and formulas; column widths and row heights; fonts, background colour, borders, alignment, wrapped text and number formats; merged cells; links; hidden rows and columns; frozen panes, zoom and a filter per sheet; page setup, print area, page breaks, header and footer; protection. Read: sheets, rows and typed cells with their number format, cached formula results, merged ranges. Not done: streamed writing, compression, charts and images, .xls (see README.md).

spider.xlsx.Workbook

zig
pub const Workbook = struct

A workbook being built. Not thread-safe; there is no global state, so separate workbooks can be built on separate threads.

Fields

  • gpa: std.mem.Allocator
  • arena: std.heap.ArenaAllocator: Owns everything the workbook keeps: sheets, cells, copied text.
  • sheets: std.ArrayList(*Sheet) = .empty
  • strings: shared_strings.Table = .{}
  • styles: styles_mod.Registry = .{}
  • has_formulas: bool = false
  • protection: ?Protected = null

xlsx.Workbook.protect

zig
pub fn protect(self: *Workbook, protection: Protection) Error!void

Protects the workbook's structure: sheets cannot be added, removed, renamed, moved or unhidden. Cells stay editable unless their sheet is protected too. See Protection.

xlsx.Workbook.init

zig
pub fn init(gpa: std.mem.Allocator) error{OutOfMemory}!*Workbook

Creates an empty workbook. All memory comes from gpa and is released by deinit. Text passed in is copied: the caller's buffers can be freed or reused right after each call.

xlsx.Workbook.deinit

zig
pub fn deinit(self: *Workbook) void

Frees the workbook with its sheets and everything set on them. *Sheet pointers are invalid afterwards; bytes returned by toOwnedSlice are not touched.

xlsx.Workbook.setDefaultFont

zig
pub fn setDefaultFont(self: *Workbook, name: []const u8, size: f32) Error!void

Sets the font of every cell whose style names none (Calibri 11 otherwise). Call it before setting any cell.

Column widths are counted in characters of the default font, so this also changes how wide a given setColumnWidth value is: a workbook copied from one that uses another default font needs the same default to keep the same column widths.

xlsx.Workbook.addSheet

zig
pub fn addSheet(self: *Workbook, name: []const u8) Error!*Sheet

Adds a sheet; sheets appear in the order they are added.

The name follows Excel's rules: 1 to 31 characters, none of / \ ? * : [ ], no control characters, no apostrophe at either end, not "History", and different from the other sheets' names whatever the case of ASCII letters.

xlsx.Workbook.writeTo

zig
pub fn writeTo(self: *Workbook, out: *Writer) Error!void

Writes the .xlsx file to out. out is not flushed: flush it afterwards if it is buffered. The workbook can be written more than once, and always produces the same bytes.

xlsx.Workbook.toOwnedSlice

zig
pub fn toOwnedSlice(self: *Workbook, allocator: std.mem.Allocator) Error![]u8

Returns the .xlsx file as bytes owned by the caller (free them with allocator).

xlsx.Workbook.writeToPackager

zig
pub fn writeToPackager(self: *Workbook, packager: zip.Packager) Error!void

Hands every part to packager and finishes it. This is the seam for another container (a compressing zip, a recorder in tests).

spider.xlsx.Sheet

zig
pub const Sheet = struct

One sheet of a workbook. Created by Workbook.addSheet; rows and columns are zero-based.

Fields

  • workbook: *Workbook
  • name: []const u8
  • cells: std.ArrayList(Cell) = .empty
  • cells_in_order: bool = true: False once a cell was set out of row/column order or twice.
  • column_widths: std.ArrayList(ColumnWidth) = .empty
  • row_heights: std.ArrayList(RowHeight) = .empty
  • hidden_columns: std.ArrayList(u16) = .empty
  • hidden_rows: std.ArrayList(u32) = .empty
  • merges: std.ArrayList(Range) = .empty
  • links: std.ArrayList(Link) = .empty
  • frozen_rows: u32 = 0
  • frozen_cols: u32 = 0
  • auto_filter: ?Range = null
  • zoom: u16 = 100: In percent.
  • page_setup: ?PageSetup = null
  • print_area: ?Range = null
  • protection: ?Protected = null
  • row_breaks: std.ArrayList(u32) = .empty: Zero-based index of the first row (column) of each new page.
  • column_breaks: std.ArrayList(u32) = .empty
  • header_footer: HeaderFooter = .{}
  • default_column_width: ?f64 = null: In characters, like column widths.
  • default_row_height: ?f64 = null
  • print_title_rows: ?[2]u32 = null: First and last row repeated on every printed page.

xlsx.Sheet.set

zig
pub fn set(self: *Sheet, row: u32, col: u32, value: Value) Error!void

Sets a cell with the default style. Cells may be set in any order; setting a cell again replaces it.

xlsx.Sheet.setStyled

zig
pub fn setStyled(self: *Sheet, row: u32, col: u32, value: Value, style: Style) Error!void

Sets a cell and its style.

xlsx.Sheet.setRow

zig
pub fn setRow(self: *Sheet, row: u32, first_col: u32, values: []const Value, style: Style) Error!void

Sets consecutive cells of one row, starting at first_col, all with the same style.

xlsx.Sheet.setColumnWidth

zig
pub fn setColumnWidth(self: *Sheet, col: u32, width: f64) Error!void

Sets a column's width, in characters of the default font (the unit Excel shows in its "Column width" dialog). 0 hides nothing but makes the column as narrow as possible.

xlsx.Sheet.setRowHeight

zig
pub fn setRowHeight(self: *Sheet, row: u32, points: f64) Error!void

Sets a row's height in points (a default row is 15). Without it a spreadsheet program sizes the row to its content when it draws the sheet, wrapped text included.

xlsx.Sheet.setRowHeightHint

zig
pub fn setRowHeightHint(self: *Sheet, row: u32, points: f64) Error!void

Records the height a row has now without fixing it: a spreadsheet program may refit the row when its content changes (and some refit it on opening, for wrapped text). This is how Excel stores rows whose height nobody set by hand.

xlsx.Sheet.hideColumn

zig
pub fn hideColumn(self: *Sheet, col: u32) Error!void

Hides a column. Its cells, and its width if one was set, stay in the file: the reader can show the column again.

xlsx.Sheet.hideRow

zig
pub fn hideRow(self: *Sheet, row: u32) Error!void

Hides a row; see hideColumn.

xlsx.Sheet.setDefaultColumnWidth

zig
pub fn setDefaultColumnWidth(self: *Sheet, width: f64) Error!void

Sets the width of every column that has no width of its own.

xlsx.Sheet.setDefaultRowHeight

zig
pub fn setDefaultRowHeight(self: *Sheet, points: f64) Error!void

Sets the height of every row that has no height of its own.

xlsx.Sheet.mergeCells

zig
pub fn mergeCells(self: *Sheet, range: Range) Error!void

Merges a rectangle of cells into one. The merged cell shows the value and the alignment of the range's top-left cell; borders and fills still come from each cell of the range, so style them all (blank cells with a style) to frame the merged cell.

The range must cover more than one cell and cannot share a cell with another merged range.

xlsx.Sheet.freeze

zig
pub fn freeze(self: *Sheet, rows: u32, cols: u32) Error!void

Keeps the first rows rows and the first cols columns in view while the rest scrolls. freeze(1, 0) pins a header row.

zig
pub fn setLink(self: *Sheet, row: u32, col: u32, target: []const u8) Error!void

Makes a cell a link to a site (http://, https://) or to an e-mail address (mailto:). Other schemes are refused, so a link built from user data cannot point at a local file or run anything. The cell keeps its own value and style: set the text to show with setStyled(row, col, value, xlsx.link_style). Setting a link again on the same cell replaces it.

xlsx.Sheet.setPageSetup

zig
pub fn setPageSetup(self: *Sheet, setup: PageSetup) Error!void

Sets paper size, orientation and margins for printing. Without it the sheet has Excel's default margins and the paper is the reader's default, which depends on the country (Letter or A4).

xlsx.Sheet.protect

zig
pub fn protect(self: *Sheet, protection: Protection) Error!void

Protects the sheet: cells cannot be edited, except those whose style has unlocked = true. See Protection for what this is and is not.

xlsx.Sheet.setPrintArea

zig
pub fn setPrintArea(self: *Sheet, range: Range) Error!void

Limits printing to range.

xlsx.Sheet.addPageBreakBeforeRow

zig
pub fn addPageBreakBeforeRow(self: *Sheet, row: u32) Error!void

Starts a new printed page at row (which cannot be the first).

xlsx.Sheet.addPageBreakBeforeColumn

zig
pub fn addPageBreakBeforeColumn(self: *Sheet, col: u32) Error!void

Starts a new printed page at col (which cannot be the first).

xlsx.Sheet.setHeaderFooter

zig
pub fn setHeaderFooter(self: *Sheet, header_footer: HeaderFooter) Error!void

Sets the text printed at the top and bottom of every page; see HeaderFooter for the notation. The text is copied.

xlsx.Sheet.setPrintTitleRows

zig
pub fn setPrintTitleRows(self: *Sheet, first_row: u32, last_row: u32) Error!void

Repeats rows first_row to last_row at the top of every printed page: the header of a long table.

xlsx.Sheet.setZoom

zig
pub fn setZoom(self: *Sheet, percent: u16) Error!void

Sets the zoom the sheet opens with, 10 to 400 percent. It only affects the screen, not printing.

xlsx.Sheet.setAutoFilter

zig
pub fn setAutoFilter(self: *Sheet, range: Range) Error!void

Turns range into a filtered table: its first row gets the filter buttons. One filter per sheet; calling again replaces it.

spider.xlsx.Value

zig
pub const Value = union(enum)

What a cell holds.

Fields

  • blank: No value. With a style, the cell is still written (an empty cell with a background, for instance).
  • text: []const u8: Text, written exactly as given. Text is never interpreted: a string that starts with =, +, - or @ stays text and is shown as typed. An empty string is the same as blank.
  • number: f64: Numbers are IEEE doubles, as in every spreadsheet: integers are exact up to 2^53 and Excel shows 15 significant digits.
  • boolean: bool
  • date: Date: Stored as a number; shown as a date because the cell gets the date number format unless the style names another one.
  • datetime: DateTime: Like date, with the datetime number format by default.
  • formula: []const u8: A formula in Excel's syntax with English function names and , between arguments, e.g. "SUM(B2:B9)". A leading = is accepted and dropped. No result is stored: the program opening the file calculates it. Never build a formula from user input.

xlsx.Value.int

zig
pub fn int(n: anytype) Value

A whole number.

spider.xlsx.Error

zig
pub const Error = error

Everything building or writing a workbook can fail with. A value is checked when it is set, so the error comes from the call that passed it.

Errors

  • RowOutOfRange: Row index past the last row of a sheet (1,048,576 rows).
  • ColumnOutOfRange: Column index past the last column of a sheet (16,384 columns).
  • InvalidRange: A range whose last row or column comes before its first, a merge of a single cell, or a page break before the first row or column.
  • TextTooLong: Cell text longer than 32,767 characters.
  • InvalidUtf8: Text, a sheet name, a formula or a link that is not valid UTF-8.
  • InvalidNumber: NaN or infinity: a cell cannot hold them.
  • InvalidDate: Not a calendar date, or outside 1900-01-01 .. 9999-12-31.
  • InvalidFormula: An empty formula, one longer than 8,192 characters, or one with characters XML cannot carry.
  • InvalidSheetName: A sheet name Excel refuses (see Workbook.addSheet).
  • DuplicateSheetName: A sheet with this name already exists.
  • InvalidColumnWidth: A column width outside 0 .. 255.
  • InvalidRowHeight: A row height outside 0 .. 409 points.
  • OverlappingMerge: A merged range that shares a cell with another one.
  • InvalidZoom: A zoom outside 10 .. 400 percent.
  • InvalidMargin: A page margin that is negative, not finite or absurdly large.
  • InvalidPageSetup: A print scale outside 10 .. 400, or both a scale and fit-to-page.
  • InvalidHeaderFooter: A header or footer longer than 255 characters or with characters XML cannot carry.
  • InvalidPassword: A protection password that is empty, longer than 255 characters or not printable ASCII.
  • InvalidLink: A link that is not http://, https:// or mailto:, is too long, or has spaces or control characters.
  • TooManyLinks: More than 65,530 links on one sheet.
  • InvalidNumberFormat: A custom number format that is empty, too long or malformed.
  • InvalidFont: A font name that is empty, too long or malformed, or a font size outside 1 .. 409 points.
  • TooManyStyles: More than 65,490 distinct styles.
  • StylesAlreadyUsed: setDefaultFont was called after a cell was given a style.
  • NoSheets: A workbook must have at least one sheet to be written.
  • ArchiveTooLarge: The package does not fit a plain zip archive (zip64 is not implemented): a part or the whole file passes 4 GiB.
  • InvalidPartName: Only reachable with a custom Packager: this module's own part names are always valid and distinct.
  • DuplicatePartName
  • OutOfMemory
  • WriteFailed: The destination writer failed.

spider.xlsx.Style

zig
pub const Style = struct

The formatting of one cell. The default value is a plain cell.

Fields

  • bold: bool = false
  • italic: bool = false
  • underline: bool = false
  • font_color: ?u24 = null: Text colour as 0xRRGGBB.
  • font_name: ?[]const u8 = null: A font family name such as "Times New Roman". The file only carries the name: the font must exist on the reader's machine. Null is the workbook's default font (Calibri unless changed).
  • font_size: ?f32 = null: Size in points, 1 to 409, in steps of a tenth. Null is the workbook's default size (11 unless changed).
  • fill: ?u24 = null: Background colour as 0xRRGGBB.
  • fill_pattern: FillPattern = .solid
  • border: Border = .none: The line on the four sides of the cell.
  • border_left: ?Border = null: One side only; when set, it replaces border for that side (.none removes the line there).
  • border_right: ?Border = null
  • border_top: ?Border = null
  • border_bottom: ?Border = null
  • border_color: ?u24 = null: Colour of the border lines as 0xRRGGBB; null is the reader's automatic colour (black).
  • number_format: NumberFormat = .general
  • h_align: HorizontalAlignment = .general
  • v_align: VerticalAlignment = .bottom
  • wrap: bool = false: Breaks long text into lines inside the cell instead of letting it run over the next cells. Line breaks in the text itself also only show when this is set.
  • shrink: bool = false: Makes the text smaller, when needed, so it fits the cell's width on one line. Spreadsheet programs ignore it when wrap is set.
  • unlocked: bool = false: Lets the cell be edited when its sheet is protected (cells are locked by default). Has no effect on an unprotected sheet.

spider.xlsx.Border

zig
pub const Border = enum

A line drawn on the four sides of a cell.

Values

  • none
  • hair
  • dotted
  • dashed
  • thin
  • medium
  • thick
  • double

spider.xlsx.FillPattern

zig
pub const FillPattern = enum

How a cell's background is painted. solid covers it with the fill colour; the others draw dots of that colour (black without one) over the plain background, from darker to lighter.

Values

  • solid
  • dark_gray
  • medium_gray
  • light_gray
  • gray125
  • gray0625

spider.xlsx.NumberFormat

zig
pub const NumberFormat = union(enum)

How a number is shown. The named ones are formats every spreadsheet program has built in, so they follow the reader's locale (decimal comma, day/month order). custom takes a format code in Excel's syntax, written with . as the decimal separator, e.g. "dd/mm/yyyy" or "#,##0.00".

Fields

  • general
  • integer: 0
  • decimal: 0.00
  • thousands: #,##0
  • thousands_decimal: #,##0.00
  • percent: 0%
  • percent_decimal: 0.00%
  • date: The reader's short date.
  • time: h:mm:ss
  • datetime: The reader's short date, then h:mm.
  • text: Shows the cell as typed, numbers included.
  • custom: []const u8

spider.xlsx.HorizontalAlignment

zig
pub const HorizontalAlignment = enum

Where a cell's content sits between its left and right edges. general is the spreadsheet's own rule: text to the left, numbers to the right.

Values

  • general
  • left
  • center
  • right

spider.xlsx.VerticalAlignment

zig
pub const VerticalAlignment = enum

Where a cell's content sits between its top and bottom edges.

Values

  • bottom
  • center
  • top

spider.xlsx.Date

zig
pub const Date = struct

A calendar date (proleptic Gregorian, no time zone).

Fields

  • year: u16
  • month: u8: 1 to 12.
  • day: u8: 1 to 31.

xlsx.Date.serial

zig
pub fn serial(date: Date) Error!u32

The day number the 1900 date system gives this date.

spider.xlsx.DateTime

zig
pub const DateTime = struct

A calendar date and a time of day (no time zone: the spreadsheet shows exactly these fields).

Fields

  • year: u16
  • month: u8
  • day: u8
  • hour: u8 = 0
  • minute: u8 = 0
  • second: u8 = 0
  • millisecond: u16 = 0

xlsx.DateTime.serial

zig
pub fn serial(dt: DateTime) Error!f64

Day number plus the fraction of the day.

xlsx.DateTime.fromUnix

zig
pub fn fromUnix(seconds: i64) Error!DateTime

The UTC date and time of a Unix timestamp (seconds since 1970-01-01). Add the zone offset to seconds first to get local time.

spider.xlsx.Range

zig
pub const Range = struct

A rectangle of cells, both corners included.

Fields

  • first_row: u32
  • first_col: u32
  • last_row: u32
  • last_col: u32

xlsx.Range.write

zig
pub fn write(range: Range, w: *Writer) Writer.Error!void

A1:D51.

xlsx.Range.writeAbsolute

zig
pub fn writeAbsolute(range: Range, w: *Writer) Writer.Error!void

$A$1:$D$51.

spider.xlsx.PageSetup

zig
pub const PageSetup = struct

How a sheet is printed.

Fields

  • paper: ?Paper = .a4: Null leaves the paper to the program that opens the file.
  • orientation: Orientation = .portrait
  • margins: Margins = .{}
  • scale: ?u16 = null: Prints at this percentage of the real size, 10 to 400.
  • fit_to_width: ?u16 = null: Shrinks the sheet to this many pages across; 0 means as many as it takes. Cannot be combined with scale. When only one of fit_to_width and fit_to_height is set, the other counts as 1 page: set it to 0 to leave that direction free.
  • fit_to_height: ?u16 = null: Likewise, for pages down.

spider.xlsx.Paper

zig
pub const Paper = enum(u8)

Paper sizes for PageSetup.paper.

Values

  • letter = 1
  • legal = 5
  • a3 = 8
  • a4 = 9
  • a5 = 11

spider.xlsx.Orientation

zig
pub const Orientation = enum

Which way the page is turned when printed.

Values

  • portrait
  • landscape

spider.xlsx.Margins

zig
pub const Margins = struct

Page margins in inches, the unit the file uses (cm converts). The defaults are Excel's "Normal" margins. header and footer are the distance from the paper's edge to the header and footer text.

Fields

  • left: f64 = 0.7
  • right: f64 = 0.7
  • top: f64 = 0.75
  • bottom: f64 = 0.75
  • header: f64 = 0.3
  • footer: f64 = 0.3

spider.xlsx.HeaderFooter

zig
pub const HeaderFooter = struct

Text printed at the top and bottom of every page, in Excel's notation: &L, &C and &R start the left, centre and right parts; &P is the page number, &N the number of pages, &D the date, &A the sheet name; && is a literal &. Example footer: "&LReport&RPage &P of &N".

Fields

  • header: ?[]const u8 = null
  • footer: ?[]const u8 = null

spider.xlsx.Protection

zig
pub const Protection = struct

Options of Workbook.protect and Sheet.protect.

Protection is a guard against editing by accident, not security: the file is not encrypted, anyone can read it, and the password is kept as a 16-bit hash that many other passwords also match.

Fields

  • password: ?[]const u8 = null: Asked for when the user removes the protection. Null: no password, protection is removed with a click.

spider.xlsx.cm

zig
pub fn cm(centimetres: f64) f64

Centimetres to inches, for Margins.

zig
pub const link_style: Style = .{ .underline = true, .font_color = 0x0563C1 }

How spreadsheet programs draw a link: blue and underlined. A link does not style its cell; pass this (or a copy with more fields set) with the cell's value.

spider.xlsx.Reader

zig
pub const Reader = struct

An open .xlsx file. open reads the list of sheets; rows reads one sheet, row by row.

zig
const book = try xlsx.Reader.open(allocator, bytes, .{});
defer book.deinit();
const rows = try book.rows(0, .{});
defer rows.deinit();
while (try rows.next()) |row| {
    for (row.cells) |cell| switch (cell.value) {
        .text => |text| std.debug.print("{d}:{d} {s}\n", .{ row.number, cell.column, text }),
        .number => |n| std.debug.print("{d}:{d} {d}\n", .{ row.number, cell.column, n }),
        else => {},
    };
}

Rows and columns the file does not have are skipped: use row.number and cell.column, not the position in the iteration.

Apart from diagnostic, the fields are the reader's own state.

Fields

  • gpa: std.mem.Allocator
  • arena: std.heap.ArenaAllocator: Owns what lives as long as the reader: names, formats.
  • archive: zip_reader.Archive
  • limits: Limits
  • diagnostic: Diagnostic = .{}: Where the last error happened.
  • sheet_list: []SheetInfo = &.{}
  • sheet_parts: []?*const zip_reader.Entry = &.{}: Null for a sheet that is not a worksheet.
  • date_system: date_mod.DateSystem = .excel_1900
  • formats: []Format = &.{}
  • strings_part: ?*const zip_reader.Entry = null
  • strings_loaded: bool = false
  • string_data: std.ArrayList(u8) = .empty: Every shared string, back to back, and where each one ends.
  • string_ends: std.ArrayList(u32) = .empty

xlsx.Reader.open

zig
pub fn open(gpa: std.mem.Allocator, bytes: []const u8, limits: Limits) Error!*Reader

Opens a workbook from the bytes of an .xlsx file. bytes must stay valid until deinit. Reads the sheet list and the number formats; sheets are read by rows. The reader is allocated with gpa: free it with deinit.

xlsx.Reader.openDiagnosed

zig
pub fn openDiagnosed(gpa: std.mem.Allocator, bytes: []const u8, limits: Limits, diagnostic: *Diagnostic) Error!*Reader

Like open; when it fails, diagnostic says where.

xlsx.Reader.deinit

zig
pub fn deinit(self: *Reader) void

Frees the reader. Free every Rows of it first. The file's bytes are no longer needed afterwards.

xlsx.Reader.sheets

zig
pub fn sheets(self: *const Reader) []const SheetInfo

The sheets, in the order of the workbook's tabs.

xlsx.Reader.sheetIndex

zig
pub fn sheetIndex(self: *const Reader, name: []const u8) ?usize

Finds a sheet by name, ignoring the case of ASCII letters.

xlsx.Reader.rows

zig
pub fn rows(self: *Reader, sheet: usize, options: Options) Error!*Rows

Starts reading the rows of the sheet at index sheet (see sheets and sheetIndex). Free the iterator with Rows.deinit; several can be open at once. The first call also loads the shared strings table. Fails with error.SheetNotFound for an index past the last sheet and error.Unsupported for a sheet that is not a worksheet.

spider.xlsx.Rows

zig
pub const Rows = struct

The rows of one sheet, read as they are asked for.

Fields

  • reader: *Reader
  • sheet: usize
  • part: *PartReader
  • options: Options
  • row_arena: std.heap.ArenaAllocator: Reset for every row: texts and formulas of the row's cells.
  • cells: std.ArrayList(Cell) = .empty
  • scratch: std.ArrayList(u8) = .empty
  • formula_scratch: std.ArrayList(u8) = .empty
  • merges: std.ArrayList(Range) = .empty
  • masters: std.AutoHashMapUnmanaged(u32, SharedFormula) = .empty: First cell of each shared formula, for the cells that reuse it.
  • masters_arena: std.heap.ArenaAllocator
  • in_sheet_data: bool = false
  • finished: bool = false
  • last_row: ?u32 = null
  • rows_read: u32 = 0

xlsx.Rows.deinit

zig
pub fn deinit(self: *Rows) void

Frees the iterator, the last row returned and the list of merged ranges. Call it before the reader's deinit.

xlsx.Rows.mergedRanges

zig
pub fn mergedRanges(self: *const Rows) []const Range

The merged ranges of the sheet. They come after the rows in the file, so the list is complete only once next has returned null.

xlsx.Rows.next

zig
pub fn next(self: *Rows) Error!?Row

The next row that exists in the file, or null after the last. After an error the iterator is finished.

spider.xlsx.ReadLimits

zig
pub const Limits = struct

How much a file may ask of the server before it is refused.

The defaults are meant for files uploaded by people you do not know: they accept any ordinary spreadsheet and bound the memory and time a hostile one can take. Limits.large is for files you expect to be big.

Fields

  • max_file_bytes: u64 = 16 << 20: Size of the .xlsx file itself.
  • max_entries: u32 = 1_000: Entries in the zip archive.
  • max_part_bytes: u64 = 64 << 20: Uncompressed size of one part (a sheet's XML, for instance).
  • max_total_bytes: u64 = 128 << 20: Uncompressed size of all parts together.
  • max_compression_ratio: u32 = 200: Uncompressed/compressed ratio of one part larger than 1 MiB.
  • max_shared_strings_bytes: u64 = 32 << 20: Memory the shared strings table may take. It is the one thing that has to be loaded whole before a sheet is read.
  • max_rows: u32 = 100_000: Rows read from one sheet: the row after the last allowed one is error.LimitExceeded, the sheet is not cut short.
  • max_columns: u32 = 16_384: Columns: a cell beyond this is an error. Excel's limit.
  • max_cell_text: u32 = 32_767: Characters in one cell's text, counted as Excel does. Excel's limit.
  • max_merged_ranges: u32 = 10_000: Merged ranges per sheet; one more is error.LimitExceeded.
  • xml: xml_reader.Limits = .{}: Depth, attributes and sizes of the XML itself.

xlsx.ReadLimits.large

zig
pub const large: Limits = .{ ...

For large files from a known source (an ERP export of a hundred thousand rows, say): files up to 256 MiB, parts up to 1 GiB, a full sheet of rows, 256 MiB of shared strings. Reading stays streamed, but the shared strings table alone may now take up to 256 MiB of memory, and parsing a gigabyte of XML takes tens of seconds of CPU: do not use it for uploads by strangers.

spider.xlsx.ReadOptions

zig
pub const Options = struct

Options of Reader.rows. .{} reads values only.

Fields

  • formulas: bool = false: Also return each formula's text.

spider.xlsx.ReadError

zig
pub const Error = error

Everything opening or reading a file can fail with. A Diagnostic says where in the file it happened.

Errors

  • LimitExceeded: One of Limits was exceeded; Diagnostic.limit says which.
  • InvalidZip: Not a zip archive, or a damaged one.
  • InvalidXml: A part is not well-formed XML (or has a document type declaration, which is never accepted).
  • InvalidFile: A valid zip and valid XML, but not a workbook this reader understands: a part is missing, a reference is malformed, rows or cells are out of order, a number is not a number.
  • Unsupported: Not an .xlsx: an old .xls, an .xlsb, a zip64 archive, a compression method other than store and deflate, or a sheet that is not a worksheet (a chart sheet, a macro sheet).
  • Encrypted: The file is protected by a password to open.
  • SheetNotFound
  • OutOfMemory

spider.xlsx.ReadDiagnostic

zig
pub const Diagnostic = struct

Where the last error happened. It never holds text from the file.

Fields

  • part: Part = .none
  • sheet: ?usize = null: Index of the sheet, when part is .sheet.
  • row: ?u32 = null: Zero-based row and column being read, when known.
  • column: ?u32 = null
  • byte_offset: ?u64 = null: How far into the part's XML the reader was, in bytes.
  • limit: ?LimitKind = null: For error.LimitExceeded: the limit.

spider.xlsx.ReadRow

zig
pub const Row = struct

One row of a sheet. cells and the texts in it are valid until the next call to Rows.next.

Fields

  • number: u32: Zero-based. Rows the file does not have are simply not returned: numbers can jump.
  • hidden: bool
  • cells: []const Cell: In column order; columns can jump too.

spider.xlsx.ReadCell

zig
pub const Cell = struct

One cell of a Row. Cells the file does not have are not returned.

Fields

  • column: u32: Zero-based.
  • value: Value
  • format: []const u8: The cell's number format code, "General" when it has none. It tells how the author meant a number to be shown: with "00000000000", 1234567890 is the document 01234567890.
  • formula: ?[]const u8 = null: The formula's text without =, when Options.formulas is set and the cell has one. It is never evaluated.

spider.xlsx.ReadValue

zig
pub const Value = union(enum)

What a cell holds.

Fields

  • empty: A cell with formatting and no content, or a formula never calculated.
  • text: []const u8
  • number: f64
  • boolean: bool
  • date: DateTime: A number shown as a date (see Cell.format), converted. The time of day is in it too. A number that is no date a spreadsheet can show (negative, day 0 or day 60 of the 1900 system) stays a number.
  • time: TimeOfDay: A number between 0 and 1 shown as a time.
  • err: []const u8: An error value such as #DIV/0! or #N/A, as text.

spider.xlsx.SheetInfo

zig
pub const SheetInfo = struct

One sheet of the file, as listed by Reader.sheets. name lives as long as the reader.

Fields

  • name: []const u8
  • visibility: Visibility

spider.xlsx.TimeOfDay

zig
pub const TimeOfDay = struct

The time of day of a cell that holds no date.

Fields

  • hour: u8
  • minute: u8
  • second: u8
  • millisecond: u16

xlsx.TimeOfDay.fromFraction

zig
pub fn fromFraction(fraction: f64) TimeOfDay

From the fraction of a day (0 up to 1), rounded to the millisecond. Anything from 1 on gives 23:59:59.999; a negative number, or one that is not a number, gives 00:00:00.

spider.xlsx.ReadLimitKind

zig
pub const LimitKind = enum

Which of Limits was exceeded; each name is the field without max_.

Values

  • file_bytes
  • entries
  • part_bytes
  • total_bytes
  • compression_ratio
  • shared_strings_bytes
  • rows
  • columns
  • cell_text
  • merged_ranges
  • xml

spider.xlsx.ReadPart

zig
pub const Part = enum { none, package, workbook, styles, shared_strings, sheet }

Which part of the file was being read.

spider.xlsx.SheetVisibility

zig
pub const Visibility = enum { visible, hidden, very_hidden }

Whether a sheet shows among the tabs. hidden and very_hidden are the file's two hidden states.

spider.xlsx.DateSystem

zig
pub const DateSystem = enum

Which day a serial number counts from. A workbook says which one it uses; almost all use 1900.

Values

  • excel_1900: Day 1 is 1900-01-01, and day 60 is the 1900-02-29 that never existed.
  • excel_1904: Day 0 is 1904-01-01; no phantom day.

spider.xlsx.Packager

zig
pub const Packager = struct

What the workbook writes its parts to. Implement this to replace the container (a compressing zip, a directory on disk for debugging, a test double that records the parts).

addPart is called once per part, in a fixed order, and finish once at the end. content is only valid during the call.

Fields

  • ptr: *anyopaque
  • vtable: *const VTable

xlsx.Packager.VTable

zig
pub const VTable = struct

The two functions of an implementation; ptr is passed back to them.

Fields

  • addPart: *const fn (ptr: *anyopaque, name: []const u8, content: []const u8) Error!void
  • finish: *const fn (ptr: *anyopaque) Error!void

xlsx.Packager.addPart

zig
pub fn addPart(p: Packager, name: []const u8, content: []const u8) Error!void

Adds the part name with content. Called by the workbook.

xlsx.Packager.finish

zig
pub fn finish(p: Packager) Error!void

Ends the package. Called by the workbook after the last part.

spider.xlsx.StoreZip

zig
pub const StoreZip = struct

A zip writer that stores every entry uncompressed.

Fields

  • allocator: std.mem.Allocator
  • out: *Writer
  • entries: std.ArrayList(Entry) = .empty
  • offset: u64 = 0: Bytes written to out so far, i.e. where the next header starts.
  • finished: bool = false

xlsx.StoreZip.init

zig
pub fn init(allocator: std.mem.Allocator, out: *Writer) StoreZip

out is not flushed by this type: flush it after finish if it is buffered (a file or socket writer).

xlsx.StoreZip.deinit

zig
pub fn deinit(self: *StoreZip) void

Frees the list of entries. Writes nothing: call finish first.

xlsx.StoreZip.packager

zig
pub fn packager(self: *StoreZip) Packager

This writer as a Packager, for Workbook.writeToPackager. It points at self, which must not move or be freed while it is in use.

xlsx.StoreZip.addPart

zig
pub fn addPart(self: *StoreZip, name: []const u8, content: []const u8) Error!void

Writes one entry: local header, then the content.

xlsx.StoreZip.finish

zig
pub fn finish(self: *StoreZip) Error!void

Writes the central directory and the end record. No part can be added afterwards.

spider.xlsx.content_type

zig
pub const content_type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"

The MIME type of a .xlsx file, for a Content-Type header.

spider.xlsx.max_rows

zig
pub const max_rows: u32 = 1_048_576

Excel's sheet size: rows 0..1,048,575 and columns 0..16,383 (XFD).

spider.xlsx.max_cols

zig
pub const max_cols: u32 = 16_384

Columns per sheet (A to XFD).

spider.xlsx.max_text_len

zig
pub const max_text_len = 32_767

Characters per cell, counted as Excel does (UTF-16 code units).

spider.xlsx.max_formula_len

zig
pub const max_formula_len = 8_192

Characters per formula.

spider.xlsx.max_sheet_name_len

zig
pub const max_sheet_name_len = 31

Characters per sheet name.

spider.xlsx.max_column_width

zig
pub const max_column_width = 255

Widest column, in characters of the default font.

spider.xlsx.max_row_height

zig
pub const max_row_height = 409

Row height, in points.

zig
pub const max_link_len = 2_079

Longest link target, in bytes.

zig
pub const max_links_per_sheet = 65_530

Links per sheet.