Search code examples
vbaexcel

Dynamically Create Dynamic Arrays in VBA


My objective is to use an array of names to create dynamic variables in VBA, heres the code:

Sub mymacro()
    Dim names()
    names = Array("cat_code()", "dog_code()", "eagle_code()")
    For Each c In names
        Dim c As Integer
    Next c
End Sub

And of course my real name array has hundreds of animals so it would be rather boring doing Dim for each and every one of them. The error I'm getting is Compile Error: Duplicate declaration in current scope

What is the best feasible solution to my objective?


Solution

  • The compile error you are getting is caused by a duplicate declaration in the current scope.

    In other words: this means you are declaring more than one variable with the same name.

    Adding an Option Explicit statement on top of you modules requires you to declare each variable you use. It's very helpful when you receive this error because you can quickly scan your code for duplicate declaration of the highlighted line Dim <variable_name>

    This is a sample demonstrating why you are getting the error:

    Option Explicit
    
    Sub Main()
    
        Dim c As Worksheet
        For Each c In Sheets
            Dim c As Long   ' you are going to get an error in here because
                            ' a variable named: c, is already declared within the sub
                            ' you can't have two variables named: c.
            For c = 1 To ws.Range("A" & Rows.Count).End(xlUp).Row
                ' some code
            Next c
        Next
    
    End Sub
    

    There is no easy work around your problem. We would have been able to provide a better solution to your problem if you better explain what you are trying to achieve.

    There is a workaround to achieve what you want but I wouldn't recommend doing it this way if you are unsure of you are actually doing ;). The below code will create a new module in your current VBA project. While iterating over the array with the animal names it will be writing new lines to Module2 so after the execution your module two will be

    enter image description here

    In order for this code to work you have to add references to Microsoft Visual Basic for Applications Extensibility 5.3". You can do that by selectingTools>>References` in the VBE window.

    Also, this requires you to Trust Access to VBA Project Object Model. Go to Excel Settings >> Trust Centre >> Macros >> tick Trust Access To VBA Project Object Model.

    enter image description here

    Run the sample code.

    Option Explicit
    
    ' this VBA project requires
    ' 1 - references to Microsoft Visual Basic For Applications Extensibility 5.3
    '     add it via Tools > References
    '
    ' 2 - trust access to VBA project object model
    '     In spreadsheet view go to Excel(application options) >> Trust Centre >> Macro Settings
    '     tick the Trust Access to VBA project object model
    
    Sub mymacro()
        Dim names
        names = Array("cat_code", "dog_code", "eagle_code")
        Dim c As Variant
        AddAModule
        For Each c In names
            ' dynamically create arrays
            WriteToModule CStr(c)
        Next
        CloseModule
    End Sub
    
    
    Private Sub AddAModule()
        Dim VBProj As VBIDE.VBProject
        Dim VBComp As VBIDE.vbComponent
        Dim CodeMod As VBIDE.CodeModule
    
        Set VBProj = ThisWorkbook.VBProject
        Set VBComp = VBProj.VBComponents.Add(vbext_ct_StdModule)
        Set CodeMod = VBComp.CodeModule
    
        With CodeMod
            .DeleteLines 1, .CountOfLines
            .InsertLines 1, "Public Sub DynamicallyCreatedArrays()"
            .InsertLines 2, "    ' code for the sub"
        End With
    End Sub
    
    Private Sub WriteToModule(arrayName As String)
        With ActiveWorkbook.VBProject.VBComponents("Module2").CodeModule
            .InsertLines .CountOfLines + 2, "    Dim " & arrayName & " as Variant"
        End With
    End Sub
    
    Private Sub CloseModule()
        With ActiveWorkbook.VBProject.VBComponents("Module2").CodeModule
            .InsertLines .CountOfLines + 2, "End Sub"
        End With
    End Sub