[英]Why do I get the "type mismatch" error when running the macro?
It's my first time doing VBA Macro and I'm having a hard time understanding the problem.这是我第一次做 VBA 宏,我很难理解这个问题。
I'm trying to filter and color cells with specific values but when I try running the code it says 'Type mismatch'.我正在尝试使用特定值过滤和着色单元格,但是当我尝试运行代码时,它显示“类型不匹配”。
Dim count, i As Long
Dim ws As Worksheet
Dim count, i As Long
Dim ws As Worksheet
Set ws = Sheets("Sheet1")
count = ws.Cells(Rows.count, "E").End(xlUp).Row
i = 2
Do While i <= count
If Cells(i, 5).Value = "#N/A" _
Or Cells(i, 5).Value = "#Ref" _
Or Cells(i, 5).Value = "Null" _
Or Cells(i, 5).Value = "" _
Or Cells(i, 5).Value = "#DIV/0!" _
Or Cells(i, 5).Value = "" _
Or Cells(i, 5).Value Like "*-*" Then
Cells(i, 5).Interior.Color = RGB(38, 201, 218)
End If
i = i + 1
Loop
ws.Range("E1").AutoFilter Field:=5, Criteria1:=RGB(38, 201, 218), Operator:=xlFilterCellColor
And when I click the debug it highlights the If statements.当我单击调试时,它会突出显示 If 语句。 Is there a way to solve this or is there a better way to filter these values while highlighting them in VBA?
有没有办法解决这个问题,或者有没有更好的方法来过滤这些值,同时在 VBA 中突出显示它们?
Not really an answer, more of a expanded comment.不是真正的答案,更多的是扩展评论。
If IsError(Cells(i, 5)) Then
Cells(i, 5).Interior.Color = RGB(0, 0, 255)
ElseIf Cells(i, 5).Value = "" Then
Cells(i, 5).Interior.Color = RGB(0, 0, 255)
Else
Cells(i, 5).Interior.Color = xlNone
End If
Also, this to sift the errors https://docs.microsoft.com/en-us/office/vba/excel/concepts/cells-and-ranges/cell-error-values此外,这是为了筛选错误https://docs.microsoft.com/en-us/office/vba/excel/concepts/cells-and-ranges/cell-error-values
First problem: If your cell contain an error, it doesn't contain the string "#N/A"
or "#Ref"
, it contains a special value.第一个问题:如果您的单元格包含错误,它不包含字符串
"#N/A"
或"#Ref"
,它包含一个特殊值。 What you see is only a visual representation of that error.您所看到的只是该错误的直观表示。 If you want to check for an error within Excel, you should use the function
IsError
.如果要检查 Excel 中的错误,应使用函数
IsError
。 That would lead to ( wait, don't use that! ):这将导致(等等,不要使用它! ):
If isError(Cells(i, 5).Value)
Or Cells(i, 5).Value = "Null" _
Or Cells(i, 5).Value = "" _
Or Cells(i, 5).Value Like "*-*" Then
Second problem: In VBA, there is no optimization for a conditional statement, VBA will always evaluate all parts.第二个问题:在 VBA 中,条件语句没有优化,VBA 将始终评估所有部分。 Your If-statement contains several conditions, combined with
Or
.您的 If 语句包含多个条件,并与
Or
结合使用。 While other programming languages quit evaluating when one condition makes the whole expression true, VBA will continue to evaluate all conditions.虽然其他编程语言在一个条件使整个表达式为真时退出评估,但 VBA 将继续评估所有条件。
Now if you have an error in a cell and you would use the code above, you will still get a type mismatch error: You cannot compare an error with a string.现在,如果您在单元格中有错误并且您将使用上面的代码,您仍然会收到类型不匹配错误:您无法将错误与字符串进行比较。 The condition
isError(Cells(i, 5).Value)
will get True, but VBA will continue to compare the cell content with strings and that gives you the mismatch.条件
isError(Cells(i, 5).Value)
将得到 True,但 VBA 将继续将单元格内容与字符串进行比较,这会导致不匹配。 You need a way to split your If-statement.您需要一种方法来拆分您的 If 语句。
Some more remarks: You are assigning the worksheet you want to work with to variable ws
, but you are not using it.更多评论:您正在将要使用的工作表分配给变量
ws
,但您没有使用它。 You will need to qualify every single usage of Cells
(write ws.Cells(i, 5)
, else VBA will assume you are working with the Active Sheet, and that may or may not be Sheet1. Usually, this is done with a With
-statement (note all the leading dots).您将需要限定
Cells
的每一次使用(写入ws.Cells(i, 5)
,否则 VBA 将假定您正在使用活动工作表,并且可能是也可能不是 Sheet1。通常,这是通过With
-statement(注意所有前导点)。
Your declaration statement is flawed (a common mistake in VBA), you will need to specify the type for every variable.您的声明语句有缺陷(VBA 中的常见错误),您需要为每个变量指定类型。 In your case,
Count
will be of type Variant
, not Long
.在您的情况下,
Count
将是Variant
类型,而不是Long
。 No problem here, but in other cases it is, so make it a habit to declare all variables correctly.这里没问题,但在其他情况下确实如此,因此请养成正确声明所有变量的习惯。
You should use a For
-Loop rather than a Do While
.您应该使用
For
-Loop 而不是Do While
。
Dim count As Long, i As Long
With ws
count = .Cells(.Rows.count, "E").End(xlUp).Row
For i = 2 to count
Dim markCell as boolean
If isError(.Cells(i, 5).Value) Then
markCell = True
ElseIf .Cells(i, 5) = "Null" _
Or .Cells(i, 5).Value = "" _
Or .Cells(i, 5).Value Like "*-*" Then
markCell = True
Else
markCell = False
End If
If markCell Then
.Cells(i, 5).Interior.Color = RGB(38, 201, 218)
End If
Next i
End With
If you want to check for specific errors you first need to check if there are errors with IsError
.如果要检查特定错误,首先需要检查
IsError
是否存在错误。 You cannot check for an error and a value in one condition:您无法在一种情况下检查错误和值:
Do While i <= count
Dim Condition As Boolean
Condition = False ' initialize when in a loop!
If IsError(Cells(i, 5).Value) Then
If Cells(i, 5).Value = CVErr(xlErrNA) _
Or Cells(i, 5).Value = CVErr(xlErrRef) _
Or Cells(i, 5).Value = CVErr(xlErrNull) _
Or Cells(i, 5).Value = CVErr(xlErrDiv0) Then
Condition = True
End If
ElseIf Cells(i, 5).Value = "" Or Cells(i, 5).Value Like "*-*" Then
Condition = True
End If
If Condition = True Then
Cells(i, 5).Interior.Color = RGB(38, 201, 218)
End If
Loop
Sub FilterByColor()
Const wsName As String = "Sheet1"
Const Col As String = "E"
Dim FilterColor As Long: FilterColor = RGB(38, 201, 218)
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets(wsName)
If ws.FilterMode Then ws.ShowAllData ' remove any filters
Dim lRow As Long: lRow = ws.Cells(ws.Rows.count, Col).End(xlUp).Row
Dim rgData As Range ' data range; no header
Set rgData = ws.Range(ws.Cells(2, Col), ws.Cells(lRow, Col))
rgData.Interior.Color = xlNone ' remove all colors
Dim rgColor As Range ' the combined range to be colored
Dim DataCell As Range ' each cell of the data range
Dim cString As String
Dim DoColor As Boolean
For Each DataCell In rgData.Cells
If IsError(DataCell) Then ' error value
DoColor = True
Else
cString = CStr(DataCell.Value)
If Len(cString) = 0 Then ' blank
DoColor = True
Else
If InStr(1, cString, "-") > 0 Then ' contains a minus ('-')
DoColor = True
End If
End If
End If
If DoColor Then
If rgColor Is Nothing Then ' combine cells into a range
Set rgColor = DataCell
Else
Set rgColor = Union(rgColor, DataCell)
End If
DoColor = False ' don't forget to reset
End If
Next DataCell
If rgColor Is Nothing Then Exit Sub
rgColor.Interior.Color = FilterColor ' apply color in one go
Dim rgTable As Range ' table range; header included
Set rgTable = ws.Range(ws.Cells(1, Col), ws.Cells(lRow, Col))
rgTable.AutoFilter 1, FilterColor, xlFilterCellColor
' To delete the rows, you could continue with e.g.:
' rgData.SpecialCells(xlCellTypeVisible).EntireRow.Delete
' ws.AutoFilterMode = False ' remove 'AutoFilter'
End Sub
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.