Skip to main content

High-performance Excel writer with automatic type detection (pandas, polars, CSV)

Project description

xlsxturbo

High-performance Excel writer with automatic type detection. Written in Rust, usable from Python.

Features

  • Direct DataFrame support for pandas and polars
  • Excel tables - filterable tables with 61 built-in styles (banded rows, autofilter)
  • Auto-fit columns - automatically adjust column widths to fit content
  • Custom column widths - set specific widths per column or cap all with _all
  • Header styling - bold, colors, font size for header row
  • Named tables - set custom table names
  • Custom row heights - set specific heights per row
  • Freeze panes - freeze header row for easier scrolling
  • Multi-sheet workbooks - write multiple DataFrames to one file
  • Per-sheet options - override settings per sheet in multi-sheet workbooks
  • Constant memory mode - minimize RAM usage for very large files
  • Parallel CSV processing - optional multi-core parsing for large files
  • Automatic type detection from CSV strings and Python objects:
    • Integers and floats → Excel numbers
    • true/false → Excel booleans
    • Dates (2024-01-15, 15/01/2024, etc.) → Excel dates with formatting
    • Datetimes (ISO 8601) → Excel datetimes
    • NaN/Inf → Empty cells (graceful handling)
    • Everything else → Text
  • ~25x faster than pandas + openpyxl
  • Memory efficient - streams data with 1MB buffer
  • Available as both Python library and CLI tool

Installation

pip install xlsxturbo

Or build from source:

pip install maturin
maturin develop --release

Python Usage

DataFrame Export (pandas/polars)

import xlsxturbo
import pandas as pd

# Create a DataFrame
df = pd.DataFrame({
    'name': ['Alice', 'Bob'],
    'age': [30, 25],
    'salary': [50000.50, 60000.75],
    'active': [True, False]
})

# Export to XLSX (preserves types: int, float, bool, date, datetime)
rows, cols = xlsxturbo.df_to_xlsx(df, "output.xlsx")
print(f"Wrote {rows} rows and {cols} columns")

# Works with polars too!
import polars as pl
df_polars = pl.DataFrame({'x': [1, 2, 3], 'y': [4.0, 5.0, 6.0]})
xlsxturbo.df_to_xlsx(df_polars, "polars_output.xlsx", sheet_name="Data")

Excel Tables with Styling

import xlsxturbo
import pandas as pd

df = pd.DataFrame({
    'Product': ['Widget A', 'Widget B', 'Widget C'],
    'Price': [19.99, 29.99, 39.99],
    'Quantity': [100, 75, 50],
})

# Create a styled Excel table with autofilter, banded rows, and auto-fit columns
xlsxturbo.df_to_xlsx(df, "report.xlsx",
    table_style="Medium9",   # Excel's default table style
    autofit=True,            # Fit column widths to content
    freeze_panes=True        # Freeze header row for scrolling
)

# Available styles: Light1-Light21, Medium1-Medium28, Dark1-Dark11
xlsxturbo.df_to_xlsx(df, "dark_table.xlsx", table_style="Dark1", autofit=True)

Custom Column Widths and Row Heights

import xlsxturbo
import pandas as pd

df = pd.DataFrame({
    'Name': ['Alice', 'Bob', 'Charlie'],
    'Department': ['Engineering', 'Marketing', 'Sales'],
    'Salary': [75000, 65000, 55000]
})

# Set specific column widths (column index -> width in characters)
xlsxturbo.df_to_xlsx(df, "report.xlsx", 
    column_widths={0: 20, 1: 25, 2: 15}
)

# Set specific row heights (row index -> height in points)
xlsxturbo.df_to_xlsx(df, "report.xlsx",
    row_heights={0: 25}  # Make header row taller
)

# Combine with other options
xlsxturbo.df_to_xlsx(df, "styled.xlsx",
    table_style="Medium9",
    freeze_panes=True,
    column_widths={0: 20, 1: 30, 2: 15},
    row_heights={0: 22}
)

Global Column Width Cap

Use column_widths={'_all': value} to cap all columns at a maximum width:

import xlsxturbo
import pandas as pd

df = pd.DataFrame({
    'Name': ['Alice', 'Bob'],
    'VeryLongDescription': ['A' * 100, 'B' * 100],
    'Score': [95, 87]
})

