Gustavo Louis Montaño

Absolutely and unequivocally living the dream!

Running Dynamic VBA Code

I don't want to open the Developer window

Forget opening the Developer window, creating a module and using keywords (Sub or Function). I want to execute code - and I want to do it now.

This article covers how to run VBA script dynamically. It requires two pieces of assumed knowledge: (1) Creating and interacting with User Forms; (2) Having an active and personal xla or xlam.

This article is separated into 3 parts:

  1. Enter dynamic VBA script into User Form
  2. VBA's Extensibility Reference
  3. Main script

Enter dynamic VBA script into User Form

Assume a User Form containing a TextBox property called input_enteredVBA. The dynamic VBA is entered into this property upon calling the User Form. It is then stored in the project's main code by calling Property Get.

Property Get getVBAInput() As String
    getVBAInput = input_enteredVBA.Text
End Property

VBA's Extensibility Reference

The secret sauce behind this project is creating a module in the back-end that holds all prequisite keywords and the dynamic code.

The reference Microsoft Visual Basic for Applications Extensibility 5.3 Library contains the required library and functions to do this. It is accessed through

Tools > Reference > Microsoft Visual Basic for Applications Extensibility 5.3 Library

Be sure the reference is selected for your active and personal xla or xlam.

Main script

The main script is explained in 3 steps

  1. Accept user's dynamic code
  2. Automating module creation
  3. Finalising the module's script

All of this is entered in your xla or xlam add-in, which is assumed to be active. You have the choice of running this script via a shortcut or a Ribbon (which I personally use)

Accept User's Dynamic Code

Given a User Form object called UF_runEnteredVBA, .Show it, and save the user's inputs into inputVBA.

    ' Open User Form and store the entered script
    With UF_runEnteredVBA
        .Show vbModal
        If .isCancelled Then
            Exit Sub
        Else
            Dim inputVBA As String: inputVBA = .input_enteredVBA.Text
        End If
    End With

Automating Module Creation

    ' Initialise VB Project variables
    Dim proj As VBIDE.VBProject: Set proj = ActiveWorkbook.VBProject
    Dim modComp As VBIDE.VBComponent: Set modComp = proj.VBComponents.Add(vbext_ct_StdModule)
    If IsEmpty(modComp) Or (modComp Is Nothing) Then Exit Sub
    Dim code As VBIDE.CodeModule: Set code = modComp.CodeModule

This section automates work that would ordinarily be done in the Developer window. proj is the VB Project - set to equal the ActiveWorkbook as it is assumed the user desires to activate code on their immediate Workbook. modComp is set to the Module Component object of proj. It is initialised with Add, and effectively creates a module. vbext_ct_StdModule is a constant for the standard module (among the many types).

Finally there's VBIDE.CodeModule, which is object of the modComp. This allows code to automatically be enterted into the module. Effectively code is being written write code.

Finalising the module's script

Here - the user's dynamic code is entered into the module and executed.

    With code
        Call .DeleteLines(1, .CountOfLines)
        Call .InsertLines(1, "Public Sub runEnteredMacro()" & vbNewLine & "On Error Resume Next")
        Call .InsertLines(3, inputVBA & vbNewLine & "On Error GoTo 0" & vbNewLine & "End Sub")
    End With

As a measure of safety, the module is cleared via DeleteLines. Next the usual Public Sub keyword is entered along with a dummy procedure name runEnteredMacro() (On Error Resume Next is also added to avoid any errors ruining the pace of execution).

With vbNewLine - 2 rows worth of script are consumed. Therefore, the dynamic code and keyword closures begin on line 3 in InsertLines(3,...). And that's it! We've created a module with the user's dynamic code.

All that is left is to execute the dynamic script.

    ' Run code and remove created module
    Application.Run "'" & ActiveWorkbook.Name & "'!" & modComp.Name & ".runEnteredMacro"
    Call proj.VBComponents.Remove(modComp)

Through Application.Run, the created procedure is executed and the project is cleaned by deleting the created module, otherwise additional modules will be created everytime.

Recall that all the code explained will be located in an active and personal xla or xlam.

The final solution below.

Public Sub GM_runEnteredMacro()

    ' =================================================================================
    ' Objective: Run code entered through a UserForm; This improves efficiency when
    '            wanting to instantly running code
    '==================================================================================

    ' Open Userform and collect entered VBA
    With UF_runEnteredVBA
        .Show vbModal
        If .isCancelled Then
            Exit Sub
        Else
            Dim inputVBA As String: inputVBA = .input_enteredVBA.Text
        End If
    End With

    ' Set Project; Set new module; Set code
    Dim proj As VBIDE.VBProject: Set proj = ActiveWorkbook.VBProject
    Dim modComp As VBIDE.VBComponent: Set modComp = proj.VBComponents.Add(vbext_ct_StdModule)
    If IsEmpty(modComp) Or (modComp Is Nothing) Then Exit Sub
    Dim code As VBIDE.CodeModule: Set code = modComp.CodeModule

    ' Add dyanmmic code
    With code
        Call .DeleteLines(1, .CountOfLines)
        Call .InsertLines(1, "Public Sub runEnteredMacro()" & vbNewLine & "On Error Resume Next")
        Call .InsertLines(3, inputVBA & vbNewLine & "On Error GoTo 0" & vbNewLine & "End Sub")
    End With
    
    ' Run code and remove created module
    Application.Run "'" & ActiveWorkbook.Name & "'!" & modComp.Name & ".runEnteredMacro"
    Call proj.VBComponents.Remove(modComp)
       
End Sub