Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vba MS Access—模块化/解耦表单以进行重构的最佳方式_Vba_Ms Access_Refactoring_Modularity - Fatal编程技术网

Vba MS Access—模块化/解耦表单以进行重构的最佳方式

Vba MS Access—模块化/解耦表单以进行重构的最佳方式,vba,ms-access,refactoring,modularity,Vba,Ms Access,Refactoring,Modularity,所以我最近一直在处理一个大型access数据库,我一直在考虑开始重构它的最佳方法。重构的主要困难之一是大多数表单依赖于其他表单中的数据 目前的做法是这样的 Form1上有一个名为Cmd1的按钮,它打开一个新表单(DoCmd.OpenForm“Form2”),并使用表单预先填充表单上的一些控件!Form2.Control=Me.Control。关闭Form2时,通过调用Forms将数据返回到Form1!Form1.Control=Me.Control 如果我想更改窗体的名称,或者更改打开弹出窗体的

所以我最近一直在处理一个大型access数据库,我一直在考虑开始重构它的最佳方法。重构的主要困难之一是大多数表单依赖于其他表单中的数据

目前的做法是这样的

Form1
上有一个名为
Cmd1
的按钮,它打开一个新表单(
DoCmd.OpenForm“Form2”
),并使用
表单预先填充表单上的一些控件!Form2.Control=Me.Control
。关闭
Form2
时,通过调用
Forms将数据返回到
Form1
!Form1.Control=Me.Control

如果我想更改窗体的名称,或者更改打开弹出窗体的窗体,则会出现问题。它还要求两个表单都是打开的,当您不能使用模式弹出表单时,您不能真正依赖于此,因为用户希望能够在表单之间进行交换

我看到了5种在表单之间来回传递值的方法,每种方法都有问题,我想知道推荐的方法是什么

  • 如上所述,该方法已经就位
  • 使用OpenArgs会使很多值变得困难,因为您必须解析字符串并且是单向的
  • 使用全局变量——这意味着在一个随机模块中有大量的变量,这将带来一场范围界定的噩梦
  • 在临时表中存储要在窗体之间传递的值
  • 使用维护对第一个表单的引用

    Public master As Form
    Private Sub Form_Load()
        Set master = Screen.ActiveForm
        Me.Control = master.Control
    End Sub
    
    这有点好,因为您可以引用祖辈表单,如
    master.master.control
    ,但如果父表单上的控件将来消失,则可能会导致一些重大问题


  • 是的,有推荐的方法吗?

    对于开发专业的、可维护的访问应用程序来说,这是一个非常关键的问题

    首先,对您的方法列表进行一些评论:

    • 我同意你对方法1和方法2缺点的评估
    • #3和#4有着相同的问题:全局表和全局变量一样全局。从根本上说,你不能限制对这两个网站的访问
    • #5将不可避免地使你陷入困境。在某些情况下,对表单的超长引用将阻止其关闭
    我建议将您的所有业务逻辑移动到单独的模块中,并按表单进行分解。这使您可以避免#3和#4的全局问题,因为模块可以具有专用模块级变量和函数

    例如,名为
    frmFoo
    的表单将获得名为
    modFrmFoo
    的匹配模块。该模块将包含使用frmFoo的所有公共方法:

    下面是一个简化的modFrmFoo:

    Private mvID As Variant
    
    ' read-only (no Let)
    Public Property Get frmFoo_ID() As Variant
        frmFoo_ID = mvID
    End Property
    
    Public Sub frmFoo_Show(ID As Variant, Name As Variant)
        ' note use of temporary object reference
        Dim rFoo As Form_frmFoo
        mvID = ID
        DoCmd.Open acForm, "frmFoo"
        Set rFoo = Forms("frmFoo")
        rFoo.ShowName Name
    End Sub
    
    frmFoo表单模块需要一个公共方法:

    ' only frmFoo should refer to its internal controls and code
    Public Sub ShowName(Name As Variant)
        lblName.Caption = Name
    End Sub
    
    以及对frmFoo的查询:

    SELECT ID, [other stuff] FROM tblFoo WHERE tblFoo.ID = frmFoo_ID() 
    
    查询将结果与属性frmFoo_ID()返回的ID值同步

    从另一个表单显示frmFoo很容易:

    ' frmBar
    Private Sub cmdShowFoo_Click() 
        frmFoo_Show 123, "your name"
    End Sub
    
    这种方法的优点:

  • 为窗体上的所有公共操作定义公共接口。外部表单调用模块,而不是直接调用表单
  • 使所有窗体的私有业务保持私有--可以重命名或删除窗体控件,而不会打乱依赖它的所有其他窗体
  • 在一次调用中定义每个方法工作所需的内容——例如,frmFoo_Show()需要ID和名称
  • 这就是我将如何从头开始创建一个新的应用程序

    改造旧的、混乱的应用程序是否可行取决于您的决定。

    这可能会有所帮助:

    您可以打开表单并控制它们,而无需使用打开参数

    您可以通过打开另一个窗体来实现这一点,就像它是一个类一样

    创建一个名为GlobalVars的模块,该模块包括以下行:

    Public Form_MyFormNameToOpen as Form_MyFormNameToOpen
    
    (您打开的表单将一直保持打开状态,直到该变量“死亡”,因此将其设置为全局以保持其活动状态)

    MyFormNameToOpen是要打开的表单的名称,在我的一些示例代码中,它前面有form_uu。这告诉access获取一个“表单类”,即您创建的表单之一

    然后在要打开表单的代码中使用:

    ' Opens the form using it as it were a class
    Set GlobalVars.Form_MyFormNameToOpen = New Form_MyFormNameToOpen
    
    ' The modify the form you have just opened however you want to.
    With Form_MyFormNameToOpen
        .Visible = True
    
        ' This relies ont he control names never changing
        .Controls("ProviderID") = 10
        .Controls("ProviderFileID") = 11
    
    
        ' it's better to use properties created on the called form
        ' eg
        .MyLetProviderID = 10
        .MyProviderFileID = 11
    End With
    
    我希望这有帮助

    我发现除了最基本的事情外,使用openargs真的很痛苦。使用这样的表格会使生活更轻松


    (也许您可以对报表、子表单等使用类似的技术。)

    既然您的所有数据都保存在某个地方,为什么不准备查询并在表单之间拉/推数据?我的意思是,与其阅读一个表单,将其发送到另一个表单进行编辑和检索,不如告诉第二个表单在哪里找到要编辑和编辑的数据?在第二个表单关闭后,只需刷新第一个表单即可获得更改?不幸的是,我不再处理此项目,但我们不这样做的原因是,所讨论的数据是我们计算其他数据的中间数据,而不是我们实际存储的数据。@wackozacko:如果你有时间,请阅读我的答案。我想要你的反馈!我不喜欢这种方法。我看不出有什么好处。表单模块可以有私有过程和变量。表单模块实际上是表单类的一部分,如果代码多次打开同一表单,它将被实例化多次(使用第二个模块将破坏执行此操作的能力)。您仍然可以将过程添加到表单模块以供外部程序使用(需要一个“规则”来不直接引用表单控件-我同意),但这比第二个模块更简单。也许将这些过程命名为“aa_myProcname”,它们将位于任何列表的顶部。。。。另请参阅我关于使用开放args的回答(在我看来,这是一种垃圾处理方式,应该改用上面提到的表单模块程序)@HarveyFrench:2点:(1)实例化多个访问表单对象的麻烦要多得多。如果你必须这样做