使用ActiveX文本框调用CountIf时触发Error438错误的求助
问题分析与修复
触发Error 438的核心原因
- 控件引用错误:代码里用
ActiveSheet.tbModel.Value,但如果运行代码时激活的不是包含tbModel这个ActiveX文本框的工作表,ActiveSheet对象就没有tbModel这个属性,直接触发438错误。应该直接引用控件所在的工作表(你定义的frm就是"UserForm"工作表,假设控件在这张表)。 - 逻辑完全颠倒:你需求是「型号不存在则新增,存在则更新」,但代码里
CountIf>0(型号存在)时执行新增,Else才去更新,完全搞反了逻辑。 - 未限定对象引用:比如
Rows.Count没指定工作表,默认用ActiveSheet的行数,可能导致错误;还有用Sheet1代替定义好的invdata,容易引发引用混乱。 - 数据类型风险:用
Integer存储行数,当工作表行数超过32767时会溢出,应该用Long类型。
修正后的代码
Sub Add() Dim invdata As Worksheet Dim frm As Worksheet Dim iqty As Integer Dim irow As Long Dim jrow As Long Dim i As Long Dim modelVal As String ' 存型号值,避免重复引用控件 ' 明确引用工作表 Set frm = ThisWorkbook.Sheets("UserForm") Set invdata = ThisWorkbook.Sheets("Inventory Database") ' 读取数量和型号,直接引用frm上的控件 iqty = frm.Range("B9").Value modelVal = frm.tbModel.Value ' 这里直接用frm引用控件,避免ActiveSheet的问题 ' 先检查型号是否存在,用Application.CountIf避免找不到时抛出错误 If Application.CountIf(invdata.Range("C:C"), modelVal) = 0 Then ' 型号不存在,新增记录 jrow = invdata.Cells(invdata.Rows.Count, 1).End(xlUp).Row + 1 With invdata .Cells(jrow, 1).Value = frm.Range("B6").Value .Cells(jrow, 2).Value = frm.Range("B7").Value .Cells(jrow, 3).Value = modelVal .Cells(jrow, 4).Value = iqty End With MsgBox "New Model Added!" Else ' 型号存在,更新数量 irow = invdata.Cells(invdata.Rows.Count, 3).End(xlUp).Row For i = 2 To irow If invdata.Cells(i, 3).Value = modelVal Then invdata.Cells(i, 4).Value = invdata.Cells(i, 4).Value + iqty MsgBox "Inventory Updated!" ' 加个提示更友好 Exit Sub End If Next i End If End Sub
关键修改说明
- 把
ActiveSheet.tbModel.Value改成frm.tbModel.Value,确保始终引用正确工作表上的控件,从根源解决438错误。 - 颠倒了判断逻辑:
CountIf=0时新增,否则更新,符合你的需求。 - 所有行数相关变量改用
Long类型,避免溢出。 - 用
Application.CountIf代替WorksheetFunction.CountIf,找不到匹配项时返回0而不是抛出错误,代码更稳定。 - 统一用
invdata代替Sheet1,避免工作表引用混乱。 - 新增了更新成功的提示框,操作反馈更清晰。
内容的提问来源于stack exchange,提问作者Splash31
相关产品推荐
相关产品推荐

