Excel Format Guide
How to Convert XLSX to XLSM and Keep Your Macros (2026 Guide)
You have an XLSX file. Someone added VBA macros to it — or you want to — and now Excel is refusing to save them, warning you that macros will be stripped. The fix is straightforward: convert XLSX to XLSM. But the path to doing it without losing anything is more nuanced than most guides admit.
This guide covers the technical difference between the two formats, three reliable conversion methods (including a Python approach for bulk work), and every common mistake that causes macros to vanish mid-conversion.
Why XLSX Can't Hold Macros
Both XLSX and XLSM are Open XML formats — essentially ZIP archives containing XML files. If you rename any Excel file to .zip and open it, you'll see folders like xl/, xl/worksheets/, and a [Content_Types].xml manifest at the root.
The critical difference is one file: xl/vbaProject.bin. This is a COM Structured Storage binary that contains every VBA module, UserForm, class module, and project reference in your workbook. XLSM files have it. XLSX files don't — and the Open XML spec explicitly forbids them from containing it.
The [Content_Types].xml file also has to declare the correct MIME type for the macro container. In an XLSM, you'll find:
<Override PartName="/xl/vbaProject.bin"
ContentType="application/vnd.ms-office.activeX+xml"/>
Without that declaration, even if you manually stuffed a vbaProject.bin into the ZIP, Excel would ignore it. This is why renaming .xlsx to .xlsm does absolutely nothing — the internal structure is wrong.
Method 1: Excel Save As (Simplest, Most Reliable)
If you have Excel installed and are working with a single file, Save As is the definitive method. It rewrites the entire file structure correctly.
- Open the XLSX file in Excel (2016 or later recommended).
- Press Alt + F11 to open the VBA editor. Confirm your macros are present in the Project Explorer. If they're already missing, the problem is upstream.
- Press F4 to close the VBA editor and return to the workbook.
- Go to File → Save As.
- In the "Save as type" dropdown, select Excel Macro-Enabled Workbook (*.xlsm).
- Click Save. Do not just hit Enter if the dialog pre-selects XLSX — confirm the dropdown first.
- Close the file, reopen the newly saved XLSM, and press Alt + F11 again to verify all modules are intact.
Method 2: Python with openpyxl (For Existing XLSM Files)
openpyxl's keep_vba=True parameter is specifically designed for the scenario where you have an existing XLSM file and want to modify workbook data (add rows, change cell values, update formulas) without destroying the embedded VBA.
import openpyxl
# Open existing XLSM — keep_vba=True preserves vbaProject.bin
wb = openpyxl.load_workbook('source.xlsm', keep_vba=True)
ws = wb.active
ws['A1'] = 'Updated by script'
# Must save with .xlsm extension
wb.save('output.xlsm')
print("Saved. VBA blob preserved.")
What keep_vba=True does internally: openpyxl reads the vbaProject.bin as a raw binary blob, keeps it in memory untouched, and writes it back to the same path inside the new ZIP. It makes no attempt to parse the COM Structured Storage format.
What it cannot do: if your source file is a plain XLSX with no existing VBA, there is no blob to preserve. In that case, you cannot use openpyxl to inject new VBA — the library simply has no VBA authoring capability. You would need to use xlwings (Windows/COM) or do the Save As method in Excel first to create a valid XLSM scaffold, then use openpyxl to modify the data layer.
Stop losing macros on every conversion
The Macro-Safe Converter Kit gives you the exact workflow, tested scripts, and decision checklist to convert without losing a single line of VBA.
Get the Kit — $9One-time · Instant download · 30-day guarantee
Method 3: LibreOffice Headless CLI
LibreOffice can convert Excel files from the command line using its headless mode, which is useful on Linux servers or in CI pipelines where Excel isn't available.
# Basic conversion — outputs to the same directory as source
libreoffice --headless --convert-to xlsm source.xlsx
# Convert all XLSX files in a folder
for f in *.xlsx; do
libreoffice --headless --convert-to xlsm "$f"
done
A critical caveat: LibreOffice uses its own BASIC macro engine by default, and its VBA compatibility mode is imperfect. Simple macros (cell manipulation, loops, basic string operations) generally survive. Macros that rely on Excel-specific objects — Application.WorksheetFunction, ActiveX controls, UserForm objects with complex event handlers — may not load correctly.
Always test a representative file before running LibreOffice on your entire archive. Open the converted XLSM in Excel afterward and run each macro manually to verify behavior.
Format Comparison Table
| Feature | XLSX | XLSM |
|---|---|---|
| Contains VBA | No | Yes |
| Open XML format | Yes | Yes |
| vbaProject.bin present | No | Yes |
| Safe to share broadly | Yes | Depends on org policy |
| Editable with openpyxl | Yes | Yes (with keep_vba=True) |
| Supported in Excel 2007+ | Yes | Yes |
Common Mistakes That Strip Macros
Mistake 1: Using online converters
Online tools like Smallpdf, ILovePDF, Convertio, and similar services are designed for document conversion — PDF, image, basic Office formats. None of them have awareness of VBA or the COM Structured Storage format inside vbaProject.bin. They will either reject the conversion or silently discard the macro container. Do not use them for macro-bearing files.
Mistake 2: Opening and re-saving in Google Sheets
Google Sheets can open XLSX files, but it does not support VBA at all. If you open an XLSM in Google Sheets and download it back as XLSX or XLSM, you get a file with macros completely removed. This is a common trap when someone uses Google Drive as a "quick converter."
Mistake 3: Not checking macro security settings
After conversion, macros may appear missing even when they aren't — because Excel's macro security settings are blocking them from loading. Go to File → Options → Trust Center → Trust Center Settings → Macro Settings and ensure "Disable all macros with notification" is selected (not "Disable all without notification"). Then reopen the file and enable macros when prompted.
Mistake 4: Saving over the original before validating
Always keep the original XLSX until you've confirmed the XLSM conversion is complete and working. Save the output to a new filename. Only delete the original after running and validating every macro in the converted file.
Batch Converting XLSX to XLSM
If you have multiple files, a Python script using the subprocess module to call LibreOffice, or a VBA macro running inside Excel that iterates a folder, are both viable approaches.
import subprocess
from pathlib import Path
source_dir = Path("/path/to/xlsx/files")
output_dir = Path("/path/to/output")
output_dir.mkdir(exist_ok=True)
for xlsx_file in source_dir.glob("*.xlsx"):
result = subprocess.run(
["libreoffice", "--headless", "--convert-to", "xlsm",
"--outdir", str(output_dir), str(xlsx_file)],
capture_output=True, text=True
)
status = "OK" if result.returncode == 0 else "FAILED"
print(f"{xlsx_file.name}: {status}")
For any file that shows FAILED, fall back to Excel's COM automation via pywin32 on Windows, which is the gold standard for accuracy but requires a licensed Excel installation.
Validating the Conversion
After any conversion, do these three checks before trusting the output:
- Check the file extension is .xlsm — obvious but easy to miss if your file manager hides extensions.
- Open the VBA editor (Alt + F11) — every module should appear in the Project Explorer on the left. Count them if you know how many there should be.
- Run each macro once — press F5 with each module selected, or use Developer → Macros to run them. A macro that opens without errors but fails at runtime probably has a reference to an object that didn't survive the format change.
If a module is missing or code is corrupted, you have two options: re-export the VBA from the original file using Alt + F11 → File → Export File, and re-import it into the converted XLSM; or restart the conversion using the Excel Save As method, which is always the most accurate path.
Frequently Asked Questions
What is the difference between XLSX and XLSM?
XLSX and XLSM are both Open XML formats stored as ZIP archives, but XLSM is the macro-enabled variant. An XLSM file contains a vbaProject.bin binary inside the ZIP that stores all VBA modules, forms, and class modules. XLSX files cannot contain VBA; if you try to save an XLSX with macros, Excel will strip them silently.
Can I rename an XLSX file to XLSM to keep macros?
No. Renaming the file extension does not change the internal XML structure. An XLSX file lacks the vbaProject.bin entry and the correct [Content_Types].xml declarations. You must go through a proper Save As conversion so Excel rewrites the file structure correctly.
Does Python's openpyxl support XLSM files with macros?
openpyxl can open and resave XLSM files in keep_vba=True mode, which preserves the vbaProject.bin blob. However, it cannot create new VBA or modify existing VBA code — it just carries the binary through. For reading or writing VBA programmatically, you need xlwings (Windows only) or a COM automation approach.
Related Guides
Stop losing macros on every conversion
The Macro-Safe Converter Kit gives you the exact workflow, tested scripts, and decision checklist to convert without losing a single line of VBA.
Get the Kit — $9One-time · Instant download · 30-day guarantee