设置(将私有事件作为Sheet1设置)sheetUI = Sheet1会导致错误438:对象不支持此属性或方法

时间:2019-04-10 14:18:26

标签: excel vba rubberduck

我正在使用this优秀的教程作为基础,利用Mathieu Guindon编写面向对象程序设计VBA代码的概念来创建一个简单的“ Hello World” Excel VBA项目,该主题在{ {3}}博客。

我创建了一个“裸露的骨头”项目,其中没有任何包含Excel工作表(HelloSheet),视图,ViewAdapter(包括ViewCommands和ViewEvents接口)的模型。 VBA项目编译没有错误,但是当我尝试运行“应用程序条目”宏时,我得到了可怕的“运行时错误438:对象不支持此属性或方法”。这发生在我的View类的Class_Initialize()子内部,在该子类中我已声明“ Private WithEvents sheetUI As HelloSheet”,并尝试设置“ sheetUI = HelloSheet”。

https://rubberduckvba.wordpress.com/是我的项目树的概述,如RubberDuck VBIDE中所示。

我尝试更新VBA项目引用以使其与“战舰”示例项目的引用完全匹配。我还尝试了在View类中实现Here的两种不同方法-与{{3}中使用的方法相比,Lazy Object / Weak Reference中链接的“ Battleship(WorksheetView).xlsm”中的一种方法},更具体地说:

Private adapter As ***IWeakReference***
Private WithEvents sheetUI As HelloSheet

Private Sub Class_Initialize()
    sheetUI = HelloSheet
End Sub

Private Property Get ViewEvents() As ISheetViewEvents
    Set ViewEvents = adapter ***.Object***
End Property

VS

Private adapter As ***SheetViewAdapter***
Private WithEvents sheetUI As HelloSheet

Private Sub Class_Initialize()
    sheetUI = HelloSheet
End Sub

Private Property Get ViewEvents() As ISheetViewEvents
    Set ViewEvents = ***adapter***
End Property

..但仍然存在“运行时错误438:对象不支持此属性或方法”。

下面是所有相关代码,分为工作表,类,接口等:

1)HelloSheet(隐藏在常规Excel工作表中的代码):

'@Folder("HelloWorld.View.Worksheet")
Option Explicit

Public Event DoubleClick(ByVal clickedRow As Integer)

Public Sub HideShape(shapeName As String)
    Dim currentShape As Shape
    Set currentShape = Me.Shapes(shapeName)
    currentShape.Visible = msoFalse
End Sub

Public Sub ShowShape(shapeName As String)
    Dim currentShape As Shape
    Set currentShape = Me.Shapes(shapeName)
    currentShape.Visible = msoTrue
End Sub

Public Sub OnLaunchCommand()
    ShowShape ("WarningTriangle")
End Sub

Public Sub TempManualHide()
    HideShape ("WarningTriangle")
End Sub

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    Cancel = True
    RaiseEvent DoubleClick(Target.Row)
End Sub

Public Sub PreviewSelectedRecord(ByVal selectedRow As Integer)
    Me.Cells(1, 1).Value2 = "Row is " & CStr(selectedRow)
End Sub

2)SheetView类:

'@Folder("HelloWorld.View.Worksheet")
Option Explicit
Implements ISheetViewCommands

Private adapter As SheetViewAdapter ' IWeakReference
Private WithEvents sheetUI As HelloSheet

Private Sub Class_Initialize()
    sheetUI = HelloSheet
End Sub

Private Property Get ViewEvents() As ISheetViewEvents
    Set ViewEvents = adapter '.Object
End Property


':GameSheet event handlers
':Messages sent from the view
':***************************

Private Sub sheetUI_DoubleClick(ByVal clickedRow As Integer)
    ViewEvents.PreviewSelectedRecord clickedRow
End Sub


':IGridViewCommands
':Messages sent from the controller
':*********************************

Private Property Set ISheetViewCommands_Events(ByVal value As ISheetViewEvents)
    Set adapter = value ' WeakReference.Create(Value)
End Property

Private Property Get ISheetViewCommands_Events() As ISheetViewEvents
    Set ISheetViewCommands_Events = adapter '.Object
End Property

Private Sub ISheetViewCommands_OnLaunchCommand()
    sheetUI.OnLaunchCommand
End Sub

Private Sub ISheetViewCommands_OnPreviewSelectedRecord(ByVal selectedRow As Integer)
    sheetUI.PreviewSelectedRecord selectedRow
End Sub

3)ISheetViewEvents接口:

'@Folder("HelloWorld.View")
'@Interface
Option Explicit

Public Sub PreviewSelectedRecord(ByVal selectedRow As Integer)
End Sub

4)ISheetViewCommands接口:

'@Folder("HelloWorld.View")
'@Interface
Option Explicit

