Recover data from XLS files that exceed the 65,536-row limit
Project description
한국어 | English
long-xls
A simple tool to recover data from XLS files that exceed the 65,536-row limit.
The XLS format is structurally limited to 65,536 rows per sheet. However, some programs — legacy reporting utils, converting tools, stock trading platform exporters, etc. — keep writing BIFF cell records past this limit. The data is physically present in the file, but most programs and libraries (Excel, pandas, xlrd) either silently truncate it or throw an error, leaving no way to read the stored data.
long-xls reads the raw BIFF binary stream, detects row-index wrap-arounds at the 65,536 boundary, and reconstructs the full dataset.
The Problem
┌─────────────────────────────────────────────────────┐
│ Your XLS file (e.g. 370,000 rows of trade data) │
│ │
│ Row 1 ............ ✓ visible in Excel │
│ Row 65,536 ....... ✓ visible in Excel │
│ Row 65,537 ....... ✗ INVISIBLE — data is there │
│ Row 370,000 ...... ✗ INVISIBLE — but recoverable! │
└─────────────────────────────────────────────────────┘
Install
pip install long-xls # xlsx output (default)
pip install "long-xls[parquet]" # + parquet support
pip install "long-xls[all]" # everything
Or download a standalone executable from Releases — no Python required.
Quick Start
# Convert to xlsx (default)
long-xls data.xls
# Convert to csv
long-xls data.xls -f csv
# Convert to parquet
long-xls data.xls -f parquet
# Include a JSON schema sidecar file
long-xls data.xls --schema
# Multiple files at once
long-xls *.xls -f csv -o output/
Commands
| Command | Description |
|---|---|
long-xls data.xls |
Convert to xlsx (default) |
long-xls data.xls -f csv |
Convert to csv |
long-xls data.xls -f parquet |
Convert to parquet |
long-xls data.xls --schema |
Also write .schema.json |
long-xls schema data.xls |
Print JSON schema to stdout |
long-xls scan data.xls |
Quick file scan (record counts only) |
Options
| Option | Default | Description |
|---|---|---|
-f, --format |
xlsx |
Output format: xlsx, csv, parquet |
-o, --output-dir |
same as input | Output directory |
-e, --encoding |
cp949 |
Text encoding for string cells |
-y, --force |
off | Overwrite existing files without asking |
--schema |
off | Write a .schema.json alongside output |
Python API
from long_xls import parse, parse_to_dataframe, schema_json
# Parse and inspect
sheet = parse("data.xls")
print(f"{sheet.num_data_rows:,} rows recovered")
# Get a pandas DataFrame
df, sheet = parse_to_dataframe("data.xls")
# Export schema as JSON
import json
print(json.dumps(schema_json(sheet), indent=2))
Schema Output Example
{
"file": "data.xls",
"file_size": 29736094,
"encoding": "cp949",
"num_columns": 4,
"num_data_rows": 371700,
"row_limit_exceeded": true,
"wraps": {"0": 5, "1": 5, "2": 5, "3": 5},
"columns": [
{"index": 0, "name": "date", "type": "string", "non_null_count": 371700},
{"index": 1, "name": "time", "type": "string", "non_null_count": 371700},
{"index": 2, "name": "price", "type": "float", "non_null_count": 371700},
{"index": 3, "name": "volume", "type": "integer", "non_null_count": 371700}
]
}
Test Files
Synthetic test files (generator included)
Run tests/generate_test_xls.py to generate long-XLS test files of
various sizes. It writes raw BIFF2 records to reproduce the row
wrap-around behaviour.
python tests/generate_test_xls.py
| File | Rows | Wraps | Encoding | Purpose |
|---|---|---|---|---|
test_100k_rows.xls |
100,000 | 1 | UTF-8 | Basic recovery verification |
test_200k_rows.xls |
200,000 | 3 | UTF-8 | Multi-wrap verification |
test_70k_cp949.xls |
70,000 | 1 | CP949 | Korean encoding verification |
Real-world example: Kiwoom Securities HTS chart data
Futures tick chart data exported from Kiwoom Securities HTS. Contains 371,700 rows, but Excel only shows up to 65,535. long-xls recovers the entire dataset.
20240808_KOSPI200_Tick_Kiwoom.xls— 371,700 rows (5 wraps), 29.7 MB
Building a Standalone Executable
pip install pyinstaller
python build_exe.py # produces dist/long-xls.exe (Windows)
Author
seonhwa17kim (with help from GPT-5.5, Gemini 3.5, Claude Opus 4.8)
License
MIT Copyright (c) 2026 seonhwa17kim
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file long_xls-0.1.0.tar.gz.
File metadata
- Download URL: long_xls-0.1.0.tar.gz
- Upload date:
- Size: 13.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b05a1ea3b2030b5a4c4f7d95830a00404e9cdc2cb3fd182222929492a15bd359
|
|
| MD5 |
92c11012d03e18244ffe167b54dedbe9
|
|
| BLAKE2b-256 |
53df36283f1258649f2aaed2642439d2d87c17fe25fe7a0c1f0c876d1ed2d08c
|
File details
Details for the file long_xls-0.1.0-py3-none-any.whl.
File metadata
- Download URL: long_xls-0.1.0-py3-none-any.whl
- Upload date:
- Size: 12.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
25f5f8b406a5f8b9d9e9fb3fa97c74836c3e22b3ebf29ab3ed0e73d27ac91877
|
|
| MD5 |
968e018a76482b95cf9c45a5db45c3bf
|
|
| BLAKE2b-256 |
28b97c12812eb068bc6d33e592aaf2449b5c687b7cea283d83caefc3632cbda0
|