Я централизовал обработку всех событий в моей книге Excel в одном классе под названием «Компоненты».Класс перемещается в отдельный файл "xlam", а этот файл "xlam" упоминается в книге Excel.
Класс "Компонент" определяется следующим образом:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "Components"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Public WithEvents WorkbookSD As Workbook, _
WithEvents SheetConfig As Worksheet, _
TableConfig As ListObject, _
TableVerValues1 As ListObject, _
TableVerValues2 As ListObject, _
TableDValues As ListObject, _
TableIGRValues As ListObject
...
Private Sub Class_Initialize()
On Error GoTo ErrorHandling
ToggleAppUpdate False
Set WorkbookSD = ActiveWorkbook
Set SheetConfig = WorkbookSD.Worksheets(SHEET_CONFIG)
Set TableConfig = SheetConfig.ListObjects(TABLE_CONFIG)
...
Private Sub SheetConfig_Activate()
On Error GoTo ErrorHandling
...
ErrorHandling:
If Err.Number <> 0 Then
ReportError
End If
End Sub
Обратите внимание, что "Атрибут VB_PredeclaredId = True ", чтобы гарантировать, что объект класса объявлен.Вроде как как это делает Form.
Поэтому я объявляю все объекты, для которых я хочу обрабатывать события в этом классе и WithEvents.«Компонент» инициализируется в событии «Class_Initialize».
Я ссылаюсь на объекты и методы из этого класса с помощью «Component.XXXX» в другом месте кода.Вот пример из другого модуля в файле "xlam":
Public Function FindCnfg(pTerm As String, pSearchBy As SearchBy) As Range
Dim lTable As ListObject, _
lRow As Range, _
lCol As Long
On Error GoTo ErrorHandling
Set FindCnfg = Nothing
Set lTable = Components.TableConfig
If lTable.DataBodyRange Is Nothing Then
Exit Function
End If
Select Case pSearchBy
Case SearchBy.ID
lCol = 1
Case SearchBy.Key
lCol = 2
Case Else
RaiseError ErrorCode.INVALID_PARAM
End Select
Set lRow = lTable.DataBodyRange.Columns(lCol).Find(What:=pTerm, LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows)
If Not lRow Is Nothing Then
Set lRow = lRow.EntireRow
Set FindCnfg = lRow
End If
ErrorHandling:
Set lTable = Nothing
Set lRow = Nothing
If Err.Number <> 0 Then
RaiseError Err.Number, "FindCnfg", Err.Description
End If
End Function
Я везде ловлю ошибки, используя "On Error GoTo X".
Все работает хорошо при нормальных обстоятельствах и событияхобрабатываются.
Но время от времени я получаю сообщение о том, что объект "Компонент" не определен или обработка событий перестает работать полностью без предупреждения или ошибки.
Он снова работает, еслиЯ вручную захожу в инструмент разработчика и запускаю метод, который ссылается на «Компонент».
Я подозреваю, что проблема связана с инициализацией предварительно объявленного объекта «Компонент».
Кто-нибудь есть идеи о том, как предотвратить эти спорадические нестабильности?Возможно, другой подход, который гарантирует, что объект «Компонент» всегда доступен.