rust-excel-core 0.1.0

Read, write, and modify Excel (.xlsx) files — combines calamine, rust_xlsxwriter, and umya-spreadsheet for best-in-class performance
Documentation
# rust-excel

A high-performance Rust toolkit for reading, writing, and modifying Excel (.xlsx) files. Combines three engines for best-in-class speed:

- **calamine** - fast bulk reads (~2.5x faster than alternatives)
- **rust_xlsxwriter** - fast file creation (~1.4x faster writes)
- **umya-spreadsheet** - full in-memory mutation (read + write + modify)

## Crates

| Crate | Description |
|-------|-------------|
| `rust-excel-core` | Library crate for Excel operations. Publish to crates.io. |
| `rust-excel-api` | REST API server (Axum) with 40+ endpoints. React 19 compatible. |

## Quick Start

### As a library

```toml
[dependencies]
rust-excel-core = "0.1"
```

```rust
use rust_excel_core::{Workbook, CellValue, sheet};

// Create a new workbook
let mut wb = Workbook::new();
let ws = wb.get_sheet_mut("Sheet1").unwrap();

// Write cells
sheet::set_cell_value(ws, 1, 1, &CellValue::String("Hello".into()));
sheet::set_cell_value(ws, 1, 2, &CellValue::Number(42.0));
sheet::set_cell_value(ws, 2, 1, &CellValue::Boolean(true));
sheet::set_cell_value(ws, 3, 1, &CellValue::Formula("=SUM(B1:B10)".into()));

// Save to bytes
let bytes = wb.save_to_bytes().unwrap();

// Open an existing file
let wb = Workbook::open("spreadsheet.xlsx").unwrap();
let ws = wb.get_sheet("Sheet1").unwrap();
let val = sheet::get_cell_value(ws, 1, 1);
```

### Fast paths

```rust
use rust_excel_core::{Workbook, CellValue, RangeData};

// Fast bulk read from raw bytes (calamine, 2.5x faster)
let bytes = std::fs::read("large_file.xlsx").unwrap();
let data = Workbook::read_data_from_bytes(&bytes, "Sheet1").unwrap();
for row in &data.rows {
    for cell in row {
        // process cells...
    }
}

// Fast file creation (rust_xlsxwriter, 1.4x faster)
let data = RangeData {
    start_row: 1, start_col: 1, end_row: 2, end_col: 2,
    rows: vec![
        vec![CellValue::String("Name".into()), CellValue::String("Age".into())],
        vec![CellValue::String("Alice".into()), CellValue::Number(30.0)],
    ],
};
let xlsx_bytes = Workbook::create_from_data(vec![("People".into(), data)]).unwrap();
```

### As a REST API

```bash
cargo run -p rust-excel-api
# Server starts on http://localhost:3001
```

```bash
# Create a workbook
curl -X POST http://localhost:3001/workbooks

# Upload an Excel file
curl -X POST http://localhost:3001/workbooks/upload \
  -F "file=@spreadsheet.xlsx"

# Read a cell
curl http://localhost:3001/workbooks/{id}/sheets/Sheet1/cells/1/1

# Write a cell
curl -X PUT http://localhost:3001/workbooks/{id}/sheets/Sheet1/cells/1/1 \
  -H "Content-Type: application/json" \
  -d '{"value": {"type": "String", "value": "Hello"}}'

# Bulk read (calamine fast path)
curl http://localhost:3001/workbooks/{id}/sheets/Sheet1/data

# Download
curl http://localhost:3001/workbooks/{id}/download -o output.xlsx
```

## API Endpoints

### Workbooks
- `POST /workbooks` - Create empty workbook
- `POST /workbooks/upload` - Upload .xlsx file (multipart)
- `GET /workbooks/{id}` - Get workbook info
- `GET /workbooks/{id}/download` - Download as .xlsx
- `DELETE /workbooks/{id}` - Delete workbook

### Sheets
- `GET /workbooks/{id}/sheets` - List sheets
- `POST /workbooks/{id}/sheets` - Add sheet
- `GET /workbooks/{id}/sheets/{name}` - Get sheet info
- `PATCH /workbooks/{id}/sheets/{name}` - Rename sheet
- `DELETE /workbooks/{id}/sheets/{name}` - Remove sheet

### Cells
- `GET /workbooks/{id}/sheets/{name}/cells/{row}/{col}` - Read cell
- `PUT /workbooks/{id}/sheets/{name}/cells/{row}/{col}` - Write cell
- `GET /workbooks/{id}/sheets/{name}/data` - Bulk read (fast)
- `GET /workbooks/{id}/sheets/{name}/range?r1=&c1=&r2=&c2=` - Read range
- `PUT /workbooks/{id}/sheets/{name}/range` - Write range

### Rows & Columns
- `POST /workbooks/{id}/sheets/{name}/rows/{at}` - Insert rows
- `DELETE /workbooks/{id}/sheets/{name}/rows/{at}` - Delete rows
- `PATCH /workbooks/{id}/sheets/{name}/rows/{at}/height` - Set row height
- `POST /workbooks/{id}/sheets/{name}/columns/{at}` - Insert columns
- `DELETE /workbooks/{id}/sheets/{name}/columns/{at}` - Delete columns
- `PATCH /workbooks/{id}/sheets/{name}/columns/{at}/width` - Set column width

### Styles
- `GET /workbooks/{id}/sheets/{name}/cells/{row}/{col}/style` - Get style
- `PATCH /workbooks/{id}/sheets/{name}/cells/{row}/{col}/style` - Apply style
- `PATCH /workbooks/{id}/sheets/{name}/range/style?r1=&c1=&r2=&c2=` - Apply range style

### Merges
- `GET /workbooks/{id}/sheets/{name}/merges` - List merges
- `POST /workbooks/{id}/sheets/{name}/merges` - Merge cells
- `DELETE /workbooks/{id}/sheets/{name}/merges` - Unmerge cells

## Benchmarks

Measured on 50,000 cells (5000 rows x 10 cols):

| Operation | Time | vs umya-spreadsheet alone |
|-----------|------|--------------------------|
| Read (calamine cached) | 27 ms | 2.5x faster |
| Read (calamine direct) | 27 ms | 2.5x faster |
| Write (rust_xlsxwriter) | 48 ms | 1.4x faster |
| Write (fast, from model) | 54 ms | 1.2x faster |
| Read (umya cell-by-cell) | 66 ms | baseline |
| Write (umya native) | 67 ms | baseline |

Run benchmarks yourself:

```bash
cargo bench -p rust-excel-core
```

## Features

- Full cell type support: strings, numbers, booleans, formulas, empty
- Sheet management: add, remove, rename, list
- Range operations: bulk read/write rectangular regions
- Row/column operations: insert, delete, resize
- Cell styling: fonts, colors, borders, alignment, number formats
- Cell merging and unmerging
- Byte-level I/O: open from bytes, save to bytes (no filesystem needed)
- Cached upload bytes for fast subsequent reads
- Automatic dirty tracking with cache invalidation
- Serde serialization for all types
- CORS-enabled REST API for React/frontend integration

## License

MIT