Skip to main content

Recover data from XLS files that exceed the 65,536-row limit

Project description

GitHub | 한국어

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


Download files

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

Source Distribution

long_xls-0.1.1.tar.gz (13.3 kB view details)

Uploaded Source

Built Distribution

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

long_xls-0.1.1-py3-none-any.whl (12.9 kB view details)

Uploaded Python 3

File details

Details for the file long_xls-0.1.1.tar.gz.

File metadata

  • Download URL: long_xls-0.1.1.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

Hashes for long_xls-0.1.1.tar.gz
Algorithm Hash digest
SHA256 a176fa6f84c435e3dbaae3f6f54489ef22c49aa3fb770d8f85519564744ec311
MD5 57a6f0fcc3a07d9905e0e43683fc165b
BLAKE2b-256 18ec505a7f34ebb982a2afcd3d9548a215a96b15c2cfb8550d38e205b544fde4

See more details on using hashes here.

File details

Details for the file long_xls-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: long_xls-0.1.1-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

Hashes for long_xls-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ea4b5d29ee4adf7572a0897449be817230e677bc46c2726ca5c85a1fbb6c6ebc
MD5 d704c89d3a8e1415528eaf6b7144b3b2
BLAKE2b-256 fbcc7ab8e7cd7792717b5c49e22598b30c064f1a9f568981ef1d4a803ee66236

See more details on using hashes here.

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