vba 检查数组中是否存在值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16027095/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
checking if value present in array
提问by sashkello
I'm using a function from thisquestion, however, it doesn't seem to work in my case.
我正在使用这个问题中的一个函数,但是,在我的情况下它似乎不起作用。
Basically, this script is going through a column selecting distinct values and populating array arr
with them. First If
is checking if the column has ended, then to avoid calling empty array I have the first IfElse
, and finally I want to check a non-empty array for cell
string. If it is not present, I want to add it.
基本上,这个脚本通过一列选择不同的值并arr
用它们填充数组。首先If
是检查列是否已经结束,然后为了避免调用空数组,我有第一个IfElse
,最后我想检查一个非空数组的cell
字符串。如果它不存在,我想添加它。
Public Function IsInArray(stringToBeFound As String, arr As Variant) As Boolean
IsInArray = (UBound(Filter(arr, stringToBeFound)) > -1)
End Function
Sub SelectDistinct()
Dim arr() As String
Dim i As Integer
Dim cells As Range
Set cells = Worksheets("types").Columns("A").Cells
i = 0
For Each cell In cells
If IsEmpty(cell) Then
Exit For
ElseIf i = 0 Then
ReDim Preserve arr(i)
arr(UBound(arr)) = cell
i = i + 1
ElseIf IsInArray(cell.Value, arr) = False Then
ReDim Preserve arr(i)
arr(UBound(arr)) = cell
i = i + 1
End If
Next cell
End Sub
For some reason, it throws "Subscript out of range" error on the call of IsInArray
function. Can someone let me know where I went wrong?
出于某种原因,它在调用IsInArray
函数时抛出“下标超出范围”错误。有人可以让我知道我哪里出错了吗?
采纳答案by David Zemens
Here is how I would do it for a one-dimensional array, using the Application.Match
function, instead of another UDF.
这是我将如何使用该Application.Match
函数而不是另一个 UDF对一维数组执行此操作。
I have consolidated some of your If/ElseIf logic with a Do...While
loop, and then use the Match
function to check whether cell value exists in the array. If it does not exist, then add it to the array and continue to the next cell in your range.
我已经用Do...While
循环合并了您的一些 If/ElseIf 逻辑,然后使用该Match
函数检查数组中是否存在单元格值。如果它不存在,则将其添加到数组中并继续到您范围内的下一个单元格。
Sub SelectDistinct()
Dim arr() As String
Dim i As Integer
Dim cells As Range
Dim cl As Range
Dim foundCl As Boolean
Set cells = Worksheets("Sheet6").Columns(1).cells
Set cl = cells.cells(1)
Do
If IsError(Application.Match(cl.Value, arr, False)) Then
ReDim Preserve arr(i)
arr(i) = cl
i = i + 1
Else:
'Comment out the next line to completely ignore duplicates'
MsgBox cl.Value & " already exists!"
End If
Set cl = cl.Offset(1, 0)
Loop While Not IsEmpty(cl.Value)
End Sub
回答by Beallio
Short answer to your "Subscript out of range" error on the call of IsInArray
function" question is that the variable arr
is dimmed as Variant
. For the Filter
function to work in the IsInArray
UDF arr
must be dimmed as a String
.
对“IsInArray
函数调用时下标超出范围”错误的简短回答是变量arr
变暗为Variant
。要Filter
在IsInArray
UDF 中工作的函数arr
必须变暗为String
。
You can try the following code which 1) Sets up a filtered String
array, and 2) avoids placing Redim Preserve
(which is a costly function) in a loop:
您可以尝试以下代码,其中 1) 设置过滤String
数组,以及 2) 避免将Redim Preserve
(这是一个代价高昂的函数)放入循环中:
Sub FilteredValuesInArray()
'http://stackoverflow.com/questions/16027095/checking-if-value-present-in-array
Dim rng As Range
Dim arrOriginal() As Variant, arrFilteredValues() As String
Dim arrTemp() As String
Dim strPrintMsg As String 'For debugging
Dim i As Long, lCounter As Long
Set rng = Cells(1, 1).CurrentRegion 'You can adjust this how you want
arrOriginal = rng
'Convert variant array to string array
ReDim arrTemp(LBound(arrOriginal) - 1 To UBound(arrOriginal) - 1)
For i = LBound(arrOriginal) To UBound(arrOriginal)
arrTemp(i - 1) = CStr(arrOriginal(i, 1))
Next i
'Setup filtered values array
ReDim arrFilteredValues(LBound(arrTemp) To UBound(arrTemp))
On Error Resume Next
Do
arrFilteredValues(lCounter) = arrTemp(0)
'Save non matching values to temporary array
arrTemp = Filter(arrTemp, arrTemp(0), False)
'If error all unique values found; exit loop
If Err.Number <> 0 Then Exit Do
lCounter = lCounter + 1
Loop Until lCounter >= UBound(arrFilteredValues)
On Error GoTo 0
'Resize array to proper bounds
ReDim Preserve arrFilteredValues(LBound(arrFilteredValues) To lCounter - 1)
'====DEBUG CODE
For i = LBound(arrFilteredValues) To UBound(arrFilteredValues)
strPrintMsg = strPrintMsg & arrFilteredValues(i) & vbCrLf
Next i
Debug.Print vbTab & "Filtered values are:" & vbCrLf & strPrintMsg
'====END DEBUG CODE
End Sub
回答by mak
Here's an easy yet dirty hack :
这是一个简单而肮脏的黑客:
Function InStringArray(str As String, a As Variant) As Boolean
Dim flattened_a As String
flattened_a = ""
For Each s In a
flattened_a = flattened_a & "-" & s
Next
If InStr(flattened_a, str) > 0 Then
InStringArray = True
Else
InStringArray = False
End If
End Function