'@Description("Gets/sets a weak refererence to the view events.")
Public Property Get Events() As ISheetViewEvents
End Property

Public Property Set Events(ByVal value As ISheetViewEvents)
End Property

Public Sub OnLaunchCommand()
End Sub

Public Sub OnPreviewSelectedRecord(ByVal selectedRow As Integer)
End Sub

5)SheetViewAdapter类(PredeclaredId /具有默认实例):

'@Folder("HelloWorld.View")
Option Explicit
'@PredeclaredId
Implements ISheetViewCommands
Implements ISheetViewEvents

Public Event OnPreviewCurrentSelectedRecord(ByVal selectedRow As Integer)

Private Type TAdapter
    SheetViewCommands As ISheetViewCommands
End Type
Private this As TAdapter

Public Function Create(ByVal view As ISheetViewCommands) As SheetViewAdapter
    With New SheetViewAdapter
        Set .SheetViewCommands = view
        Set view.Events = .Self
        Set Create = .Self
    End With
End Function

Public Property Get Self() As SheetViewAdapter
    Set Self = Me
End Property

'@Description("Gets/sets a reference that exposes commands to send to the view.")
Public Property Get SheetViewCommands() As ISheetViewCommands
    Set SheetViewCommands = this.SheetViewCommands
End Property

Public Property Set SheetViewCommands(ByVal value As ISheetViewCommands)
    Set this.SheetViewCommands = value
End Property


':IGridViewEvents
':Messages sent from the view
':***************************

Private Sub ISheetViewEvents_PreviewSelectedRecord(ByVal selectedRow As Integer)
    RaiseEvent OnPreviewCurrentSelectedRecord(selectedRow)
End Sub


':IGridViewCommands
':Messages sent from the controller
':*********************************

Private Property Set ISheetViewCommands_Events(ByVal value As ISheetViewEvents)
    Err.Raise 5, TypeName(Me), "Invalid use of property"
End Property

Private Property Get ISheetViewCommands_Events() As ISheetViewEvents
    Set ISheetViewCommands_Events = Me
End Property

Private Sub ISheetViewCommands_OnLaunchCommand()
    this.SheetViewCommands.OnLaunchCommand
End Sub

Private Sub ISheetViewCommands_OnPreviewSelectedRecord(ByVal selectedRow As Integer)
    this.SheetViewCommands.OnPreviewSelectedRecord selectedRow
End Sub

6)HelloController类:

'@Folder("HelloWorld")
Option Explicit

Private viewCommands As ISheetViewCommands
Private WithEvents viewAdapter As SheetViewAdapter

Public Sub Launch(ByVal adapter As SheetViewAdapter)
    Set viewAdapter = adapter
    Set viewCommands = adapter
    viewCommands.OnLaunchCommand
End Sub

Private Sub viewAdapter_OnPreviewCurrentSelectedRecord(ByVal selectedRow As Integer)
    viewCommands.OnPreviewSelectedRecord selectedRow
End Sub

7)最后是充当入口点的“ Macros”标准模块。这是我遇到错误的地方(“设置视图=新建SheetView”行):

'@Folder("HelloWorld")
'@Description("Application entry points.")
Option Explicit
'@Ignore MoveFieldCloserToUsage
Private controller As HelloController

Public Sub LaunchWorksheetInterface()
    Dim view As SheetView
    Set view = New SheetView

    Set controller = New HelloController
    controller.Launch SheetViewAdapter.Create(view)
End Sub

假设我可以解决入门级错误,那么我希望它具有非常简单的功能:

1)隐藏的Excel形状在HelloSheet(OnLaunchCommand)上可见;

2)双击一个单元格时,该行所在的行将在同一工作表的A1单元格中报告(Worksheet_BeforeDoubleClick事件)。

显然,用于完成这些简单任务的代码量过大了-我的想法是,一旦我掌握了将这些Model类添加到项目并将它们映射到工作簿中某些区域(即Tables / ListObjects)的基础知识。

任何帮助将不胜感激!对于在这篇相当长的文章结尾写过这篇文章的人,我深表感谢:)

1 个答案:

答案 0 :(得分:2)

Private WithEvents sheetUI As HelloSheet

Private Sub Class_Initialize()
    sheetUI = HelloSheet
End Sub

sheetUI是一个对象引用,分配它需要使用Set关键字:

Private WithEvents sheetUI As HelloSheet

Private Sub Class_Initialize()
    Set sheetUI = HelloSheet
End Sub

每当您尝试访问Worksheet类的默认成员时,都会引发错误438,因为Worksheet没有默认成员-此代码从立即窗格:

?Sheet1

或者:

foo = Sheet1

橡胶鸭检查应该在“代码质量问题”下对此发出警告:

  

分配了对象变量'sheetUI'时未使用'Set'关键字。