Setting (Private WithEvents As Sheet1) sheetUI = Sheet1 导致错误 438: Object doesn't support this 属性 or method
Setting (Private WithEvents As Sheet1) sheetUI = Sheet1 causes error 438: Object doesn't support this property or method
我正在使用 this excellent tutorial as a base to create a simple "Hello World" Excel VBA project leveraging on Mathieu Guindon's concept of writing Object-Oriented Programming VBA code, discussed in a series of articles on the https://rubberduckvba.wordpress.com/ 博客。
我创建了一个 "bare bones" 项目,没有任何模型包含 Excel 作品sheet (HelloSheet)、一个视图、一个 ViewAdapter(包括 ViewCommands 和 ViewEvents 接口)和一个控制器. VBA 项目编译没有错误,但是当我尝试 运行 "application entry" 宏时,我得到了可怕的 "Run-time error 438: Object doesn't support this property or method"。这发生在我的视图 class 的 Class_Initialize() 子内部,我在其中声明了 "Private WithEvents sheetUI As HelloSheet" 并尝试设置 "sheetUI = HelloSheet"。
Here 是我的项目树的概览,如 RubberDuck VBIDE 中所示。
我已尝试更新 VBA 项目引用以与 "Battleship" 示例项目的引用完全匹配。我还尝试了两种不同的方法来实现 Lazy Object / Weak Reference in the View class - the one in the "Battleship (WorksheetView).xlsm" linked in the original article vs the approach used in the latest version on GitHub,更具体地说:
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
..但 "Run-time error 438: Object doesn't support this property or method" 仍然存在。
以下是 sheets、classes、接口等中的所有相关代码拆分:
1) HelloSheet(常规 Excel sheet 代码隐藏):
'@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) 工作表视图 class:
'@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 class (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 class:
'@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" 标准模块。这是我遇到错误的地方("Set view = New 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中报告sheet(Worksheet_BeforeDoubleClick事件)
显然,如此简单的任务需要大量代码 - 我的想法是,一旦我掌握了这些基础知识,就可以将模型 classes 添加到项目并将它们映射到某些区域(即 Tables/ListObjects) 在工作簿中。
任何帮助将不胜感激!并感谢所有完成这篇相当长的文章的人 post :)
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
class 的默认成员时都会抛出错误 438,因为 Worksheet
没有默认成员 - 此代码重现了 直接窗格:
?Sheet1
或:
foo = Sheet1
Rubberduck 检查 应该 对此发出警告,在 "Code Quality Issues":
下
Object variable 'sheetUI' is assigned without the 'Set' keyword.
我正在使用 this excellent tutorial as a base to create a simple "Hello World" Excel VBA project leveraging on Mathieu Guindon's concept of writing Object-Oriented Programming VBA code, discussed in a series of articles on the https://rubberduckvba.wordpress.com/ 博客。
我创建了一个 "bare bones" 项目,没有任何模型包含 Excel 作品sheet (HelloSheet)、一个视图、一个 ViewAdapter(包括 ViewCommands 和 ViewEvents 接口)和一个控制器. VBA 项目编译没有错误,但是当我尝试 运行 "application entry" 宏时,我得到了可怕的 "Run-time error 438: Object doesn't support this property or method"。这发生在我的视图 class 的 Class_Initialize() 子内部,我在其中声明了 "Private WithEvents sheetUI As HelloSheet" 并尝试设置 "sheetUI = HelloSheet"。
Here 是我的项目树的概览,如 RubberDuck VBIDE 中所示。
我已尝试更新 VBA 项目引用以与 "Battleship" 示例项目的引用完全匹配。我还尝试了两种不同的方法来实现 Lazy Object / Weak Reference in the View class - the one in the "Battleship (WorksheetView).xlsm" linked in the original article vs the approach used in the latest version on GitHub,更具体地说:
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
..但 "Run-time error 438: Object doesn't support this property or method" 仍然存在。
以下是 sheets、classes、接口等中的所有相关代码拆分:
1) HelloSheet(常规 Excel sheet 代码隐藏):
'@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) 工作表视图 class:
'@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 class (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 class:
'@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" 标准模块。这是我遇到错误的地方("Set view = New 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中报告sheet(Worksheet_BeforeDoubleClick事件)
显然,如此简单的任务需要大量代码 - 我的想法是,一旦我掌握了这些基础知识,就可以将模型 classes 添加到项目并将它们映射到某些区域(即 Tables/ListObjects) 在工作簿中。
任何帮助将不胜感激!并感谢所有完成这篇相当长的文章的人 post :)
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
class 的默认成员时都会抛出错误 438,因为 Worksheet
没有默认成员 - 此代码重现了 直接窗格:
?Sheet1
或:
foo = Sheet1
Rubberduck 检查 应该 对此发出警告,在 "Code Quality Issues":
下Object variable 'sheetUI' is assigned without the 'Set' keyword.