2010-08-25 12 views
7

Mam skoroszyt programu Excel zawierający elementy sterujące ComboBox umieszczone bezpośrednio na arkuszach. Są to standardowe pola kombi na pasku narzędzi Forms.Excel VBA: Zapisz jako powoduje zmianę zdarzenia w ComboBox

Gdy użytkownik używa "Zapisz jako", aby zapisać skoroszyt o innej nazwie, wywoła to zdarzenie Zmień we wszystkich polach kombi, w tym na arkuszach, które nie są aktywne. Wydaje się to nieuzasadnione, ponieważ wybór nie ulegnie zmianie. Powoduje to różne niepożądane zachowania z powodu kodu w procedurach obsługi zdarzeń. Zdarzenie nie jest wyzwalane na zwykłym "Zapisz".

Google suggests jest to znany problem w programie Excel. Istnieje rumours, który jest spowodowany przez użycie nazwanego zakresu jako ListFillRange dla pola kombi, które zrobiłem, chociaż nie jest to nazwa lotna. Szukam sposobu, aby temu zapobiec, wprowadzając minimalne zmiany w kodzie i arkuszu kalkulacyjnym. Czy ktoś ma sprawdzone rozwiązanie?

+3

Nie mogę odtworzyć tego zachowania za pomocą programu Excel 2007, ani przy użyciu normalnych zakresów, ani przy użyciu nazwanych zakresów. Być może powinieneś przesłać przykład ... –

+0

@belisarius Nie mogę załadować pełnego skoroszytu, ponieważ zawiera on wiele zastrzeżonych kodów. Nie mam teraz czasu, aby wypróbować mały przykład :( – MarkJ

+1

Nie mogę potwierdzić w programie Excel 2003. Czy możesz potwierdzić, że używasz formantu "Forms", a nie kontrolki "Controls"? cholera, Microsoft!) Formant Forms nie ma zdarzenia 'Change' ani właściwości takich jak' ListFillRange'. – Lunatik

Odpowiedz

2

Można ustawić flagę w przypadku skoroszytu za BeforeSave a następnie sprawdzić tę flagę przed przetworzeniem zdarzenia zmiany w każdym z pól kombi. Wydaje się, że nie ma zdarzenia AfterSave, więc trzeba wyczyścić flagę po sprawdzeniu jej w zdarzeniach zmiany pola kombi. Flaga musi być czymś więcej niż zwykłą boolowską, ponieważ nie można jej wyłączyć, dopóki nie zostaną przetworzone wszystkie zdarzenia zmiany pola kombi. Oto niektóre przykładowy kod:

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 

ustawić liczbę zdarzeń zmian pola kombi jako stała, ale nie może być jakiś sposób, aby określić tę liczbę programowo. To obejście wymaga dodania kodu do każdego zdarzenia zmiany pola kombi, ale powinno być łatwe, ponieważ wystarczy tylko skopiować i wkleić wiersz If JustSaved Then Exit Sub na początku każdego zdarzenia.

To rozwiązanie zakłada, że ​​zdarzenie skoroszyt BeforeSave zostanie sprawdzony przed wydarzeniami zmian pola kombi. Nie wiem na pewno, jeśli tak jest.

+0

To nie jest zły pomysł, ale oznacza to, że musisz znać liczbę obiektów OLEO, które rzucają zmianę Zdarzenie na SaveAs.Również korzystanie z Const jest nieortodoksyjne, stała nie powinna być zmieniana.To rozwiązanie opiera się na nieudokumentowanej funkcji kodu buggy.Nie ma gwarancji, że będzie on wiarygodny.Jest to, co się musi stać, jest to, że niektóre Zdarzenia _bona fide_ zostaną pominięte. – adamleerich

3

zrobiłem następujące w nowym skoroszycie z tylko jednym arkuszu Arkusz1, i wydawało się do pracy, aby Diable wydarzenia przed zapisać, a następnie ponownie włączyć je później. Powinien ominąć problem, który widzisz, symulując wydarzenie AfterSave. To jest mój kod zdarzenia na Arkusz1 (może być kod OLEObject, zbyt)

Option Explicit 

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

To jest mój kod 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 

Sposób .OnTime rzuca "event" AfterSave na kolejce wykonania. To działa!