How to Convert XLS to XLSX Without Losing Macros (2026)
That said, "convert XLS to XLSX without losing macros" is one of the most-searched Excel questions, so let me give you the complete picture: what's technically happening, what your actual options are, and the exact steps that preserve every VBA module.
Why XLSX Cannot Contain Macros (The Technical Reason)
XLS is the legacy binary format (BIFF8) used by Excel 97–2003. It stores everything — worksheets, styles, and VBA — in a single binary blob using the Compound Document File Format.
When Microsoft introduced the OOXML format family in 2007, they split the file types by capability:
| Extension | Full Name | Macros Allowed? | Use Case |
|---|---|---|---|
| .xlsx | Excel Workbook | No | Data, charts, formulas — no code |
| .xlsm | Excel Macro-Enabled Workbook | Yes | Everything + VBA modules |
| .xlsb | Excel Binary Workbook | Yes | Large files, VBA, fast open |
| .xls | Excel 97–2003 Workbook | Yes | Legacy compatibility |
The XLSX specification (ISO 29500 Part 1) explicitly prohibits VBA storage. This isn't a tool limitation — it's a format specification. No tool can create a valid XLSX file that contains VBA macros. Any tool that claims to do so is either:
- Producing an XLSM file and calling it XLSX (extension lie)
- Producing a broken file that Excel will warn about on open
- Simply stripping your macros silently
The Correct Conversion: XLS → XLSM
If you want to modernise your XLS files while keeping macros, the target format is .xlsm. Here are three ways to do it, from easiest to most automatable.
Method 1: Excel Desktop (Recommended for Single Files)
Method 2: LibreOffice Command Line (Batch Conversion)
For batches of 10+ files, LibreOffice headless is reliable. It preserves VBA storage but marks macros as "from a potentially unsafe source" on first open in Excel — a one-time click-through per file.
libreoffice --headless --convert-to xlsm --outdir ./output/ *.xls
Caveats with LibreOffice:
- Complex ActiveX controls may not convert correctly
- Excel-specific API calls in VBA (e.g.,
Application.ActiveSheet) work fine; LO-specific calls won't exist in XLSM - Password-protected macros will not convert — you must unprotect in the original XLS first
Method 3: Python with openpyxl + xlrd (Programmatic, Advanced)
If you need to automate this as part of a pipeline, the cleanest approach is to extract macro bytes directly from the XLS binary and transplant them into a new XLSM container.
import xlrd
import zipfile
import shutil
import os
# This is a simplified illustration — full implementation requires VBA storage extraction
# which is available in the MacroKit technical guide
def extract_vba_storage(xls_path):
"""Extract the VBA Storage binary from an XLS file (Compound Document format)"""
with open(xls_path, 'rb') as f:
data = f.read()
# VBA storage is identified by the signature at the Compound Document root
# Full extraction logic: see MacroKit technical guide
return data
def transplant_to_xlsm(xlsm_template, vba_bytes, output_path):
"""Inject VBA storage into an XLSM container"""
shutil.copy(xlsm_template, output_path)
with zipfile.ZipFile(output_path, 'a') as z:
z.writestr('xl/vbaProject.bin', vba_bytes)
The full, tested implementation is in the MacroKit research kit — it handles edge cases including workbook protection, UserForm objects, and class modules.
What Online Converters Do to Your Macros
| Tool | XLS → XLSM Macro Preservation | Notes |
|---|---|---|
| CloudConvert | Strips macros | Converts via LibreOffice but exports XLSX, not XLSM |
| Zamzar | Strips macros | No XLSM output option |
| ILovePDF | Not applicable | PDF-focused, no XLSM output |
| Aspose.Cells | Partial | API supports XLSM output but requires paid licence for VBA |
| Excel Desktop | Full preservation | Gold standard — see Method 1 above |
| LibreOffice headless | Full preservation | Minor compatibility gaps for complex ActiveX |
Checking Your Macros After Conversion
Always run this three-step verification on converted files before you delete the originals:
Batch Conversion: 50+ Files
If you're migrating a library of XLS files — common when companies leave SharePoint 2010 or transition from on-premise Excel to Microsoft 365 — the LibreOffice command above scales cleanly to hundreds of files:
#!/bin/bash # Batch convert all XLS in current directory to XLSM mkdir -p ./xlsm-output find . -maxdepth 1 -name "*.xls" | while read f; do echo "Converting: $f" libreoffice --headless --convert-to xlsm --outdir ./xlsm-output/ "$f" done echo "Done. Check ./xlsm-output/"
After batch conversion, run the XLSM Macro Inspector on a sample (10% of files) to verify macro preservation rates before deleting your originals.
FAQ
Can you convert XLS to XLSX without losing macros?
No — XLSX cannot contain macros by specification. Convert to XLSM instead. That is the correct modernisation path for any XLS file with VBA.
My IT department requires XLSX. What do I do?
Two options: (1) Keep the macros in a separate XLSM file and use Power Query to pull data into your XLSX reports. (2) Re-implement your macros as Python scripts or Power Automate flows that operate on XLSX files. Option 1 is faster; Option 2 is more future-proof.
Will my macros work after converting from XLS to XLSM?
In most cases, yes. The main compatibility issues are: (1) XLS-era API calls that were deprecated in Excel 2013+, (2) password-protected VBA projects (must be unprotected before conversion), (3) complex UserForm controls with embedded binary objects. Run your macros in test mode after conversion.
What if my colleague receives XLSM files and doesn't have macro-enabled Excel?
All modern Excel versions (2007+) open XLSM files. If they receive the file and see "Macros have been disabled", they need to click Enable Content once. The file format itself is not the issue — it's Excel's security settings per-machine.
Need to Migrate a Library of XLS Files?
The MacroKit research pack includes a complete migration checklist, the full Python implementation for batch VBA transplanting, and the keyword matrix for every XLSM/XLS conversion search query. $9 one-time.
Get MacroKit — $9 →