You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VBA使用ClassFactory创建自定义对象报对象变量未设置错误

错误根因梳理

你遇到的报错由以下3个问题共同导致:

  1. 对象变量赋值缺少Set关键字
    ws是Worksheet对象类型,所有对象赋值必须加Set关键字。你当前代码里两处ws = ThisWorkbook.Worksheets("Sheet1")(分别在ClassFactory函数和Init过程中)都缺少Set,这是触发「Object variable or With block variable not set」报错的直接原因。
  2. 工厂方法调用逻辑矛盾
    你写的Set oLI = oLI.ClassFactory(rowNum)存在逻辑悖论:调用ClassFactory方法时,oLI还没有被实例化,本身就是空对象,调用空对象的成员方法必然报错。
    你参考的示例可以不加oLI.前缀,是因为示例要么把ClassFactory方法放在了标准模块中,要么给LineItem类开启了*预声明实例(PredeclaredId)*属性。
  3. 工厂方法返回值覆盖不全
    如果当前行的类型不是Budget,ClassFactory函数没有返回值,后续调用oLI时仍会触发空对象报错。

修复方案(推荐)

步骤1:修改LineItem类模块代码

Option Explicit

Private ws As Worksheet
Private mLInum As Integer
Private mRowNum As String
Private mCostCode As String
Private mDescription1 As String
Private mDescription2 As String
Private mNote1 As String
Private mNote2 As String
Private mDebugInfo As String

Sub Init(rowNum As Integer)
    ' 对象赋值加Set
    Set ws = ThisWorkbook.Worksheets("Sheet1")
    mRowNum = rowNum
    mLInum = ws.Cells(rowNum, 1).Value
    mCostCode = ws.Cells(rowNum, 3).Value
    mDescription1 = ws.Cells(rowNum, 5).Value
    mDescription2 = ws.Cells(rowNum + 1, 5).Value
    mNote1 = ws.Cells(rowNum, 6).Value
    mNote2 = ws.Cells(rowNum + 1, 6).Value
    mDebugInfo = "string outputting member vars"
    MsgBox mDebugInfo
End Sub

步骤2:将工厂方法移到标准模块

把原来类模块里的ClassFactory函数剪切到你存放CreateLineItemObject的标准模块中,同时修正ws赋值和返回值逻辑:

Public Function ClassFactory(ByVal rowNum As Integer) As LineItem
    ' 对象赋值加Set
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("Sheet1")
    Dim liType As String
    Dim oLI As LineItem
    
    liType = ws.Cells(rowNum, 2).Value
    Select Case liType
        Case "Budget"
            Set oLI = New LineItem
            oLI.Init rowNum
            Set ClassFactory = oLI
        Case "Actual"
            MsgBox "Actual Line Item found, use this on Actual Line Item"
            Set ClassFactory = Nothing
        Case Else
            MsgBox "Unknown Error"
            Set ClassFactory = Nothing
    End Select
End Function

步骤3:修改主调用代码

Sub CreateLineItemObject()
    Dim oLI As LineItem
    Dim rowNum As Integer
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("Sheet1")
    rowNum = Application.Selection.Row
    ' 直接调用标准模块里的工厂方法即可
    Set oLI = ClassFactory(rowNum)
    
    ' 可选:加非空判断避免后续报错
    If oLI Is Nothing Then
        Exit Sub
    End If
    ' 后续你的业务逻辑
End Sub

如果你希望保留类内的工厂方法,只需给LineItem类开启PredeclaredId属性(按F4打开类的属性窗口,将PredeclaredId改为True),调用时直接写Set oLI = LineItem.ClassFactory(rowNum)即可,无需提前实例化。

内容的提问来源于stack exchange,提问作者Gary Z

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 20:15:01