问题描述
我有一个自定义功能区,它只有 1 个按钮作为测试,当我在 onAction 属性中使用宏时,它工作得很好,但是当我添加一个普通的回调函数时,我写的只是找不到它。 所以问题是在哪里编写这些回调(在我的例子中,我创建了一个模块并将我的回调函数设为该模块中的公共子)。
这里是xml代码:
<Relationship Id="customUIRelID" Type="http://schemas.microsoft.com/office/2006/relationships/ui/extensibility" Target="customUI/customUI.xml"/>
<ribbon startFromScratch="true">
<tabs>
<tab id="CustomTab" label="My Tab">
<group id="SimpleControls" label="My Group">
<button id="Button1" imageMso="HappyFace" size="large" label="Large Button" onAction="ribbonopenForm"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
回调函数是:
Public Sub ribbonopenForm(control As IRibbonControl)
Dim formName As String
formName = control.Tag
If formName = "" Then
MsgBox "No Name"
Exit Sub
End If
DoCmd.OpenForm formName
End Sub
当我在 xml 代码中添加一个 smale 编辑时:onAction="ribbonopenForm"
我收到一个新错误。
编辑后的错误:
解决方法
嗯,第一个也是最好的答案?不要使用回调。使用回调的最大缺点当然是您编写的代码必须位于标准全局代码模块中。这样的代码不能是表单代码模块。 鉴于按钮,甚至自定义菜单栏(过去)在大多数情况下都会并且确实会在表单中运行代码?那么您想对自定义功能区执行相同操作是理所当然的 - 尤其是针对给定表单的功能区。
因此,功能区中的回调函数是这样定义的:
onAction="MyDelete"
然后你需要一个标准代码模块中的公共子(注意我说的是公共子)。此类代码不能放在表单代码模块中(正如我所指出的,在大多数情况下它属于并且需要)。
但是,当你放置一个按钮、自定义菜单栏,甚至是宏代码(不是 VBA)时,你可以让那个“东西”在表单代码模块中执行代码!!!
这样做的方法是使用这样的表达式:
onAction="=MyDelete()"
请注意“=”符号和 () 的使用。现在?
您不需要回调函数 - 您只需将此代码放在 CURRENT formrs 代码模块中即可:
Public Function MyDelete()
dim lngID as Long
lngID = me!id
bla bla bla.
但是,它变得更好。另一个很棒的功能是您可以将值传递给函数。
所以,你可以说这样做:
<button id="MyDelete" label="Delete Record"
imageMso="Delete" size="large"
onAction="=MyDelete('Staff','tblStaff')"
supertip="Delete this record"
/>
我们的公共函数形式可能是这样的:
Public Function MyDelete(strPrompt As String,strTable As String)
Dim strSql As String
Dim f As Form
Set f = Screen.ActiveForm
If MsgBox("Delete this " & strPrompt & " record?",_
vbQuestion + vbYesNoCancel,"Delete?") = vbYes Then
currentdb.Execute "DELETE * from " & strTable & " WHERE ID = " & me!id
所以在上面,我们传递了“提示文本”和表名。现在上面有点蹩脚,因为如果代码在当前表单中已经存在,那么您当然可以删除当前记录 - 但它显示了我们如何将值从功能区传递给函数的想法。
奖励部分!!!!
如果表单中不存在公共函数,则运行标准(非表单)代码模块中具有相同名称的全局公共函数。因此,实际上,您可以有 5 个表单 - 删除代码可以是一个全局函数,但是一个有特殊需求的表单在表单代码模块中只具有一个同名的公共函数 - 如果在表单中找到它就会运行。
注意到使用 =MyPublicFunctionNameGoesHere() 也很有趣
也是右键单击和自定义菜单栏使用的完全相同的格式。那么,如果您要将现有的菜单条码转换为功能区?您使用相同的函数和语法 - 您的所有代码都保持在给定的形式中。和菜单栏一样,如果窗体中不存在该函数,则使用同名的全局函数。因此,再一次,您可以构建一个菜单(或功能区),它“主要”使用所有相同的功能,例如删除或添加记录,但对于具有不同需求的特殊表单,您可以将这些功能放在表单中 - 这样功能区可以在功能区中具有相同“选项”的许多不同表单上运行 - 但是将根据当前打开并具有焦点的表单运行非常不同的代码。
因此,如果您使用格式“=MyPublicFunction()”,那么您不需要也不会使用回调,更好的是,现在可以将函数名称放在表单中。
如前所述,如果您使用回调,则此类代码(子)不能放在当前表单代码模块中 - 它必须放在标准代码模块中。函数调用不是这样 - 它们可以自由地放置在表单代码模块中,或放置在全局模块中。
,如果您不熟悉从 RibbonX 管理回调,我建议您使用 Case 语句方法
考虑以下事项
改变
<button id="Button1" imageMso="HappyFace" size="large" label="Large Button" onAction="ribbonOpenForm"/>
到
<button id="OpenForm" imageMso="HappyFace" size="large" label="Large Button" onAction="Button_OnAction"/>
假设我们还有其他一些按钮
<button id="OpenForm2" imageMso="HappyFace" size="large" label="Large Button" onAction="Button_OnAction"/>
<button id="OpenForm3" imageMso="HappyFace" size="large" label="Large Button" onAction="Button_OnAction"/>
<button id="OpenForm4" imageMso="HappyFace" size="large" label="Large Button" onAction="Button_OnAction"/>
在 VBA 中你会写
Public Function Button_OnAction(byRef Control as IRibbonCOntrol,BYVal pressed as Boolean)
Select Case Control.Id
Case "OpenForm1"
' Do open form 1 stuff
Case "OpenForm2"
' Do open Form 2 stuff
Case "Open Form3"
' Do open form 3 stuff
Case "Open form 4
' do open form 4 stuff
Else
End Select
End Sub
这个想法是你对每个对象/动作类型只有一个回调,然后通过控件 id 进行区分。
通过这种方式,您可以将模块专用于每种类型的对象、按钮、tohggle 按钮、下拉菜单等。每个对象模块将具有相同的对象所需的 valbacks 前缀
例如模块 CheckBoxCallbacks 将有 Subs for
togglebutton_getPressed
toggleButton_onAction
DropDownCallbacks 的模块会有 subs
DropDown_getItemCount
DropDown_GetItemLabel
DropDown_getSelectedItem
DropDown_onAction
等等等等