mbtexcel

    A MoonBit port of the Go excelize library for reading and writing XLSX (Excel) spreadsheets.

    excel
    xlsx
    spreadsheet
    ooxml
    office
    Download zip
    Version
    0.1.10
    License
    Apache-2.0
    Last updated
    3 hours ago
    Downloads
    2

    #mbtexcel

    A pure MoonBit library for reading and writing Microsoft Excel (XLSX) files. This is a port of the popular Go excelize library.

    #Features

    • Create, read, and write XLSX spreadsheets
    • Cell value manipulation (strings, numbers, booleans, formulas)
    • Cell styling (fonts, colors, borders, alignment, number formats)
    • Charts and images
    • Data validation and conditional formatting
    • Pivot tables and slicers
    • Sparklines
    • Sheet protection and workbook encryption
    • Formula evaluation with 300+ built-in functions
    • Typed date/time and duration cells with automatic number formats
    • Streaming API for large files
    • Embedded cell image reading (WPS DISPIMG, rich-value "Place in cell", IMAGE())
    • OOXML package validation and a command-line tool

    #Installation

    Add the dependency to your module:

    moon add moonbitlang/mbtexcel

    Then import it in the moon.pkg of the package that uses it:

    import { "moonbitlang/mbtexcel", }

    Call the library through its default alias @mbtexcel (e.g. @mbtexcel.new_workbook()).

    #Quick Start

    #Creating and Reading Workbooks

    ///|
    test "workbook roundtrip" {
    let workbook = @mbtexcel.new_workbook()
    let sheet = workbook.add_sheet("Sheet1")
    sheet.set_cell("A1", "hello")
    sheet.set_cell_formula("B1", "A1", value="hello")
    let bytes = @mbtexcel.write(workbook)
    let parsed = @mbtexcel.read(bytes)
    debug_inspect(parsed.get_cell("Sheet1", "A1"), content="Some(\"hello\")")
    debug_inspect(parsed.get_cell_formula("Sheet1", "B1"), content="Some(\"A1\")")
    }

    #Row and Column Helpers

    ///|
    test "row and column helpers" {
    let workbook = @mbtexcel.new_workbook()
    ignore(workbook.add_sheet("Sheet1"))
    workbook.set_row("Sheet1", 1, ["a", "b", "c"])
    workbook.set_col("Sheet1", 2, ["x", "y"])
    debug_inspect(
    workbook.get_row("Sheet1", 1),
    content=(
    #|["a", "x", "c"]
    ),
    )
    debug_inspect(workbook.get_col("Sheet1", 2), content="[\"x\", \"y\"]")
    }

    #Cell Reference Utilities

    ///|
    test "cell reference conversion" {
    // Split cell name into column and row
    debug_inspect(@mbtexcel.split_cell_name("AB123"), content="(\"AB\", 123)")

    // Join column and row into cell name
    inspect(@mbtexcel.join_cell_name("AB", 123), content="AB123")

    // Convert between cell name and coordinates (1-indexed)
    debug_inspect(@mbtexcel.cell_name_to_coordinates("B3"), content="(2, 3)")
    inspect(@mbtexcel.coordinates_to_cell_name(2, 3), content="B3")

    // Absolute references
    inspect(@mbtexcel.coordinates_to_cell_name(2, 3, abs=true), content="$B$3")

    // Column name/number conversion
    inspect(@mbtexcel.column_name_to_number("AB"), content="28")
    inspect(@mbtexcel.column_number_to_name(28), content="AB")
    }

    #Working with Multiple Sheets

    ///|
    test "multiple sheets" {
    let workbook = @mbtexcel.new_workbook()
    ignore(workbook.add_sheet("Sales"))
    ignore(workbook.add_sheet("Expenses"))
    ignore(workbook.add_sheet("Summary"))

    // Get list of all sheets
    debug_inspect(
    workbook.get_sheet_list(),
    content="[\"Sales\", \"Expenses\", \"Summary\"]",
    )

    // Access sheet by name
    guard workbook.sheet("Sales") is Some(sales) else { return }
    sales.set_cell("A1", "Revenue")
    debug_inspect(sales.get_cell("A1"), content="Some(\"Revenue\")")
    }

    #Cell Types and Values

    ///|
    test "cell value types" {
    let workbook = @mbtexcel.new_workbook()
    let sheet = workbook.add_sheet("Data")

    // String values
    sheet.set_cell("A1", "Hello")

    // Numeric values (auto-detected from string)
    sheet.set_cell("A2", "42")
    sheet.set_cell("A3", "3.14159")

    // Using typed CellValue enum for explicit types
    sheet.set_cell_value("B1", String("Text"))
    sheet.set_cell_value("B2", Numeric(100.5))
    sheet.set_cell_value("B3", Bool(true))

    // Read back values
    debug_inspect(sheet.get_cell("A1"), content="Some(\"Hello\")")
    debug_inspect(sheet.get_cell("A2"), content="Some(\"42\")")
    debug_inspect(sheet.get_cell_value_raw("B2"), content="Some(Numeric(100.5))")
    debug_inspect(sheet.get_cell_value_raw("B3"), content="Some(Bool(true))")
    }

    #Formulas

    ///|
    test "formulas" {
    let workbook = @mbtexcel.new_workbook()
    let sheet = workbook.add_sheet("Calc")

    // Set some values
    sheet.set_cell("A1", "10")
    sheet.set_cell("A2", "20")
    sheet.set_cell("A3", "30")

    // Set formula with cached value
    sheet.set_cell_formula("A4", "SUM(A1:A3)", value="60")

    // Read formula back
    debug_inspect(sheet.get_cell_formula("A4"), content="Some(\"SUM(A1:A3)\")")

    // Calculate formula value
    inspect(workbook.calc_cell_value("Calc", "A4"), content="60")
    }

    #Merged Cells

    ///|
    test "merged cells" {
    let workbook = @mbtexcel.new_workbook()
    let sheet = workbook.add_sheet("Report")

    // Set value before merging
    sheet.set_cell("A1", "Title")

    // Merge cells A1:D1
    sheet.merge_cells("A1:D1")

    // Get merged cell ranges
    debug_inspect(sheet.merged_cells().to_owned(), content="[\"A1:D1\"]")
    }

    #Styling Cells

    ///|
    test "cell styling" {
    let workbook = @mbtexcel.new_workbook()
    ignore(workbook.add_sheet("Sheet1"))
    workbook.set_cell("Sheet1", "A1", "1234.5")

    // A style combines a number format with a font, fill, border, etc.
    let style = workbook.new_style(
    @xlsx.Style::builtin_number_format(2) // "0.00"
    .with_font(@xlsx.Font::with_values(bold=true, color="#FF0000")),
    )
    workbook.set_cell_style("Sheet1", "A1", style)
    debug_inspect(
    workbook.get_cell_style("Sheet1", "A1"),
    content="Some(\{style})",
    )
    }

    #Dates and Times

    ///|
    test "typed dates" {
    let workbook = @mbtexcel.new_workbook()
    ignore(workbook.add_sheet("Sheet1"))

    // Store a datetime; it is written as an Excel date serial with a default
    // date number format (honoring the workbook's 1900/1904 date system).
    workbook.set_cell_time("Sheet1", "A1", @time.date_time(2024, 7, 3))
    debug_inspect(
    workbook.get_cell("Sheet1", "A1"),
    content=(
    #|Some("45476")
    ),
    )

    // The reverse conversion is available directly.
    inspect(
    @mbtexcel.time_to_excel_date(@time.date_time(2021, 1, 1, hour=12)),
    content="44197.5",
    )
    }

    #Streaming Large Sheets

    For workbooks with many rows, the streaming writer avoids holding every cell in memory at once.

    ///|
    test "streaming writer" {
    let workbook = @mbtexcel.new_workbook()
    ignore(workbook.add_sheet("Big"))
    let stream = workbook.new_stream_writer("Big")
    for r in 11000 {
    stream.set_row_cells("A\{r}", [
    @xlsx.StreamCell::new("row \{r}"),
    @xlsx.StreamCell::new_value(Numeric(r.to_double())),
    ])
    }
    stream.flush()
    let parsed = @mbtexcel.read(@mbtexcel.write(workbook))
    debug_inspect(
    parsed.get_cell("Big", "B1000"),
    content=(
    #|Some("1000")
    ),
    )
    }

    #Password Protection

    ///|
    test "password protection" {
    let workbook = @mbtexcel.new_workbook()
    ignore(workbook.add_sheet("Secret"))
    workbook.set_cell("Secret", "A1", "classified")

    let encrypted = @mbtexcel.write_with_password(workbook, "s3cret")
    let reopened = @mbtexcel.read_with_password(encrypted, "s3cret")
    debug_inspect(
    reopened.get_cell("Secret", "A1"),
    content=(
    #|Some("classified")
    ),
    )
    }

    #Validating the Output Package

    validate_ooxml_package runs fast structural checks (content-type coverage, relationship integrity, required parts, well-formed part names) — the common causes of Excel's "we found a problem" repair dialog. An empty result means the package is well-formed.

    ///|
    test "validate output" {
    let workbook = @mbtexcel.new_workbook()
    ignore(workbook.add_sheet("Sheet1"))
    workbook.set_cell("Sheet1", "A1", "hello")
    debug_inspect(
    @xlsx.validate_ooxml_package(@mbtexcel.write(workbook)),
    content="[]",
    )
    }

    #Unified Office command

    moonx moonbitlang/office is the agent-oriented facade for DOCX and XLSX packages. Its registry-driven help, format detection, validated raw OOXML fallback, and structured reads use versioned JSON envelopes and explicit resource limits:

    moonx moonbitlang/office help docx moonx moonbitlang/office identify report.docx --json moonx moonbitlang/office outline report.docx --json moonx moonbitlang/office get report.docx '/docx/body/p[1]' --json moonx moonbitlang/office text report.docx --under '/docx/comments/comment[id="0"]' moonx moonbitlang/office query report.docx --kind paragraph --text revenue --ignore-case --json moonx moonbitlang/office outline book.xlsx --json moonx moonbitlang/office get book.xlsx '/xlsx/sheet[name="Data"]/range[A1:C12]' --json moonx moonbitlang/office text book.xlsx --under '/xlsx/sheet[name="Data"]' --json moonx moonbitlang/office query book.xlsx 'cell[type=formula]' --under '/xlsx/sheet[name="Data"]' --json moonx moonbitlang/office create xlsx new-book.xlsx --sheet Data --json moonx moonbitlang/office batch new-book.xlsx changes.json --out revised.xlsx --json

    DOCX results use the office.docx.{outline,element,text,query}/1 family and XLSX reads use office.xlsx.{outline,element,text,query}/1; creation and batch use office.xlsx.{create,batch}/1. Every result is inside office.output/1. See Unified Office DOCX reads, Unified Office XLSX reads, Transactional Office XLSX mutations, and Canonical Office selectors.

    #XLSX command-line tool

    The repo ships a small CLI (cmd/xlsx) for common operations without writing code:

    moon run cmd/xlsx -- create book.xlsx --sheet Data moon run cmd/xlsx -- set book.xlsx Data A1 Hello moon run cmd/xlsx -- get book.xlsx Data A1 # -> Hello moon run cmd/xlsx -- sheets book.xlsx # -> Data moon run cmd/xlsx -- rows book.xlsx # CSV of the sheet moon run cmd/xlsx -- view book.xlsx # sheet as an ASCII table moon run cmd/xlsx -- validate book.xlsx # -> valid

    view renders a sheet as an ASCII table (first row treated as a header):

    +-------+-------+ | Name | Score | +-------+-------+ | Alice | 90 | | Bob | 7 | +-------+-------+

    The library and CLI build for the wasm backend as well as native and js (the CLI needs the nightly toolchain for wasm filesystem support):

    moon run --target wasm cmd/xlsx -- view book.xlsx

    #Demos

    This repo includes a runnable demo generator that produces real .xlsx files you can open in Excel/Numbers/LibreOffice.

    moon run cmd/demos

    This writes multiple workbooks into ./demos_out/ (by default). You can also run a single demo:

    moon run cmd/demos -- dashboard demos_out moon run cmd/demos -- stream_big demos_out 50000

    Run the demo roundtrip regression gate (local/CI):

    scripts/test_demo_roundtrip.sh

    Run the combined parity + demo regression gate:

    scripts/test_parity_gates.sh

    #Parity Commands

    For semantic parity and CI wrapper usage details, see:

    • docs/excelize-parity.md
    • docs/parity-commands.md

    Common commands:

    scripts/test_parity_gates.sh scripts/test_semantic_parity.sh scripts/test_semantic_parity_fast.sh scripts/test_semantic_parity_ultrasmoke.sh

    See docs/demos.md for what each demo generates and how the code is structured.

    #API Reference

    #Workbook Creation

    FunctionDescription
    new_workbook()Create an empty workbook (no sheets)
    new_file()Create a workbook with one sheet named "Sheet1"
    read(bytes)Parse XLSX bytes into a workbook
    read_with_password(bytes, password)Parse encrypted XLSX
    open_file(path)(async) Open XLSX file from path

    #Workbook Output

    FunctionDescription
    write(workbook)Serialize workbook to XLSX bytes
    write_with_password(workbook, password)Serialize with encryption
    encrypt(bytes)Encrypt raw XLSX bytes
    decrypt(bytes)Decrypt encrypted XLSX bytes

    #Cell Reference Utilities

    FunctionDescription
    split_cell_name("A1")Returns ("A", 1)
    join_cell_name("A", 1)Returns "A1"
    cell_name_to_coordinates("B3")Returns (2, 3) (col, row)
    coordinates_to_cell_name(2, 3)Returns "B3"
    column_name_to_number("AB")Returns 28
    column_number_to_name(28)Returns "AB"

    #Color Utilities

    FunctionDescription
    rgb_to_hsl(r, g, b)Convert RGB to HSL
    hsl_to_rgb(h, s, l)Convert HSL to RGB
    theme_color(base, tint)Apply tint to theme color

    #Date Utilities

    FunctionDescription
    excel_date_to_time(serial)Convert Excel date serial to ZonedDateTime
    time_to_excel_date(datetime)Convert a ZonedDateTime to an Excel date serial

    #Validation

    FunctionDescription
    @xlsx.validate_ooxml_package(bytes)Return a list of OOXML package structure problems (empty = valid)

    #Core Types

    The main types are available from the @xlsx package:

    • @xlsx.Workbook - The main workbook container
    • @xlsx.Worksheet - A single worksheet
    • @xlsx.Cell - Cell data with value, type, formula, and style
    • @xlsx.Style - Cell styling (font, fill, border, alignment, number format)
    • @xlsx.Options - Read/write options

    For detailed documentation on all types and methods, see the xlsx package documentation.

    #Error Handling

    All functions that can fail raise @xlsx.XlsxError. Common error variants:

    • SheetNotFound - Referenced sheet does not exist
    • InvalidCellRef - Invalid cell reference format
    • InvalidSheetName - Sheet name is invalid or too long
    • EncryptedPackage - File is encrypted but no password provided
    • InvalidPassword - Decryption failed with given password

    Handle errors with try/catch:

    ///|
    fn describe(bytes : Bytes) -> String {
    try {
    let workbook = @mbtexcel.read(bytes)
    "loaded \{workbook.get_sheet_list().length()} sheets"
    } catch {
    err => "read failed: \{err}"
    }
    }

    #Package Structure

    moonbitlang/mbtexcel # Facade package (this package) -> moonbitlang/mbtexcel/xlsx # Core implementation -> moonbitlang/mbtexcel/ooxml # OOXML metadata helpers -> moonbitlang/mbtexcel/zip # ZIP archive handling

    #License

    Apache-2.0

    cell_name_to_coordinates

    fn cell_name_to_coordinates(cell : StringView) -> (Int, Int) raise
    XlsxError

    Converts a cell reference to column and row coordinates.

    Parameters

    • cell: Cell reference like "A1", "B3", "5"

    Returns

    Tuple of (column, row) where both are 1-indexed

    Example

    let (col, row) = cell_name_to_coordinates("B3")
    // col = 2, row = 3

    column_name_to_number

    fn column_name_to_number(name : StringView) -> Int raise
    XlsxError

    Converts a column name to a column number.

    Parameters

    • name: Column name like "A", "Z", "AA", "XFD"

    Returns

    Column number (1-indexed, where "A" = 1)

    Example

    let num = column_name_to_number("AA")
    // num = 27

    column_number_to_name

    fn column_number_to_name(col : Int) -> String raise
    XlsxError

    Converts a column number to a column name.

    Parameters

    • col: Column number (1-indexed, where 1 = "A")

    Returns

    Column name like "A", "Z", "AA", "XFD"

    Example

    let name = column_number_to_name(27)
    // name = "AA"

    coordinates_to_cell_name

    fn coordinates_to_cell_name(col : Int, row : Int, abs? : Bool) -> String raise
    XlsxError

    Converts column and row coordinates to a cell reference.

    Parameters

    • col: Column number (1-indexed, where 1 = "A")
    • row: Row number (1-indexed)
    • abs: If true, creates absolute reference with $ signs (default: false)

    Returns

    Cell reference string like "B3" or "3" if abs=true

    Example

    let ref = coordinates_to_cell_name(2, 3) // ref = "B3" let abs_ref = coordinates_to_cell_name(2, 3, abs=true) // abs_ref = "$B$3"

    decrypt

    Decrypts encrypted XLSX bytes.

    Parameters

    • raw: Encrypted XLSX file content
    • options: Options containing the password
    • limits: Optional encrypted and decrypted package resource policy

    Returns

    Decrypted XLSX file content

    encrypt

    Encrypts raw XLSX bytes with a password.

    Parameters

    • raw: Unencrypted XLSX file content
    • options: Options containing the password

    Returns

    Encrypted file content

    excel_date_to_time

    fn excel_date_to_time(excel_date : Double, use_1904_format? : Bool) ->
    ZonedDateTime
    raise
    XlsxError

    Converts an Excel date serial number to a ZonedDateTime.

    Excel stores dates as floating-point numbers where:
    • The integer part is days since the epoch
    • The fractional part is the time of day

    Parameters

    • excel_date: Excel date serial number
    • use_1904_format: If true, use Mac Excel's 1904 date system (default: false)

    Returns

    ZonedDateTime representing the date and time

    Example

    let dt = excel_date_to_time(44197.5) // 2021-01-01 12:00:00

    hsl_to_rgb

    fn hsl_to_rgb(h : Double, s : Double, l : Double) -> (Byte, Byte, Byte)

    Converts HSL (Hue, Saturation, Lightness) color values to RGB.

    Parameters

    • h: Hue (0.0 to 1.0, representing 0-360 degrees)
    • s: Saturation (0.0 to 1.0)
    • l: Lightness (0.0 to 1.0)

    Returns

    Tuple of (red, green, blue) where each is 0-255

    Example

    let (r, g, b) = hsl_to_rgb(0.0, 1.0, 0.5) // Red
    // r = 255, g = 0, b = 0

    join_cell_name

    fn join_cell_name(col : StringView, row : Int) -> String raise
    XlsxError

    Joins column name and row number into a cell reference.

    Parameters

    • col: Column name like "A", "AB", "XFD"
    • row: Row number (1-indexed)

    Returns

    Cell reference string like "A1", "AB123"

    Example

    let ref = join_cell_name("AB", 123) // ref = "AB123"

    new_data_validation

    fn new_data_validation(allow_blank : Bool) ->
    DataValidation

    Creates a new data validation object.

    Data validations restrict what users can enter in cells.

    Parameters

    • allow_blank: Whether empty cells are considered valid

    Example

    let dv = new_data_validation(true)
    dv.set_drop_list(["Option1", "Option2", "Option3"])
    dv.set_sqref("A1:A100")
    sheet.add_data_validation(dv)

    new_file

    Creates a new workbook with a default sheet named "Sheet1".

    This is a convenience function for the common case of creating a workbook with one initial worksheet.

    Example

    let wb = new_file()
    wb.set_cell("Sheet1", "A1", "Hello")

    new_workbook

    Creates a new empty workbook without any sheets.

    Use add_sheet on the returned workbook to add worksheets.

    Example

    let wb = new_workbook()

    let sheet = wb.add_sheet("Data")

    open_file

    async fn open_file(path : String, password? : String, options? :
    Options
    , limits? :
    ReadLimits
    , transcoder? : (String, Bytes) -> String raise
    XlsxError
    ) ->
    Workbook

    Opens an XLSX file from a file path asynchronously.

    Parameters

    • path: Path to the XLSX file
    • password: Password if the file is encrypted (default: empty)
    • options: Optional read options
    • limits: Optional fail-closed package, ZIP, and XML resource policy
    • transcoder: Optional charset transcoder

    Returns

    Parsed Workbook object

    Example

    let wb = open_file("report.xlsx")

    let wb_protected = open_file("secret.xlsx", password="pass123")

    open_reader

    Opens an XLSX file from a Reader asynchronously.

    Parameters

    • reader: Any type implementing the Reader trait
    • password: Password if the file is encrypted (default: empty)
    • options: Optional read options
    • limits: Optional fail-closed package, ZIP, and XML resource policy
    • transcoder: Optional charset transcoder

    Returns

    Parsed Workbook object

    read

    Reads an XLSX file from bytes into a Workbook.

    Parameters

    • bytes: Raw XLSX file content
    • options: Optional read options
    • limits: Optional fail-closed package, ZIP, and XML resource policy
    • transcoder: Optional function for charset transcoding (for non-UTF8 files)

    Returns

    Parsed Workbook object

    Example

    let bytes = read_file("report.xlsx")

    let wb = read(bytes)

    let value = wb.get_cell("Sheet1", "A1")

    read_bounded_archive

    Reads an XLSX workbook from a pristine archive created by a sufficiently strict bounded ZIP read, without inflating the package again. Constructed, compatibility-read, mutated, or more loosely bounded archives are rejected.

    read_with_password

    Reads a password-protected XLSX file from bytes.

    Parameters

    • bytes: Raw encrypted XLSX file content
    • password: Password used to encrypt the file
    • options: Optional read options
    • limits: Optional fail-closed package, ZIP, and XML resource policy
    • transcoder: Optional charset transcoder

    Returns

    Parsed Workbook object

    Errors

    • InvalidPassword: If the password is incorrect
    • EncryptedPackage: If decryption fails

    Example

    let bytes = read_file("protected.xlsx")

    let wb = read_with_password(bytes, "secret123")

    read_zip_reader

    Reads an XLSX from a ZIP reader asynchronously.

    This is a lower-level function that allows reading from a ZIP stream that's already being read.

    Parameters

    • reader: Any type implementing the Reader trait
    • password: Password if the file is encrypted (default: empty)
    • options: Optional read options
    • limits: Optional fail-closed package, ZIP, and XML resource policy
    • transcoder: Optional charset transcoder

    Returns

    Parsed Workbook object

    rgb_to_hsl

    fn rgb_to_hsl(r : Byte, g : Byte, b : Byte) -> (Double, Double, Double)

    Converts RGB color values to HSL (Hue, Saturation, Lightness).

    Parameters

    • r: Red component (0-255)
    • g: Green component (0-255)
    • b: Blue component (0-255)

    Returns

    Tuple of (hue, saturation, lightness) where:
    • hue: 0.0 to 1.0 (representing 0-360 degrees)
    • saturation: 0.0 to 1.0
    • lightness: 0.0 to 1.0

    Example

    let (h, s, l) = rgb_to_hsl(255, 0, 0) // Red
    // h ≈ 0, s = 1.0, l = 0.5

    split_cell_name

    fn split_cell_name(cell : StringView) -> (String, Int) raise
    XlsxError

    Splits a cell reference into column name and row number.

    Parameters

    • cell: Cell reference like "A1", "AB123", "5"

    Returns

    Tuple of (column_name, row_number) where row is 1-indexed

    Example

    let (col, row) = split_cell_name("AB123")
    // col = "AB", row = 123

    theme_color

    fn theme_color(base_color : String, tint : Double) -> String

    Applies a tint to a base color.

    Theme colors in Excel can have tint values that lighten or darken the base color.

    Parameters

    • base_color: Hex color string like "FF0000"
    • tint: Tint value from -1.0 (darken) to 1.0 (lighten)

    Returns

    Tinted hex color string

    Example

    let lighter = theme_color("FF0000", 0.5) // Lighter red

    let darker = theme_color("FF0000", -0.5) // Darker red

    time_to_excel_date

    fn time_to_excel_date(value :
    ZonedDateTime
    , use_1904_format? : Bool) -> Double

    Converts a datetime to an Excel date serial number, the reverse of excel_date_to_time. Mirrors Excelize's timeToExcelTime, including the intentional Lotus 1-2-3 leap-year bug in the 1900 date system; datetimes before the epoch return 0.

    Parameters

    • value: The datetime to convert (wall-clock fields are used)
    • use_1904_format: If true, use Mac Excel's 1904 date system (default: false)

    Example

    let serial = time_to_excel_date(@time.date_time(2021, 1, 1, hour=12)) // 44197.5

    write

    Writes a Workbook to XLSX bytes.

    Parameters

    • workbook: The workbook to serialize

    Returns

    XLSX file content as bytes

    Example

    let wb = new_file()
    wb.set_cell("Sheet1", "A1", "Hello")
    let bytes = write(wb)
    write_file("output.xlsx", bytes)

    write_with_password

    fn write_with_password(workbook :
    Workbook
    , password : String) -> Bytes raise
    XlsxError

    Writes a Workbook to password-protected XLSX bytes.

    The file will be encrypted using the ECMA-376 encryption standard.

    Parameters

    • workbook: The workbook to serialize
    • password: Password to protect the file with

    Returns

    Encrypted XLSX file content as bytes

    Example

    let wb = new_file()
    wb.set_cell("Sheet1", "A1", "Confidential")
    let bytes = write_with_password(wb, "secret123")

    Source Files