关闭屏幕更新并重新打开(如果一开始是打开的)
本文关键字:一开始 如果 屏幕 更新 新打开 | 更新日期: 2023-09-27 18:00:55
运行使用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()
之前打开的应用程序设置。什么是编写代码的好方法
一些想法:
- 我想我需要以某种方式保存应用程序设置的先前状态。例如,通过书写:
布尔屏幕更新=AddinModule.CurrentInstance.ExcelApp.ScreenUpdate;
我希望最终结果是正确的,即使一个关闭和打开应用程序设置的函数也会调用另一个关闭或打开应用程序的函数。
我不知道使用一个命令(如
API.TurnAppSettingsOff()
(设置所有设置是否最好,或者使用API.TurnScreenUpdatingOff()
和API.TurnEventsOff()
是否更明智。
我只想创建一个内部管理器类来处理类似于以下的整个事情:
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();
你完了!
这是我自己为解决这个问题而提出的解决方案。对我来说,这似乎比其他建议的解决方案更简单。如果你认为你有更好的解决方案,请告诉我!
(我下面的代码恰好在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
我建议使用整数来表示状态,并使用布尔值隐藏它。这就是我的意思:
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--;
}
}
}
在内部,它只记得使用该整数设置的工作次数。如果working
是0
,那么您已恢复正常。
您可以根据需要多次设置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();
}
您可以使用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
}
}