Yes. In Excel VBA, one macro can run another by calling its Sub procedure by name, such as FormatReport, or by using the optional Call keyword. The procedures must be available in the relevant scope, and the calling macro must supply any required arguments.
What it means for one macro to call another
An Excel macro is usually a VBA procedure declared with Sub. When a procedure reaches the name of another procedure, VBA runs that procedure and then returns to the next statement in the caller. This lets you split a long task into smaller, reusable steps—for example, one procedure can prepare data, another can format it, and a third can save or print a report.
A direct call is different from starting a macro manually from Excel’s Macros dialog. The caller does not need to pause for you to choose the next procedure: the order is defined in code. The called procedure must be one VBA can access from the caller, and it must be in a workbook or add-in that is available when the code runs.
For ordinary procedures, the call is synchronous: VBA finishes the called procedure before continuing in the caller. If the called procedure encounters an unhandled error, execution can stop before the caller reaches its next line. Understanding that flow is useful when you are deciding where to put error handling and cleanup.
A basic example of calling another macro
In this example, PrepareReport calls FormatReport. Both procedures are in the same standard VBA module. The helper procedure is marked Private, so it is intended for use within that module.
Option Explicit
Public Sub PrepareReport()
Dim reportDate As Date
reportDate = Date
FormatReport reportDate
End Sub
Private Sub FormatReport(ByVal reportDate As Date)
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Report")
ws.Range("B1").Value = reportDate
ws.Range("B1").NumberFormat = "mmmm d, yyyy"
End Sub
To try the example, create a worksheet named Report, open the Visual Basic Editor, and put the procedures in a standard module. Run PrepareReport. It passes today’s date to the helper, which writes it to cell B1 and applies a date display format. The example also shows why declaring variables and qualifying the worksheet are helpful: the code is clearer about what it expects and which workbook it targets.
To call a procedure with no arguments, write its name on a line by itself, such as RefreshReport. You can also write Call RefreshReport, but VBA’s syntax rules differ when arguments are present. Most VBA examples omit Call because the procedure name alone is concise and avoids that distinction.
Passing information to the called procedure
A procedure can accept arguments so it can work with different sheets, ranges, or values rather than relying on hard-coded references. Put the arguments in parentheses in the procedure declaration. When calling the procedure without the Call keyword, write the argument list without parentheses, separating multiple arguments with commas.
Option Explicit
Public Sub MakeSummary()
Dim sourceSheet As Worksheet
Set sourceSheet = ThisWorkbook.Worksheets("Data")
AddTotal sourceSheet, "B2:B100"
End Sub
Public Sub AddTotal(ByVal targetSheet As Worksheet, ByVal sourceAddress As String)
targetSheet.Range("D2").Formula = "=SUM(" & sourceAddress & ")"
End Sub
Here, the caller supplies a worksheet object and a range address. The called procedure writes a SUM formula in D2 on the supplied sheet. With the example’s address, the formula placed in that cell is =SUM(B2:B100). If you instead use the optional keyword, the equivalent call syntax is Call AddTotal(sourceSheet, "B2:B100"); parentheses are required around the argument list after Call.
Use ByVal when the called procedure should receive a value to work with, and consider ByRef when you deliberately want it to be able to change the caller’s variable. VBA defaults to passing arguments by reference if you do not specify otherwise. For object arguments, such as a Worksheet, the object reference is passed; the called procedure can still change that worksheet’s contents. Passing a range or worksheet explicitly is often easier to test and reuse than making a helper depend on whichever sheet happens to be active.
Calling a Function when you need a result
Use a Function rather than a Sub when a procedure needs to return a value to its caller. A Function can be called in an expression, with its result assigned to a variable or used in another calculation. For example, this pair of procedures counts filled cells in a specified range:
Option Explicit
Public Sub ShowCount()
Dim filled As Long
filled = CountFilled(ThisWorkbook.Worksheets("Data").Range("A2:A100"))
MsgBox filled
End Sub
Private Function CountFilled(ByVal target As Range) As Long
CountFilled = Application.WorksheetFunction.CountA(target)
End Function
With the example, the number displayed depends on the contents of Data!A2:A100. The function returns its result by assigning a value to its own name. A Sub, by contrast, does not return a value in that way. This distinction matters when you want the caller to make a decision based on the helper’s result, such as continuing only when a required range contains data.
Scope, modules, and which procedures are visible
Where a procedure is declared affects whether another procedure can call it. A Public Sub in a standard module is generally available to other VBA code in the same VBA project. A Private Sub is limited to its containing module. If a helper is private, put the caller in the same module; otherwise, make the helper public when it should be called from elsewhere.
Procedures in worksheet modules, the ThisWorkbook module, and class modules have different roles from ordinary macros in standard modules. Worksheet and workbook modules commonly contain event procedures, such as a procedure that runs when a cell changes or a workbook opens. Those event procedures have required names and arguments and are normally triggered by the relevant Excel event, not treated as general-purpose macros to call directly. Put reusable work in a separate standard-module procedure, then have the event procedure call that helper.
For example, an event handler can call a public helper in a standard module after checking that the change is relevant. This keeps event-specific logic apart from the task itself and makes the task easier to call from a button or another macro. Be careful not to call an event procedure manually unless you understand its arguments and the effects; it may assume Excel supplied a valid event context.
Calling a macro in another workbook
A normal procedure call is simplest when both procedures belong to the same VBA project. To start a public macro by name at runtime, VBA also provides Application.Run. This can be useful when the macro name is stored in a variable, or when the target macro is in another open workbook. For example, a caller can run a public procedure in an open workbook by supplying a qualified macro name such as 'Sales.xlsm'!Module1.RefreshReport.
Workbook qualification is important if more than one open workbook contains a macro with the same name. The workbook name must match the open workbook, and the target macro must be accessible. A workbook that is closed is not automatically made available merely by naming its macro; code would need to open the workbook first or use another deliberate loading strategy. Renaming a workbook can also make a hard-coded workbook-qualified name stop matching.
Use a direct procedure call when the target is a known part of the same project. Use Application.Run when the runtime name or workbook selection is genuinely useful. It is less convenient for compile-time checking: a misspelled name inside a text string may only fail when that line runs. For procedures with arguments, Application.Run can also pass arguments after the macro name, but its string-based nature makes careful testing especially important.
Choosing a reliable order for a multi-step macro
A calling procedure is useful as an orchestrator: it shows the intended sequence while helpers do focused work. For instance, a report routine might validate inputs, import data, format the output, and then save the workbook. Keep each helper’s purpose clear, and pass important inputs explicitly. If a helper quietly depends on the active workbook, selected cell, or current sheet, the same call may behave differently depending on what the user did immediately before running it.
Some tasks also require restoring Excel’s application settings if an error occurs. If code turns off screen updating or changes calculation mode, the caller should ensure those settings are restored whether the work succeeds or fails. Do not add these settings automatically to every macro: they can affect the user’s Excel session, and they are unnecessary for many small tasks. If you use them, capture the original setting and restore that original value rather than assuming a particular default.
Similarly, avoid having procedures call each other in a loop without a clear stopping condition. A calls B, and B calls A can create recursive execution until VBA runs out of stack space or another limit is reached. Recursion is appropriate for some problems, but ordinary spreadsheet workflows are usually clearer as a one-way sequence or a loop with an explicit exit condition.
Common errors and how to diagnose them
If VBA reports “Sub or Function not defined,” check the spelling, the procedure’s scope, and whether it is in the expected VBA project. A private helper cannot be called from a different module. A procedure in another workbook is not made available to an ordinary direct call just because that workbook is open; qualify or otherwise reference it appropriately.
Argument errors usually mean the caller supplied the wrong number or type of arguments, or used parentheses incorrectly with the Call keyword. Compare the call with the procedure declaration, including whether it expects a worksheet, a range, or a text address. If a procedure compiles but fails at runtime, inspect assumptions about sheet names, workbook references, and ranges. A sheet named Report must actually exist in the workbook referenced by ThisWorkbook.
Use the Visual Basic Editor’s Debug menu to compile the project and step through code, and set a breakpoint by clicking beside a line or pressing F9. When execution pauses, F8 steps through one line at a time on Windows. On Mac, the Visual Basic Editor and shortcut behavior can depend on the keyboard and Excel settings; use the editor’s menus if a function-key shortcut is intercepted. A breakpoint in the caller and another in the helper can make the transfer of control easy to follow.
Running, saving, and platform considerations
In Excel for Microsoft 365 on Windows, open the VBA editor with Alt+F11 and open the macro list with Alt+F8. You can also use Developer > Visual Basic to edit code, or Developer > Macros to run an available macro. If Developer is not visible, enable it in File > Options > Customize Ribbon by selecting Developer. On Mac, Excel supports VBA, but keyboard shortcuts can vary by keyboard; use the Developer tab or Excel’s menus where available. Excel for the web cannot create, edit, or run VBA macros, so open the workbook in the desktop application.
Save a workbook containing VBA in a macro-enabled format such as .xlsm; saving it as .xlsx removes VBA code. Macro security may also prevent code from running. Only enable macros in files from sources you trust, and follow your organization’s security policy. A macro can change or delete workbook data, and its actions generally cannot be reversed with Ctrl+Z. Save a copy of the workbook before running unfamiliar or consequential code. Macros using Windows-specific features, such as certain ActiveX controls or Windows API calls, may not work on Mac even though basic VBA is supported there.
Frequently Asked Questions
Can one Excel macro run another macro?
Yes. Put the second procedure in an accessible scope and call its name from the first procedure. Add arguments in the call if the second procedure requires them.
Do I need to write Call before a macro name?
No. In standard VBA, a Sub can usually be called by writing its name and, if needed, its arguments. The optional Call keyword is allowed, but when you use it with arguments, put the arguments in parentheses.
Can a macro in one module call a macro in another module?
Yes, if the target procedure is accessible. A public procedure in a standard module can generally be called elsewhere in the same VBA project. A private procedure can only be called from within its own module.
Can a macro call a macro in a different workbook?
Yes, when the other workbook is available and the target procedure is accessible. Application.Run with a workbook-qualified macro name is one option. Confirm the workbook name and macro name, especially when more than one workbook is open.
Can I undo changes made by a macro with Ctrl+Z?
Usually not. Running VBA clears Excel’s normal undo history, and macro actions cannot generally be undone with Ctrl+Z. Save a separate copy before running code that changes important data.
Related
- AI Data Validation: How It Works and Why It Matters
- Insert a Row in an Excel PivotTable: Steps and Fixes
- Conditional Formatting Greater Than or Equal To in Excel
Try it: the Column Letter to Number: aA is 27, XFD is 16,384. Converts both ways.
More in VBA & macros
- VBA AutoFilter by Color: Filter Fill and Font ColorsYes. In Excel VBA, use the AutoFilter method with Operator:=xlFilterCellColor to filter by a cell’s fill color, or…
- Excel VBA: Create a Word Document from a TemplateTo create a Word document from an Excel VBA macro on Windows, use Word’s automation object to open…
- Google Sheets Macros: How to Create, Run, and Edit ThemYes. You can create macros in Google Sheets using its built-in recorder: in a desktop web browser, choose…
- Simple Macro Recorder and Auto Clicker: How They WorkA simple macro recorder captures a sequence of actions—such as clicks, keystrokes, and pauses—and plays them back; an…
- Excel VBA Error Handling: On Error, Err, and RecoveryIn Excel VBA, handle runtime errors with On Error GoTo HandlerLabel, inspect the failure through the Err object,…
- Excel VBA: Loop Through All Open Workbooks in a MacroTo loop through every workbook currently open in desktop Excel, use a For Each loop over Application.Workbooks. Declare…
Sources: Function behaviour and menu paths: Microsoft Support documentation for Excel. Method & sources
Spotted an error in this guide? Let us know.