从VBA中的范围创建数组

时间:2016-06-07 21:40:11

标签: arrays excel vba range

我有一个看似基本的问题,但无法找到解决问题的资源。

简单地说,我只想将一系列单元格(所有一列)的内容加载到数组中。

我能够通过

来实现这一目标
DirArray = Array(Range("A1"), Range("A2"))

但出于某种原因,我不能用这种方式创建数组:

DirArray = Array(Range("A1:A2"))

我的真实范围要长得多(并且长度可能不同),所以我不想以这种方式单独枚举单元格。谁能告诉我如何将整个范围正确加载到数组中?

后面的代码:

MsgBox UBound(DirArray, 1)

MsgBox UBound(DirArray)

返回0,而前者则返回1.

7 个答案:

答案 0 :(得分:35)

只需将变量定义为变量,并使它们相等:

Dim DirArray As Variant
DirArray = Range("a1:a5").Value

不需要Array命令。

答案 1 :(得分:18)

使用Value2可带来性能优势。根据{{​​3}}

  

Range.Value2的工作方式与Range.Value相同,只是它不检查单元格格式并转换为Date或Currency。这可能就是为什么它在检索数字时比.Value更快。

所以

DirArray = [a1:a5].Value2

答案 2 :(得分:11)

如果我们这样做的话:

Dim myArr as Variant
myArr = Range("A1:A10")

新数组将具有二维。使用它并不总是那么舒服:

enter image description here

要摆脱两个维度,当将单个列放入数组时,我们可以使用内置的Excel函数“ Transpose”。有了它,数据就变成了一维:

enter image description here

如果我们连续有数据,则单个转置将无法完成任务。我们需要两次使用移调功能:

enter image description here

答案 3 :(得分:1)

此函数返回一个数组,而不管范围的大小如何。

除非范围只有1个单元格,否则范围将返回一个数组,然后它将返回单个值。此函数会将单个值转换为数组(从1开始,与范围返回的数组相同)

此答案对先前的答案进行了改进,因为无论大小如何,它将返回一个范围内的数组。其他答案也更有效,因为如果可能的话,它将返回范围生成的数组。适用于一维和多维数组

该函数通过尝试查找数组的上限来工作。如果失败,则该值必须为单个值,因此我们将创建一个数组并将该值分配给它。

db.collection.aggregate([
  {
    $set: {
      "a": {
        $function: {
          body: "function(a){a.sort((x, y)=>x-y);return a;}",
          args: [
            "$a"
          ],
          lang: "js"
        }
      },
      "b": {
        $function: {
          body: "function(b){b.sort((x, y)=>x-y);return b;}",
          args: [
            "$b"
          ],
          lang: "js"
        }
      },
      "c": {
        $function: {
          body: "function(c){c.sort((x, y)=>x-y);return c;}",
          args: [
            "$c"
          ],
          lang: "js"
        }
      }
    }
  }
])

答案 4 :(得分:0)

除了提出的解决方案外,如果您具有一维范围到一维数组,我更喜欢通过以下函数对其进行处理。原因很简单:如果我出于某种原因将范围缩小到1个元素范围,据我所知,Range()。Value不会返回变量数组,而只会返回变量,您将无法分配变量变量到变量数组(先前已声明)。

我必须将可变大小范围转换为双精度数组,并且当范围为1个像元大小时,我无法使用诸如range()。value之类的构造,因此我将继续执行以下函数。 / p>

Public Function Rng2Array(inputRange As Range) As Double()

    Dim out() As Double    
    ReDim out(inputRange.Columns.Count - 1)

    Dim cell As Range
    Dim i As Long
    For i = 0 To inputRange.Columns.Count - 1
        out(i) = inputRange(1, i + 1) 'loop over a range "row"
    Next

    Rng2Array = out  
End Function

答案 5 :(得分:0)

在@Vityata的答案中,以下是我用来在1D数组中转换行/列向量的函数:

Function convertVecToArr(ByVal rng As Range) As Variant
'convert two dimension array into a one dimension array
    
    Dim arr() As Variant, slicedArr() As Variant
    arr = rng.value   'arr = rng works too (https://bettersolutions.com/excel/cells-ranges/vba-working-with-arrays.htm)
    
    If UBound(arr, 1) > UBound(arr, 2) Then
        slicedArr = Application.WorksheetFunction.Transpose(arr)
    Else
        slicedArr = Application.WorksheetFunction.index(arr, 1, 0)  'If you set row_num or column_num to 0 (zero), Index returns the array of values for the entire column or row, respectively._
                                                                   'To use values returned as an array, enter the Index function as an array formula in a horizontal range of cells for a row,_
                                                                   'and in a vertical range of cells for a column.
                                                                   'https://usefulgyaan.wordpress.com/2013/06/12/vba-trick-of-the-week-slicing-an-array-without-loop-application-index/
    End If
convertVecToArr = slicedArr
End Function

答案 6 :(得分:0)

我再次投票支持遍历范围内的单元格。除非有人找到了解决方法,否则我尝试将范围直接分配给 Variant 的经验是它工作正常(尽管当我真的只需要 1D 时返回一个二维数组)除非如果我的范围有多个区域,例如,当我只想要过滤表的列中的可见单元格时,或者如果我在工作表上按 ctrl 选择不同的单元格块。

使用 for..each 循环遍历范围内的所有单元格总是会产生我期望的结果。

Public Function RangeToArray(ByRef myRange As Range)
    Dim i As Long
    Dim individualCell As Range
    
    ReDim myArray(myRange.Count - 1)

    For Each individualCell In myRange
        myArray(i) = individualCell.Text         ' or maybe .Value
        i = i + 1
    Next
    RangeToArray = myArray
    
End Function

我想将此作为评论添加到 Paolo 的答案中,因为它非常相似,但我是新手并且没有足够的声誉,所以这是另一个稍微不同的答案。