Я использую это превосходное учебное пособие в качестве основы для создания простого проекта Excel VBA "Hello World", использующего концепцию Матье Гиндона о написании кода VBA объектно-ориентированного программирования, обсуждаемого в серии статей оhttps://rubberduckvba.wordpress.com/ блог.
Я создал проект «без костей» без какой-либо модели, содержащей лист Excel (HelloSheet), View, ViewAdapter (включая интерфейсы ViewCommands и ViewEvents) и контроллер,Проект VBA компилируется без ошибок, но когда я пытаюсь запустить макрос «запись приложения», я получаю страшное «Ошибка времени выполнения 438: объект не поддерживает это свойство или метод».Это происходит внутри подпрограммы Class_Initialize () моего класса View, где я объявил «Private WithEvents sheetUI As HelloSheet» и пытаюсь установить «sheetUI = HelloSheet».
Здесь - это обзор дерева моего проекта, как видно из RubberDuck VBIDE.
Я попытался обновить ссылки на проект VBA, чтобы они точно соответствовали ссылкам на «Морской бой»образец проекта.Я также попробовал два разных подхода к реализации Ленивый объект / Слабая ссылка в классе View - тот, что в «Морском бою (WorksheetView) .xlsm», связанный в оригинальной статье vsподход, использованный в последней версии на 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
.. но "Ошибка времени выполнения 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) И, наконец, стандартный модуль «Макросы», который служит в качестветочка входа.Вот где я сталкиваюсь с ошибкой (строка «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тот же рабочий лист (событие Worksheet_BeforeDoubleClick).
Очевидно, что этот объем кода для таких простых задач является излишним - моя идея состоит в том, как только я получу эти основы, работающие над добавлением классов Model в проект и сопоставлением их с определенными областями (т.е.Tables / ListObjects) внутри рабочей книги.
Любая помощь будет принята с благодарностью!И слава всем, кто добрался до конца этого довольно длинного поста:)