# Cap all columns at 30 characters
xlsxturbo.df_to_xlsx(df, "capped.xlsx", column_widths={'_all': 30})

# Mix specific widths with global cap (specific overrides '_all')
xlsxturbo.df_to_xlsx(df, "mixed.xlsx", column_widths={0: 15, '_all': 30})

# Autofit with cap: fit content, but never exceed 25 characters
xlsxturbo.df_to_xlsx(df, "fitted.xlsx", autofit=True, column_widths={'_all': 25})

Named Excel Tables

Set custom names for Excel tables:

import xlsxturbo
import pandas as pd

df = pd.DataFrame({'Product': ['A', 'B'], 'Price': [10, 20]})

# Name the Excel table
xlsxturbo.df_to_xlsx(df, "report.xlsx", 
    table_style="Medium2", 
    table_name="ProductPrices"
)

# Invalid characters are auto-sanitized, digits get underscore prefix
xlsxturbo.df_to_xlsx(df, "report.xlsx",
    table_style="Medium2",
    table_name="2024 Sales Data!"  # Becomes "_2024_Sales_Data_"
)

Header Styling

Apply custom formatting to header cells:

import xlsxturbo
import pandas as pd

df = pd.DataFrame({'Name': ['Alice', 'Bob'], 'Score': [95, 87]})

# Bold headers
xlsxturbo.df_to_xlsx(df, "bold.xlsx", header_format={'bold': True})

# Full styling with colors
xlsxturbo.df_to_xlsx(df, "styled.xlsx", header_format={
    'bold': True,
    'bg_color': '#4F81BD',   # Blue background
    'font_color': 'white'    # White text
})

# Available options:
# - bold (bool): Bold text
# - italic (bool): Italic text
# - font_color (str): '#RRGGBB' or named color (white, black, red, blue, etc.)
# - bg_color (str): Background color
# - font_size (float): Font size in points
# - underline (bool): Underlined text

Multi-Sheet Workbooks

import xlsxturbo
import pandas as pd

# Write multiple DataFrames to separate sheets
df1 = pd.DataFrame({'product': ['A', 'B'], 'sales': [100, 200]})
df2 = pd.DataFrame({'region': ['East', 'West'], 'total': [500, 600]})

xlsxturbo.dfs_to_xlsx([
    (df1, "Products"),
    (df2, "Regions")
], "report.xlsx")

# With styling applied to all sheets
xlsxturbo.dfs_to_xlsx([
    (df1, "Products"),
    (df2, "Regions")
], "styled_report.xlsx", table_style="Medium2", autofit=True, freeze_panes=True)

# With column widths applied to all sheets
xlsxturbo.dfs_to_xlsx([
    (df1, "Products"),
    (df2, "Regions")
], "report.xlsx", column_widths={0: 20, 1: 15})

Per-Sheet Options

Override global settings for individual sheets using a 3-tuple with options dict:

import xlsxturbo
import pandas as pd

df_data = pd.DataFrame({'Product': ['A', 'B'], 'Price': [10, 20]})
df_instructions = pd.DataFrame({'Step': [1, 2], 'Action': ['Open file', 'Review data']})

# Different settings per sheet:
# - "Data" sheet: has header, table style, autofit
# - "Instructions" sheet: no header (raw data), no table style
xlsxturbo.dfs_to_xlsx([
    (df_data, "Data", {"header": True, "table_style": "Medium2"}),
    (df_instructions, "Instructions", {"header": False, "table_style": None})
], "report.xlsx", autofit=True)

# Old 2-tuple API still works - uses global defaults
xlsxturbo.dfs_to_xlsx([
    (df_data, "Sheet1"),  # Uses global header=True, table_style=None
    (df_instructions, "Sheet2", {"header": False})  # Override just header
], "mixed.xlsx", header=True, autofit=True)

Available per-sheet options:

  • header (bool): Include column names as header row
  • autofit (bool): Automatically adjust column widths
  • table_style (str|None): Excel table style or None to disable
  • freeze_panes (bool): Freeze header row
  • column_widths (dict): Custom column widths
  • row_heights (dict): Custom row heights
  • table_name (str): Custom Excel table name
  • header_format (dict): Header cell styling

