xls2xlsx
xls2xlsx converts Excel 97–2003 .xls workbooks to .xlsx or .xlsm
directly from the published file-format specifications.
The distribution is named msxls2xlsx. The Python package and command-line
program are both named xls2xlsx.
The converter uses only the Python standard library at runtime. It does not
require xlrd, openpyxl, Pillow, olefile, Microsoft Excel, LibreOffice,
COM, Java, or external processes.
Installation
python -m pip install msxls2xlsx
To install from source:
python -m pip install .
Python API
Import convert for normal conversions:
from xls2xlsx import convert
result = convert("input.xls", "output.xlsx")
print(result.output_path)
print(result.report.warnings)
print(result.report.statistics)
The converter does not overwrite existing files unless overwrite=True is
set. It preserves styles, VBA, and an exact copy of the source workbook by
default:
result = convert(
"input.xls",
"output.xlsx",
overwrite=True,
preserve_styles=True,
preserve_vba=True,
preserve_source=True,
)
When no destination is given, a regular workbook is written as .xlsx. A
workbook containing VBA is written as .xlsm unless VBA preservation is
disabled.
Inspect a workbook without converting it
inspect_xls is optional and independent of conversion. Use it when you need
to examine the BIFF version, sheet list, VBA status, or container metadata
without creating an output file:
from xls2xlsx import inspect_xls
info = inspect_xls("input.xls")
print(info.to_dict())
Command line
Convert one workbook
xls2xlsx input.xls
xls2xlsx input.xls -o output.xlsx --report report.json
Inspect a workbook
xls2xlsx inspect input.xls
xls2xlsx inspect input.xls --json
The inspect command is read-only and does not create an .xlsx or .xlsm
file.
Convert a directory
xls2xlsx batch ./legacy -o ./converted
xls2xlsx batch ./legacy -o ./converted --recursive --report batch.json
Batch conversion:
- ignores Excel
~$lock files; - processes files in deterministic relative-path order;
- preserves the input directory structure under the output directory;
- isolates failures so one invalid workbook does not stop the batch;
- checks for output and report-path collisions before conversion;
- exits with status
1when some files fail.
Recover the original XLS file
xls2xlsx recover converted.xlsx -o recovered.xls
Recovery verifies the embedded file's length and SHA-256 digest. The same operation is available through the Python API:
from xls2xlsx import read_original_source, recover_original_source
stored = read_original_source("converted.xlsx")
recover_original_source("converted.xlsx", "recovered.xls")
Common options
--overwrite Replace existing output and report files
--no-styles Skip style conversion
--no-vba Discard VBA and write an .xlsx file
--no-source-archive Do not embed the original XLS file
--report FILE Write a structured JSON report atomically
--json Print structured output as JSON
--quiet Suppress success messages
Exit status 0 means success, 1 means conversion failure or partial batch
failure, and 2 means invalid input or command usage.
Conversion reports
Reports use a stable top-level structure:
{
"source": "/path/input.xls",
"destination": "/path/output.xlsx",
"diagnostics": [],
"statistics": {
"sheets": 1,
"cells": 42,
"vba_preserved": false,
"source_archive_preserved": true
}
}
Diagnostics have info, warning, or error severity. A diagnostic location
may identify a worksheet, cell, OLE stream, or BIFF offset. JSON reports are
written to a temporary file in the destination directory and then replaced
atomically.
Source preservation and fidelity
The project provides two layers of preservation:
- Native conversion. BIFF and OfficeArt content that has an OOXML
equivalent is converted to editable
.xlsxor.xlsmcontent. - Byte-for-byte source preservation. The complete original
.xlsfile is embedded in a custom XML part by default, together with its file name, length, SHA-256 digest, and conversion report.
Recoverable source data does not mean that every runtime behavior can be reproduced in OOXML. ActiveX events, legacy OLE activation, some combined or 3D charts, and complex grouped shapes have no exact OOXML equivalent. The converter reports these cases and keeps the original bytes in the embedded source archive.
Using --no-source-archive or preserve_source=False disables byte-for-byte
source recovery.
Supported content
- Text, numbers, booleans, errors, dates, formulas, and cached formula values
- Fonts, colors, fills, borders, alignment, number formats, and protection
- Rich text, merged cells, row and column sizing, hiding, grouping, and outlines
- Sheet order and visibility, active sheets, panes, and page breaks
- Hyperlinks, comments, conditional formatting, data validation, filters, and print settings
- JPEG, PNG, DIB/BMP, TIFF, WMF, and EMF images
- Line, bar, area, pie, and scatter charts, including titles, legends, and series
- Basic DrawingML shapes and the original payloads of embedded OLE objects
- VBA projects and module streams in
.xlsmoutput
Format references
The implementation is based primarily on Microsoft's published MS-CFB, MS-XLS, and MS-ODRAW documentation, together with the published ISO/IEC 29500 implementation notes.
Related projects
xls2xlsx follows the same package and command conventions as
doc2docx and
ppt2pptx:
| Distribution | Python package / CLI | Conversion |
|---|---|---|
msdoc2docx |
doc2docx |
DOC to DOCX |
msxls2xlsx |
xls2xlsx |
XLS to XLSX/XLSM |
ppt2pptx |
ppt2pptx |
PPT to PPTX |
The projects share a consistent API, CLI structure, report format, and exit status conventions. Their conversion engines remain separate because the Word, Excel, and PowerPoint binary formats use different data models.
Development
Run the test suite with:
PYTHONPATH=src python -m unittest discover -s tests -v
The tests cover protocol parsing, formulas, styles, objects, VBA, source
recovery, structured reports, CLI workflows, isolated installation, and real
.xls fixtures from Apache POI. Fixture licensing information is available in
tests/fixtures/apache-poi/.
License
This project is licensed under the MIT License.
Metadata
Release files for msxls2xlsx 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| msxls2xlsx-0.1.2.tar.gz | 998.4 kB | With provenance | Details for msxls2xlsx-0.1.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| msxls2xlsx-0.1.2-py3-none-any.whl | Python 3 | none | any | Details for msxls2xlsx-0.1.2-py3-none-any.whl |
Total release size: 1.1 MB
Release files / msxls2xlsx-0.1.2.tar.gz
| Download URL | msxls2xlsx-0.1.2.tar.gz |
|---|---|
| Size | 998.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bb258a6783d5a1506d5416bcb03903ab0269b3ae22e22762f07df0d801780e12
|
|
BLAKE2b-256 checksum How to use checksums |
f0676e233289295c71696e40710170d72e64b1c3ea6bf414922d39324b16167f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 9, 2026.
Transparency logRelease files / msxls2xlsx-0.1.2-py3-none-any.whl
| Download URL | msxls2xlsx-0.1.2-py3-none-any.whl |
|---|---|
| Size | 94.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
20042f5eabb67042b810967799bd2596e4271a53ccd763bb52c38a9d2f0b15f5
|
|
BLAKE2b-256 checksum How to use checksums |
49fc8b73111b1ea2382c92837f07fb6e3243fbb71b7415a8c98ab824f7c82fc1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 9, 2026.
Transparency logSecurity for msxls2xlsx 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for msxls2xlsx-0.1.2.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 9, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.