How to safely remove vba macros from an excel file received by email
- Step 1Save the attachment without opening it — In your mail client, save the
.xlsmto disk (right-click, Save As). Do not double-click it — double-clicking opens it in Excel, which is exactly what you are trying to avoid. - Step 2Open the VBA Macro Stripper — On a Developer-tier account, open /excel-tools/excel-vba-macro-stripper. Lower tiers are blocked at run time with
VBA Macro Stripper requires Developer tier. - Step 3Drop in the saved attachment — Drag the saved
.xlsminto the tool, or browse for it. The picker filter shows.xlsx, .xls, .ods; select your saved file. One file per run. - Step 4Run the strip — Click run. JSZip unzips the attachment in your browser and deletes
vbaProject.bin,vbaData.xml, and anything underxl/macrosheets/. The macro code is never executed. - Step 5Read the findings — The panel shows
N macro file(s) removedand lists each removed path. A non-zero count confirms the attachment really did carry macros. - Step 6Open the clean copy to inspect — Download
<file>-no-macros.xlsxand open it in Excel. No Enable Content banner appears; you can read the content safely. Keep the original on disk for IT/forensics.
What the stripper removes vs preserves
The tool opens the workbook as an OOXML ZIP with JSZip and deletes only macro-bearing parts by path match. Every other part is repacked byte-for-byte. Path matching is case-insensitive substring matching.
| Container part | Action | Why |
|---|---|---|
xl/vbaProject.bin | Removed | The compiled VBA project — every Sub, Function, UserForm, and class module lives here. Deleting it removes all VBA code. |
xl/vbaProjectSignature.bin / *vbaData.xml | Removed | Digital-signature stub and the VBA data manifest. Any path containing vbadata.xml is dropped so no orphaned macro metadata remains. |
xl/macrosheets/… | Removed | Excel 4.0 / XLM macro sheets. The stripper deletes this folder, so legacy XLM auto-open macros are removed alongside VBA — not just VBA. |
xl/_rels/workbook.xml.rels | Edited | The <Relationship … vbaProject …> entry is stripped so the workbook does not reference the now-deleted binary. |
xl/printerSettings/printerSettings*.bin | Preserved | Binary print settings are explicitly kept — only macro binaries are targeted, not every .bin. |
Worksheet XML, sharedStrings.xml, styles, charts, pivots | Preserved | All data, formulas, formatting, charts, and pivot tables are repacked unchanged. The output is a faithful copy minus the code. |
docProps/core.xml / docProps/app.xml | Preserved | Author, company, and revision metadata are untouched. Use the Core/App metadata wipers if you also need those gone. |
Tier access and file-size limits
The VBA Macro Stripper is gated to Developer tier and above (it throws VBA Macro Stripper requires Developer tier. on lower tiers). One file per run — there is no batch queue. Row limits do not apply: this is a binary ZIP operation, so reported input/output rows are always 0.
| Tier | Can run this tool? | Max file size | Files per run |
|---|---|---|---|
| Free | No — blocked | 5 MB (family cap) | 1 |
| Pro | No — blocked | 50 MB (family cap) | 1 |
| Pro-media | No — blocked | 200 MB (family cap) | 1 |
| Developer | Yes | 500 MB | 1 |
| Enterprise | Yes | 2 GB (streaming) | 1 |
Input formats — what actually unzips
The tool registers xlsx as its accepted format, so the file picker offers .xlsx, .xls, .ods. Under the hood it requires a valid OOXML ZIP. Pick the matching row before you upload — a file that is not a ZIP cannot be processed.
| File you have | ZIP-based? | Result |
|---|---|---|
.xlsm (macro-enabled workbook) | Yes | Primary use case. vbaProject.bin and xl/macrosheets/ are removed; you get a clean .xlsx. |
.xlsx that secretly carries a VBA project | Yes | Rare but real — a workbook renamed to .xlsx can still contain vbaProject.bin. The stripper finds and removes it. |
.xlam (macro-enabled add-in) | Yes | Same OOXML+VBA layout, so the macro binary is removed. Output is repacked as .xlsx. |
.xltm (macro-enabled template) | Yes | Unzips and strips like .xlsm. The template's cell content survives; its VBA does not. |
.xls (legacy BIFF8 binary) | No | Not a ZIP — JSZip.loadAsync throws. Re-save as .xlsm/.xlsx in Excel first, then strip. |
.ods (OpenDocument) | Yes (ZIP) | Unzips, but ODF stores macros under Basic/, not vbaProject.bin — nothing matches, so no macros are removed. |
Cookbook
Real triage flows for the kinds of macro-enabled attachments that land in an inbox. Sender names and data are anonymised; the tool behaviour is exact.
Classic phishing .xlsm with an auto-open macro
An 'invoice' attachment from an unknown sender with a Workbook_Open routine. Strip it before opening to read what it really contains.
Saved (not opened): Invoice_2026_06.xlsm Result panel: 1 macro file(s) removed. findings.macroFiles = ["xl/vbaProject.bin"] Open Invoice_2026_06-no-macros.xlsx: -> no Enable Content banner; safe to read
Attachment using an Excel 4.0 (XLM) macro instead of VBA
Some campaigns avoid VBA entirely and hide in XLM macro sheets to dodge scanners. The stripper removes those too.
Saved: Statement.xlsm xl/macrosheets/sheet1.xml <- XLM auto-open (no xl/vbaProject.bin) Result panel: 1 macro file(s) removed. findings.macroFiles = ["xl/macrosheets/sheet1.xml"]
Encrypted attachment with the password in the email body
Attackers password-protect the file so gateways cannot scan it. JSZip cannot read an encrypted package — decrypt first.
Saved: secure_doc.xlsm (opens only with password 'invoice') Upload result: Error: file could not be read as a ZIP Fix: open in Excel with the password, Save As an unencrypted .xlsm, THEN run the stripper.
Double-extension lure (.xlsx that is really macro-enabled)
The file shows as .xlsx to look harmless but still ships a VBA project. The stripper checks ZIP paths, not the name.
Saved: Receipt.xlsx (carries xl/vbaProject.bin) Result panel: 1 macro file(s) removed. Open Receipt-no-macros.xlsx safely.
Sanitise, then audit any links the macro would have used
Macros often pull payloads from external URLs referenced as links. After stripping, audit the workbook's links.
Step 1 VBA Macro Stripper: suspicious.xlsm -> suspicious-no-macros.xlsx Step 2 External Link Auditor (/excel-tools/excel-external-link-auditor): lists every external reference left in the file
Edge cases and what actually happens
Password-encrypted workbook uploaded
Fails — encryptedExcel encryption wraps the OOXML package in an OLE/CFB container, so JSZip cannot read it as a ZIP and loading fails. Decrypt in Excel (File, Info, Protect Workbook, remove the password) first, then strip the macros from the decrypted copy.
Legacy `.xls` (BIFF8 binary) uploaded
Fails — not a ZIPA true legacy .xls is a compound binary file, not a ZIP, so JSZip.loadAsync throws and no output is produced. Open it in Excel and Save As .xlsm (or .xlsx) first to convert it to the OOXML ZIP format, then run the stripper.
`.xlsx` that secretly contains a VBA project
RemovedA workbook renamed from .xlsm to .xlsx can still carry vbaProject.bin inside the ZIP — and Excel will still run it. The stripper matches by ZIP path, not extension, so it finds and removes the binary regardless of the file's name.
`xl/macrosheets/` present (Excel 4.0 / XLM macros)
RemovedXLM macros are a classic malware vector that does not live in vbaProject.bin. Because the stripper deletes anything under xl/macrosheets/, these are removed too — the findings list will name each macrosheet part it dropped.
Attachment double-clicked before saving
Risk already takenIf you opened the .xlsm in Excel and clicked Enable Content before stripping, any macro has already run — the tool cannot undo that. Strip the saved file to neutralise it for future use, but treat the machine as potentially exposed and tell IT.
File had no macros at all
ExpectedNothing matches the macro filter, so the result reports 0 macro file(s) removed and you still receive a repacked .xlsx. It is a clean no-op, not a failure — handy as a confidence check that a file is already macro-free.
`docProps/app.xml` still lists the original editing app
By designThe stripper only removes macro parts; document metadata is preserved. If the editing-app fingerprint or author also needs to go, chain the App Metadata Wiper or the Core Metadata Wiper after stripping.
Run attempted on Free, Pro, or Pro-media tier
403 tier blockedThe processor checks the tier first and throws VBA Macro Stripper requires Developer tier. before any unzip happens. Upgrade to Developer or Enterprise to run it.
Sender used a .docm/.pptm, not Excel
Wrong toolThis stripper only handles Excel OOXML packages. A macro-enabled Word .docm or PowerPoint .pptm is a different package layout — it will either fail to match or unzip into an unexpected shape. Use a Word/PowerPoint macro remover for those.
`.ods` (OpenDocument) uploaded
No macros matchedAn .ods is a ZIP and will unzip, but ODF stores Basic macros under Basic/, not vbaProject.bin. Nothing matches the filter, so 0 is reported and no macro code is actually removed.
Frequently asked questions
Should I open the attachment first to check it?
No. Save it to disk without double-clicking and strip it first. Opening an .xlsm and clicking Enable Content is exactly the action the attacker wants — the stripper deletes the macro before you ever open it in Excel.
Does the macro code ever run while it is being removed?
No. The tool opens the workbook with JSZip and treats vbaProject.bin as opaque binary to delete. It is never loaded into a VBA host or interpreted, so an auto-open or Workbook_Open payload cannot fire during processing.
Is the file uploaded anywhere?
No. Processing happens entirely in your browser tab. The bytes are read locally, unzipped in memory, repacked, and offered as a download. Nothing is sent to a server.
Does it remove Excel 4.0 (XLM) macros too?
Yes. XLM macro sheets live under xl/macrosheets/, not in vbaProject.bin, and the stripper deletes that folder. Many tools that only target VBA leave XLM behind — this one removes both.
What if the attachment is password-protected?
An encrypted workbook is an OLE/CFB container, not a plain ZIP, so JSZip cannot read it and the run fails. Open it in Excel with the password, Save As an unencrypted copy, then strip that copy.
Does stripping prove the attachment was safe?
It proves the file no longer contains executable macros, which is the most common Excel vector. It does not vet links, embedded objects, or the data itself — for links, run the External Link Auditor after stripping, and always verify the sender.
What exactly gets deleted?
Any ZIP entry whose path contains vbaproject.bin, vbadata.xml, or xl/macrosheets/ (case-insensitive), plus the vbaProject relationship in xl/_rels/workbook.xml.rels. Everything else is preserved.
Will my formulas, charts, and formatting survive?
Yes. Cell values, formulas, data validation, named ranges, conditional formatting, charts, and pivot tables are all repacked unchanged. Only the macro parts are dropped.
Does it modify my original file?
No. The original on disk is never touched. The tool produces a separate downloaded copy, so you keep the macro-enabled source until you choose to delete it.
What tier do I need?
Developer tier or higher. Free, Pro, and Pro-media accounts can see the tool but are blocked at run time with VBA Macro Stripper requires Developer tier.
Why does the output extension change to .xlsx?
The .xlsm extension is Excel's promise that the file may contain macros. Once the macro parts are gone, the honest extension is .xlsx. The tool names the result <original>-no-macros.xlsx.
Can I forward the cleaned file to colleagues?
Yes — the output is a normal .xlsx with no executable code, so recipients see no Enable Content banner. Keep the original .xlsm so your security team can analyse the sample if needed.
Privacy first
Every JAD Excel tool runs entirely in your browser using SheetJS and ExcelJS. Your spreadsheets, formulas, and data never leave your device — verified by zero outbound network requests during processing.