Constant Memory Mode (Large Files)

For very large files (millions of rows), use constant_memory=True to minimize RAM usage:

import xlsxturbo
import polars as pl

# Generate a large DataFrame
large_df = pl.DataFrame({
    'id': range(1_000_000),
    'value': [i * 1.5 for i in range(1_000_000)]
})

# Use constant_memory mode for large files
xlsxturbo.df_to_xlsx(large_df, "big_file.xlsx", constant_memory=True)

# Also works with dfs_to_xlsx
xlsxturbo.dfs_to_xlsx([
    (large_df, "Data")
], "multi_sheet.xlsx", constant_memory=True)

Note: Constant memory mode disables some features that require random access:

  • table_style (Excel tables)
  • freeze_panes
  • row_heights
  • autofit

Column widths still work in constant memory mode.

CSV Conversion

import xlsxturbo

# Convert CSV to XLSX with automatic type detection
rows, cols = xlsxturbo.csv_to_xlsx("input.csv", "output.xlsx")
print(f"Converted {rows} rows and {cols} columns")

# Custom sheet name
xlsxturbo.csv_to_xlsx("data.csv", "report.xlsx", sheet_name="Sales Data")

# For large files (100K+ rows), use parallel processing
xlsxturbo.csv_to_xlsx("big_data.csv", "output.xlsx", parallel=True)

CLI Usage

xlsxturbo input.csv output.xlsx [--sheet-name "Sheet1"] [-v]

Options

  • -s, --sheet-name: Name of the Excel sheet (default: "Sheet1")
  • -v, --verbose: Show progress information

Example

xlsxturbo sales.csv report.xlsx --sheet-name "Q4 Sales" -v

Performance

Benchmarked on 525,684 rows x 98 columns:

Method Time Speedup
xlsxturbo 28.5s 26.7x
PyExcelerate 107s 7.1x
pandas + xlsxwriter 374s 2.0x
pandas + openpyxl 762s 1.0x
polars.write_excel 1039s 0.7x

Type Detection Examples

CSV Value Excel Type Notes
123 Number Integer
3.14159 Number Float
true / FALSE Boolean Case insensitive
2024-01-15 Date Formatted as date
2024-01-15T10:30:00 DateTime ISO 8601 format
NaN Empty Graceful handling
hello world Text Default

Supported date formats: YYYY-MM-DD, YYYY/MM/DD, DD-MM-YYYY, DD/MM/YYYY, MM-DD-YYYY, MM/DD/YYYY

Building from Source

Requires Rust toolchain and maturin:

# Install maturin
pip install maturin

# Development build
maturin develop

# Release build (optimized)
maturin develop --release

# Build wheel for distribution
maturin build --release

Benchmarking

Run the included benchmark script:

# Default: 100K rows x 50 columns
python benchmark.py

# Custom size
python benchmark.py --rows 500000 --cols 100

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

