Excel 具有1个条目的数组循环
我的数组来自一个可以有可变条目数的范围Excel 具有1个条目的数组循环,excel,vba,Excel,Vba,我的数组来自一个可以有可变条目数的范围 Dim myArray as Variant, elem as Variant myArray = hSheet.Range("A1:A" & hSheet.Cells(Rows.Count, 1).End(xlUp).Row) 我使用这个数组来循环它的值并做一些事情 For Each elem In myArray Magic Next elem 当我的数组有超过1个值(范围有超过1个条目)时,这种方法非常有效
Dim myArray as Variant, elem as Variant
myArray = hSheet.Range("A1:A" & hSheet.Cells(Rows.Count, 1).End(xlUp).Row)
我使用这个数组来循环它的值并做一些事情
For Each elem In myArray
Magic
Next elem
当我的数组有超过1个值(范围有超过1个条目)时,这种方法非常有效。但是,当只有1个值/条目时,会出现“类型不匹配”错误
我需要这是灵活的,与多个值的工作,但也只有1个值。
如果您在数组旁边还有其他建议,我洗耳恭听。因为您
将myArray设置为变量
变量myArray
也可以是一个简单的值(而不是数组)。所以如果只有像这样的细胞
myArray = Range("A1")
然后它不是数组而是一个值,因此没有可循环的元素
如果使用toDebug.Print VarType(myArray)
将看到:
- 在
之后返回egmyArray=Range(“A1”)
(VarType=8
)或vbString
(5
),这意味着它是一个值vbDouble
- 在
之后返回egmyArray=Range(“A1:A5”)
=VarType=8204
(8192+12
+vbArray
)vbVariant
If VarType(myArray) >= 8192 Then 'is array
Debug.Print Join(myArray, ";") 'print whole array
Else
Debug.Print myArray 'print single value
End If
第二种解决方案 请注意,使用
Dim myArray()作为变量
可以强制变量始终为数组。但是,然后输入一个简单的值(单个单元格)myArray=Range(“A1”)
将失败,并出现类型不匹配错误
因此,您需要以不同的方式填充变量myArray
:
Dim myArray() as Variant 'forced to be an array!
Dim MyRange As Range
Set MyRange = hSheet.Range("A1:A" & hSheet.Cells(Rows.Count, 1).End(xlUp).Row)
If MyRange.Cells.Count > 1 Then 'is array
myArray = MyRange.Value
Else
'create an array with only one item
ReDim myArray(1 To 1, 1 To 1) As Variant
myArray(1, 1) = MyRange.Value
End If
'now you can always loop even if only one cell was in the range
For Each elem In myArray
Magic
Next elem
在操作代码中,当范围计算为单个单元格时,嵌套循环失败。以这种方式,Excel按照其规范执行。这并不能阻止错误变得令人讨厌 在我之前的评论中,我观察到Excel的行为不是正交的,因为如果一个范围计算为一行或一列,那么实际上会得到一个二维数组,即其中一个维度的范围为1到1 下面的代码试图通过允许范围返回2D数组(即使范围的计算结果为单个单元格)来协调上述观察结果。此外,可选参数允许返回表示范围真实大小的值、单个单元格返回单个值、单个行或列返回一维数组等 应该注意的是,当可选变量为False,并且返回一维数组时,将丢失原始范围的方向 在下面的测试中,即使范围指定了单个单元格,嵌套循环也会正确运行
Public Sub ttest()
Dim myVar As Variant
myVar = GetRange(ThisWorkbook.Sheets.Item(1).Range("A1:A1"))
Dim myRow As Long
For myRow = LBound(myVar, 1) To UBound(myVar, 1)
Dim myCOl As Long
For myCOl = LBound(myVar, 2) To UBound(myVar, 2)
Debug.Print "Row "; myRow, "Col "; myCOl, " is ", myVar(myRow, myCOl)
Next
Next
End Sub
Public Function GetRange(ByVal ipRange As Excel.Range, Optional ByVal RangeAsTable As Boolean = True) As Variant
If RangeAsTable Then
GetRange = GetRangeAsTable(ipRange)
Else
GetRange = GetRangeAsSized(ipRange)
End If
End Function
Private Function GetRangeAsTable(ByVal ipRange As Excel.Range) As Variant
Dim myArray As Variant
If ipRange Is Nothing Then
ReDim myArray(1 To 1, 1 To 1)
GetRangeAsTable = myArray
Exit Function
End If
Dim xlArray As Variant
xlArray = ipRange.Value
If Not IsArray(xlArray) Then
ReDim myArray(1 To 1, 1 To 1)
myArray(1, 1) = xlArray
GetRangeAsTable = myArray
Exit Function
End If
GetRangeAsTable = xlArray
End Function
Private Function GetRangeAsSized(ByVal ipRange As Excel.Range) As Variant
Dim xlArray As Variant
xlArray = ipRange.Value
If Not IsArray(xlArray) Then
GetRangeAsSized = xlArray
Exit Function
End If
If UBound(xlArray, 1) = 1 Or UBound(xlArray, 2) = 1 Then
GetRangeAsSized = Application.WorksheetFunction.Transpose(xlArray)
Exit Function
End If
GetRangeAsSized = xlArray
End Function
Probably not the neatest or most efficient code but at least it demonstrates the point, and, more importantly, allows the OP to use a nested loop even if the range is a single cell.
语句
myArray=hSheet.Range(“A1:A”&hSheet.Cells(Rows.Count,1).End(xlUp.Row)
相当于(IMO-cleaner)
当numRows>1
时,它会返回一个漂亮的2d数组。结果是形状与
ReDim myArray(1 to numRows, 1 to 1)
但是当numRows=1
时,结果只是一个值。不是二维数组,也不是一维数组,而是单个值。为了处理此情况,请按如下方式修改上述代码:
Dim numRows as Long
numRows = hSheet.Cells(Rows.Count, 1).End(xlUp).Row
Dim myArray as Variant
if numRows>1 Then
myArray = hSheet.Range("A1").Resize(numRows,1).Value2
Else
ReDim myArray(1 to 1, 1 to 1)
myArray(1,1) = hSheet.Range("A1").Resize(numRows,1).Value2
End If
从这一点开始,
myArray
保证包含二维数组。在for each之前添加行“如果不是IsArray(myArray),那么myArray=array(myArray)@freeflow这将在读取二维范围时生成一维数组。因此,这可能是危险的,因为您有两种不同类型的数组@如果myArray不是数组,那么我不理解你的评论。@freeflow OP做的是myArray=Range(“A1:A5”)。Value
这会产生一个二维数组myArray(行、列)
,但你所做的会产生一个一维数组myArray(索引)
。因此,对于这两种情况,您最终得到了两种不同类型的数组。@PEH,这是一种令人困惑的行为(而且是错误的),因为A1:A5是一维数组。因此,我建议在获取范围时使用转置函数,以便最终得到一维变量数组,而不是伪二维数组。
Dim numRows as Long
numRows = hSheet.Cells(Rows.Count, 1).End(xlUp).Row
Dim myArray as Variant
if numRows>1 Then
myArray = hSheet.Range("A1").Resize(numRows,1).Value2
Else
ReDim myArray(1 to 1, 1 to 1)
myArray(1,1) = hSheet.Range("A1").Resize(numRows,1).Value2
End If