-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclsExecutionContext.cls
More file actions
289 lines (253 loc) · 10.3 KB
/
Copy pathclsExecutionContext.cls
File metadata and controls
289 lines (253 loc) · 10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "clsExecutionContext"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
'@Folder "3-Aplicac (Coord)"
'@Description: Provee acceso seguro y explícito al contexto de ejecución (Workbook, Worksheet, Chart, Selection)
'@Note: Centraliza la suscripción a eventos de Application y propaga cambios a otras clases.
' Diseñado para reemplazar ActiveWorkbook/ActiveSheet/ActiveChart/Selection con acceso seguro.
Option Explicit
Private Const MODULE_NAME As String = "clsExecutionContext"
' ==========================================
' EVENTOS PUBLICOS - Otras clases pueden suscribirse
' ==========================================
Public Event WorkbookOpened(ByVal wb As Workbook)
Public Event WorkbookActivated(ByVal wb As Workbook)
Public Event WorkbookBeforeClose(ByVal wb As Workbook, ByRef Cancel As Boolean)
Public Event WorksheetActivated(ByVal ws As Worksheet)
Public Event WorksheetDeactivated(ByVal ws As Worksheet)
Public Event SheetActivated(ByVal sh As Object)
Public Event SheetDeactivated(ByVal sh As Object)
Public Event SelectionChanged(ByVal sel As Object)
' ==========================================
' SUSCRIPCION A EVENTOS DE APPLICATION
' ==========================================
Private WithEvents m_xlApp As Application
Attribute m_xlApp.VB_VarHelpID = -1
' ==========================================
' CACHE DE ESTADO
' ==========================================
Private m_lastWorkbookObjKey As Double ' Cache coherente (solo si sigue vigente)
Private m_lastWorksheetObjKey As Double
Private m_lastChartObjKey As Double
Private m_lastSelectionObjKey As Double
Private Type T_CachedChartInfo
IsValid As Boolean
Chart As Chart ' Chart activo (ActiveChart o desde ChartObject/Selection)
SourceType As String ' "ActiveChart", "ChartObject", "ChartArea", etc.
ParentType As String ' "ChartSheet", "Worksheet"
End Type
Private m_cachedChartInfo As T_CachedChartInfo
' ---------------------------------------------------------------------------
' INICIALIZACIÓN
' ---------------------------------------------------------------------------
Public Sub Initialize()
Set m_xlApp = Application
' No cacheamos nada aquí ? lazy evaluation segura
LogInfo MODULE_NAME, "[Initialize] - Suscrito a eventos de Application"
End Sub
' ---------------------------------------------------------------------------
' EVENTOS DE APPLICATION - Capturados y propagados
' ---------------------------------------------------------------------------
Private Sub m_xlApp_WorkbookOpen(ByVal wb As Workbook)
LogDebug MODULE_NAME, "[xlApp_WorkbookOpen] " & wb.Name
RaiseEvent WorkbookOpened(wb)
End Sub
Private Sub m_xlApp_WorkbookActivate(ByVal wb As Workbook)
LogDebug MODULE_NAME, "[xlApp_WorkbookActivate] " & wb.Name
m_lastWorkbookObjKey = ObjPtr(wb)
RaiseEvent WorkbookActivated(wb)
End Sub
Private Sub m_xlApp_WorkbookBeforeClose(ByVal wb As Workbook, Cancel As Boolean)
LogDebug MODULE_NAME, "[xlApp_WorkbookBeforeClose] " & wb.Name
RaiseEvent WorkbookBeforeClose(wb, Cancel)
End Sub
Private Sub m_xlApp_SheetActivate(ByVal sh As Object)
LogDebug MODULE_NAME, "[xlApp_SheetActivate] " & TypeName(sh) & " '" & sh.Name & "'"
If TypeOf sh Is Worksheet Then
m_lastWorksheetObjKey = ObjPtr(sh)
RaiseEvent WorksheetActivated(sh)
End If
RaiseEvent SheetActivated(sh)
End Sub
Private Sub m_xlApp_SheetDeactivate(ByVal sh As Object)
LogDebug MODULE_NAME, "[xlApp_SheetDeactivate] " & sh.Name
If TypeOf sh Is Worksheet Then
RaiseEvent WorksheetDeactivated(sh)
End If
RaiseEvent SheetDeactivated(sh)
End Sub
' ---------------------------------------------------------------------------
' PROPIEDADES PÚBLICAS — seguras y con fallback explícito
' ---------------------------------------------------------------------------
Public Property Get Workbook() As Workbook
On Error GoTo SafeExit
If m_xlApp Is Nothing Then Exit Property
If m_xlApp.ActiveWorkbook Is Nothing Then Exit Property
If ObjPtr(m_xlApp.ActiveWorkbook) = m_lastWorkbookObjKey Then
Set Workbook = m_xlApp.ActiveWorkbook
Exit Property
End If
' Refrescar cache
m_lastWorkbookObjKey = ObjPtr(m_xlApp.ActiveWorkbook)
Set Workbook = m_xlApp.ActiveWorkbook
Exit Property
SafeExit:
Set Workbook = Nothing
End Property
Public Property Get Worksheet() As Worksheet
On Error GoTo SafeExit
If m_xlApp Is Nothing Then Exit Property
If TypeOf m_xlApp.ActiveSheet Is Worksheet Then
If ObjPtr(m_xlApp.ActiveSheet) = m_lastWorksheetObjKey Then
Set Worksheet = m_xlApp.ActiveSheet
Exit Property
End If
m_lastWorksheetObjKey = ObjPtr(m_xlApp.ActiveSheet)
Set Worksheet = m_xlApp.ActiveSheet
End If
Exit Property
SafeExit:
Set Worksheet = Nothing
End Property
Public Property Get Selection() As Object
On Error GoTo SafeExit
If m_xlApp Is Nothing Then Exit Property
Set Selection = m_xlApp.Selection
Exit Property
SafeExit:
Set Selection = Nothing
End Property
Public Property Get Application() As Application
Set Application = m_xlApp
End Property
' ---------------------------------------------------------------------------
' CHART — LA PARTE CRÍTICA (logica para detectar chart activo)
' ---------------------------------------------------------------------------
Public Property Get Chart() As Chart
On Error GoTo SafeExit
If m_xlApp Is Nothing Then Exit Property
' Si ya está cacheado y válido, devolverlo
If m_cachedChartInfo.IsValid Then
Set Chart = m_cachedChartInfo.Chart
Exit Property
End If
' === LÓGICA IDÉNTICA A TU EsValidoInvertirEjes ===
Dim Ch As Chart
Dim sel As Object
' 1. Caso 1: ActiveChart (ChartSheet o Chart activado en hoja)
Set Ch = m_xlApp.ActiveChart
If Not Ch Is Nothing Then
m_cachedChartInfo.Chart = Ch
m_cachedChartInfo.SourceType = "ActiveChart"
m_cachedChartInfo.ParentType = TypeName(Ch.Parent)
m_cachedChartInfo.IsValid = True
Set Chart = Ch
Exit Property
End If
' 2. Caso 2: Selection es ChartObject, ChartArea, PlotArea, etc.
Set sel = Me.Selection
If Not sel Is Nothing Then
Select Case TypeName(sel)
Case "ChartObject"
Set Ch = sel.Chart
Case "ChartArea", "PlotArea", "Legend", "Axis", "Series"
' Subir hasta encontrar el Chart
Dim obj As Object: Set obj = sel
Do While Not (TypeOf obj Is Chart) And Not (obj Is Nothing)
On Error Resume Next
Set obj = obj.Parent
On Error GoTo 0
If obj Is Nothing Then Exit Do
Loop
If TypeOf obj Is Chart Then Set Ch = obj
Case Else
' No es un gráfico - salir
End Select
End If
' Si encontramos un Chart, cachearlo
If Not Ch Is Nothing Then
m_cachedChartInfo.Chart = Ch
m_cachedChartInfo.SourceType = TypeName(sel)
If TypeOf Ch.Parent Is Worksheet Then
m_cachedChartInfo.ParentType = "Worksheet"
ElseIf TypeOf Ch.Parent Is Chart Then
m_cachedChartInfo.ParentType = "ChartSheet"
Else
m_cachedChartInfo.ParentType = TypeName(Ch.Parent)
End If
m_cachedChartInfo.IsValid = True
Set Chart = Ch
Exit Property
End If
' No hay gráfico activo
m_cachedChartInfo.IsValid = False
Set Chart = Nothing
Exit Property
SafeExit:
m_cachedChartInfo.IsValid = False
Set Chart = Nothing
End Property
' ---------------------------------------------------------------------------
' MÉTODOS DE CONVENIENCIA — seguros
' ---------------------------------------------------------------------------
Public Property Get HasWorkbook() As Boolean
HasWorkbook = Not (Me.Workbook Is Nothing)
End Property
Public Property Get HasWorksheet() As Boolean
HasWorksheet = Not (Me.Worksheet Is Nothing)
End Property
Public Property Get HasSelection() As Boolean
HasSelection = Not (Me.Selection Is Nothing)
End Property
Public Property Get HasChart() As Boolean
HasChart = Not (Me.Chart Is Nothing)
End Property
Public Function GetSelectedRange() As Range
On Error GoTo SafeExit
Dim sel As Object: Set sel = Me.Selection
If TypeName(sel) = "Range" Then
Set GetSelectedRange = sel
End If
SafeExit:
' Nada ? Nothing por defecto
End Function
' ---------------------------------------------------------------------------
' DIAGNÓSTICO — clave para depuración
' ---------------------------------------------------------------------------
Public Function Diagnostics() As String
Dim s As String
s = "Contexto actual:" & vbCrLf
s = s & " Workbook: " & IIf(Me.HasWorkbook, Me.Workbook.Name, "(ninguno)") & vbCrLf
s = s & " Worksheet: " & IIf(Me.HasWorksheet, Me.Worksheet.Name, "(ninguna)") & vbCrLf
s = s & " Selection: " & IIf(Me.HasSelection, TypeName(Me.Selection), "(nada)") & vbCrLf
If Me.HasChart Then
With m_cachedChartInfo
s = s & " Chart: Sí (" & .SourceType & " en " & .ParentType & ")" & vbCrLf
End With
Else
s = s & " Chart: No" & vbCrLf
End If
' Diagnóstico adicional para depuración de errores de contexto
On Error Resume Next
If Not m_xlApp Is Nothing Then
s = s & " App.ActiveChart: " & IIf(m_xlApp.ActiveChart Is Nothing, "Nothing", "Sí") & vbCrLf
s = s & " App.Selection: " & TypeName(m_xlApp.Selection) & vbCrLf
End If
On Error GoTo 0
Diagnostics = s
End Function
' ---------------------------------------------------------------------------
' LIMPIEZA
' ---------------------------------------------------------------------------
Private Sub Class_Terminate()
LogDebug MODULE_NAME, "[Class_Terminate]"
Set m_xlApp = Nothing
m_cachedChartInfo.IsValid = False
Set m_cachedChartInfo.Chart = Nothing
End Sub