VBA运行时错误13(类型不匹配)问题排查求助
解决VBA运行时错误13(类型不匹配)问题
错误根源分析
你的代码在第一个工作表正常运行,但第二个工作表报错,核心原因包括:
- 部分工作表的B列存在错误值(如#N/A、#VALUE!),直接和空字符串比较会触发类型不匹配
Application.Match查找时,权限值的数据类型不匹配(比如原单元格是数值,写入G列后自动转为文本)- 当某个权限没有关联用户时,
Join函数处理空字典的Keys数组会报错 - 未处理工作表只有表头、无数据的情况(
lastRow为1)
修改后的代码
Sub ProcessWorksheets() Dim ws As Worksheet Dim lastRow As Long, i As Long Dim permissionDict As Object Dim permission As Variant Dim usersDict As Object Dim rowIndex As Variant ' 改为Variant,兼容Match返回的错误值 ' 遍历除Sheet1外的所有工作表 For Each ws In ThisWorkbook.Sheets If ws.Name <> "Sheet1" Then Set permissionDict = CreateObject("Scripting.Dictionary") permissionDict.CompareMode = vbTextCompare ' 忽略大小写匹配,可选 ' 清空目标列并设置表头 ws.Range("G:J").ClearContents ws.Cells(1, "G").Value = "Permissions" lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row ' 处理无数据的情况(仅表头) If lastRow < 2 Then GoTo NextWorksheet ' 填充权限字典:先过滤错误值和空值 For i = 2 To lastRow With ws.Cells(i, "B") If Not IsError(.Value) Then Dim permValue As String permValue = Trim(.Value) ' 去除首尾空格 If permValue <> "" Then permissionDict(permValue) = Empty End If End If End With Next i ' 写入权限到G列:先判断字典是否有内容 If permissionDict.Count > 0 Then ws.Range("G2").Resize(permissionDict.Count, 1).Value = Application.Transpose(permissionDict.Keys) End If ' 遍历每个权限 For Each permission In permissionDict.Keys Set usersDict = CreateObject("Scripting.Dictionary") usersDict.CompareMode = vbTextCompare ' 收集关联用户:过滤错误值和空用户名 For i = 2 To lastRow With ws.Cells(i, "B") If Not IsError(.Value) Then If Trim(.Value) = permission Then Dim userValue As String userValue = Trim(ws.Cells(i, "A").Value) If userValue <> "" Then usersDict(userValue) = True End If End If End If End With Next i ' 查找权限所在行:缩小查找范围,避免无效匹配 rowIndex = Application.Match(permission, ws.Range("G1:G" & ws.Cells(ws.Rows.Count, "G").End(xlUp).Row), 0) If Not IsError(rowIndex) Then ' 处理空字典的情况,避免Join报错 If usersDict.Count > 0 Then ws.Cells(rowIndex, "H").Value = Join(usersDict.Keys, ", ") Else ws.Cells(rowIndex, "H").Value = "无关联用户" ' 或设为空字符串 End If End If ' 填充I、J列数据 For i = 2 To lastRow With ws.Cells(i, "B") If Not IsError(.Value) Then If Trim(.Value) = permission Then ws.Cells(i, "I").Value = ws.Cells(i, "C").Value ws.Cells(i, "J").Value = ws.Cells(i, "D").Value End If End If End With Next i Next permission NextWorksheet: ' 释放对象,避免内存泄漏 Set usersDict = Nothing Set permissionDict = Nothing End If Next ws End Sub
关键修改点说明
- 错误值全面拦截:所有读取B列的操作都先通过
Not IsError(.Value)判断,避免错误值参与比较运算 - 数据类型统一:将权限、用户值转为字符串并去除首尾空格,解决数值/文本类型不匹配导致的
Match失败问题 - 边界场景处理:
- 判断工作表无数据时直接跳过
- 字典为空时不执行
Transpose写入操作 Join前先检查用户字典是否有数据,避免空数组报错
- 查找范围优化:将
Match的查找范围从整列缩小到实际有数据的区域,提升运行效率 - 对象资源释放:每次循环结束后释放字典对象,避免内存占用过高
内容的提问来源于stack exchange,提问作者Sid
相关产品推荐
相关产品推荐

