Excel Format Guide

Convert XLS to XLSM: Keep Every Macro in the New Format (2026)

Sponsored

Updated April 2026 · By MacroKit Team · 9 min read

XLS to XLSM is a more treacherous conversion than most people expect. The naive assumption is: both formats support VBA, so any converter should handle it. The reality is that XLS and XLSM store VBA in fundamentally different ways, and most tools silently drop the macros without warning.

This guide explains exactly why, gives you two reliable paths to make the conversion correctly, and shows you how to validate that nothing was lost.

How XLS Stores VBA (And Why It's Different)

The XLS format is officially called BIFF8 — Binary Interchange File Format, version 8. It's a compound document format based on the OLE (Object Linking and Embedding) Structured Storage specification, which Microsoft developed in the early 1990s. Think of it as a miniature filesystem embedded inside a single binary file, with directories ("storages") and files ("streams") inside.

VBA in an XLS file lives in a storage called _VBA_PROJECT_CUR inside the compound document. Inside that storage are streams including VBA (the compiled p-code and source), _VBA_PROJECT (project metadata), and one stream per module. The source code itself is compressed using a simple run-length scheme defined in the MS-OVBA specification.

XLSM is entirely different. It's a ZIP archive of XML files, and VBA lives in a file called xl/vbaProject.bin inside that ZIP. This vbaProject.bin is itself a COM Structured Storage document — essentially the same OLE compound document structure extracted from the old XLS binary and dropped into the new container as a binary blob.

So converting XLS to XLSM means: extract the VBA compound document from the BIFF8 stream, write it as a standalone .bin file, package it inside a ZIP alongside new XML worksheets, and update the content type manifest. This is what Excel's engine does. Most third-party converters do not — they parse the worksheets and data, rebuild the XML, and never touch the VBA storage at all.

Attribute XLS (BIFF8) XLSM (Open XML)
Container format OLE Compound Document ZIP archive
VBA storage location _VBA_PROJECT_CUR stream xl/vbaProject.bin
VBA encoding MS-OVBA compressed streams Same (vbaProject.bin is OLE)
Max file size ~256 MB (practical limit) Effectively unlimited
Max rows 65,536 1,048,576
Excel version support All versions Excel 2007+

Path 1: Excel Save As (Recommended)

When Excel opens an XLS file and you Save As XLSM, Excel's engine does the OLE extraction and repackaging correctly. This is the most reliable method available because Microsoft wrote both the XLS parser and the XLSM writer.

  1. Open the XLS file in Excel. If you see a compatibility warning about features not available in XLS format, that's normal — click OK.
  2. Before doing anything else, press Alt + F11 to open the VBA editor. In the Project Explorer (left panel), expand the project tree and verify all modules are listed. Take note of how many modules, class modules, and UserForms exist.
  3. Close the VBA editor and return to the workbook.
  4. Go to File → Save As. In the "Save as type" dropdown, select Excel Macro-Enabled Workbook (*.xlsm).
  5. Give the file a new name (do not overwrite the original XLS yet).
  6. Click Save. Excel will rewrite the file completely.
  7. Close Excel, reopen the new XLSM, and verify:
Why keep the original XLS? Some legacy XLS files contain Excel 4.0 macro sheets (XLM macros) — a separate macro system that predates VBA. These look like worksheet tabs but contain formula-based macros. Excel carries these through to XLSM in most cases, but they may not execute correctly. Keep the original until you've validated every execution path.

Path 2: LibreOffice Headless CLI

On Linux or macOS without Excel, LibreOffice is the best available option. Its XLS reader is mature (it's been reading BIFF8 files since the early 2000s), and its XLSM writer correctly packages VBA as a vbaProject.bin.

# Single file conversion
libreoffice --headless --convert-to xlsm yourfile.xls

# With explicit output directory
libreoffice --headless --convert-to xlsm --outdir /output/ yourfile.xls

# Batch: all XLS files in current directory
libreoffice --headless --convert-to xlsm *.xls

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 — $9

One-time · Instant download · 30-day guarantee

The VBA compatibility limitations with LibreOffice are real and worth understanding specifically for the XLS case:

For any macro in the "risky" category, test in Excel after conversion. If a macro fails, you may need to adjust it for the minor differences between Excel's VBA runtime and LibreOffice's compatibility shim.

The Two-Step Path for Complex Files

For XLS files with complex macros that you know need to run perfectly in Excel, a two-step approach on Windows gives you maximum fidelity:

  1. Step 1 — XLS to XLSM via Excel Save As. This gives you a correctly structured XLSM with VBA intact.
  2. Step 2 — Validate with a Python script that opens the XLSM and confirms the vbaProject.bin is present and non-empty.
import zipfile
from pathlib import Path

def validate_xlsm(path: str) -> dict:
    p = Path(path)
    if p.suffix.lower() != '.xlsm':
        return {"valid": False, "reason": "Not an XLSM file"}

    with zipfile.ZipFile(path, 'r') as z:
        names = z.namelist()
        has_vba = 'xl/vbaProject.bin' in names
        if not has_vba:
            return {"valid": False, "reason": "vbaProject.bin missing"}
        vba_size = z.getinfo('xl/vbaProject.bin').file_size
        return {
            "valid": True,
            "vba_bin_size_bytes": vba_size,
            "files_in_archive": len(names)
        }

result = validate_xlsm("output.xlsm")
print(result)

A valid XLSM will have xl/vbaProject.bin present and its size will be at minimum a few kilobytes (even a minimal VBA project is several KB due to the OLE compound document overhead). If vba_bin_size_bytes is 0 or the key is missing, the conversion failed to preserve VBA.

What About XLS Files With No Macros?

If your XLS file has no VBA at all, converting to XLSM is unnecessary. Convert to XLSX instead — it's the current standard format, smaller on disk, and more widely supported by modern tools. XLSM should only be your target when you need macro capability in the output.

If you're not sure whether an XLS file has macros: open it in Excel, press Alt + F11, and look at the Project Explorer. If you see any modules, class modules, or forms listed, macros are present. If the tree is empty, there's nothing to preserve and XLSX is the better target.

Validation Steps After Any XLS to XLSM Conversion

Run these checks in sequence before retiring the original XLS:

  1. File size sanity check. XLSM files are generally similar in size to the original XLS (often slightly smaller due to ZIP compression of the XML worksheets). If the output file is dramatically smaller (e.g., 500KB XLS becomes 12KB XLSM), something was dropped.
  2. Module count check. Open both the original XLS and the converted XLSM, press Alt + F11 in each, and count modules. They should match exactly.
  3. Line count check. For critical modules, compare the line count of source code between original and converted. In the VBA editor, Ctrl + End moves to the last line — the line number shown in the status bar is your total.
  4. Runtime test. Run each macro with representative data. Note any runtime errors that weren't present in the original XLS.
  5. Named ranges and defined names. Macros often reference named ranges. Go to Formulas → Name Manager and verify all named ranges survived intact.

Frequently Asked Questions

Why is converting XLS to XLSM harder than XLSX to XLSM?

XLS uses the BIFF8 (Binary Interchange File Format) binary structure, which is entirely different from the Open XML ZIP architecture used by XLSM. The VBA is embedded directly in the BIFF stream as a separate storage object. Converting to XLSM requires extracting that VBA storage and repackaging it as a vbaProject.bin — a transformation that Excel's own engine handles correctly but most third-party parsers get wrong.

Can I convert XLS to XLSM without Excel installed?

LibreOffice is the best option without Excel. Run: libreoffice --headless --convert-to xlsm yourfile.xls. VBA compatibility is good for simple macros but degrades with complex Excel-specific objects. Always validate the output in Excel before relying on it in production.

Will my XLS macros run without modification in XLSM?

Most will, because XLSM macros run in the same VBA 7.x engine as XLS macros. However, macros that reference the Excel 4 macro language (XLM), use old-style dialog sheets, or call deprecated functions from the Analysis ToolPak may need small updates. Test each macro after conversion.

Related Guides

Best Macro-Safe Excel Converter Tools 2026Tool comparison guide Excel Macro Migration Guide 2026Complete migration walkthrough Convert XLS to XLSX Without Losing MacrosStep-by-step guide

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 — $9

One-time · Instant download · 30-day guarantee