首页 > 解决方案 > 如何通过使用 VBA 在 Access 中加载表单来使特定选项卡可见或不可见?

问题描述

问题

如何通过使用 VBA 在 Access 中加载表单来使特定选项卡可见或不可见?

解释:

我有一个带有 4 个包含按钮的表单的 Acess 数据库。今天我开始创建丝带来摆脱表格中的那些,所以一切都被分类并且易于概览。我希望我的 Access 数据库中的选项卡是不可见的,直到我从我的主表单打开一个表单。

主表单(未显示选项卡)-> 通过单击主表单中的按钮切换到另一个表单(现在我想在打开表单后显示特定选项卡)

我使用“Ribbon Creator 2019”为 Office 2019 创建了我的功能区。

问题:

我无法解决它......我尝试了很多东西,直到我找到一个具有通过切换工作表来显示特定选项卡的功能的 Excel 工作表。这正是我想要的,但我无法让它为我的访问工作。

通过获取活动表单的名称,我无法让它工作,在我看来,这将是最快的方式。

我的做法:

我在我的 XML 中将“StartFromScratch”设置为“true”,并为我的选项卡命名,如下所示:“CustomTagValue1:=xstart”。

我的标签(模块)的代码:

Sub GetVisible(control As IRibbonControl, ByRef visible)
    ' Callbackname in XML File "getVisible"

    ' To set the property "visible" to a Ribbon Control
    ' For further information see: http://www.accessribbon.de/en/index.php?Downloads:12
    ' Setzen der Visible Eigenschaft eines Ribbon Controls
    ' Weitere Informationen: http://www.accessribbon.de/index.php?Downloads:12

    Select Case control.ID

            Case "tab_3"
            ' Tab:   tab_3
            visible = False

            Case "tab0"
            ' Tab:   tab0
            visible = False

            Case "tab1"
            ' Tab:   tab1
            visible = False


        Case Else
            visible = True

    End Select

End Sub

来自另一个模块的代码来声明我的标签:

Option Compare Database
Option Explicit

'**************************************************************************
'                      About this Code:
'
' This Code checks if a Formular is in active use by his 'Name'. Simple.
'**************************************************************************


Dim MyTag As String

'Callback for customUI.onLoad
Sub RibbonOnLoad(ribbon As IRibbonUI)
    Set Rib = ribbon
End Sub

Sub GetVisible(control As IRibbonControl, ByRef visible)
    If control.Tag Like MyTag Then
        visible = True
    Else
        visible = False
    End If
End Sub

Sub RefreshRibbon(Tag As String)
    MyTag = Tag
    If Rib Is Nothing Then
        MsgBox "Fehler RBC1018, bitte starten Sie das Programm neu."
    Else
        Rib.Invalidate
    End If
End Sub

表单 onLoad 中的代码:

Private Sub Form_Load(ByVal Sh As Object)

    Select Case Screen.ActiveForm
    Case "frmVerteiler": Call RefreshRibbon(Tag:="xverteiler")
    Case Else: Call RefreshRibbon(Tag:="")
    End Select


End Sub

帮助:

我希望它像在这个 excel 文档中一样工作:https ://www.rondebruin.nl/win/s2/win012.htm

标签: vbams-accesstabs

解决方案


为每个表单创建自定义功能区的工作量要少得多,而且要容易得多,这样您就不必编写各种代码来隐藏功能区上的显示选项卡。因此,只需为给定表单指定正确的功能区,无需代码。

我还建议您不要在功能区中使用回调。如果你采用这种方式,那么ribbon可以直接调用你的EXISTING按钮代码。因此,您现在拥有的代码和按钮可以转移到该表单的功能区,并且您不必设置功能区回调,并且所有现有按钮代码都可以保持“原样”并直接从功能区调用- 功能区将运行表单中的按钮代码。

您需要做的就是将您想要调用的任何函数声明为公共函数。

然后按如下方式设置 on 操作:

=MyPublicFunctionName()

请注意我们如何拥有=()(您必须拥有这些),并且它们必须在引号下。

例如,对于我们拥有的 xml:

onAction="=MyDelete()"

