我正在使用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)的基础知识。
任何帮助将不胜感激!对于在这篇相当长的文章结尾写过这篇文章的人,我深表感谢:)
答案 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'关键字。