Pre-Conversion Protocol

How to Backup Excel Macros Before Any Conversion
(Never Lose VBA Again)

Sponsored
By MacroKit · Updated April 2026 · 9 min read

Most macro loss happens in the 90 seconds before conversion. Someone opens a converter, drags in the file, downloads the result, and moves on. The macros vanish silently. No error. No warning. Just gone.

The fix is a 2-minute pre-conversion backup routine. Do it once before every format change and you'll never lose VBA code again. This guide gives you three methods: manual (Excel built-in), scripted (Python), and automated (one-click batch).

Before you start: Use the free Macro Inspector to confirm your file actually contains macros. Many files are named .xlsm without any VBA — no backup needed, convert freely.

Method 1 — Manual Backup (Excel VBA Editor)

This method works without any scripts or third-party tools. Takes 2-5 minutes per file.

  1. Open the XLSM file in Excel
  2. Open the VBA Editor: Alt + F11
  3. In the Project Explorer (left panel), expand your workbook's project
  4. For each module/class/form, right-click → Export File
  5. Save to a folder named [workbook-name]_vba_backup_YYYY-MM-DD
Project itemFile extensionContains
Standard Module.basSub and Function procedures
Class Module.clsClass definitions, properties, methods
UserForm.frm + .frx.frm = layout code; .frx = binary control data
ThisWorkbook.clsWorkbook-level event handlers
Sheet1, Sheet2….clsSheet-level event handlers (often missed!)
Don't miss sheet modules: The modules under individual sheet names (Sheet1, Sheet2) contain critical event handlers like Worksheet_Change and Worksheet_SelectionChange. These are easy to overlook in the Project Explorer and are almost never exported by automated tools.

Method 2 — Python Script (Automated Extract)

For more than 3 files, do this programmatically. The script below uses only the standard library for the ZIP extraction part, with an optional oletools enhancement for readable source code.

Option A — Extract vbaProject.bin (fast, any file)

"""
vba_backup.py — Extract VBA binary from XLSM for archiving
No dependencies beyond stdlib. Run before any format conversion.
Usage: python vba_backup.py workbook.xlsm
"""
import sys, zipfile, shutil
from pathlib import Path
from datetime import date

def backup_vba(xlsm_path):
    p = Path(xlsm_path).resolve()
    if not p.exists():
        print(f"Error: {p} not found"); return

    today = date.today().isoformat()
    backup_dir = p.parent / f"{p.stem}_vba_backup_{today}"
    backup_dir.mkdir(exist_ok=True)

    # Copy original XLSM to backup
    shutil.copy2(p, backup_dir / p.name)
    print(f"Original archived: {backup_dir / p.name}")

    # Extract vbaProject.bin
    found = False
    with zipfile.ZipFile(p, 'r') as z:
        for entry in z.namelist():
            if 'vbaProject' in entry:
                z.extract(entry, backup_dir)
                print(f"VBA binary extracted: {entry}")
                found = True

    if not found:
        print("No VBA found in this file — safe to convert without backup")
    else:
        print(f"Backup complete: {backup_dir}")
        print("To restore: re-import vbaProject.bin via the MacroKit restore script")

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print("Usage: python vba_backup.py ")
        sys.exit(1)
    backup_vba(sys.argv[1])

Option B — Extract readable source code (requires oletools)

# pip install oletools
from oletools.olevba import VBA_Parser

def extract_vba_source(xlsm_path, output_dir):
    """Extract VBA source code as readable .bas/.cls files."""
    from pathlib import Path
    out = Path(output_dir)
    out.mkdir(exist_ok=True)

    vba_parser = VBA_Parser(xlsm_path)
    if not vba_parser.detect_vba_macros():
        print("No VBA macros detected")
        return

    for (filename, stream_path, vba_filename, vba_code) in vba_parser.extract_macros():
        # Determine extension from stream path
        ext = '.cls' if 'Class' in stream_path else '.bas'
        safe_name = vba_filename.replace('/', '_').replace('\\', '_')
        out_file = out / f"{safe_name}{ext}"
        out_file.write_text(vba_code, encoding='utf-8')
        print(f"Extracted: {out_file.name} ({len(vba_code)} chars)")

    vba_parser.close()

# Example usage:
extract_vba_source("report-automation.xlsm", "vba_backup_2026-04-15")

Method 3 — Pre-Conversion Checklist (for teams)

If you're working with others or running a regular conversion process, use this checklist before any format change:

Where to Store Macro Backups

Storage optionProsCons
Local folder (same directory)Fast, zero setupLost if drive fails, not searchable
Dated subfolderClear versioningStill local-only
Git repositoryFull history, diff-able VBA code, searchableRequires git setup, .frx binaries not diff-able
SharePoint / OneDriveAutomatic version historyMacros blocked in online edit; only useful as backup
Dedicated archive ZIPSingle file to move aroundNo easy browsing without extraction
Best practice: Store .bas and .cls files in a git repository. VBA is plain text — you can diff modules, see who changed what, and roll back to any version. The .frx binary (UserForm controls) can't be diffed but should still be committed for restore purposes.

Restoring Macros After a Bad Conversion

If you have a backup and need to restore:

  1. Open the converted file in Excel
  2. Save As → XLSM (must be XLSM to accept macros)
  3. Open VBA Editor (Alt+F11)
  4. File → Import File → select each .bas / .cls from your backup
  5. For UserForms: place .frm and .frx in the same folder, import the .frm
  6. Test all macros — update any references that changed during conversion

If you only have the vbaProject.bin binary (not readable source), use the oletools library to extract the source from the binary before re-importing.

Automating Backups System-Wide

For teams that run regular conversions, automate the backup step so it can't be forgotten:

#!/bin/bash
# pre-convert-hook.sh — Run before any XLSM conversion
# Add to your conversion pipeline as a required step

FILE="$1"

if [[ "$FILE" == *.xlsm ]] || [[ "$FILE" == *.xls ]]; then
  echo "Macro-capable file detected. Running backup..."
  python3 vba_backup.py "$FILE"
  if [ $? -ne 0 ]; then
    echo "ERROR: Backup failed. Aborting conversion."
    exit 1
  fi
  echo "Backup complete. Proceeding with conversion."
fi

Complete pre-conversion workflow kit

MacroKit includes the full backup script, pre-conversion checklist, restore guide, and batch conversion workflow — everything you need to handle XLSM conversions without ever losing a line of VBA code.

Get MacroKit — $9

Or check if your file has macros first: Free Macro Inspector →

Related Guides