在VBA中dynamic创builddynamic数组

我的目标是使用一个名称数组在VBA中创builddynamicvariables,inheritance人的代码:

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

当然,我的真名数组有数百个动物,所以对于每一个动物都会变得无聊。 我得到的错误是Compile Error: Duplicate declaration in current scope

什么是我的目标的最佳可行解决scheme?

您正在收到的编译错误是由当前作用域中的重复声明引起的。

换句话说:这意味着你声明了多个具有相同名称的variables。

在你的模块上添加一个Option Explicit语句需要你声明你使用的每个variables。 当您收到此错误时,这非常有帮助,因为您可以快速扫描代码以查找突出显示的行Dim <variable_name>重复声明

这是一个示例,说明为什么你得到错误:

 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 

你的问题没有简单的工作。 如果你能更好地解释你正在努力达到的目标,我们将能够为你的问题提供更好的解决scheme。

有一个解决方法,以实现你想要的,但我不会推荐这样做,如果你不确定你在做什么;)。 下面的代码将在您当前的VBA项目中创build一个新模块。 在使用动物名称迭代数组时,将会在Module2写入新行,以便在模块2执行后执行

在这里输入图像描述

为了使此代码正常工作,必须添加对Microsoft Visual Basic for Applications Extensibility 5.3". You can do that by selecting引用, Microsoft Visual Basic for Applications Extensibility 5.3". You can do that by selecting在VBE窗口中Microsoft Visual Basic for Applications Extensibility 5.3". You can do that by selecting Tools >> References`来实现。

此外,这需要您Trust Access to VBA Project Object Model 。 转到Excel设置>>信任中心>>macros>> tick信任访问VBA项目对象模型。

在这里输入图像描述

运行示例代码。

 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 

VBA不能真正做你想做的事情,而没有进入一个可怕的复杂世界。

如何使用VBA Collection对象? 您需要创build一个简单的类来保存这个数字,因为VBA集合使用引用而不是值。

所以我创build了一个类,并将其名称设置为“ AnimalCounter ”,其内容如下:

 Public Counter As Integer 

然后你的macros变成这样:

 Sub mymacro() Dim coll As New Collection Dim c As Variant Dim ac As AnimalCounter For Each c In Array("cat", "dog", "eagle") Set ac = New AnimalCounter coll.Add ac, c Next Debug.Print coll("cat").Counter ' what's in "cat"? coll("dog").Counter = coll("dog").Counter + 1 ' update "dog" by one Debug.Print coll("dog").Counter ' "dog" should now be one more End Sub 

如果你想要数组,把一个数组放入类。 或者另一个Collection ,也许?

麦克·伍德豪斯(Mike Woodhouse)有正确的理念,使用动物的钥匙Collection 。 我添加两个注释:

首先,我会推荐使用一个Dictionary 。 它比Collection更快,并允许显式访问KeysItems集合。 使用Collection ,实际上没有办法获取密钥,因为基本目的是一个有序的项目列表 ,而不是像Dictionary一样的不依赖于订单的散列。

要早期使用Dictionarytypes,请添加对Microsoft脚本运行时的引用。

其次, 不要为个别动物使用数组! 。 原因是因为VBA中的数组使用了按值的语义(请参阅VBA中的集合 – VBA中的概述值和引用数组赋值规则以获取更多信息)。 总之,每当你从包含的CollectionDictionary获取一个数组的实例,你将得到整个数组的一个新的副本 。 因此,对该数组的内容所做的任何更改都不会影响DictionaryCollection的实际数组。 为了解决这个问题,请使用Collection 。 这将使用通过引用的语义,并使附加新项更容易。

所以这就是你想要做的:

 Sub ReadCodes() Dim ws As Worksheet Dim strAnimalName As String Dim dctAnimalCodes As New Dictionary Dim colAnimalCodes As Collection Dim lngAnimalCode As Long Set ws = Worksheets("Animal Code Data") For iRow = 1 To ws.UsedRange.Rows.Count strAnimalName = ws.Cells(iRow, 1) lngAnimalCode = ws.Cells(iRow, 2) ' Easy to check if key exists If Not dctAnimalCodes.Exists(strAnimalName) Then Set dctAnimalCodes(strAnimalName) = New Collection End If ' Getting the collection for this animal Set colAnimalCodes = dctAnimalCodes(strAnimalName) ' Easy appending of new code colAnimalCodes.Add lngAnimalCode Next End Sub