【问题标题】:Excel VBA - assigning an array changes LBound and UBoundExcel VBA - 分配数组更改 LBound 和 UBound
【发布时间】:2013-10-20 21:33:41
【问题描述】:

我在 Excel 中有一些非常大的数据集,我需要对其进行解析 - 在数组中进行解析比在工作表中循环遍历数据要快。将所有数据加载到数组中会导致内存问题(数据集那么大),因此我计划将数据的子集加载到数组中,对其进行处理,然后再加载另一个子集。我希望使用定义 LBound 和 UBound 的数组“功能”来帮助我跟踪我在工作表中的位置。但我发现将工作表值分配给数组会改变界限。 下面的代码演示了这个问题...

    Sub myTest3()
    Dim myRange As Range
    Dim myArray As Variant
    Dim myOffset As Long

        myOffset = 10
        Set myRange = Worksheets("RawData").Range("A1").CurrentRegion
        ReDim myArray(myOffset To myRange.Rows.Count, myRange.Columns.Count)
        MsgBox LBound(myArray, 1) & " to " & UBound(myArray)

        Set myRange = myRange.Offset(myOffset, 0).Resize(myRange.Rows.Count - myOffset, myRange.Columns.Count)

        myArray = myRange.Value2

        MsgBox LBound(myArray, 1) & " to " & UBound(myArray)

    End Sub

第一个 MsgBox 给了我“10 到 10931”。 第二个 MsgBox 给了我“1 到 10921”。

关于保持我最初定义的数组边界的任何想法?我知道循环遍历工作表以进行分配会做到这一点,但会很慢。

提前致谢。

【问题讨论】:

  • 使用 .Value 从一个范围内分配一个数组总是会创建一个从 1 开始的数组。如果您需要不同的行为,那么您需要使用循环填充数组。
  • 让我伤心。谢谢蒂姆。我想我需要重组我的代码,以便我可以使用循环跟踪我的位置。
  • 问题是你使用ReDim 语句来重新声明下界为10 的数组,这里:ReDim myArray(myOffset to ...。你到底想用myOffset 变量做什么?我认为这就是原因。
  • 实际上,大卫,这就是我想要利用的“功能”。在 VBA 中,您可以将 LBound 设置为您想要的任何值。在我的项目中(不一定是示例代码),我希望分配数组的下限和上限以对应于数据来自的工作表中的行。这将使我能够在适当的更改后将其放回相同的位置。我认为蒂姆的评论是......当从一个范围分配一个数组时,它似乎会自动用 LBound = 1 重新调整数组。
  • @OldUgly 我认为this 可以帮助你。

标签: arrays excel vba bounds


【解决方案1】:

在这种情况下,Excel VBA 无法按您希望的方式工作。当您执行myArray = myRange.Value2 时,myArray 的原始内容已被替换。 Redimmed 数组被扔掉了。 Excel/VBA 不查看目标,而是替换它,或者更准确地说,它创建一个新数组并使myaArray 变量指向它。

因此,您将需要更多代码才能到达您想去的地方。我会考虑将用于获取下一个块的代码放入一个单独的函数中并在那里进行簿记:

Function ChunkAtOffset(rng As Range, rowsInChunk As Long, colsInChunk As Long, offsetRows As Long) As Variant
' Note: doesn't cater for the case where there are fewer than 'offsetRows' in the target    
Dim arr As Variant, result As Variant
Dim r As Long, c As Long

    arr = rng.offset(offsetRows).Resize(rowsInChunk, colsInChunk).Value2

    ReDim result(offsetRows To offsetRows + rowsInChunk - 1, 1 To colsInChunk)

    For r = 1 To rowsInChunk
        For c = 1 To colsInChunk
            result(offsetRows - 1 + r, c) = arr(r, c)
        Next
    Next

    ChunkAtOffset = result

End Function

如果我运行这个:

Sub myTest4()

    Dim curReg As Range, ary As Variant, offset As Long
    With Range("A1")
        Set curReg = .CurrentRegion
        Do
            ary = ChunkAtOffset(.CurrentRegion, 10, .CurrentRegion.Columns.Count, offset)
            Debug.Print LBound(ary, 1) & " to " & UBound(ary)
            offset = offset + 10
        Loop Until offset >= .CurrentRegion.Rows.Count
    End With

End Sub

...我现在明白了:

0 to 9
10 to 19
20 to 29

【讨论】:

  • 这看起来不错。我最终做了类似的事情。感谢大家的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多