VBA中With New MyTestableMacro .Run代码的功能及用法咨询
With New MyTestableMacro .Run ... End With in VBA (For RubberduckVBA Testing) Great question—this syntax is a bit of a lesser-known shortcut in VBA, and it’s especially handy when you’re working with testable code (like you are with RubberduckVBA). Let’s break down exactly what it does, why it’s useful, and how to get your implementation working.
What This Syntax Actually Does
This line is a concise way to:
- Create a new instance of the
MyTestableMacroclass - Call its
Runmethod with the provided stub parameters - Automatically clean up the instance once the
End Withis reached (since no other variable is holding a reference to it)
Without this shortcut, you’d write equivalent code like this:
Dim tempMacro As New MyTestableMacro tempMacro.Run dataServiceStub, wsServiceStub Set tempMacro = Nothing ' Explicit cleanup (VBA does this automatically, but it's clear to write)
The With New version just condenses all that into one block—perfect when you only need to call one method on the class and don’t need to keep the instance around.
Why It’s Used with RubberduckVBA
RubberduckVBA pushes for test-driven development (TDD) and dependency injection, which is exactly what your code snippet is doing:
dataServiceStubandwsServiceStubare test stubs—fake implementations of your real data/worksheet services, used to isolate the code inMyTestableMacroduring testing.- The
With Newsyntax lets you quickly spin up an instance of your testable macro, pass in the stubs, run the logic, and discard the instance—no extra variable clutter.
Troubleshooting: Why Your Implementation Failed
If you created the MyTestableMacro class and added a Run method but couldn’t get it to work, you’re likely hitting one of these common issues:
- Your class isn’t publicly accessible: By default, VBA class modules have an
Instancingproperty set toPrivate, which means you can’t useNewon them from a standard module. Fix this: open the class module, go to the Properties window (F4), setInstancingtoPublic. - The
Runmethod isn’t public: Make sure yourRunsub is declared withPublic—if it’sPrivate, external code (like your standard module) can’t call it. - Parameter type mismatch: Double-check that the parameters in your
Runmethod match the type ofdataServiceStubandwsServiceStub. If you’re using Rubberduck’s interface-based stubs (best practice for testing), yourRunmethod should accept the interface type, not the concrete stub class.
Working Example
Here’s a minimal, correct setup to match your snippet:
- Create an interface (for dependency injection, optional but recommended for Rubberduck testing):
- Add a class module named
IDataService, setInstancingtoPublic, add:Public Function GetData() As String End Function - Add another class module named
IWorksheetService, setInstancingtoPublic, add:Public Sub WriteData(ByVal content As String) End Sub
- Add a class module named
- Create your stub classes:
- Add
DataServiceStubclass, implementIDataService:Implements IDataService Private Function IDataService_GetData() As String IDataService_GetData = "Test data from stub" End Function - Add
WorksheetServiceStubclass, implementIWorksheetService:Implements IWorksheetService Private Sub IWorksheetService_WriteData(ByVal content As String) Debug.Print "Stub wrote: " & content End Sub
- Add
- Create
MyTestableMacroclass:- Set
InstancingtoPublic, add:Public Sub Run(ByVal dataService As IDataService, ByVal wsService As IWorksheetService) Dim data As String data = dataService.GetData() wsService.WriteData data End Sub
- Set
- Call it from a standard module:
Sub TestMacro() Dim dataStub As New DataServiceStub Dim wsStub As New WorksheetServiceStub With New MyTestableMacro .Run dataStub, wsStub End With End Sub
Run this, and you’ll see the stub output in the Immediate Window (Ctrl+G).
Key Takeaways
With New [ClassName]is a VBA shortcut for creating a temporary class instance, using it once, and letting it be cleaned up automatically.- It’s ideal for testing scenarios (like RubberduckVBA) where you need to quickly execute logic with test stubs without keeping the instance around.
- Always ensure your class is public, your method is public, and parameter types match to avoid runtime errors.
内容的提问来源于stack exchange,提问作者Alfa Bravo

