Remove the VBA project from an Excel workbook or Word document and write a separate copy.
dotnet add package RecursiveAI.OneDocument.DocumentsRequires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.
using RecursiveAI.OneDocument.Vba; foreach (var pair in new[] { (Input: "sample.docm", Output: "clean.docx"), (Input: "sample.xlsm", Output: "clean.xlsx") }) { var report = VbaRemoval.Remove(pair.Input, pair.Output); Console.WriteLine($"Wrote {pair.Output}; notes: {report.NotDone.Count}"); foreach (var note in report.NotDone) Console.WriteLine($"{note.Code}: {note.Message}"); }
Wrote clean.docx; notes: 0 Wrote clean.xlsx; notes: 0
The source file is untouched; ActiveX controls and XLM macro sheets are kept, and XLSB keeps its binary-workbook format.
Unzip the example, then dotnet run.
sample.docm and sample.xlsm are in the zip. They are generated repository fixtures containing a VBA project with document, procedural and class modules; their provenance and license ship with the example.
The full program
The download’s Program.cs uses the supplied samples:
using RecursiveAI.OneDocument.Vba; foreach (var pair in new[] { (Input: "sample.docm", Output: "clean.docx"), (Input: "sample.xlsm", Output: "clean.xlsx") }) { var report = VbaRemoval.Remove(pair.Input, pair.Output); Console.WriteLine($"{pair.Input} -> {pair.Output}"); Console.WriteLine($"Had project: {report.HadProject}"); Console.WriteLine($"Project remains: {VbaProject.Open(pair.Output) is not null}"); }
dotnet run prints:
sample.docm -> clean.docx Had project: True Project remains: False sample.xlsm -> clean.xlsx Had project: True Project remains: False
Encrypted legacy DOC, XLS or PPT files raise OfficeUnsupportedException; the removal report lists work not done.
VBA removal has not been independently audited; the project’s own redaction and sanitizing reviews are not external audits of VBA removal.
Variations
Remove macros through the document model
using RecursiveAI.OneDocument.Documents; using var doc = Document.Open("sample.docm"); doc.RemoveVbaProject(); doc.SaveAs("clean-document.docx"); Console.WriteLine("Wrote clean-document.docx");
Output:
Wrote clean-document.docxRelated recipes
The short answer
Use VbaRemoval.Remove(source, destination) to write a new file without the VBA project. For the examples here, DOCM becomes DOCX and XLSM becomes XLSX. The source is untouched. VBA is read as data: the library never compiles, interprets or runs the project.
Removal is an explicit operation, not a side effect of changing an extension. The VBA documentation specifies which project storage, signature parts and relationships are removed for each format and what remains.
How do I remove macros from an Excel document?
For an XLSM workbook, pass the XLSM source and an XLSX destination to VbaRemoval.Remove, as in the snippet at the top. The remover deletes the VBA project and its signature parts, removes the corresponding relationships and content types, and changes the main part to the macro-free type. Other OOXML parts are copied as stored.
The full example reports HadProject and then asks VbaProject.Open whether the output still has a project. That demonstrates what happened to these sample files. For production inputs, also inspect the returned report’s NotDone items rather than equating a written file with every possible kind of active content having been removed.
XLSB and add-in formats do not have a corresponding macro-free file type. The remover keeps those formats while removing their projects and reports vba.no-macro-free-type. Legacy XLS stays XLS: removal edits the compound-file storage and the relevant workbook records rather than converting the workbook to XLSX.
How do I remove macros from Microsoft Word?
For DOCM, use a DOCX destination. The remover removes the project, project signatures and Word’s VBA data part, as well as the relationships and content types belonging to them. The variation shows the same explicit choice through a Document: open it, call RemoveVbaProject, then save it in the macro-free format.
Simply opening a macro-enabled document and saving it without an explicit removal does not strip the project. OneDocument preserves project bytes when saving unchanged and refuses a macro-free output while a project remains. That refusal protects against accidental, silent removal.
A legacy DOC stays DOC under the direct removal operation: its Macros storage is removed without doing a DOC-to-DOCX conversion. Choose conversion separately if the recipient also needs the newer format. The report records format changes and what was removed, including modules and signatures.
How do I turn macros off?
Disabling execution in an Office application and removing a project from a file are different choices. This recipe changes the file. It does not configure Word or Excel security settings, and it does not prove that the document contains no other active or risky content.
The documented removal scope deliberately keeps XLM macro sheets, ActiveX controls, code-name attributes and Ribbon action names. Encrypted OOXML is decrypted for reading and written unencrypted, with a report item; encrypted legacy DOC, XLS and PPT inputs are refused. Preserve any required encryption policy separately. Use the returned report to distinguish a removed VBA project, an input with no project, and a case the remover could not complete.