2015-07-02 12 views
6

Podczas uruchamiania procedur korzystających z programu Excel zazwyczaj wyłączam niektóre ustawienia aplikacji na początku procedury, a następnie włączam je ponownie po zakończeniu procedury.Wyłącz aktualizację ekranu i włącz ją ponownie, jeśli była włączona?

Kod do toczenia ustawienia aplikacji i wyłączanie:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace XLTimeTracker 
{ 
    class API 
    { 
     public static void TurnAppSettingsOff() 
     { 
      AddinModule.CurrentInstance.ExcelApp.EnableEvents = false; 
      AddinModule.CurrentInstance.ExcelApp.ScreenUpdating = false; 
     } 

     public static void TurnAppSettingsOn() 
     { 
      if (AddinModule.CurrentInstance.ExcelApp == null) return; 

      AddinModule.CurrentInstance.ExcelApp.EnableEvents = true; 
      AddinModule.CurrentInstance.ExcelApp.ScreenUpdating = true; 
     } 
    } 
} 

Ja nazywam to procedury w następujący sposób:

API.TurnAppSettingsOff(); 
// my code 
API.TurnAppSettingsOn(); 

Działa to dobrze.

Ale powiedz, że chcę tylko włączyć ustawienia aplikacji, które były włączone, zanim uruchomiłem API.TurnAppSettingsOff(). Jaki byłby dobry sposób, aby to zakodować?

Niektóre myśli:

  • Chyba musiałbym zapisać poprzedni stan ustawieniach aplikacji jakoś. Na przykład pisząc:

Boolean screenUpdating = AddinModule.CurrentInstance.ExcelApp.ScreenUpdating;

  • Chciałbym końcowy wynik będzie prawidłowy, nawet jeśli funkcja, która włącza i wyłącza AppSettings wzywa również inną funkcję, która zamienia ustawienia aplikacji i wyłączać.

  • ja nie wiem, czy to najlepiej ustawić wszystkie ustawienia za pomocą jednego polecenia, takie jak API.TurnAppSettingsOff() lub jeśli byłoby rozsądniej użytkownik API.TurnScreenUpdatingOff() i API.TurnEventsOff().

Odpowiedz

-1

Można użyć klasy Stack<T> wdrożyć ostatni-in-first-out (LIFO) zachowanie.

struct ExcelEventSettings 
{ 
    public bool EnableEvents; 
    public bool ScreenUpdating; 
} 

class Example 
{ 
    private Stack<ExcelEventSettings> settingStack = new Stack<ExcelEventSettings>(); 

    // you can call this function as often as you called SaveAppSettings 
    public void RestoreAppSettings() 
    { 
     if (settingStack.Count == 0) 
      throw new Exception("There is no previous state!"); 

     ExcelEventSettings prevState = settingStack.Pop(); 

     setCurrentEnableEvents(prevState.EnableEvents); 
     setCurrentScreenUpdating(prevState.ScreenUpdating); 
    } 

    public void SetAppSettings(bool enableEvents, bool screenUpdating) 
    { 
     ExcelEventSettings currentState; 

     currentState.EnableEvents = getCurrentEnableEvents(); 
     currentState.ScreenUpdating = getCurrentScreenUpdating(); 

     settingStack.Push(currentState); 

     setCurrentScreenUpdating(enableEvents); 
     setCurrentEnableEvents(screenUpdating); 
    } 

    private bool getCurrentEnableEvents() 
    { 
     // Here you would call your Excel function 
    } 

    private bool getCurrentScreenUpdating() 
    { 
     // Here you would call your Excel function 
    } 

    private void setCurrentEnableEvents(bool value) 
    { 
     // Here you would call your Excel function 
    } 

    private void setCurrentScreenUpdating(bool value) 
    { 
     // Here you would call your Excel function 
    } 
} 
+1

Bez wyjaśnienia, w jaki sposób operator może to wykorzystać, nie jest to nic więcej niż komentarz. – Sayse

+0

Przygotowuję przykład właśnie w tych chwilach. –

-1

Zalecam użycie liczby całkowitej do przedstawienia stanu i ukrycie go za pomocą wartości logicznej. To, co mam na myśli:

this.Working = true; 

try 
{ 
    // do something 
} 
finally 
{ 
    this.Working = false; 
} 

Następnie wdrożyć właściwość Working tak:

private int working; 
public bool Working 
{ 
    get { return working > 0; } 
    set 
    { 
     if (value) 
     { 
      working++; 
     } 
     else 
     { 
      working--; 
     } 
    } 
} 

