使用简单命令(无循环)从非连续范围的并集获取值到VBA数组

Flo*_*ris 6 arrays excel vba excel-vba

我有以下(表面上看,简单)任务:

使用VBA将电子表格中多个列的值复制到二维数组中.

为了让生活更有趣,列不是相邻的,但它们的长度都相同.显然,人们可以依次循环遍历每个元素,但这似乎非常不优雅.我希望有一个更紧凑的解决方案 - 但我很难找到它.

以下是我会考虑"简单方法"的一些尝试 - 为简单起见,我将范围放在A1:A5, D1:D5- 两个范围内总共10个单元格.

Private Sub testIt()
  Dim r1, r2, ra, rd, rad
  Dim valString, valUnion, valBlock
  Set r1 = Range("A1:A5")
  Set r2 = Range("D1:D5")
  valString = Range("A1:A5,D1:D5").Value
  valUnion = Union(r1, r2).Value
  valBlock = Range("A1:D5").Value
End Sub
Run Code Online (Sandbox Code Playgroud)

当我查看每个变量时,前两个具有维度,(1 To 5, 1 To 1)而最后一个具有维度(1 To 5, 1 To 4).我期待(1 To 5, 1 To 2)前两个,但事实并非如此.

如果我可以在一列中循环数据,并将一列中的所有值分配给数组中的一列,我会很高兴 - 但我也无法弄清楚如何做到这一点.就像是

cNames = Array("A", "D")
ci = 1
For Each c in columnNames
  vals( , ci) = Range(c & "1:" & c & "5").Value
  ci = ci + 1
Next c  
Run Code Online (Sandbox Code Playgroud)

但那不是正确的语法.我希望得到的结果将实现

cNames = Array("A", "D")
ci = 1
For Each c in columnNames
  For ri = 1 To 5
    vals(ri , ci) = Range(c & "1").offset(ri-1,0).Value
  Next ri
  ci = ci + 1
Next c  
Run Code Online (Sandbox Code Playgroud)

但那很难看.所以这是我的问题:

是否有可能将"复合范围"(多个非连续块)的值放入一个数组中 - 要么一次全部,要么一次一列?如果是这样,我该怎么办?

额外奖励积分 - 任何人都可以解释为什么返回的数组testIt()是尺寸的Base 1,而我的VBA设置为Option Base 0?换句话说 - 他们为什么不(0 To 4, 0 To 0)呢?这只是微软的一个不一致吗?

Tim*_*ams 13

如果每个区域rng具有相同的行数,那么这应该有效.

Function ToArray(rng) As Variant()
    Dim arr() As Variant, r As Long, nr As Long
    Dim ar As Range, c As Range, cnum As Long, rnum As Long
    Dim col As Range

    nr = rng.Areas(1).Rows.Count
    ReDim arr(1 To nr, 1 To rng.Cells.Count / nr)
    cnum = 0
    For Each ar In rng.Areas
        For Each col In ar.Columns
        cnum = cnum + 1
        rnum = 1
        For Each c In col.Cells
            arr(rnum, cnum) = c.Value
            rnum = rnum + 1 'EDIT: added missing line...
        Next c
        Next col
    Next ar

    ToArray = arr
End Function
Run Code Online (Sandbox Code Playgroud)

用法:

Dim arr
arr = ToArray(Activesheet.Range("A1:A5,D1:D5"))
Debug.Print UBound(arr,1), UBound(arr,2)
Run Code Online (Sandbox Code Playgroud)

至于为什么数组来自rng.Value1而不是从0开始,我猜它是因为它更容易映射到工作表上的实际行/列数,而不是从零开始.该Option Base x设置被忽略