【问题标题】:Redim variable number of dimensions in VBARedim VBA中的可变维数
【发布时间】:2015-09-25 21:53:30
【问题描述】:

我在 Excel 宏 (VBA) 中有一个案例,我想对一个数组进行标注,其中维数和每个维的边界是在运行时确定的。我让用户通过为每个选项类型创建一列并填写下面的可能性来指定一系列组合选项。列数和选项数在运行时通过检查工作表来确定。

一些代码需要遍历每个组合(从每一列中选择一个),我想将结果存储在一个多维数组中。

维度的数量可能在 2 到 6 之间,所以如果必须的话,我总是可以退回到一堆 if else 块,但感觉应该有更好的方法。

我在想如果我可以在运行时将Redim 语句构造为字符串并执行该字符串就可以做到,但这似乎是不可能的。

有没有办法动态地Redim 使用不同数量的维度?

【问题讨论】:

  • 您是否需要多达六个维度,或者您只需要一个具有 1 到 6 的第二个等级的二维数组?即 redim myArr(1 to 99, 1 to 6) 或 redim myArr(1 to 9, 1 to 9, 1 to 9, 1 to 9, 1 to 9, 1 to 9)
  • "在运行时将 Redim 语句构造为字符串并执行该字符串" : 这种委托类型的执行在 VBA 中是不可能的。 “变维数”:所以你想把单个D数组改成多D然后来回改还是继续改多D?

标签: arrays vba excel multidimensional-array


【解决方案1】:

我很确定没有办法在单个 ReDim 语句中执行此操作。 Select Case 可能比“一堆If...Else 块”稍微整洁,但你仍然写出很多单独的ReDims。

使用 VBA 中的数组,您事先不知道它们将有多少维,这有点像 PITA - 以及 ReDim 不是很灵活,也没有测试数组的简洁方法查看它有多少维度(您必须循环尝试访问更高维度并捕获错误,或者在底层内存结构中四处乱窜 - see this question)。因此,您需要跟踪维数,并在每次需要访问数组时编写长 Case 语句,因为语法会有所不同。

我建议创建具有您认为需要的最大维数的数组,然后将任何未使用维中的元素数设置为 1 - 这样您每次访问数组时始终使用相同的语法,如果需要,可以使用UBound() 进行检查。这是 Excel 开发人员自己为 Range.Value 属性采用的方法 - 即使对于一维 Range,它也始终返回二维数组。

【讨论】:

  • 我认为您正确理解了这个问题。我发现实际上可以用变体数组的变体数组做一些事情,但它比使用 case 语句更可怕。问题之一(我一开始真的应该意识到)是,如果很难对具有可变维度的数组进行标注,那么即使您知道索引是什么,也很难对其进行索引。我将使用此处建议的方法,并使用固定的最大维度数,因为这将是最干净的解决方案。
【解决方案2】:

据我了解,您的用户可以通过填写 excel 表来指定尺寸和尺寸。这意味着您必须获取包含值的最后一行和最后一列。

因此,看看:Excel VBA- Finding the last column with data

使用Redim 更改数组的大小。如果您想保留某种条目,请使用Redim Preserve

【讨论】:

    【解决方案3】:

    "有些代码需要遍历每个组合(从 每列),我想将结果存储在多维中 数组。”

    首先,我会将所需的 Range 对象转置为 Variant。

    Dim vArray as Variant
    '--as per your defined Sheet, range
    'this creates a two dimensional array
    vArray = ActiveWorkbook.Sheets("Sheet1").Range("A1:Z300").Value2
    

    然后您可以遍历此数组以找到您需要的大小和数据,您可以将其保存到您需要的数组(带有维度)中。


    小背景:

    Redim:为数组变量重新分配存储空间。

    如果您最初使用 Dim 语句定义数组,则不允许 Redim 数组。 (例如Dim vArray(1 to 6) As Variant)。

    UPDATE:明确显示 Redim 允许和不允许的内容。

    每次您使用 Redim 时,它重置您的原始 Array 对象到您接下来定义的维度。

    有一种方法可以使用 Redim Preserve 来保存您的数据,但它只允许您更改多维数组的最后一维,其中第一维保持原始。

    【讨论】:

    • “您可以将它保存到您需要的数组(具有尺寸)中” - 我认为这是 OP 询问如何做的位。
    • @aucuparia 当 OP 遍历(转置范围)数组时,他有机会为行和列设置一个 计数器。所以他有机会找出声明他想要的数组的维度。或者他可以简单地继续创建新数组并将它们复制到另一个数组,直到完成。我也对他对这个维度的需求持怀疑态度:无论是带有等级的 2D 还是完全多 D。请原谅我的懒惰。
    • "如果您最初使用 Dim 语句定义数组,则不允许 Redim 数组" 这不准确 - 除非您最初 Dim 没有维度.
    • @Rory you can't Redim unless you initially Dim without dimensions 如果我没记错的话,你可以提供你不指定类型。这个Redim x(1 To 3) 将在没有Dim x 的情况下工作。
    • @L42 是的,我应该更明确一点——我的意思是你可以先使用 Dim 语句,但不能包含维度。您确实可以在完全不使用 Dim 的情况下 Redim 变体 - 尽管我认为这是不好的做法。
    猜你喜欢
    • 1970-01-01
    • 2021-05-07
    • 1970-01-01
    • 1970-01-01
    • 2014-09-25
    • 1970-01-01
    • 1970-01-01
    • 2012-09-04
    • 2015-05-06
    相关资源
    最近更新 更多