动态调整数组大小而不在VBA中重新调整它?

时间:2012-11-28 13:42:53

标签: excel vba

我目前正在开发一个与Microsoft Excel连接的报表包。我使用的语言主要是Java,Perl和Python。我认为自己是一名新手程序员。我选择使用VBA的唯一原因是因为它被建议作为编写Microsoft Office扩展时使用的最佳语言。

考虑到这些事情,我绝对讨厌数组在VBA中执行的方式。具体而言,必须定义数组的大小,而不是允许它动态增长。

如何创建动态数组而不必重新创建它们?我试图避免这种情况,因为它显然是资源密集型的。

我找到的唯一解决方案是如果你使用单个循环,你可以设置元素的数量等于循环的上限(假设计数1次迭代)。

当我不使用单循环时,我该怎么办?这不是一个选项?

重整是不可避免的吗?

2 个答案:

答案 0 :(得分:4)

这不是"数组"但是VBA确实有一个Dictionary对象(这个link也很有用)可能适合您的需求。您需要添加对Microsoft Scripting Runtime的引用,但是您可以创建一个无类型的键控字典(实际上Item属性是Variant),它可以动态增长。链接有更完整的示例,但用法基本上是:

Set dict = New Dictionary

'Example for adding item to Dictionary
For i = 1 to 100
    dict.Add Key:=i, Item:=someData
Next

'Example for retrieving item from dictionary by Key
For i = 1 to 100
    Debug.Print dict(i)
Next

还有一个Collection对象,它提供了类似的功能和相似的用法,但不需要添加对Microsoft Scripting Runtime的引用,但Dictionary提供了一些更有用的方法,如dict.Exists()检查是否存在特定密钥。 .Keys中还有.ItemsDictionary个属性,允许您将所有项目或键提取为Variant类型的数组

即使你明确声明你不想重新调整数组,在创建之后调整数组大小的唯一其他选择是使用redim语句中的Preserve修饰符。这将允许您在创建后更改阵列大小的灵活性。我说的原因"一些灵活性"你是否只能改变数组的最后一个维度。

Dim myarray(2, 2)
Redim Preserve myarray(2, 4) 'this works
Redim Preserve myarray(3, 4) 'this is not allowed

正如您所提到的,这是资源密集型的,因为您实际上并未更改数组的大小,实际上您只是创建一个新数组并将旧数组的内容复制到其中。

您拥有的最后一个选项是从VBA切换到.NET。假设您有适当的version of Visual Studio,您可以访问VSTO而不是Office附带的VBA编辑器,然后您就可以开发CLR- Excel和其他Office产品的兼容加载项。然后,您可以访问所有.NET集合。同样,这些不是"数组"因为.NET数组具有相同的限制(它们无法调整大小),但是您可以根据需要动态调整大小的集合。

答案 1 :(得分:1)

这是一个相当古老的问题,但我想在已经给出的答案中添加一些背景信息。

VBA不直接为动态数组提供类型,并且需要重新调整才能更改大小。这似乎是低效的,因为它可能需要将数组的内容复制到内存中的新位置。然而,这正是动态阵列在引擎盖下所做的事情:它们通常在装满时加倍尺寸,当尺寸减小到四分之一时缩小到一半尺寸。这保证了添加和删除O(1)项的平均运行时间。

因此,如果您希望在VBA中使用数组,因为索引查找速度很快,并且您还需要动态大小,则可以简单地模拟此行为。

编辑: 一个小小的修正。添加或删除数组末尾的平均性能为O(1)。在随机位置添加对于数组总是O(N)。 (你必须改变一切。) 如果你想在随机位置添加,你应该更好地使用链表,它具有糟糕的索引查找性能(枚举具有良好的性能),跳过列表,这更复杂,但具有良好的查找性能,牺牲了插入性能,或者哈希集,其密钥查找速度非常快但具有更大的空间要求。