2014-02-27 24 views
5

Ich habe ein Excel-VBA-Makro, das für eine lange Zeit läuft (möglicherweise für Tage, führt es Datenerfassung). Es wurde ursprünglich für Excel 2003 geschrieben und verfügt über benutzerdefinierte Symbolleisten und Menüs. Ich habe es kürzlich aktualisiert, um eine Ribbon-Schnittstelle mit RibbonXML zu verwenden.Excel VBA Ribbon getEnabled nicht aufgerufen, wenn der Code läuft

Wenn das Makro läuft ich einige Interface-Elemente (wie zum Beispiel „Start Test“) deaktivieren möchten, und andere ermöglichen (wie die „Stop-Test“ -Taste.)

Das Problem, das ich ist haben, dass Anrufe to band.invalidate werden nur verarbeitet nach der Makrocode wurde bis zum Abschluss ausgeführt.

Sie diesen Effekt sehen kann ganz leicht mit einem einfachen Testprogramm

Sub test() 

ribbon.Invalidate 
DoEvents 
Sleep (5000) 

End Sub 

A debug.print in dem Band „getEnabled“ Rückruf wird erst am Ende des 5 Sekunden Schlaf actioned werden sehen.

Gibt es eine Möglichkeit, ein Farbband zu erzwingen.Invalidate wird dort aktiviert?

:: Edit 1 ::

ich eine kleine Demo-Arbeitsmappe erstellt haben, um das Problem zu mitströmen: http://www.bodgesoc.org/Button_Demo.xlsm

:: Edit 2 ::

Ein Mitglied aus einem anderen Forum ein gefundenes Lösung, obwohl es ein etwas hässlicher ist. Ich denke, das kann jetzt als "beantwortet" markiert werden, aber eine elegantere Lösung würde geschätzt werden.

Application.ScreenUpdating = False 
Application.ExecuteExcel4Macro "Show.ToolBar(""Ribbon"",False)" 
Application.ExecuteExcel4Macro "Show.ToolBar(""Ribbon"",True)" 
Application.ScreenUpdating = True 

Antwort

0

Ich weiß nicht, ob dies als nicht weniger hässlich ist, was Sie haben, aber ...

'Callback for Run onAction 
Sub Run_r(control As IRibbonControl) 

    SetRunning "Run_r_procedure" 
    DoEvents 

End Sub 

Sub Run_r_procedure() 
    Dim T As Single 

    Sheet1.Range("A10").Value = "Run pressed, button states changed, and ribbon invalidated. Waiting 5 seconds in loop" 
    T = Timer 
    Do While Timer - T < 5 
     DoEvents 
    Loop 
    Sheet1.Range("A10") = "" 

End Sub 

Und dann in SetRunning

Sub SetRunning(ByVal ProcToRun As String) 

    Sheet1.Range("B1") = "Disabled" 
    Sheet1.Range("B2") = "Disabled" 
    Sheet1.Range("B3") = "Enabled" 
    Sheet1.Range("B4") = "Enabled" 
    Sheet1.Range("B5") = "Enabled" 
    Sheet1.Range("B6") = "Enabled" 
    Sheet1.Range("B7") = "Enabled" 

    myRibbon.Invalidate 
    myRibbon.InvalidateControl ("Run") 

    Application.OnTime Now, ProcToRun 

End Sub 

Also muss man haben zwei Prozeduren pro Callback - der Callback und dann was auch immer SetRunning aufrufen wird, das tut die eigentliche Arbeit. Der Code ist genauso hässlich, aber die Benutzeroberfläche ist etwas weniger seltsam für den Benutzer.

+0

Danke, ich habe mich darüber gewundert, den Code tatsächlich stoppen zu lassen und eine zeitgesteuerte Prozedur wie diese einzureihen, aber ich hatte Angst, dass sich das auf unvorhersehbare Art und Weise ändern könnte. Aber jetzt weiß ich, dass jemand anderes die Idee hatte, dass ich zumindest überzeugt bin, dass es nicht total verrückt ist, und ich könnte es versuchen. – bodgesoc