2010-08-25 14 views
7

Ho una cartella di lavoro di Excel contenente alcuni controlli ComboBox posizionati direttamente sui fogli. Si tratta di caselle combinate standard dalla barra degli strumenti Moduli.Excel VBA: trigger Salva come Modifica evento in ComboBox

Quando l'utente utilizza "Salva con nome" per salvare la cartella di lavoro con un nome diverso, attiva l'evento Cambia in tutte le caselle combinate, incluse quelle su fogli che non sono attivi. Ciò sembra irragionevole in quanto la selezione non è effettivamente cambiata. Ciò causa vari comportamenti indesiderati a causa del codice nei gestori di eventi. L'evento non viene attivato su un semplice "Salva".

Google suggests questo è un problema noto in Excel. Ci sono rumours che è causato dall'utilizzo di un intervallo denominato come ListFillRange per la casella combinata, cosa che ho fatto, sebbene non sia un nome volatile. Sto cercando un modo per evitare che ciò accada con modifiche minime al codice e al foglio di calcolo. Qualcuno ha una soluzione comprovata?

+3

Non riesco a riprodurre questo comportamento utilizzando Excel 2007, né utilizzando intervalli normali né utilizzando intervalli denominati. Forse dovresti caricare un esempio ... –

+0

@belisarius Non riesco a caricare la cartella di lavoro completa perché contiene un sacco di codice proprietario. Non ho tempo adesso per provare a produrre un piccolo esempio :( – MarkJ

+1

Impossibile confermare in Excel 2003. Potresti confermare che stai utilizzando il controllo "Forms" e non il controllo erm, "Controls"? dannazione, Microsoft!) Il controllo Forms non ha un evento 'Change' o proprietà come' ListFillRange'. – Lunatik

risposta

2

È possibile impostare un flag nell'evento BeforeSave della cartella di lavoro e quindi controllare tale flag prima di elaborare un evento di modifica in ciascuna casella combinata. Non sembra esserci un evento AfterSave, quindi è necessario cancellare la bandiera dopo averla controllata all'interno degli eventi di modifica della casella combinata. La bandiera avrebbe dovuto essere più di un semplice booleano poiché non poteva essere disattivata fino a quando non venivano elaborati tutti gli eventi di modifica della casella combinata. Ecco alcuni esempi di codice:

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 

ho impostare il numero di eventi di modifica casella combinata come una costante, ma ci può essere qualche modo per determinare il numero di programmazione. Questa soluzione alternativa richiede l'aggiunta di codice ad ogni evento di modifica casella combinata, ma dovrebbe essere semplice poiché tutto ciò che devi fare è copiare e incollare la riga If JustSaved Then Exit Sub all'inizio di ogni evento.

Questa soluzione alternativa presuppone che l'evento Workbook BeforeSave venga chiamato prima degli eventi di modifica della casella combinata. Non so per certo se questo è il caso.

+0

Questa non è una cattiva idea, ma significa che devi conoscere il numero di OLEObjects che genererà un cambiamento evento su SaveAs.Inoltre, l'uso di un Const non è ortodosso: una costante non dovrebbe essere modificata.Questa soluzione si basa su una funzionalità non documentata di codice buggato.Non vi è alcuna garanzia che sia affidabile.Quello che è destinato a accadere è che alcuni Gli eventi di _bona fide verranno persi. – adamleerich

3

Ho eseguito le seguenti operazioni in una nuova cartella di lavoro con un solo foglio, Foglio1, e sembrava funzionare per gli eventi diable prima di salvarli e quindi riattivarli dopo. Dovrebbe bypassare il problema che si vede simulando un evento AfterSave. Questo è il mio codice di evento di Sheet1 (potrebbe essere il codice OLEObject, troppo)

Option Explicit 

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

Questo è il mio codice 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 

Il metodo .OnTime lancia l ' "evento" AfterSave nella coda di esecuzione. Funziona!