请注意,上面的内容与功能区的回调有何不同(并且回调使用 sub,这是一个函数)。更好的是,以上意味着您不必将代码放置在标准代码模块中,而是可以将函数放置在当前形式中。因此,不需要宏,不需要回调,并且代码可以以当前形式运行(就像它对命令按钮所做的那样)。归根结底,在十分之九的情况下,特定表单和按钮所需的代码无论如何都属于该特定表单代码模块。事实上,开始获取属于表单的代码并将该代码放在标准的公共代码模块中是一种非常糟糕的编程实践。原因有很多,但是如果您有多个允许访问的相同表单的实例,则可能会出现各种问题。此外,当在应用程序之间复制表单,甚至在同一个应用程序中复制表单时,意味着您具有我们通常作为访问开发人员所不期望的外部代码依赖关系(我们假设大部分是我们正在使用的代码)因为表单属于表单代码模块,我 100% 同意)。我对这样的想法持开放态度,即这确实违背了众所周知的将 UI 和代码分开的概念,但这是“如何”访问的作品。所以访问方式确实违背了我们行业的趋势。我对这样的想法持开放态度,即这确实违背了众所周知的将 UI 和代码分开的概念,但这是“如何”访问的作品。所以访问方式确实违背了我们行业的趋势。我对这样的想法持开放态度,即这确实违背了众所周知的将 UI 和代码分开的概念,但这是“如何”访问的作品。所以访问方式确实违背了我们行业的趋势。

请记住,上述函数调用的想法与我们可以并且从第一天开始就一直使用的格式相同,在以前的访问版本中带有菜单栏。因此,如果您想将菜单条码更改为功能区,请使用上述想法。此外,如果您有多个按钮以给定的形式运行代码,那么上述语法再次允许您以当前形式保留代码并简单地将按钮代码声明为公共函数(因此,您可以真正轻松地从如果你这样做,形成一个丝带)。

如果您在菜单或功能区中指定的函数名称在表单的代码模块中被命名为 public,则具有 CURRENT FOCUS 的 CURRENT FORM 是首先查找要执行的函数的位置。这一点非常重要,因为这意味着您可以为五种不同的表单使用一个自定义菜单栏,但五种不同的表单中的每一种都会运行一个自定义删除例程,例如(不要弄乱 screen.Activeform)。而且,您不必像使用回调一样使用一堆杂乱的 case 语句。事实上,所有的代码都停留在它可能曾经是或属于它的表单中,那就是表单代码模块。

因此,如果您有特定的和专门的删除代码,可能需要给定的具有焦点的表单,那么当从菜单栏中的 on 操作调用它时,或者现在,表单模块中的表单功能代码将运行丝带。

这意味着如果您将 on 操作设置为 =MyDelete()

然后在您拥有的每种形式中,您只需声明一个公共函数,例如

CODE
Public function MyDelete() 
    Code here to delete the record 
End function

然而事实证明,可能超过一半甚至接近 90% 的表单,您完全有可能需要一个通用的包罗万象的删除例程,该例程适用于不需要专门的自定义删除代码的所有表单。在这种情况下,您只需将函数放在标准代码模块中(并再次作为公共)。如果当前表单没有该功能,则它从标准代码模块运行(再次,理想行为,这也是 onAction 在功能区之前的工作方式)。

另外,请注意,您还可以直接从功能区传递值。

因此,功能区 xml 可能是:

CODE
   <button id="MyDelete" label="Delete Record"
    imageMso="Delete" size="large"
    onAction="=MyDelete('Staff','tblStaff')"
    supertip="Delete this record"
 />

在上面,我传递了表名,以及 Staff 的提示文本。

标准代码模块中的公共捕获所有功能将是:

CODE
 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

 etc....

再次注意我如何将两个参数传递给删除例程(文本必须在单引号下)。提示部分,因此 msgbox 命令将显示“删除此员工?”。而且,然后我还传递了表名。上面的意思是,对于十个表单,如果你没有在表单内部指定一个公共函数,当点击菜单按钮时,标准代码模块(非表单代码模块)中的catchall通用例程将跑。

对于少数专门删除代码的表单,表单代码模块内部的功能将运行。该代码可能如下所示:

CODE
Public Function MyDelete(s1 as string, s2 as string)

' 检查历史记录 .... lngHistory = Nz(DLookup("ContactId", "NHistory", "ContactID = " & Me.ContactID), 0)

 If lngHistory > 0 Then
    Beep
    MsgBox "You cannot delete a person with past history bookings!" & vbCrLf & vbCrLf & _
              "You should simply check the 'Do NOT INCLUDE in mailings' to remove from" & vbCrLf & _
              " future mailings.", vbExclamation, "Rides"
  Exit Sub

End If

...在此处使用 sql 代码删除记录....

所以有几件事:我将为给定的表单创建一个功能区(为给定的选项卡获取您的 xml,并创建一个全新的功能区)。现在,如果您打开了 2 或 5 个表单,那么功能区将自动为您翻转和更改。如果您尝试使用标签,那么将焦点简单地更改为另一种形式将需要您隐藏+显示给定的标签 - 它很快就会变得一团糟。


推荐阅读