Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel 具有1个条目的数组循环_Excel_Vba - Fatal编程技术网

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")
然后它不是数组而是一个值,因此没有可循环的元素

如果使用to
Debug.Print VarType(myArray)
将看到:

  • myArray=Range(“A1”)
    之后返回eg
    VarType=8
    vbString
    )或
    5
    vbDouble
    ),这意味着它是一个值
  • myArray=Range(“A1:A5”)
    之后返回eg
    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