【问题标题】:Type mismatch error on multi-cell entry in Worksheet_Change handlerWorksheet_Change 处理程序中多单元格条目的类型不匹配错误
【发布时间】:2018-09-02 17:06:20
【问题描述】:

我有一个Worksheet_Calculate 处理程序,一旦将一行添加到活动工作表上的表中,它就会自动在另一个工作表上创建新记录。问题是,另一个用于删除记录的子程序(Worksheet_Change 处理程序)一直给我这个错误:

运行时错误“13”:类型不匹配

当我尝试将值粘贴到表格中的多个单元格时,我只会收到此错误。当我将一个值粘贴到单个单元格中时,没有问题。甚至在粘贴到现有行并覆盖预先存在的数据时也会发生这种情况。

这个 sub 甚至不应该运行。

当我去调试器时,它表明问题出在这一行:

If Target.Column = 2 And Target.Row > 1 And Target.Value = "" Then

除非删除第 1 行下方第 2 列中的数据,否则我希望该表的行为类似于常规表。在所有其他情况下,它的功能应该与任何其他表一样。

删除记录时出现错误的代码:

Public Sub Worksheet_Change(ByVal Target As Range) '_Change  creates the variable as a target, transferred as a value to "ProjectName"
    Dim ans As Integer 

    If Target.Column = 2 And Target.Row > 1 And Target.Value = "" Then

        ans = MsgBox("Are you sure you want to Delete......This cannot Be Undone !!!", vbYesNo)
            If ans = vbYes Then

                With Application
                    .EnableEvents = False ' freeze WorkSheetChange event since you're about to UNDO a change
                    .Undo ' undo the change
                    ProjectName = Target.Value ' assign the deleted-undone value in to YYY
                    Rows(ActiveCell.Row).EntireRow.Delete ' delete that row
                    .EnableEvents = True ' re-enable all events
                End With
                MsgBox ProjectName & " has been deleted."  ' now you have that value in ProjectName

            End If

    End If
DeleteRows (ProjectName) 'Gives sub-routine "DeleteRows" the company name
End Sub

【问题讨论】:

    标签: vba excel


    【解决方案1】:

    粘贴多个值时出现错误的原因是,如果Target 超过一个单元格,则Target.Value 返回一个数组,并且您无法将数组与字符串进行比较。这就是“类型不匹配”的意思。 Target.Value (Array) 的类型 Target.Value = """" (String) 的类型。

    要解决问题,您可以尝试用Target.Cells(1).Value 替换出现的Target.Value,但您的代码仍然无法正常工作,因为还有更多未解决的相关问题以及其他问题不相关的问题:

    这个 sub 甚至不应该运行。

    你误解了Worksheet_Change(ByVal Target As Range) 是什么。它是一个事件处理程序,每次任何工作表中的单元格被修改删除时都会自动运行。 (从技术上讲,一个单元格可以被“清除”或“删除”,两者之间存在细微差别。)

    Target 是已更改的单元格范围。它可以是一个细胞或多个细胞。您需要专门检查Target 是否与您感兴趣的单元格范围匹配并排除所有其他单元格。要检查已删除(又名“清除”)的单元格,您需要检查单元格内容是否为空白。检查真正的删除有点复杂。

    我可以将 _Change 更改为 _OnDelete 或类似的东西吗? *

    不,没有“删除”事件。如上所述,可以从“更改”事件中检测到删除。要查看可用事件列表,请在代码窗口顶部的左侧下拉列表中选择“WorkSheet”,然后单击右侧的下拉列表。

    我以为我的代码在说,“当 B 列中大于第 1 行(标题行)的单元格被删除时,运行其余代码*

    不完全是。

    1. 只有在单个单元格被删除时才能正常运行。多个删除的单元格将导致与上述相同的错误。
    2. DeleteRows (ProjectName) 位于 IF 块之外,因此它始终在任何任何单元格更改时运行。幸运的是,ProjectName 在除 B 列(不包括标题)之外的所有情况下都是空白的,因此实际上没有删除任何内容。

    为了解决所有问题,我已将您的代码更新为更强大的版本(以及一些更漂亮的消息框):

    Private Sub Worksheet_Change(ByVal Target As Range) ' Runs every time ANY cell in the sheet is modified , cleared or deleted
      'v0.1.1
      Dim rngClippedTarget As Range
      Set rngClippedTarget = Intersect(Target, Columns(2).Resize(Rows.Count - 1).Offset(1)) ' Extract the 2nd column, row 2 downwards, cells from Target (if any)
      If rngClippedTarget Is Nothing Then Exit Sub 'Ignore changes if there are none in column 2 (excluding header row)
      If rngClippedTarget.Cells(1).Value2 <> vbNullString Then Exit Sub ' Ignore changes if the first changed cell in column 2 has not been "emptied"
    
      With Application
        .EnableEvents = False ' Otherwise, the Worksheet_Change event is re-triggered by the .Undo
        .Undo ' Restore cleared values
        .EnableEvents = True
      End With
      Dim lngCellCount As Long
      lngCellCount = rngClippedTarget.Cells.Count
      Dim strConfirmMsg As String
      strConfirmMsg _
      = rngClippedTarget.Cells(1).Value2 _
      & IIf(lngCellCount = 1, "", " and " & lngCellCount - 1 & " other project" & IIf(lngCellCount = 2, "", "s")) _
      & " will be deleted." & vbCrLf _
      & "Are you sure? (This cannot be undone!)"
      If vbCancel = MsgBox(strConfirmMsg, vbCritical + vbOKCancel) Then Exit Sub 'Abort with all changes reverted
    
      Dim rngCell As Range
      For Each rngCell In rngClippedTarget
        DeleteRows rngCell.Value2 ' Delete the appropriate Database rows
      Next rngCell
      With Application
        .EnableEvents = False ' Otherwise, the Worksheet_Change event is re-triggered by the .Delete
        rngClippedTarget.EntireRow.Delete ' Delete all the changed rows in the sheet
        .EnableEvents = True
      End With
      MsgBox lngCellCount & " project" & IIf(lngCellCount = 1, " has", "s have") & " been deleted.", vbInformation
    
    End Sub
    

    注意事项:

    • 允许粘贴多个值而不会出错。
    • 允许一次性删除多个项目。如果不希望这样做,可以将其更改为提醒用户并中止。
    • 修复了取消删除未恢复已删除项目名称的问题。
    • 使用vbOKCancel 代替vbYesNo 允许按Esc 中止删除。
    • 使用.Value2 代替Value 更快,并且可以避免潜在的问题,因为不执行隐式类型转换。
    • 使用RVBA Naming Conventions

    注意事项:

    • 如果用户实际删除工作表或表格行,则不起作用。删除工作表或表格行的 contents 可以正常工作。 (可以更新代码以允许实际删除,但有点复杂)
    • 如果删除了一个已经为空的单元格,它会尝试删除一个名为“”的项目。
    • 不会忽略表格下方“项目名称”(B) 列中的单元格,因此如果用户删除了此处的单元格,则上一点适用。
    • 对于多个项目删除,它假定如果第一个项目名称为空,则其余项目名称也是如此。因此,如果用户将多个值粘贴到 B 列中的现有值之上,并且只有第一个粘贴的值是空白的,所有这些预先存在的项目将被删除,而不仅仅是第一个。

    * 来自已删除的 cmets

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-28
      • 2017-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-04
      • 1970-01-01
      相关资源
      最近更新 更多