-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmodMACROAppLifecycle.bas
More file actions
423 lines (342 loc) · 14.6 KB
/
Copy pathmodMACROAppLifecycle.bas
File metadata and controls
423 lines (342 loc) · 14.6 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
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
Attribute VB_Name = "modMACROAppLifecycle"
' ==========================================
' CICLO DE VIDA DE LA APLICACION
' ==========================================
' Funciones publicas para gestion de la aplicacion y Ribbon
' ==========================================
'@Folder "1-Inicio e Instalacion.Ciclo de vida"
Option Explicit
Private Const MODULE_NAME As String = "clsRibbonEvents"
Public Function App() As clsAplicacion
Attribute App.VB_Description = "[modMACROAppLifecycle] App (función personalizada). Aplica a: ThisWorkbook"
Attribute App.VB_ProcData.VB_Invoke_Func = " \n23"
Set App = ThisWorkbook.App
End Function
'@Description: Fuerza el reinicio completo de la aplicacion
Public Sub ReiniciarAplicacion()
Attribute ReiniciarAplicacion.VB_ProcData.VB_Invoke_Func = " \n0"
Dim result As VbMsgBoxResult
result = MsgBox("Esto reiniciara completamente el complemento ABC." & vbCrLf & vbCrLf & _
"Se cerrara y volvera a inicializar la aplicacion." & vbCrLf & _
"¿Desea continuar?", _
vbQuestion + vbYesNo, "Reiniciar Aplicacion")
If result <> vbYes Then Exit Sub
LogInfo MODULE_NAME, "[ReiniciarAplicacion] - Reinicio solicitado por usuario"
On Error Resume Next
' Terminar aplicacion actual
ThisWorkbook.TerminateApp
' Reinicializar
DoEvents
Application.Wait Now + TimeSerial(0, 0, 1)
DoEvents
' Forzar reinicio llamando a App()
Dim dummy As clsAplicacion
Set dummy = App()
On Error GoTo 0
' Verificar estado
If IsRibbonAvailable() Then
MsgBox "Aplicación reiniciada correctamente." & vbCrLf & vbCrLf & _
App.Ribbon.GetQuickDiagnostics(), vbInformation, "Reinicio Exitoso"
Else
MsgBox "Aplicación reiniciada, pero el Ribbon puede requerir atención adicional." & vbCrLf & _
"Ejecute 'RecuperarRibbon' si es necesario.", _
vbExclamation, "Reinicio Parcial"
End If
End Sub
' ==========================================
' GESTION DEL COMPLEMENTO XLAM
' MACROS PUBLICAS (Accesibles por el usuario)
' ==========================================
'@Description: Activa temporalmente la visibilidad del XLAM para operaciones de copia
' Muestra el libro que contiene este XLAM, haciéndolo visible en la interfaz de Excel.
'@Scope: Manipula el libro host del complemento XLAM cargado.
'@ArgumentDescriptions: (no tiene argumentos)
'@Returns: (ninguno)
'@Category: ComplementosExcel
Sub DesactivarModoAddin()
Attribute DesactivarModoAddin.VB_ProcData.VB_Invoke_Func = " \n0"
On Error GoTo ErrHandler
If ThisWorkbook.IsAddin Then
ThisWorkbook.IsAddin = False ' Hace que el libro se muestre
Debug.Print "[DesactivarModoAddin] - XLAM visible temporalmente"
End If
ErrHandler:
Err.Raise Err.Number, "modMACROBackups.DesactivarModoAddin", _
"Error desactivando el modo de AddIn: " & Err.Description
End Sub
'@Description: Restaura el estado de IsAddin del XLAM
' Oculta el libro que contiene este XLAM, dejando el complemento operativo pero sin mostrar su ventana.
'@Scope: Manipula el libro host del complemento XLAM cargado.
'@ArgumentDescriptions: (no tiene argumentos)
'@Returns: (ninguno)
'@Category: ComplementosExcel
Sub RestaurarModoAddin()
Attribute RestaurarModoAddin.VB_ProcData.VB_Invoke_Func = " \n0"
On Error GoTo ErrHandler
ThisWorkbook.IsAddin = True
Debug.Print "[RestaurarModoAddin] - XLAM restaurado como Add-in"
ErrHandler:
Err.Raise Err.Number, "modMACROBackups.DesactivarModoAddin", _
"Error desactivando el modo de AddIn: " & Err.Description
End Sub
' ==========================================
' GESTION DEL RIBBON
' MACROS PUBLICAS (Accesibles por el usuario)
' ==========================================
'@Description: Procedimiento puente para el atajo de teclado
Public Sub ToggleRibbonTab()
Attribute ToggleRibbonTab.VB_ProcData.VB_Invoke_Func = " \n0"
On Error GoTo ErrHandler
If Not App() Is Nothing Then
App().ToggleRibbonMode
End If
Exit Sub
ErrHandler:
Debug.Print "[ToggleRibbonTab] Error: " & Err.Description
MsgBox "Error al cambiar modo del Ribbon: " & Err.Description, vbExclamation
End Sub
'@Description: Macro publica para recuperar el Ribbon manualmente
'@Note: Ejecutar esta macro si el Ribbon desaparece o no responde
'@Category: Ribbon / Recuperacion
Public Sub RecuperarRibbon()
Attribute RecuperarRibbon.VB_ProcData.VB_Invoke_Func = " \n0"
Dim result As VbMsgBoxResult
LogInfo MODULE_NAME, "[RecuperarRibbon] - Solicitado por usuario"
Debug.Print GetRibbonDiagnostics()
' Si ya esta disponible, no hacer nada
If IsRibbonAvailable() Then
MsgBox "El Ribbon ya esta funcionando correctamente.", vbInformation, "Ribbon OK"
Exit Sub
End If
' Confirmar con el usuario
result = MsgBox("El Ribbon no esta disponible." & vbCrLf & vbCrLf & _
"Se intentara recuperar. Esto puede requerir" & vbCrLf & _
"recargar el complemento temporalmente." & vbCrLf & vbCrLf & _
"Consulte el log: " & GetLogFilePath() & vbCrLf & vbCrLf & _
"Desea continuar?", _
vbQuestion + vbYesNo, "Recuperar Ribbon")
If result <> vbYes Then Exit Sub
' Intentar recuperacion
If TryRecoverRibbon() Then
MsgBox "Ribbon recuperado exitosamente." & vbCrLf & vbCrLf & _
App.Ribbon.GetQuickDiagnostics(), vbInformation, "Recuperacion Exitosa"
Else
MsgBox "No se pudo recuperar el Ribbon automaticamente." & vbCrLf & vbCrLf & _
"Recomendaciones:" & vbCrLf & _
"1. Cierre Excel completamente" & vbCrLf & _
"2. Vuelva a abrir Excel" & vbCrLf & vbCrLf & _
"Consulte el log: " & GetLogFilePath(), _
vbExclamation, "Recuperacion Fallida"
End If
End Sub
'@Description: Muestra el diagnostico del Ribbon en un cuadro de dialogo
Public Sub MostrarDiagnosticoRibbon()
Attribute MostrarDiagnosticoRibbon.VB_ProcData.VB_Invoke_Func = " \n0"
LogInfo MODULE_NAME, "MostrarDiagnosticoRibbon - Solicitado"
MsgBox GetRibbonDiagnostics(), vbInformation, "Diagnostico del Ribbon"
End Sub
' ------------------------------------------
' FUNCIONES DE DIAGNOSTICO
' ------------------------------------------
'@Description: Obtiene informacion de diagnostico del estado del Ribbon
'@Returns: String | Descripcion del estado actual
Public Function GetRibbonDiagnostics() As String
Attribute GetRibbonDiagnostics.VB_Description = "[modMACROAppLifecycle] FUNCIONES DE DIAGNOSTICO Obtiene informacion de diagnostico del estado del Ribbon"
Attribute GetRibbonDiagnostics.VB_ProcData.VB_Invoke_Func = " \n23"
Dim info As String
info = "=== DIAGNOSTICO DEL RIBBON ===" & vbCrLf
info = info & "Fecha/Hora: " & Now & vbCrLf
info = info & "Log Path: " & GetLogFilePath() & vbCrLf
info = info & vbCrLf
' Estado de App
If App Is Nothing Then
info = info & "[X] App: Nothing (CRITICO)" & vbCrLf
GetRibbonDiagnostics = info
Exit Function
Else
info = info & "[OK] App: Disponible" & vbCrLf
End If
' Estado de Ribbon (clsRibbonEvents)
If App.Ribbon Is Nothing Then
info = info & "[X] App.Ribbon: Nothing (ERROR)" & vbCrLf
Else
info = info & "[OK] App.Ribbon: Disponible" & vbCrLf
' Diagnostico detallado
info = info & " -> " & App.Ribbon.GetQuickDiagnostics() & vbCrLf
' Estado de ribbonUI (IRibbonUI)
On Error Resume Next
If App.Ribbon.ribbonUI Is Nothing Then
info = info & "[X] ribbonUI: Nothing (PERDIDO)" & vbCrLf
info = info & " -> El Ribbon necesita recuperacion" & vbCrLf
Else
info = info & "[OK] ribbonUI: Conectado" & vbCrLf
info = info & " -> Tipo: " & TypeName(App.Ribbon.ribbonUI) & vbCrLf
End If
On Error GoTo 0
End If
' Estado de RibbonState
If App.RibbonState Is Nothing Then
info = info & "[X] RibbonState: Nothing" & vbCrLf
Else
info = info & "[OK] RibbonState: " & App.RibbonState.RibbonStateDescription & vbCrLf
End If
GetRibbonDiagnostics = info
End Function
'@Description: Verifica si el Ribbon esta disponible y funcional
' DESDE EL CONTEXTO GLOBAL
'@Returns: Boolean | True si el Ribbon esta operativo
Public Function IsRibbonAvailable() As Boolean
Attribute IsRibbonAvailable.VB_Description = "[modMACROAppLifecycle] Verifica si el Ribbon esta disponible y funcional DESDE EL CONTEXTO GLOBAL"
Attribute IsRibbonAvailable.VB_ProcData.VB_Invoke_Func = " \n23"
On Error Resume Next
' Verificar que App existe
If App Is Nothing Then
LogDebug MODULE_NAME, "IsRibbonAvailable: App Is Nothing"
IsRibbonAvailable = False
Exit Function
End If
' Verificar que Ribbon existe
If App.Ribbon Is Nothing Then
LogDebug MODULE_NAME, "IsRibbonAvailable: App.Ribbon Is Nothing"
IsRibbonAvailable = False
Exit Function
End If
' Verificar que ribbonUI existe
If App.Ribbon.ribbonUI Is Nothing Then
LogDebug MODULE_NAME, "IsRibbonAvailable: ribbonUI Is Nothing"
IsRibbonAvailable = False
Exit Function
End If
' Intentar una operacion simple para verificar que funciona
Dim testResult As Boolean
testResult = Not (TypeName(App.Ribbon.ribbonUI) = "Nothing")
If Err.Number <> 0 Then
LogWarning MODULE_NAME, "IsRibbonAvailable: Error al verificar - " & Err.Description
IsRibbonAvailable = False
Err.Clear
Else
IsRibbonAvailable = testResult
End If
On Error GoTo 0
End Function
' ------------------------------------------
' FUNCIONES DE RECUPERACION
' ------------------------------------------
'@Description: Intenta recuperar el Ribbon automaticamente
'@Returns: Boolean | True si la recuperacion fue exitosa
Public Function TryRecoverRibbon() As Boolean
Attribute TryRecoverRibbon.VB_Description = "[modMACROAppLifecycle] FUNCIONES DE RECUPERACION Intenta recuperar el Ribbon automaticamente"
Attribute TryRecoverRibbon.VB_ProcData.VB_Invoke_Func = " \n23"
On Error GoTo ErrHandler
LogInfo MODULE_NAME, "TryRecoverRibbon - Iniciando recuperacion..."
' METODO 1: Soft refresh (no invasivo)
If RecoverBySoftRefresh() Then
LogInfo MODULE_NAME, "TryRecoverRibbon - Exito via SoftRefresh"
TryRecoverRibbon = True
Exit Function
End If
' METODO 2: UI Refresh
If RecoverByUIRefresh() Then
LogInfo MODULE_NAME, "TryRecoverRibbon - Exito via UIRefresh"
TryRecoverRibbon = True
Exit Function
End If
' METODO 3: Toggle del add-in (ultimo recurso, solo en intento 2+)
If False Then
LogWarning MODULE_NAME, "TryRecoverRibbon - Intentando toggle del add-in (ultimo recurso)"
If RecoverByAddinToggle() Then
LogInfo MODULE_NAME, "TryRecoverRibbon - Exito via AddinToggle"
TryRecoverRibbon = True
Exit Function
End If
End If
LogError MODULE_NAME, "TryRecoverRibbon - Recuperacion fallida"
TryRecoverRibbon = False
Exit Function
ErrHandler:
LogError MODULE_NAME, "TryRecoverRibbon - Error", Err.Number, Err.Description
TryRecoverRibbon = False
End Function
'@Description: Intenta recuperar sin ningun reinicio
Private Function RecoverBySoftRefresh() As Boolean
On Error Resume Next
LogDebug MODULE_NAME, "RecoverBySoftRefresh - Verificando puntero"
DoEvents
Dim dummy As Object
Set dummy = Nothing
DoEvents
RecoverBySoftRefresh = IsRibbonAvailable()
If RecoverBySoftRefresh Then
LogInfo MODULE_NAME, "RecoverBySoftRefresh - Puntero recuperado sin reinicio"
End If
On Error GoTo 0
End Function
'@Description: Intenta recuperar forzando redibujado de la UI
Private Function RecoverByUIRefresh() As Boolean
On Error Resume Next
LogDebug MODULE_NAME, "RecoverByUIRefresh - Forzando redibujado de UI"
Application.ScreenUpdating = False
DoEvents
Application.ScreenUpdating = True
DoEvents
If Not ActiveWindow Is Nothing Then
ActiveWindow.Visible = True
End If
DoEvents
Application.Wait Now + TimeSerial(0, 0, 1)
DoEvents
RecoverByUIRefresh = IsRibbonAvailable()
If RecoverByUIRefresh Then
LogInfo MODULE_NAME, "RecoverByUIRefresh - Ribbon recuperado via UI refresh"
End If
On Error GoTo 0
End Function
'@Description: Recupera el Ribbon toggleando el estado del add-in
Private Function RecoverByAddinToggle() As Boolean
On Error GoTo ErrHandler
LogInfo MODULE_NAME, "RecoverByAddinToggle - Iniciando toggle del add-in"
Dim ai As AddIn
Dim targetAddin As AddIn
' Buscar nuestro add-in
For Each ai In Application.AddIns
If ai.Name = APP_NAME & ".xlam" Then
Set targetAddin = ai
Exit For
End If
Next ai
If targetAddin Is Nothing Then
LogError MODULE_NAME, "RecoverByAddinToggle - Add-in no encontrado: " & APP_NAME & ".xlam"
RecoverByAddinToggle = False
Exit Function
End If
' Solo proceder si esta instalado
If Not targetAddin.Installed Then
LogError MODULE_NAME, "RecoverByAddinToggle - Add-in no esta instalado"
RecoverByAddinToggle = False
Exit Function
End If
' Toggle: desactivar y reactivar
LogDebug MODULE_NAME, "RecoverByAddinToggle - Desactivando add-in..."
targetAddin.Installed = False
' Pequeña pausa
DoEvents
Application.Wait Now + TimeSerial(0, 0, 1)
DoEvents
LogDebug MODULE_NAME, "RecoverByAddinToggle - Reactivando add-in..."
targetAddin.Installed = True
' Pausa para que se recargue
DoEvents
Application.Wait Now + TimeSerial(0, 0, 2)
DoEvents
' Verificar si se recupero
RecoverByAddinToggle = IsRibbonAvailable()
If RecoverByAddinToggle Then
LogInfo MODULE_NAME, "RecoverByAddinToggle - Ribbon recuperado via toggle"
Else
LogWarning MODULE_NAME, "RecoverByAddinToggle - Toggle completado pero Ribbon no disponible"
End If
Exit Function
ErrHandler:
LogError MODULE_NAME, "RecoverByAddinToggle - Error", Err.Number, Err.Description
RecoverByAddinToggle = False
End Function