2010-08-25 27 views
7

Tengo un libro de Excel que contiene algunos controles ComboBox colocados directamente en las hojas. Estos son cuadros combinados estándar de la barra de herramientas Formularios.Excel VBA: Guardar como activa el evento Cambiar en ComboBox

Cuando el usuario utiliza "Guardar como" para guardar el libro con un nombre diferente, esto desencadena el evento Cambiar en todos los cuadros combinados, incluidos los que se encuentran en las hojas que no están activas. Esto parece irrazonable ya que la selección no ha cambiado realmente. Esto provoca varios comportamientos no deseados debido al código en los controladores de eventos. El evento no se desencadena en un simple "Guardar".

Google suggests este es un problema conocido en Excel. Hay rumours que es causado por el uso de un rango con nombre como ListFillRange para el cuadro combinado, que he hecho, aunque no es un nombre volátil. Estoy buscando una manera de evitar que esto ocurra con cambios mínimos en el código y la hoja de cálculo. ¿Alguien tiene una solución probada?

+3

No soy capaz de reproducir este comportamiento utilizando Excel 2007, ni utilizando rangos normales ni usando rangos con nombre. Quizás deba subir un ejemplo ... –

+0

@belisarius No puedo cargar el libro de trabajo completo porque contiene una gran cantidad de código de propiedad. No tengo tiempo en este momento para tratar de producir un pequeño ejemplo :( – MarkJ

+1

No se puede confirmar en Excel 2003. ¿Podría confirmar que está utilizando el control "Formularios" y no el control "Controles"? ¡Maldito seas, Microsoft!) El control Forms no tiene un evento 'Change' o propiedades como' ListFillRange'. – Lunatik

Respuesta

2

Puede establecer un indicador en el evento BeforeSave del Libro de trabajo y luego verificar ese indicador antes de procesar un evento de cambio en cada uno de los cuadros combinados. No parece haber un evento AfterSave, por lo que necesitaría borrar el indicador después de verificarlo dentro de los eventos de cambio de cuadro combinado. La bandera necesitaría ser más que un booleano simple ya que no se podría desactivar hasta que se procesen todos los eventos de cambio del cuadro combinado. He aquí algunos ejemplos de código:

Public ComboBoxChangeCounter As Integer 

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) 
    Const NumOfComboBoxChangeEvents As Integer = 5 
    ComboBoxChangeCounter = NumOfComboBoxChangeEvents 
End Sub 

Function JustSaved() As Boolean 
    If ComboBoxChangeCounter > 0 Then 
     ComboBoxChangeCounter = ComboBoxChangeCounter - 1 
     JustSaved = True 
    End If 
End Function 

Private Sub Combo1_Change() 
    If JustSaved Then Exit Sub 
    'Your existing code ' 
    ' ... ' 
    ' ... ' 
    ' ... ' 
End Sub 

que establecer el número de eventos de cambio de cuadro combinado como una constante, pero puede haber alguna manera para que usted pueda determinar ese número mediante programación. Esta solución requiere agregar código a cada evento de cambio de cuadro combinado, pero debe ser fácil ya que todo lo que necesita hacer es copiar y pegar la línea If JustSaved Then Exit Sub al comienzo de cada evento.

Esta solución supone que se llamará al evento Workbook BeforeSave antes de que el cuadro combinado cambie los eventos. No sé de hecho si ese es el caso.

+0

Esto no es una mala idea, pero significa que debes saber la cantidad de OLEObjects que lanzarán un cambio evento en SaveAs. Además, el uso de un Const no es ortodoxo, no se debe cambiar una constante. Esta solución se basa en una característica no documentada del código erróneo. No hay garantía de que sea confiable. Lo que es inevitable es que algunos _bona fide_ events se perderán. – adamleerich

3

Hice lo siguiente en un nuevo libro de trabajo con una sola hoja, Sheet1, y parecía funcionar para predecir eventos antes de guardar y luego volver a habilitarlos. Debería eludir el problema que ves al imitar un evento AfterSave. Este es mi código de evento en Sheet1 (podría ser el código OLEObject, también)

Option Explicit 

Private Sub Worksheet_Change(ByVal Target As Range) 
    MsgBox Target.Address & ": " & Target.Value 
End Sub 

Este es mi código ThisWorkbook

Option Explicit 

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) 

    ' To see the change code work before disabling 
    ' Should show a message box 
    Sheet1.Range("A1") = "Before After Events Off" 

    Application.EnableEvents = False 
    Application.OnTime Now, "ThisWorkbook.Workbook_AfterSave" 

    ' This time it will not show a message box 
    ' You will never see this one . . . 
    Sheet1.Range("A1") = "After After Events Off" 

End Sub 

Private Sub Workbook_AfterSave() 
    Application.EnableEvents = True 
End Sub 

El método .OnTime lanza el "evento" afterSave en la cola de ejecución. ¡Funciona!