Wewnętrznie to tylko pamięta, ile razy pracujący jako ustalono, stosując tę ​​całkowitą. Jeśli working jest 0, oznacza to, że powróciłeś do normalności.

Możesz ustawić Working tyle razy, ile chcesz. Dopóki jest to > 0, zwróci true. Nie zapomnij zawinąć kodu w numer try...catch, bo stracisz rachubę.

Możesz wykonać wywołanie API, jeśli Working jest ustawione na false.Następnie ustawić go do true:

if (!this.Working) 
{ 
    // do API call 
    this.TurnAppSettingsOff(); 
} 

this.Working = true; 

try 
{ 
    // do something 
} 
finally 
{ 
    this.Working = false; 
} 

if (!this.Working) 
{ 
    // do reset API call 
    this.TurnAppSettingsOn(); 
} 
1

bym po prostu wzbudzać wewnętrzny klasy menedżera, który obsługuje całość podobny do następującego:

public sealed class ApplicationSettingsManager 
{ 
    readonly object app; 
    readonly Dictionary<string, object> appSettings; 

    public ApplicationSettingsManager(object app) 
    { 
     this.app = app; 
     appSettings = new Dictionary<string, object>(); 
    } 

    public object Application { get { return app; } } 

    public void SaveSetting(string settingName) 
    { 
     var propInfo = app.GetType().GetProperty(settingName); 
     if (propInfo == null) 
      throw new ArgumentException("Specified name is not a valid storable setting.", "setting"); 

     var value = propInfo.GetValue(app); 

     if (appSettings.ContainsKey(settingName)) 
     { 
      appSettings[settingName] = value; 
     } 
     else 
     { 
      appSettings.Add(settingName, value); 
     } 
    } 

    public void SaveAllSettings() 
    { 
     var properties = app.GetType().GetProperties().Where(p => p.CanWrite && 
                  p.CanRead && 
                  p.SetMethod.IsPublic && 
                  p.GetMethod.IsPublic); 

     foreach (var p in properties) 
     { 
      var value = p.GetValue(app); 

      if (appSettings.ContainsKey(p.Name)) 
      { 
       appSettings[p.Name] = value; 
      } 
      else 
      { 
       appSettings.Add(p.Name, value); 
      } 
     } 
    } 

    public void RestoreSetting(string settingName) 
    { 
     if (!appSettings.ContainsKey(settingName)) 
      throw new ArgumentException("Specified name does not correspond to a valid stored setting.", "settingName"); 

     var propInfo = app.GetType().GetProperty(settingName); 
     propInfo.SetValue(app, appSettings[settingName]); 
    } 

    public void RestoreAllSettingas() 
    { 
     foreach (var p in appSettings) 
     { 
      RestoreSetting(p.Key); 
     } 
    } 
} 

To powinno załatwić sprawę. Użyłbyś go w następujący sposób;

var excelSettingsManager = new ApplicationSettingsManager(AddinModule.CurrentInstance.ExcelApp); 

//store all settings you are going to tamper with... 
excelSettingsManager.SaveSetting("EnableEvents"); 
excelSettingsManager.SaveSetting("ScreenUpdating"); 

//change excel setting and do your thing... 
//... 
//when done, restore settings 

excelSettingsManager.RestoreAllSettings(); 

I gotowe!

0

Oto moje własne rozwiązanie, które wymyśliłem, aby rozwiązać problem. Wydaje mi się to prostsze niż inne sugerowane rozwiązania. Daj mi znać, jeśli uważasz, że masz lepsze rozwiązanie!

(Mój kod poniżej dzieje się w VB.NET)

Klasa obsłużyć zmianę ustawień i przechowywania stanu pierwotnego:

Public Class ApplicationSettings 
    Implements IDisposable 
    Private ScreenUpdating As Boolean 
    Private Events As Boolean 
    Private Production As Boolean = True 

    Public Sub New() 
     MyBase.New() 
     ScreenUpdating = AddinModule.ExcelApp.ScreenUpdating 
     Events = AddinModule.ExcelApp.EnableEvents 
    End Sub 

    Public Sub Dispose() Implements IDisposable.Dispose 
     AddinModule.ExcelApp.ScreenUpdating = ScreenUpdating 
     AddinModule.ExcelApp.EnableEvents = Events 
    End Sub 
End Class 

A oto jak go używać w kodzie:

Private Sub AdxRibbonButton1_OnClick(sender As Object, control As IRibbonControl, pressed As Boolean) Handles AdxRibbonButton1.OnClick 
    Using New ApplicationSettings 
     'My code 
    End Using 
End Sub 
Powiązane problemy