'For next' 循环在到达 'ubound' 之前重置计数器,导致无限循环...可能 name/reference 冲突?
'For next' loop resets counter before reaching 'ubound' resulting in infinite loop... possible name/reference clash?
我正在开发一个多千行程序,该程序 gathers/generates 一堆数据文件,所有格式都非常不同,然后收集(表格化)数据的一个子集并进行一些分析。
该程序几周前运行良好。现在,尽管没有触及它,但两次连续的测试运行和两次逐步调试会话已经进入无限期 for i = lbound(...) to ubound(...) .... next i loops。相关代码转载,如下。
显示的函数只是循环遍历二维数组(通过将范围分配给变体创建)以获取类似于一维数组中的字符串。导致错误的范围是 238x33。但是,"row" 索引 "i" 达到 44,然后重置回 0,而不是增加到 45 或更高。此外,当发生这种情况时,被 LIKE 反对的字符串会从“* example*”变为“** example**”,每次 "i" 计数器重置为 0 时,每边的星号数量都会增加。
我最好的猜测是存在某种 name/reference 冲突。但是,为什么现在才出现,而且还在猜测,我有点想不通。
函数定义:
Function arrayFirstLike(ByRef dataArr As Variant, ByVal fieldArr As Variant, _
Optional ByVal byRows As Boolean = True, Optional ByVal exactSearch As Boolean = False) As Variant
呼叫线路:
Set infowb = addSaveTemplate(rootPath & templatesPath & "\yFcstIndexInfo", rootPath & countryInfoPath & "\matureMarketFcst")
Set datawb = Workbooks.Open(rootPath & countryPath & "\spdjFcst", updateLinks:=False, ReadOnly:=True)
dataArr = datawb.Worksheets("ESTIMATES&PEs").UsedRange.Value
Call closeNoAlerts(datawb)
fieldArr = Array("Data as of the close of", "S&P 500 5YR")
fieldArr2 = arrayFirstLike(dataArr, fieldArr) 'returns 2x3 zero base array of variants
函数体(请注意,这是一个在程序其他地方成功调用的实用函数:因此,在嵌套循环开始之前,函数参数被重组):
Dim i As Long, j As Long, k As Long, fieldsFound As Long
Dim tempArr() As Variant
If Not IsArray(fieldArr) Then 'fieldArr is a single string
fieldArr = Array(fieldArr)
Else
On Error GoTo skipRedim
i = LBound(fieldArr, 2)
On Error GoTo 0
ReDim tempArr(LBound(fieldArr, 1) To UBound(fieldArr, 1)) As Variant
For i = LBound(tempArr, 1) To UBound(tempArr, 1)
tempArr(i) = fieldArr(i, LBound(fieldArr, 2))
Next i
fieldArr = tempArr
afterRedim:
End If
If Not exactSearch Then
For i = LBound(fieldArr, 1) To UBound(fieldArr, 1)
fieldArr(i) = "*" & fieldArr(i) & "*"
Next i
End If
ReDim tempArr(LBound(fieldArr, 1) To UBound(fieldArr, 1), 0 To 2) As Variant
fieldsFound = 0
If byRows Then
For i = LBound(dataArr, 1) To UBound(dataArr, 1) 'rows
For j = LBound(dataArr, 2) To UBound(dataArr, 2) 'cols
For k = LBound(fieldArr, 1) To UBound(fieldArr, 1) 'searchlist
If tempArr(k, 0) = Empty Then 'check for nonoccurance
If dataArr(i, j) Like fieldArr(k) Then 'k,1: seach string
tempArr(k, 0) = dataArr(i, j): tempArr(k, 1) = i: tempArr(k, 2) = j
fieldsFound = fieldsFound + 1
Exit For
End If
End If
Next k
If fieldsFound = UBound(fieldArr, 1) - LBound(fieldArr, 1) + 1 Then Exit For
Next j
If fieldsFound = UBound(fieldArr, 1) - LBound(fieldArr, 1) + 1 Then Exit For
Next i
Else
For j = LBound(dataArr, 2) To UBound(dataArr, 2) 'cols
For i = LBound(dataArr, 1) To UBound(dataArr, 1) 'rows
For k = LBound(fieldArr, 1) To UBound(fieldArr, 1)
If tempArr(k, 1) = Empty Then 'check first occurance
If dataArr(i, j) Like fieldArr(k) Then 'k,1: seach string
tempArr(k, 0) = dataArr(i, j): tempArr(k, 1) = i: tempArr(k, 2) = j
fieldsFound = fieldsFound + 1
Exit For
End If
End If
Next k
If fieldsFound = UBound(fieldArr, 1) - LBound(fieldArr, 1) + 1 Then Exit For
Next i
If fieldsFound = UBound(fieldArr, 1) - LBound(fieldArr, 1) + 1 Then Exit For
Next j
End If
arrayFirstLike = tempArr
Exit Function
skipRedim:
Resume afterRedim
这个怎么样:
On Error GoTo skipRedim
i = LBound(fieldArr, 2)
On Error GoTo 0
如果出现错误,您会跳到 afterRedim:
,因此永远不会执行 On Error GoTo 0
。这意味着以后的任何错误都将使用相同的错误处理程序,并且很容易导致您描述的行为。我会先尝试解决这个问题。
编辑:您可以创建一个函数来检查数组维度 - 请参阅此处答案中的示例 VBA check if array is one dimensional
我正在开发一个多千行程序,该程序 gathers/generates 一堆数据文件,所有格式都非常不同,然后收集(表格化)数据的一个子集并进行一些分析。
该程序几周前运行良好。现在,尽管没有触及它,但两次连续的测试运行和两次逐步调试会话已经进入无限期 for i = lbound(...) to ubound(...) .... next i loops。相关代码转载,如下。
显示的函数只是循环遍历二维数组(通过将范围分配给变体创建)以获取类似于一维数组中的字符串。导致错误的范围是 238x33。但是,"row" 索引 "i" 达到 44,然后重置回 0,而不是增加到 45 或更高。此外,当发生这种情况时,被 LIKE 反对的字符串会从“* example*”变为“** example**”,每次 "i" 计数器重置为 0 时,每边的星号数量都会增加。
我最好的猜测是存在某种 name/reference 冲突。但是,为什么现在才出现,而且还在猜测,我有点想不通。
函数定义:
Function arrayFirstLike(ByRef dataArr As Variant, ByVal fieldArr As Variant, _
Optional ByVal byRows As Boolean = True, Optional ByVal exactSearch As Boolean = False) As Variant
呼叫线路:
Set infowb = addSaveTemplate(rootPath & templatesPath & "\yFcstIndexInfo", rootPath & countryInfoPath & "\matureMarketFcst")
Set datawb = Workbooks.Open(rootPath & countryPath & "\spdjFcst", updateLinks:=False, ReadOnly:=True)
dataArr = datawb.Worksheets("ESTIMATES&PEs").UsedRange.Value
Call closeNoAlerts(datawb)
fieldArr = Array("Data as of the close of", "S&P 500 5YR")
fieldArr2 = arrayFirstLike(dataArr, fieldArr) 'returns 2x3 zero base array of variants
函数体(请注意,这是一个在程序其他地方成功调用的实用函数:因此,在嵌套循环开始之前,函数参数被重组):
Dim i As Long, j As Long, k As Long, fieldsFound As Long
Dim tempArr() As Variant
If Not IsArray(fieldArr) Then 'fieldArr is a single string
fieldArr = Array(fieldArr)
Else
On Error GoTo skipRedim
i = LBound(fieldArr, 2)
On Error GoTo 0
ReDim tempArr(LBound(fieldArr, 1) To UBound(fieldArr, 1)) As Variant
For i = LBound(tempArr, 1) To UBound(tempArr, 1)
tempArr(i) = fieldArr(i, LBound(fieldArr, 2))
Next i
fieldArr = tempArr
afterRedim:
End If
If Not exactSearch Then
For i = LBound(fieldArr, 1) To UBound(fieldArr, 1)
fieldArr(i) = "*" & fieldArr(i) & "*"
Next i
End If
ReDim tempArr(LBound(fieldArr, 1) To UBound(fieldArr, 1), 0 To 2) As Variant
fieldsFound = 0
If byRows Then
For i = LBound(dataArr, 1) To UBound(dataArr, 1) 'rows
For j = LBound(dataArr, 2) To UBound(dataArr, 2) 'cols
For k = LBound(fieldArr, 1) To UBound(fieldArr, 1) 'searchlist
If tempArr(k, 0) = Empty Then 'check for nonoccurance
If dataArr(i, j) Like fieldArr(k) Then 'k,1: seach string
tempArr(k, 0) = dataArr(i, j): tempArr(k, 1) = i: tempArr(k, 2) = j
fieldsFound = fieldsFound + 1
Exit For
End If
End If
Next k
If fieldsFound = UBound(fieldArr, 1) - LBound(fieldArr, 1) + 1 Then Exit For
Next j
If fieldsFound = UBound(fieldArr, 1) - LBound(fieldArr, 1) + 1 Then Exit For
Next i
Else
For j = LBound(dataArr, 2) To UBound(dataArr, 2) 'cols
For i = LBound(dataArr, 1) To UBound(dataArr, 1) 'rows
For k = LBound(fieldArr, 1) To UBound(fieldArr, 1)
If tempArr(k, 1) = Empty Then 'check first occurance
If dataArr(i, j) Like fieldArr(k) Then 'k,1: seach string
tempArr(k, 0) = dataArr(i, j): tempArr(k, 1) = i: tempArr(k, 2) = j
fieldsFound = fieldsFound + 1
Exit For
End If
End If
Next k
If fieldsFound = UBound(fieldArr, 1) - LBound(fieldArr, 1) + 1 Then Exit For
Next i
If fieldsFound = UBound(fieldArr, 1) - LBound(fieldArr, 1) + 1 Then Exit For
Next j
End If
arrayFirstLike = tempArr
Exit Function
skipRedim:
Resume afterRedim
这个怎么样:
On Error GoTo skipRedim
i = LBound(fieldArr, 2)
On Error GoTo 0
如果出现错误,您会跳到 afterRedim:
,因此永远不会执行 On Error GoTo 0
。这意味着以后的任何错误都将使用相同的错误处理程序,并且很容易导致您描述的行为。我会先尝试解决这个问题。
编辑:您可以创建一个函数来检查数组维度 - 请参阅此处答案中的示例 VBA check if array is one dimensional