带日志类的Excel加载项:如何应对VBA状态丢失? 设置

带日志类的Excel加载项:如何应对VBA状态丢失? 设置,excel,excel-addins,vba,Excel,Excel Addins,Vba,我正在开发和维护一个Excel加载项,它在Excel的功能区UI中有自己的控件选项卡。我以前遇到过状态丢失的问题(意味着丢失所有具有全局范围的变量、静态变量等,当然包括我对RibbonUI的引用)。关于ribbon引用,我通过包含一个“Reset ribbon”(重置ribbon)按钮“解决”了这个问题,该按钮从持久存储的指针恢复引用,然后使ribbon无效。虽然肯定不是最优雅的,但这一部分工作得很好 然而,在引入日志类之后,状态丢失问题再次困扰着我。记录器在该工作簿的模块中实例化: Priva

我正在开发和维护一个Excel加载项,它在Excel的功能区UI中有自己的控件选项卡。我以前遇到过状态丢失的问题(意味着丢失所有具有全局范围的变量、静态变量等,当然包括我对RibbonUI的引用)。关于ribbon引用,我通过包含一个“Reset ribbon”(重置ribbon)按钮“解决”了这个问题,该按钮从持久存储的指针恢复引用,然后使ribbon无效。虽然肯定不是最优雅的,但这一部分工作得很好

然而,在引入日志类之后,状态丢失问题再次困扰着我。记录器在该工作簿的模块中实例化:

Private Sub Workbook_Open()
    Set LogToFile = SingletonFactory.getToFileLogger
End Sub
然后开始工作,例如,如下所示:

Private Sub buttonReloadObjects_onAction(ByVal control As IRibbonControl)
    LogToFile.trace "Event firing: buttonReloadObjects_onAction"
    ' more stuff happening...
    invalidateRibbon ' restores ribbon object and invalidates it
End Sub
加载外接程序时会实例化记录器,这样我就可以在外接程序代码的范围内自由地记录我想要的任何内容。它有几个日志记录级别,如跟踪/调试/错误/。。。还有一些其他的方法。通常情况下,它工作正常-直到状态丢失(通常由不相关的错误引起,然后单击“结束”)

国家损失 此时,VBA环境忘记了my
LogToFile
对象的存在,任何东西都不再起作用,因为每次单击功能区控件都会触发运行时错误91:Object variable或with block variable not set,指向第一个包含对
LogToFile
的引用的行

解决方案? 现在,除了做一些疯狂的变通方法,比如

if not isObject(LogToFile) then
    Set LogToFile = SingletonFactory.getToFileLogger
end if
LogToFile.trace "Message"
在出现任何
LogToFile
之前,我能想到的唯一真正的“解决方案”是将所有记录器调用封装在函数中(驻留在标准模块中),并在任何时候向日志发送内容时调用这些函数。这样,我就可以在需要对象之前捕获丢失的对象引用,并且避免调用未实例化对象的方法。
然而,在将所有内容整齐地封装在类模块中之后,我觉得沿着这条路线走下去很奇怪,甚至可能是错误的(?)


那么,对于丢失记录器实例的问题是否有“适当”的解决方案?或者,我建议的方法已经尽可能恰当了吗



注意:这个问题当然不是特定于日志类的。它影响所有全局变量,尤其是我的ApplicationEventClass。这个问题恰好是logger最突出的问题,因为它经常在代码的所有入口点使用。

您只需要一个返回原始变量或重置它的函数。如果调用该函数
LogToFile
,则无需更改任何其他代码,只需删除
Workbook\u Open
代码,这是多余的。因此:

Function LogToFile() As WhateverVariableType
Static temp as WhateverVariableType
If temp is Nothing then Set temp = SingletonFactory.getToFileLogger
Set LogToFile = temp
End Function
这样,在编写代码时,您仍将受益于Intellisense


注意:您可能实际上并不需要temp变量-这取决于是否有您想要持久化的设置。如果有,您可能也希望在函数中重置它们。

您只需要一个返回原始变量或重置原始变量的函数。如果调用该函数
LogToFile
,则无需更改任何其他代码。有趣的想法。但是我是否仍然可以使用日志记录方法,如
LogToFile.warn“Warning message”
?是的
LogToFile
将返回正确的对象,因此您可以像以前一样调用这些方法。你不再需要
工作簿\u open
代码了。哇,只是尝试了一下这个概念。真漂亮!(乍一看也有点混乱,但与使用带有数字返回值的函数相比,它基本上与对象相同。)您介意将此作为一个答案发布吗?否则我可以试着写点东西。最后一个问题:这项技术有什么缺点吗?非常感谢!实际上,在我的
SingletonFactory
模块中已经有了类似于您的示例函数的东西。我缺少的难题是,我可以直接用一个返回记录器类型的函数替换记录器变量的任何事件,并且仍然可以访问记录器的所有公共属性和方法。