在我写这篇文章的时候,这个问题已经相当老了(已经有5年了),但是这个问题为我提供了我需要完全解决这个问题的信息。我能够采用@jerryact提供的答案并加以扩展来解决我的问题。
首先,与原帖作者类似,我将我的UDF注册在Workbook_Open
事件中,当作为Add-In加载时,会导致打开Excel时显示Run-time error '1004': Cannot edit a macro on a hidden workbook. Unhide the workbook using the Unhide command.
错误消息。
使用上面@jerryact的答案中的信息,我将我的代码更改为以下内容:
Option Explicit
Private WithEvents App As Application
Private Sub Workbook_BeforeClose(Cancel As Boolean)
modUDFs.UnregisterUDF "DMS_2_DD"
modUDFs.UnregisterUDF "DD_2_DMS"
modUDFs.UnregisterUDF "ElapsedTime"
End Sub
Private Sub Workbook_Open()
Set App = Application
End Sub
Private Sub App_WorkbookActivate(ByVal Wb As Workbook)
modUDFs.RegisterUDF "Converts Decimal Degrees to Degrees, Minutes, Seconds" & vbLf & "rbcDD_2_DMS(<Decimal Degrees>)", "DD_2_DMS", 3
modUDFs.RegisterUDF "Converts Degrees, Minutes, Seconds to Decimal Degrees" & vbLf & "rbcDMS_2_DD(<Degrees Minutes Seconds>)", "DMS_2_DD", 3
modUDFs.RegisterUDF "Calculates the Time between two time stamps" & vbLf & _
"rbcElapsedTime(<end time>,<start time>,<output code>)" & vbLf & _
"0 = <Seconds>, 1 = <Minutes:Seconds>" & vbLf & _
"2 = <Hours:Minutes:Seconds>, 3 = <Days Hours:Minutes:Seconds>", "ElapsedTime", 2
End Sub
这个方法非常有效,看起来解决了我的问题(99.9%的情况下都是如此)。然而,我知道用户随时可以卸载我的插件,所以我想确保当我的插件被卸载时,它提供和注册的UDF也被注销。这意味着@jerryact提供的解决方案会导致与之前相同的错误消息,但只在用户打开Excel但在实际打开工作簿或创建空白工作簿之前关闭应用程序的特定情况下。这让我想到了最终的解决方案,如下所示:
Option Explicit
Private WithEvents App As Application
Private Sub App_WindowDeactivate(ByVal Wb As Workbook, ByVal Wn As Window)
modUDFs.UnregisterUDF "DMS_2_DD"
modUDFs.UnregisterUDF "DD_2_DMS"
modUDFs.UnregisterUDF "ElapsedTime"
End Sub
Private Sub Workbook_Open()
Set App = Application
End Sub
Private Sub App_WorkbookActivate(ByVal Wb As Workbook)
modUDFs.RegisterUDF "Converts Decimal Degrees to Degrees, Minutes, Seconds" & vbLf & "rbcDD_2_DMS(<Decimal Degrees>)", "DD_2_DMS", 3
modUDFs.RegisterUDF "Converts Degrees, Minutes, Seconds to Decimal Degrees" & vbLf & "rbcDMS_2_DD(<Degrees Minutes Seconds>)", "DMS_2_DD", 3
modUDFs.RegisterUDF "Calculates the Time between two time stamps" & vbLf & _
"rbcElapsedTime(<end time>,<start time>,<output code>)" & vbLf & _
"0 = <Seconds>, 1 = <Minutes:Seconds>" & vbLf & _
"2 = <Hours:Minutes:Seconds>, 3 = <Days Hours:Minutes:Seconds>", "ElapsedTime", 2
End Sub
请注意,
Workbook_BeforeClose
事件已经被移除了,我将取消注册调用移到了
App_WindowDeactivate
事件中。这解决了两个问题,并使我的Add-In可以注册和取消注册我的UDF。上面的所有代码都放在了
ThisWorkbook
中,下面的代码处理UDFs的注册和取消注册,并放在我的
modUDFs
代码模块中。
Sub RegisterUDF(ByVal fDescription As String, ByVal fUDFName As String, ByVal fCategory As Variant)
'Integer Category
'1 Financial
'2 Date & Time
'3 Math & Trig
'4 Statistical
'5 Lookup & Reference
'6 Database
'7 Text
'8 Logical
'9 Information
'10 Commands
'11 Customizing
'12 Macro control
'13 DDE/External
'14 User Defined
'15 First custom category
'16 Second custom category
'17 Third custom category
'18 Fourth custom category
'19 Fifth custom category
'20 Sixth custom category
'21 Seventh custom category
'22 Eighth custom category
'23 Ninth custom category
'24 Tenth custom category
'25 Eleventh custom category
'26 Twelfth custom category
'27 Thirteenth custom category
'28 Fourteenth custom category
'29 Fifteenth custom category
'30 Sixteenth custom category
'31 Seventeenth custom category
'32 Eighteenth custom category
If IsNull(fCategory) Then fCategory = 9
If fCategory = "" Then fCategory = 9
Application.MacroOptions Macro:=fUDFName, Description:=fDescription, Category:=fCategory
End Sub
Sub UnregisterUDF(ByVal fUDFName As String)
Application.MacroOptions Macro:=fUDFName, Description:=Empty, Category:=Empty
End Sub
MyRegister
只需要运行一次。为了避免在激活多个工作簿时重复执行,请考虑在MyRegister
后添加Set App = Nothing
。 - J. Woolley