我修改了找到的VBA代码 checking if value present in array代码如下。用户将选择一个字段名称,我希望代码找到列出该字段的列,并创建该列中所有项目的数组,但我希望每个非空值在数组中只显示一次。我不想要任何重复。
例如,如果列具有值A,B,A,C,D,我希望代码将数组返回为A,B,C,D。
我得到运行时错误13 - 在代码的这一行输入不匹配:
If cell.Value <> "" And IsError(WorksheetFunction.Match(cell.Value, MyArray, 0)) Then
我很困惑,因为看起来我的所有数据类型都是正确的。任何人都可以提供任何帮助吗?
Sub ChangeBlock()
Dim MyArray() As String
Dim cell As Range
Dim ColNum As Integer
Dim i As Integer
If Not Intersect(ActiveCell, Range("Block1")) Is Nothing Then
If ActiveCell.Value = "" Then Exit Sub
ColNum = WorksheetFunction.Match(ActiveCell.Value, Sheets("Budget Table").Range("A1:AG1"), 0)
For Each cell In Sheets("Budget Table").Columns(ColNum)
If cell.Value <> "" And IsError(WorksheetFunction.Match(cell.Value, MyArray, 0)) Then
ReDim Preserve MyArray(i)
MyArray(i) = cell.Value
i = i + 1
End If
Next
End If
MsgBox (MyArray)
End Sub
答案 0 :(得分:2)
要使用IsError
,请使用Application.Match
代替WorksheetFunction.Match
。
尽管这两种方法相似,但它们处理错误的方式略有不同。前者返回一个错误变体,您可以使用IsError
进行测试,而后者只是throws
一个错误,您只能通过错误处理机制来捕获。
最后,如果您的数据很大,这不是检查重复数据的最佳方式;你应该考虑使用Dictionary
。
答案 1 :(得分:1)
错误13类型不匹配是由此引起的:
cell.Value <> ""
这里的Value
是二维数组(如1到1048576,1到1),并且无法将此数组与字符串进行比较,因此类型不匹配。
编辑:
实际上,变量cell
是一列,因此为了正确比较,有必要说明比较哪个数组元素,例如对于第一个元素:
cell.Value()(1, 1) = ""
更正确的是将变量cell
重命名为例如oneColumn
因为变量cell
实际上包含对列的引用,例如像这样:
Dim myColumns As Range
Set myColumns = Sheets("Budget Table").Columns(ColNum)
Dim oneColumn As Range
For Each oneColumn In myColumns
' ...
Next oneColumn
注意:此处for-each
没有意义,因为myColumns
仅引用一列而myColumns.Columns.Count
返回1
。所以你想要的只是myColumns.Cells
,它返回列的所有单元格。
oneColumn
的值是2D数组,说实话,我不知道为什么它是2D而不仅仅是1D。当您检查例如Value
时Range("A1:C3")
然后你看到它返回2D数组,这是可以理解的。但是为什么一列的列也会返回2D?对我来说似乎也很奇怪:)。 1D阵列的示例是Dim oneDArray: oneDArray = Array("A", "B", "C")
。据我所知,1D-array永远不会从Range.Value
属性返回。 Here有趣的文章介绍了VBA中的数组维度。
但这不是必需的,因为每个Range
都有一个属性Cells
。所以这里应该使用Columns(ColNum).Cells
。
完整的代码看起来像下面这样但有点太复杂了。首先,数组有很多空元素,因为使用了整个列,然后考虑使用像@ A.S.H这样的字典提出的解决方案。 HTH
Dim MyArray() As String
Dim cell As Range
Dim ColNum As Integer
Dim i As Integer
ReDim MyArray(0 To 0)
With Sheets("Budget Table")
If Intersect(ActiveCell, .Range("Block1")) Is Nothing Then _
Exit Sub
If ActiveCell.Value = "" Then _
Exit Sub
ColNum = Application.Match(ActiveCell.Value, .Range("A1:AG1"), 0)
For Each cell In .Columns(ColNum).Cells
If cell.Value = "" Then _
GoTo continue
If IsError(Application.Match(cell.Value, MyArray, 0)) Then
If i > 0 Then
ReDim Preserve MyArray(i)
End If
MyArray(i) = cell.Value
i = i + 1
End If
continue:
Next cell
End With