> ## Documentation Index
> Fetch the complete documentation index at: https://jetxl.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Jetxl

> A fast Excel writer for Python, built in Rust

Jetxl turns a DataFrame into an `.xlsx` file. It's written in Rust, reads Arrow memory directly without copying it, and suits the case where the spreadsheet is large enough that writing it has become the slow part of your job.

<CardGroup cols={3}>
  <Card title="0.66s for 1M rows" icon="gauge-high">
    Against 42.5s for openpyxl on the same machine
  </Card>

  <Card title="Polars, Pandas, Arrow" icon="table">
    Or plain Python dictionaries
  </Card>

  <Card title="Formatting included" icon="palette">
    Charts, tables, images, styles, validation
  </Card>
</CardGroup>

## Is this the right tool?

Jetxl writes files. It doesn't read them, and it can't edit an existing workbook.

<AccordionGroup>
  <Accordion title="Good fit" icon="check">
    Exporting a large DataFrame to Excel. Generating reports on a schedule. Returning a spreadsheet from a web API. Anywhere you produce the file fresh each time and write speed matters.
  </Accordion>

  <Accordion title="Poor fit" icon="xmark">
    Reading an existing spreadsheet, or opening one and changing a few cells. Use `openpyxl` for that, since it handles reading and Jetxl doesn't.
  </Accordion>

  <Accordion title="Probably unnecessary" icon="circle-question">
    A few hundred rows with no formatting. At that size every library is instant and the choice doesn't matter. Reach for Jetxl when the numbers get large or the formatting gets involved.
  </Accordion>
</AccordionGroup>

<Warning>
  Jetxl is experimental, and says so itself. Writing without optional parameters is well covered. Combining several formatting parameters at once is where bugs are most likely, and the shape of existing parameters may still change. Pin your version and check the output before you depend on it in production.
</Warning>

## The shape of the API

Six functions. Choosing between them comes down to three questions: Arrow or dictionaries, one sheet or many, a file on disk or bytes in memory.

|                | One sheet                    | Many sheets                   |
| -------------- | ---------------------------- | ----------------------------- |
| **To a file**  | `write_sheet_arrow`          | `write_sheets_arrow`          |
| **To bytes**   | `write_sheet_arrow_to_bytes` | `write_sheets_arrow_to_bytes` |
| **From dicts** | `write_sheet`                | `write_sheets`                |

Every formatting feature in this documentation is a keyword argument on `write_sheet_arrow`, and the same arguments work as dictionary keys when you write multiple sheets.

<Card title="Which function do I call?" icon="signs-post" href="/choosing-an-api">
  A short decision guide if the table above didn't settle it.
</Card>

## A first file

```python theme={null}
import polars as pl
import jetxl as jet

df = pl.DataFrame({
    "Product": ["Widget", "Gadget", "Doohickey"],
    "Revenue": [1250.00, 3400.50, 890.25],
})

jet.write_sheet_arrow(df.to_arrow(), "revenue.xlsx")
```

That's the whole thing. Everything else on this site is optional refinement.

<Columns cols={2}>
  <Card title="Install it" icon="download" href="/installation">
    One command, plus what to know about versions.
  </Card>

  <Card title="Quickstart" icon="rocket" href="/quickstart">
    Working examples for Polars, Pandas, PyArrow and dicts.
  </Card>
</Columns>