xlsxturbo-0.6.0.tar.gz (37.6 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

xlsxturbo-0.6.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (882.5 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

xlsxturbo-0.6.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (885.8 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

xlsxturbo-0.6.0-cp38-abi3-win_amd64.whl (901.7 kB view details)

Uploaded CPython 3.8+Windows x86-64

xlsxturbo-0.6.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (948.0 kB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ x86-64

xlsxturbo-0.6.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (885.4 kB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ ARM64

xlsxturbo-0.6.0-cp38-abi3-macosx_11_0_arm64.whl (857.9 kB view details)

Uploaded CPython 3.8+macOS 11.0+ ARM64

xlsxturbo-0.6.0-cp38-abi3-macosx_10_12_x86_64.whl (912.1 kB view details)

Uploaded CPython 3.8+macOS 10.12+ x86-64

File details

Details for the file xlsxturbo-0.6.0.tar.gz.

File metadata

  • Download URL: xlsxturbo-0.6.0.tar.gz
  • Upload date:
  • Size: 37.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for xlsxturbo-0.6.0.tar.gz
Algorithm Hash digest
SHA256 1c440faabfce0e44ba2200c3531fbbfaf54efa28802efb4bffd128749306e644
MD5 f2ec7369eca0d4c05242636f56cffbc6
BLAKE2b-256 3b64da1052b29f6196a6a5c3eeb24efbe2ef98d5395c4d47747bb072dc3ec490

See more details on using hashes here.

Provenance

The following attestation bundles were made for xlsxturbo-0.6.0.tar.gz:

Publisher: release.yml on tstone-1/xlsxturbo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xlsxturbo-0.6.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for xlsxturbo-0.6.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 67a57bc35c6e8e597c8670846b153f91a76114bc428074e7710483a035695cff
MD5 924e599452b82a5d0025c36dc1a252c9
BLAKE2b-256 f9ce7dca67c8bb8d9988b32d72205ecffbdc122d2e69831fb70a92fb29f6ae3e

See more details on using hashes here.

Provenance

The following attestation bundles were made for xlsxturbo-0.6.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on tstone-1/xlsxturbo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xlsxturbo-0.6.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for xlsxturbo-0.6.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 ef103c2180a2b3f8bd5609c1ec9ef7a92809f4ddd5832bc4669c9b816aa288ec
MD5 f5b0480b2cbfae38b2d18a59ddc33a81
BLAKE2b-256 c4f1e47b2a675611e84962b3bb8acdfee9f02785a1694a88cdcc3aa23f30b0cc

See more details on using hashes here.

Provenance

The following attestation bundles were made for xlsxturbo-0.6.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on tstone-1/xlsxturbo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xlsxturbo-0.6.0-cp38-abi3-win_amd64.whl.

File metadata

  • Download URL: xlsxturbo-0.6.0-cp38-abi3-win_amd64.whl
  • Upload date:
  • Size: 901.7 kB
  • Tags: CPython 3.8+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for xlsxturbo-0.6.0-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 6e9980cad1074101a8a9c00714996c5c6d920752f99eb813776251163946e053
MD5 eaf725b60b9c4e5cf54c5c17024d7f5a
BLAKE2b-256 216be1db323f39dd0754de752c05ea5d16bcbfa0c2835d51c4575f29ab612581

See more details on using hashes here.

Provenance

The following attestation bundles were made for xlsxturbo-0.6.0-cp38-abi3-win_amd64.whl:

Publisher: release.yml on tstone-1/xlsxturbo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xlsxturbo-0.6.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for xlsxturbo-0.6.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a7eca68e553f75441146b52fc00dd3303e804186a6e13decd27161015945e12c
MD5 709fe53834991281a4d9db15041e275a
BLAKE2b-256 e175f67a7f12e031fb7150a0968acbbf57214e50cc4773c8eec563ae663f98bf

See more details on using hashes here.

Provenance

The following attestation bundles were made for xlsxturbo-0.6.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on tstone-1/xlsxturbo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xlsxturbo-0.6.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for xlsxturbo-0.6.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 14e21d312e44ecda8d965a25f1ddd9861e3b026872eb91b352b238d91a21f1ab
MD5 406974f6cb5630238ee5b0fb0312c79d
BLAKE2b-256 46acb67e0c6a3dda96f5451de7049fd09d2497a507689b8debe339de6b1833ce

See more details on using hashes here.

Provenance

The following attestation bundles were made for xlsxturbo-0.6.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on tstone-1/xlsxturbo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xlsxturbo-0.6.0-cp38-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for xlsxturbo-0.6.0-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d1d754fbbb4323b4d9d5a0d0ea543f6135b90f1c1656ddfd3bd55a34829bca24
MD5 da29540d53bbded2b4fed2dd8c80f6b7
BLAKE2b-256 922a5fea9ba80c97419754ae647b7766ef092912b2795f2fdce5179a95e15425

See more details on using hashes here.

Provenance

The following attestation bundles were made for xlsxturbo-0.6.0-cp38-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on tstone-1/xlsxturbo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xlsxturbo-0.6.0-cp38-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for xlsxturbo-0.6.0-cp38-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 904f87dde3cfc4e2de5291dd1055f31a95775fb7677d346ae85209a79b426174
MD5 051e400b27f263da99b75cc16267471e
BLAKE2b-256 7db9bde5985d01859a97e4e823f8151a61b9c65742f024e65d1d20348411a767

See more details on using hashes here.

Provenance

The following attestation bundles were made for xlsxturbo-0.6.0-cp38-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on tstone-1/xlsxturbo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page