同步访问屏幕行上的两个数据表
Posted
技术标签:
【中文标题】同步访问屏幕行上的两个数据表【英文标题】:Synchronize Access two datasheets on screen rows 【发布时间】:2015-03-05 05:26:35 【问题描述】:我使用子表单数据表模式来显示表格。如果我只使用一个子表单,表格会很宽。我将字段划分为几个组。每个组将由一个子表单显示,每个子表单将位于选项卡控件的选项卡中。如何同步屏幕行上的每个子表单?例如,用户滚动子表单 A 和第 12~23 行现在在屏幕上,而第 15 行被选中。我可以将屏幕上的其他子窗体设置为第 12~23 行并且也选择第 15 行吗?表示所有子窗体显示行和选中行同步。
【问题讨论】:
【参考方案1】:在主窗体上,放置一个文本框,例如 txtSyncSubforms。
将此控制源应用到它:
=SyncSubforms([subControlFirst]![ID],[subControlSecond]![ID], .., [subControlLast]![ID])
将 subControlxxxx 和 ID 替换为子表单控件的实际名称和 ID,当然,ID 必须是唯一的。
在表单后面添加以下代码:
Option Compare Database
Option Explicit
' Automatic synchronizing of multiple subforms.
' 2019-01-05. Gustav Brock, Cactus Data ApS, CPH.
' Version 1.2.0
' License: MIT.
' Index for Split to separate the name of the subform control from
' the name of the control with the key.
' [subControlAny]![ID]
' will be split into:
' [subControlAny]
' and:
' [ID]
Enum ControlName
SubForm = 0
Key = 1
End Enum
Private Function SyncSubforms(ParamArray sControls() As Variant) As Variant
' Array sControls() holds the values of the key controls on the subform controls
' to be held in sync.
' Name of visible textbox on main form bound to this function.
Const cControl As String = "txtSyncSubforms"
' Static to store the value of the key of the last synced record.
Static wLastID As Variant
Dim rst As DAO.Recordset
Dim wSubform As Form
' Array to hold the names of the subform controls and key controls.
Dim aControls() As String
Dim bmk As Variant
Dim wNew As Boolean
Dim wThisID As Variant
Dim wIndex As Integer
Dim wItem As Integer
Dim wCount As Long
Dim wFieldName As String
' If any key value is Null, we have moved to a new record.
' No syncing shall take place.
For wIndex = LBound(sControls()) To UBound(sControls())
wThisID = sControls(wIndex).Value
If IsNull(wThisID) Then
If sControls(wItem).Parent.Name = Me.ActiveControl.SourceObject Then
' New record. Don't sync.
wNew = True
Exit For
End If
ElseIf IsNull(wLastID) Or Me.ActiveControl.Form.NewRecord Then
' Initial opening of form, or new record has been created.
' Set wLastID to the value of the current key of the first subform
' or to the key of the new record.
wLastID = wThisID
' Stop further processing.
wNew = True
Exit For
ElseIf IsEmpty(wThisID) Then
' Record has been deleted.
' Pull the ID from the active subform.
For wItem = LBound(sControls) To UBound(sControls)
If sControls(wItem).Parent.Name = Me.ActiveControl.SourceObject Then
wThisID = Me.ActiveControl(sControls(wItem).Name).Value
' Store as the current key.
wLastID = wThisID
Exit For
End If
Next
Exit For
ElseIf wThisID <> wLastID Then
' This key is the new value to sync the other subforms to.
' Store the current key.
wLastID = wThisID
Exit For
End If
Next
If wNew = True Then
' New record or initial opening. Do nothing.
Else
' ControlSource of cControl will read like:
' =SyncSubforms([subControlFirst]![ID],[subControlSecond]![ID], .., [subControlLast]![ID])
'
' Build array of the names of the subform controls with the key controls:
' [subControlFirst]![ID]
' [subControlSecond]![ID]
' ...
' [subControlAny]![ID]
' ...
' [subControlLast]![ID]
' by extracting arg names between "(" and ")".
aControls = Split(Replace(Split(Me(cControl).ControlSource, "(")(1), ")", ""), ",")
' Get current record count as it will change after an append or delete in one of the subforms.
For wIndex = LBound(aControls()) To UBound(aControls())
If Me(Split(aControls(wIndex), "!")(ControlName.SubForm)).Name = Me.ActiveControl.Name Then
Set wSubform = Me(Split(aControls(wIndex), "!")(ControlName.SubForm)).Form
wCount = wSubform.RecordsetClone.RecordCount
Exit For
End If
Next
' Loop to locate and sync those subforms that haven't changed.
For wIndex = LBound(aControls()) To UBound(aControls())
' Extract name of subform control using Split:
' [subControlAny]
Set wSubform = Me(Split(aControls(wIndex), "!")(ControlName.SubForm)).Form
If wCount <> wSubform.RecordsetClone.RecordCount Then
' A record has been added or deleted in another subform.
wSubform.Requery
End If
If IsNull(sControls(wIndex)) Or sControls(wIndex) <> wThisID Then
' This subform is to be synced.
Set rst = wSubform.RecordsetClone
' Find record for current key.
' Extract name of control on subform using Split:
' [ID]
' Then use ControlSource to get the name of the field to search.
wFieldName = wSubform(Split(aControls(wIndex), "!")(ControlName.Key)).ControlSource
' Wrap the fieldname in brackets in case it should contain spaces or special characters.
If Left(wFieldName, 1) <> "[" Then
wFieldName = "[" & wFieldName & "]"
End If
rst.FindFirst wFieldName & " = " & wThisID
If Not rst.NoMatch Then
bmk = rst.Bookmark
wSubform.Bookmark = bmk
End If
rst.Close
End If
Next
End If
Set rst = Nothing
Set wSubform = Nothing
SyncSubforms = wLastID
End Function
下载完整的文档和演示在这里: Synchronizing Multiple Subforms in Access
【讨论】:
该解决方案似乎有效。但是,我不能让它工作。你能传递一个示例工作文件吗? 事实上我有。配有指南。上面插入了链接。 非常感谢。它完美地工作。还有一个额外的问题:是否可以同步屏幕记录上的所有子表单?例如,当第一个子窗体显示记录 10~21 时,每个子窗体将是相同的记录 10~21。 这并不容易,因为同步的子表单不知道它们同步到的子表单的记录的物理位置。此外,您可以使用鼠标和键盘浏览记录。这会很好,但我发现用户最关心的是,记录是可见的和视觉标记的。所以我不会说,这是不可能的,只是不值得努力。 谢谢,你的 cmets 是有效的。以上是关于同步访问屏幕行上的两个数据表的主要内容,如果未能解决你的问题,请参考以下文章