更新:我一直在阅读一些关于在子和函数之间传递数组的网站和论坛。但它让我思考我的变量声明是否是问题?目前我的所有数组(Results1,2,3,FinalResults,X& Y)都被声明为variant。我认为这可能会导致在函数之间传递数组时出现问题。有人知道这个问题是否与我的代码有关?另外,只是为了澄清我希望Results1,2,3中的值传递给函数。
当我尝试在VBA中运行以下函数时,我一直得到'下标超出范围'。 X和Y都是一维数组,我试图将数据合并到一个新数组中。当我尝试指定数组X的下限和上限时发生错误。
Function lnArray(X() As Variant, Y() As Variant) As Variant
Dim counter1 As Long
Dim xcount As Long
Dim t As Long
Dim FinalResults() As Variant
counter1 = 0
For xcount = LBound(X) To UBound(X)
On Error Resume Next
t = Application.Match(X(xcount, 1), Y, 0)
If Err.Number = 0 Then
If (t > 0) Then
counter1 = counter1 + 1
ReDim Preserve FinalResults(counter1)
FinalResults(counter1) = X(xcount, 1)
End If
End If
On Error GoTo 0
Next xcount
lnArray = FinalResults
End Function
更新 - 这是我现在的代码,我做了一些更正。即确保通过引用将数组传递给函数并将所有内容更改为一维数组。然而,同样的问题仍然存在。我已经检查过,我的Results1()和Results2()数组都存储了值,但它没有被传递给我的UDF X()和Y()变量。我在代码中包含了传递函数的部分代码,请看一下。
Sub search()
Dim Results1() As Variant, Results2() As Variant, FinalResults() As Variant
FinalResults = lnArray(Results1, Results2)
End Sub
Function lnArray(ByRef X() As Variant, ByRef Y() As Variant) As Variant
Dim counter1 As Long
Dim xcount As Long
Dim t As Long
Dim FinalResults() As Variant
counter1 = 0
For xcount = LBound(X) To UBound(X)
On Error Resume Next
t = 0
t = Application.Match(X(xcount), Y, 0)
If Err.Number = 0 Then
If (t > 0) Then
counter1 = counter1 + 1
ReDim Preserve FinalResults(counter1)
FinalResults(counter1) = X(xcount)
End If
End If
On Error GoTo 0
Next xcount
lnArray = FinalResults
End Function
编辑 - 以下是我为Results1()和Results2()数组填充数据的方法。如果需要更多信息,请告诉我。
Sub Search()
Dim TextBox1 As Long
Dim TextBox3 As Long
Dim Results1() As Variant
Dim Results2() As Variant
Dim FindRange1 As Range
Dim Find1 As Range
Dim FindRange2 As Range
Dim Find2 As Range
Dim i1 As Long
Dim i2 As Long
TextBox1 = ILsearch.TextBox1.Value
TextBox3 = ILsearch.TextBox3.Value
Set FindRange1 = Worksheets("Properties").Range("P7:P1000")
If ILsearch.P1B1.Value = True Then
For Each Find1 In FindRange1
If (Find1.Value < TextBox1) And (Find1.Value > 0) Then
i1 = i1 + 1
ReDim Preserve Results1(i1)
Results1(i1) = Find1.Address
End If
Next Find1
End If
Set FindRange2 = Worksheets("Properties").Range("P7:P1000")
If ILsearch.P2B1.Value = True Then
For Each Find2 In FindRange2
If (Find2.Value < TextBox3) And (Find2.Value > 0) Then
i2 = i2 + 1
ReDim Preserve Results2(i2)
Results2(i2) = Find2.Address
End If
Next Find2
End If
End Sub
Edit2 - 目前我正在选择合并哪些数组并在结果中显示。我有3个搜索变量(Results1,2和3),如果只选择1,显示它很容易。但是,根据选择的变量,我还需要合并数组(1 + 2,1 + 3,2 + 3或全部3个数组)。我意识到它是多么混乱和可能效率低下但是我无法想出更好的方法。
'For a single property selection
Dim p1results As Range
Dim shProperties As Worksheet
Dim shSearchResult As Worksheet
Set shProperties = ActiveWorkbook.Worksheets("properties")
Set shSearchResult = ActiveWorkbook.Worksheets("searchresult")
If (ILsearch.ComboBox1.Enabled = True) And (ILsearch.ComboBox2.Enabled = False) And (ILsearch.ComboBox3.Enabled = False) Then
On Error Resume Next
For i1 = LBound(Results1) To UBound(Results1)
Set NextRow = shSearchResult.Cells(shSearchResult.Rows.Count, 4).End(xlUp).Offset(1, -3)
shProperties.Range(Results1(i1)).EntireRow.Copy NextRow
Next i1
End If
'repeat same if/then code for Results2 and Results3
Dim FinalResults() As Variant
Dim FinCount As Integer
Dim Counter1 As Long
Dim t As Long
If (ILsearch.ComboBox1.Enabled = True) And (ILsearch.ComboBox2.Enabled = True) And (ILsearch.ComboBox2.Enabled = False) Then
If IsArrayAllocated(Results1) = True And IsArrayAllocated(Results2) = True Then
Else
Debug.Print "Empty Array"
End If
FinalResults = lnArray(Results1, Results2)
On Error Resume Next
For FinCount = LBound(FinalResults) To UBound(FinalResults)
Set NextRow = shSearchResult.Cells(shSearchResult.Rows.Count, 4).End(xlUp).Offset(1, -3)
shProperties.Range(Results3(i3)).EntireRow.Copy NextRow
Next FinCount
End If
'repeat same if/then for (1+3) arrangement and (2+3)arrangement
Dim intResults() As Variant
If (ILsearch.ComboBox1.Enabled = True) And (ILsearch.ComboBox2.Enabled = True) And (ILsearch.ComboBox2.Enabled = True) Then
intResults = lnArray(Results1, Results2)
FinalResults = lnArray(intResults, Results3)
On Error Resume Next
For FinCount = LBound(FinalResults) To UBound(FinalResults)
Set NextRow = shSearchResult.Cells(shSearchResult.Rows.Count, 4).End(xlUp).Offset(1, -3)
shProperties.Range(Results3(i3)).EntireRow.Copy NextRow
Next FinCount
End If
答案 0 :(得分:2)
听起来X不是数组:尝试显示VBE Locals窗口以查看X确实是什么
答案 1 :(得分:2)
您的代码中有一条混合消息:
您说明,您的代码行For xcount = LBound(X) To UBound(X)
需要1维数组
但是,Application.Match(X(xcount, 1), Y, 0)
表示两个或更多维度(, 1
位)。错误支持这一点,如果X实际上是二维的,则会返回错误。
当代码运行并出现错误时,请在监视窗口中检查X以确定其真实形式
修改强>
请参阅Phydaux的评论 - LBound(X)
默认为多维数组的维度1。
<强> EDIT2 强>
两个潜在问题:
如果P1B1
或P2B1
= FALSE
,或者数据中未找到任何匹配项,则Results1
或Results2
分别从不标注尺寸。在未扩展的数组上调用LBound
或UBound
将导致错误
信不信由你,在一维数组上调用X(xcount,1)错误。但由于On Error Resume Next
处于活动状态,因此不会报告错误。
所以,你需要:
处理X或Y未标注尺寸的情况
从,1
X(xcount, 1)
我建议您查看Chip Pearson数组处理代码的优秀网站
答案 2 :(得分:1)
使用on error resume next
进行编程可能很难调试。
这段代码只适用于一次错误发生。
For xcount = LBound(X) To UBound(X)
On Error Resume Next
t = 0
t = Application.Match(X(xcount), Y, 0)
If Err.Number = 0 Then
If (t > 0) Then
当第一个错误发生时,If Err.Number = 0
将因所有剩余的迭代而失败。
为避免这种情况,您应该使用Err.clear
For xcount = LBound(X) To UBound(X)
On Error Resume Next
t = 0
t = Application.Match(X(xcount), Y, 0)
If Err.Number <> 0 Then
Err.clear 'ignore match error
Else
If (t > 0) Then
最后,您可以通过在Err.Clear
之前添加日志记录来扩展此方法,例如:
debug.print Err.number,Err.message....
答案 3 :(得分:0)
要检查match
是否有效,您最好使用:
t = Application.Match(X(xcount, 1), Y, 0)
If IsEmpty(t) Then
counter1 = counter1 + 1
End If
取决于您是否还需要测试您的t&gt; 0
答案 4 :(得分:0)
编辑:问题似乎是在未分配数组时可以调用该函数。如果没有匹配或ILsearch.P1B1.Value = False
或ILsearch.P2B1.Value = False
,则可能会发生这种情况。
我添加了一个检查if the arrays are allocated
的函数Sub Search()
Dim TextBox1 As Long
Dim TextBox3 As Long
Dim Results1() As Variant
Dim Results2() As Variant
Dim FindRange1 As Range
Dim Find1 As Range
Dim FindRange2 As Range
Dim Find2 As Range
Dim i1 As Long
Dim i2 As Long
TextBox1 = ILsearch.TextBox1.Value
TextBox3 = ILsearch.TextBox3.Value
Set FindRange1 = Worksheets("Properties").Range("P7:P1000")
If ILsearch.P1B1.Value = True Then
For Each Find1 In FindRange1
If (Find1.Value < TextBox1) And (Find1.Value > 0) Then
i1 = i1 + 1
ReDim Preserve Results1(i1)
Results1(i1) = Find1.Address
End If
Next Find1
End If
Set FindRange2 = Worksheets("Properties").Range("P7:P1000")
If ILsearch.P2B1.Value = True Then
For Each Find2 In FindRange2
If (Find2.Value < TextBox3) And (Find2.Value > 0) Then
i2 = i2 + 1
ReDim Preserve Results2(i2)
Results2(i2) = Find2.Address
End If
Next Find2
End If
If IsArrayAllocated(Results1) = True And _
IsArrayAllocated(Results2) = True Then
Z = lnArray(Results1, Results2)
Else
Debug.Print "Empty Array"
End If
End Sub
Function lnArray(X() As Variant, Y() As Variant) As Variant
Dim counter1 As Long
Dim xcount As Long
Dim t As Long
Dim FinalResults() As Variant
counter1 = 0
For xcount = LBound(X) To UBound(X)
On Error Resume Next
t = 0
t = Application.Match(X(xcount), Y, 0)
If (t > 0) Then
counter1 = counter1 + 1
ReDim Preserve FinalResults(counter1)
FinalResults(counter1) = X(xcount)
End If
On Error GoTo 0
Next xcount
lnArray = FinalResults
End Function
Function IsArrayAllocated(Arr As Variant) As Boolean
'**Determines whether an array is allocated to avoid UBound errors
On Error Resume Next
IsArrayAllocated = IsArray(Arr) And _
Not IsError(LBound(Arr, 1)) And _
LBound(Arr, 1) <= UBound(Arr, 1)
On Error GoTo 0
End Function