Gemeinsam zu mehr Effizienz in der Anwendungserstellung
K |
K (→Hilfsfunktion RequeryFormData mit API-Aufruf von SendMessage) |
||
Zeile 60: | Zeile 60: | ||
Public Sub RequeryFormData(ByVal frm As Form, ByVal DataSourceUniqueFieldName As String, ByVal DetailSectionControl As Control) | Public Sub RequeryFormData(ByVal frm As Form, ByVal DataSourceUniqueFieldName As String, ByVal DetailSectionControl As Control) | ||
' DataSourceUniqueFieldName ... Name eines eindeutigen Datenfeldes um den aktuellen Datensatz zu identifizieren | ' DataSourceUniqueFieldName ... Name eines eindeutigen Datenfeldes um den aktuellen Datensatz zu identifizieren | ||
- | ' DetailSectionControl ... Referenz auf Steuerelement im Detailbereich, damit bei Bedarf der Fokus in den Detailbereich verlegt werden kann. | + | ' DetailSectionControl ... Referenz auf Steuerelement im Detailbereich, |
+ | ' damit bei Bedarf der Fokus in den Detailbereich verlegt werden kann. | ||
Dim varIDValue As Variant | Dim varIDValue As Variant |
Wenn bei einem Endlosformular ein Requery ausgeführt wird, erhält der erste Datensatz im Formular-Recordset den Fokus.
Den zuletzt aktiven Datensatz kann man durch einstellen der Bookmark-Eigenschaft erreichen. Beispiel:
Dim lngCurrentID as Long lngCurrentID = Me!ID Me.Requery GotoFormBookmark Me, "ID", lngCurrentID
Public Function GotoFormBookmark(ByVal frm As Form, ByVal BookmarkID_Name As String, ByVal BookmarkID_Value As Variant) Dim rst As Object Dim strCriteria As String If IsNumeric(BookmarkID_Value) Then strCriteria = BookmarkID_Name & "=" & BookmarkID_Value Else strCriteria = BookmarkID_Name & "='" & Replace(BookmarkID_Value, "'", "''") & "'" End If Set rst = frm.Recordset.Clone 'Recordset wegen Ac2000, da hier bei ADO kein Recordsetclone möglich ist! If TypeOf rst Is DAO.Recordset Then With rst .FindFirst strCriteria If .NoMatch = False Then frm.Bookmark = .Bookmark End If End With ElseIf TypeOf rst Is ADODB.Recordset Then With rst .Find strCriteria, , adSearchForward If Not .EOF Then frm.Bookmark = .Bookmark End If End With End If Set rst = Nothing End Function
Mit diesem Ablauf ist aber nicht sichergestellt, dass auch die Position des aktuellen Datensatzes erhalten bleibt. Und das zu erreichen kann man auf API-Funktionen zurückgreifen.
Programmier-Konzepte |
|
Private Const WM_VSCROLL = &H115 Private Const SB_LINEUP = 0 Private Const SB_LINEDOWN = 1 Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" ( _ ByVal Hwnd As Long, ByVal wMsg As Long, _ ByVal wParam As Long, lParam As Any) As Long Public Sub RequeryFormData(ByVal frm As Form, ByVal DataSourceUniqueFieldName As String, ByVal DetailSectionControl As Control) ' DataSourceUniqueFieldName ... Name eines eindeutigen Datenfeldes um den aktuellen Datensatz zu identifizieren ' DetailSectionControl ... Referenz auf Steuerelement im Detailbereich, ' damit bei Bedarf der Fokus in den Detailbereich verlegt werden kann. Dim varIDValue As Variant Dim lngPos As Long, lngPosDiff As Long Dim lngDirection As Long Dim i As Long 'Aktuelle Position merken If frm.ActiveControl.Section <> acDetail Then 'Fokus muss im Detailbereich sein, sonst DetailSectionControl.SetFocus End If lngPos = (frm.CurrentSectionTop - frm.Section(acHeader).Height) \ frm.Section(0).Height varIDValue = Null If Len(DataSourceUniqueFieldName) > 0 Then With frm.Recordset If .RecordCount > 0 Then varIDValue = .Fields(DataSourceUniqueFieldName).value End If End With End If frm.Requery If IsNull(varIDValue) = False Then 'zu Bookmark springen GotoFormBookmark frm, DataSourceUniqueFieldName, varIDValue 'letzte Position wieder herstellen lngPosDiff = lngPos - ((frm.CurrentSectionTop - frm.Section(acHeader).Height) \ frm.Section(0).Height) If lngPosDiff <> 0 Then If lngPosDiff > 0 Then lngDirection = SB_LINEUP Else lngDirection = SB_LINEDOWN lngPosDiff = Abs(lngPosDiff) End If For i = 1 To lngPosDiff SendMessage frm.Hwnd, WM_VSCROLL, lngDirection, 0& Next i End If End If End Sub
Anwendung:
RequeryFormData Me, "ID", Me.EinSteuerelementImDetailbereich