简体   繁体   English

为什么运行宏时会出现“类型不匹配”错误?

[英]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

Filter By Color按颜色过滤

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM