何时为 Excel 插件设置 MacroOptions
When to set MacroOptions for Excel Addin
我正在制作一个 Excel 插件。它由模块中的几个函数组成,如下所示:
Public Function MyFunctionOne(X As Range, Y As Double) As Double
MyFunctionOne = 1 'Example
End Function
Public Function MyFunctionTwo(X As Range, Y As Double) As Double
MyFunctionTwo = 2 'Example
End Function
Public Function MyFunctionThree(X As Range, Y As Double) As Double
MyFunctionThree = 3 'Example
End Function
我已将整个内容保存为 .xlam
Excel 插件。因此,每次我开始新的传播时,这些功能都可用 sheet。
我最近了解到我可以将我的功能分配给一个类别,这真的很有帮助。这使得它们易于从 Excel 函数向导中使用。我使用以下代码分配类别:
Public Sub MyRegister()
Application.MacroOptions Macro:="MyFunctionOne", Description:="Returns 1", Category:="My New Category"
Application.MacroOptions Macro:="MyFunctionTwo", Description:="Returns 2", Category:="My New Category"
Application.MacroOptions Macro:="MyFunctionThree", Description:="Returns 3", Category:="My New Category"
End Sub
现在,如果我手动 运行 宏,MyRegister
,所有函数都会获得新类别,并且效果很好。但我不想每次开始新的传播时都必须手动 运行 宏 sheet。我的问题是,插件如何为每个新点差自动执行此操作sheet?
我试过像这样把它放在插件的 Workbook_Open
中:
Private Sub Workbook_Open()
Call MyRegister
End Sub
问题是它不起作用。每当 Excel 启动时,我都会收到错误消息:“Cannot edit a macro on a hidden workbook.” 所以 Workbook_Open
事件似乎是执行此操作的错误位置。
所以我的问题是,如何在适当的时候 运行 MyRegister
宏将我的插件函数分配给类别?
对了,我真的不想做模板。我真的只保留它和插件。
谢谢!
快到了。只需将加载项转换为普通工作簿,设置选项并重置为加载项。详情见代码注释。
Public Sub MyRegister()
Application.ScreenUpdating = False '/ Turn it off to avoid flicker.
ThisWorkbook.IsAddin = False '/ Make the add-in workbook as normal, hence unhiding sheets
Application.MacroOptions Macro:="MyFunctionOne", Description:="Returns 1", Category:="My New Category"
Application.MacroOptions Macro:="MyFunctionTwo", Description:="Returns 2", Category:="My New Category"
Application.MacroOptions Macro:="MyFunctionThree", Description:="Returns 3", Category:="My New Category"
ThisWorkbook.IsAddin = True '/ Set back as add-in, hides everything.
Application.ScreenUpdating = True '/ Turn on screen updating
End Sub
除了使用 Workbook_Open
,您还可以这样做:
Private WithEvents App As Application
Private Sub App_WorkbookActivate(ByVal Wb As Workbook)
MyRegister
End Sub
Private Sub Workbook_Open()
Set App = Application
End Sub
这样它会 运行 当工作簿处于活动状态时,您将避免遇到错误。
在我写这篇文章的时候,这个问题已经很老了(已经有 5 年了),但是这个问题为我提供了完全解决这个问题所需的信息。我能够采用@jerryact 提供的答案并对其进行扩展以解决我的问题。
首先,与原始海报类似,我在 Workbook_Open
事件中注册了我的 UDF,当它作为加载项加载时,会导致显示 Run-time error '1004': Cannot edit a macro on a hidden workbook. Unhide the workbook using the Unhide command.
错误消息打开时 Excel.
使用@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
事件。这解决了这两个问题,并为我提供了一个可以注册和取消注册我的 UDF 的插件。以上所有代码都放在 ThisWorkbook
中,下面的代码处理 UDF 的注册和注销,放在我的 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
我正在制作一个 Excel 插件。它由模块中的几个函数组成,如下所示:
Public Function MyFunctionOne(X As Range, Y As Double) As Double
MyFunctionOne = 1 'Example
End Function
Public Function MyFunctionTwo(X As Range, Y As Double) As Double
MyFunctionTwo = 2 'Example
End Function
Public Function MyFunctionThree(X As Range, Y As Double) As Double
MyFunctionThree = 3 'Example
End Function
我已将整个内容保存为 .xlam
Excel 插件。因此,每次我开始新的传播时,这些功能都可用 sheet。
我最近了解到我可以将我的功能分配给一个类别,这真的很有帮助。这使得它们易于从 Excel 函数向导中使用。我使用以下代码分配类别:
Public Sub MyRegister()
Application.MacroOptions Macro:="MyFunctionOne", Description:="Returns 1", Category:="My New Category"
Application.MacroOptions Macro:="MyFunctionTwo", Description:="Returns 2", Category:="My New Category"
Application.MacroOptions Macro:="MyFunctionThree", Description:="Returns 3", Category:="My New Category"
End Sub
现在,如果我手动 运行 宏,MyRegister
,所有函数都会获得新类别,并且效果很好。但我不想每次开始新的传播时都必须手动 运行 宏 sheet。我的问题是,插件如何为每个新点差自动执行此操作sheet?
我试过像这样把它放在插件的 Workbook_Open
中:
Private Sub Workbook_Open()
Call MyRegister
End Sub
问题是它不起作用。每当 Excel 启动时,我都会收到错误消息:“Cannot edit a macro on a hidden workbook.” 所以 Workbook_Open
事件似乎是执行此操作的错误位置。
所以我的问题是,如何在适当的时候 运行 MyRegister
宏将我的插件函数分配给类别?
对了,我真的不想做模板。我真的只保留它和插件。
谢谢!
快到了。只需将加载项转换为普通工作簿,设置选项并重置为加载项。详情见代码注释。
Public Sub MyRegister()
Application.ScreenUpdating = False '/ Turn it off to avoid flicker.
ThisWorkbook.IsAddin = False '/ Make the add-in workbook as normal, hence unhiding sheets
Application.MacroOptions Macro:="MyFunctionOne", Description:="Returns 1", Category:="My New Category"
Application.MacroOptions Macro:="MyFunctionTwo", Description:="Returns 2", Category:="My New Category"
Application.MacroOptions Macro:="MyFunctionThree", Description:="Returns 3", Category:="My New Category"
ThisWorkbook.IsAddin = True '/ Set back as add-in, hides everything.
Application.ScreenUpdating = True '/ Turn on screen updating
End Sub
除了使用 Workbook_Open
,您还可以这样做:
Private WithEvents App As Application
Private Sub App_WorkbookActivate(ByVal Wb As Workbook)
MyRegister
End Sub
Private Sub Workbook_Open()
Set App = Application
End Sub
这样它会 运行 当工作簿处于活动状态时,您将避免遇到错误。
在我写这篇文章的时候,这个问题已经很老了(已经有 5 年了),但是这个问题为我提供了完全解决这个问题所需的信息。我能够采用@jerryact 提供的答案并对其进行扩展以解决我的问题。
首先,与原始海报类似,我在 Workbook_Open
事件中注册了我的 UDF,当它作为加载项加载时,会导致显示 Run-time error '1004': Cannot edit a macro on a hidden workbook. Unhide the workbook using the Unhide command.
错误消息打开时 Excel.
使用@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
事件。这解决了这两个问题,并为我提供了一个可以注册和取消注册我的 UDF 的插件。以上所有代码都放在 ThisWorkbook
中,下面的代码处理 UDF 的注册和注销,放在我的 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