关闭屏幕更新,如果它一直打开,请将其重新打开?

时间:2015-07-02 09:19:31

标签: c# excel

运行使用Excel的程序时,我通常会在程序开始时关闭某些应用程序设置,然后在程序结束时再次打开它们。

关闭和打开应用程序设置的代码:

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;
        }
    }
}

我按以下方式调用此程序:

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

这很有效。

但是说我只想在运行API.TurnAppSettingsOff()之前打开已启用的应用设置。什么是编码的好方法?

一些想法:

  • 我想我需要以某种方式保存应用程序设置的先前状态。例如,写下:

Boolean screenUpdating = AddinModule.CurrentInstance.ExcelApp.ScreenUpdating;

  • 我希望最终结果是正确的,即使关闭和打开appsettings的函数也会调用另一个关闭和打开应用程序设置的功能。

  • 我不知道是否最好使用API.TurnAppSettingsOff()之类的命令设置所有设置,或者用户API.TurnScreenUpdatingOff()API.TurnEventsOff()是否更明智

4 个答案:

答案 0 :(得分:1)

我只是掀起一个内部经理类来处理类似于以下内容的整个事情:

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);
        }
    }
}

这应该可以解决问题。您可以按如下方式使用它;

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();

你完成了!

答案 1 :(得分:0)

这是我自己提出的解决问题的解决方案。对我来说,这似乎比其他建议的解决方案更简单。如果您认为自己有更好的解决方案,请告诉我们!

(我的代码恰好在VB.NET中)

处理更改设置和存储原始状态的类:

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

以下是我在代码中使用它的方法:

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

答案 2 :(得分:-1)

您可以使用Stack<T>类来实现后进先出(LIFO)行为。

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
    }
}

答案 3 :(得分:-1)

我建议使用整数来表示状态,并使用布尔值隐藏它。这就是我的意思:

this.Working = true;

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

然后实现Working属性,如下所示:

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

在内部,它只记得使用该整数设置的工作次数。如果working0,那么您将恢复正常。

您可以根据需要设置Working次。只要> 0它就会返回true。不要忘记将代码包装成try...catch,否则您将失去计数。

如果Working设置为false,您可以执行API调用。然后将其设置为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();
}