MS Access Pass Form功能

时间:2017-10-01 21:00:53

标签: ms-access access-vba ms-access-2010 ms-access-2016

我正在尝试创建一个允许我使用各种命令按钮而不必每次都重新创建代码的函数。

为此,我必须通过函数

传递表单名称

功能:

public Function NewRecord(controlForm, focusForm)
focusForm.SetFocus
DoCmd.GoToRecord , , acNewRecord
controlForm.SetFocus

controlForm - 这是类似于Me函数的主要形式

focusForm - 这不仅适用于主窗体,而且当我创建子窗体时,我必须关注子窗体以使命令有效。

要调用该函数,我执行了以下操作:

public sub Command19_Click()
Dim controlForm
Dim focusForm

Set controlForm = Forms![frm_Sales_CustomerProfile]
Set focusForm = Forms![frm_Sales_CustomerProfile]

Call NewRecord(controlForm, focusForm)

End Sub

我收到状态:编译错误:无效使用属性的错误。

2 个答案:

答案 0 :(得分:1)

您使用已在此上下文(表单)中使用标识符并且未使用强名称(NameOfLibrary.NameOfFunction)来捕获。NewRecord是表单属性,因此Invalid Use Of Property有意义。如果你使用MyModulName.NewRecord(frm1,frm2)一切都很好。如果你在ModuleòrClass中使用NewRecord它也可以,因为没有相同名称的属性(我假设; - ))。

老实说,我也不使用强名称(除了数据库或记录集对象,因为我也被困在那里,假设DAO,使用ADODB),但专业人士建议,现在我们知道为什么!

你的函数应该只有一个参数,因为如果你需要那个形式NewRecord(frm as Access.Form)就足以只传递子表格引用(注意强名称!)。您可以使用Set mfrm = frm.Parent

轻松引用mainform

您的代码;

Public Function FrmNewRecord(frm As Access.Form)
    frm.Recordset.AddNew
End Function

Public Sub Command19_Click()
    FrmNewRecord(Forms![frm_Sales_CustomerProfile]) ' mainform
    FrmNewRecord(Forms![frm_Sales_CustomerProfile]!sfrmControl.Form) ' subform
End Sub

您在代码中传递了两次相同的表单,无论如何?如果Forms[frm_Sales_CustomerProfile]包含Command19,请使用Me。 我放弃.SetFocus部分作为没有必要或任何理由设置焦点?为什么NewRecord是一个功能?不归还任何东西。 顺便说一句:我正在开发一个SubForms(frm)函数,它返回所有子表单的集合。

代码:

'SubForms(frm As Access.Form) returns a collection of all subform references in frm

Public Function SubForms(frm As Access.Form) As VBA.Collection
Dim ctr As Access.Control
Dim sfrm As Access.Form
Dim col As New VBA.Collection

For Each ctr In frm.Controls
    If ctr.ControlType = acSubform Then
        On Error Resume Next
        Set sfrm = ctr.Form
        If Err.Number = 0 Then
            col.Add sfrm, sfrm.Name
        End If
        On Error GoTo 0
    End If
Next ctr
Set SubForms = col
End Function

答案 1 :(得分:0)

作为构建自定义菜单栏或色带的一般规则,您可以编写“形式”中性的代码,如下所示:

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

请注意我们根本不需要传递表单名称 - 上面的代码只是将活动屏幕选为变量“f”。

此时,您可以执行任何操作,就像代码在表单中一样。

所以

Me.Refresh    (code inside the form)

变为

f.Refresh

因此,这里的关键概念是您不需要传递当前活动表单,因为screenActive表单将使您能够获取当前表单对象。

但是,对于子表单和“常见”类型的代码,上面的内容会分崩离析,因为screen.ActiveForm将返回主窗体,而不是子窗体实例。

因此,作为第二种推荐方法,只需将当前上下文形式对象“me”传递给它:

Call MySub(me)

你定义你的子像:

Sub MySub(f as form)

现在在这段代码中,我们可以参考"任何事情"通过使用" f"代替" me"

f.Refresh

如果您使用子表单,那么只需传递“我”。鉴于上述信息,您的代码将变为:

public sub Command19_Click()

   Call NewRecord(me)


End Sub

NewReocrd成为:

Sub NewRecord(f as form)

现在在你的newreocrd代码中,你可以使用对象中的“任何东西”,例如:

f.Name    ' get name of the form.

City = f.City    ' get value of city control

所以传递“整体”形式背景。

你可以说做一个例程来显示任何形式的City值:

致电ShowCity(我," City")

然后

Sub ShowCity(f为表单,strControlToShow为字符串)

   Msgbox "City value = " & f(strControlToShow)

因此,OFTEN将通过简单地选取当前活动表单来编写适用于任何表单的代码:

  Dim f             As Form
  Set f = Screen.ActiveForm

并注意上面的代码如何立即获取活动表单 - 这是一个好主意,因为如果焦点发生变化,“f”引用将保持完整,因为后面的代码会被调用的“常规”例程+用于多种形式。

但是由于子表单问题,通常最好总是将“整个”表单实例/对象传递给:

Call MyNewRecord(me)

然后将sub定义为:

Sub MyNewReocord(f as form)

   DoCmd.GoToRecord acDataForm, f.Name, acNewRec

End Sub

你可以通过

选择添加“焦点”到上面

f.SetFocus

因此,对于很多菜单或功能区代码,您不会传递表单对象,只需使用screen.ActiveForm,您也可以使用Screen.ActiveControl(再次强大的菜单栏或功能区代码来抓取什么控制有焦点)。然而,由于子形式的限制,经常通过" me"如果在某些情况下不是更好,那么例行程序将取得类似的结果。