我有一个看起来有点复杂的Access Form,带有连续显示(意味着一次显示多个记录)。我想更改所选记录的背景颜色,以便最终用户可以轻松判断他们所在的记录。
我想的可能是条件格式或类似的东西:
Private Sub Detail_HasFocus()
Detail.BackColor(me.color)=vbBlue
End Sub
以及当该行失去焦点时类似的东西。这段代码片段显然不起作用,但它是我想要实现的那种代码。
答案 0 :(得分:0)
这是一个完整的解决方案,可以正确处理新编辑的记录,以及处理Access UI怪癖(即失败的重新绘制,不一致的行为取决于如何选择记录 - 通过鼠标或键盘或记录选择器等)。我包括详细的注释,因为Access需要详细解释,因为它存在许多不一致和/或错误。我尝试过更精简的解决方案,但如果没有强制Access重绘表单的技巧,或者在Detail_Paint()事件处理程序中确定当前记录的复杂方法,它不可避免地表现不佳。
代码用于Access表单,其中文本框绑定到ID Autonumber字段。该表单还有一个名为boxCurrent的Rectangle控件,该控件将更新以突出显示当前选定的记录(它具有宽的颜色鲜艳的边框)。我发现Rectangle控件提供了比设置Detail.BackColor更多的可视选项,尽管这些细节可以使用整体模式公开配置。使用Access 2013和2016进行开发和测试。
'* Set this value in From_Current event handler
Private vCurrentAutonumber As Variant
Private Sub Detail_Paint()
'* Delcare static variables to make often repeated calls more efficient.
Static iActive As Integer
Static vThisValue As Variant, vOldValue As Variant
On Error Resume Next
iActive = 0 '* Default to False/hidden value
vThisValue = Me.ID.Value
If Err.Number = 0 Then
If Not IsNull(vCurrentAutonumber) Then
If vThisValue = vCurrentAutonumber Then iActive = 1
ElseIf Me.NewRecord Then
'* Form currently set to "New Record", but may or may not be in edit mode.
'* When in EDIT MODE, AutonumberControl.Value will HAVE A VALUE
' AND AutonumberControl.OldValue will be null
' When NOT in edit mode, AutonumberControl.Value will be null
' AND AutonumberControl.OldValue will also be null
'*** That is the only way I have found to determine for sure
' if the currently-edited-new-record is the available record for
' this particular call of Detail_Paint().
' Other properties like CurrentRecord, NewRecord, etc. remain
' unchanged during repeated calls to Detail_Paint()
' and access has no other convenient way to determine the
' newly-added autonumber value, so it must be deduced using
' this trick.
If IsNull(vThisValue) Then
If Not Me.Dirty Then
'Record selector on *(New Record) row, but not edited yet.
If Err.Number = 0 Then iActive = 1
End If
Else
vOldValue = Me.ID.OldValue
If Err.Number = 0 Then
If IsNull(vOldValue) Then
'* Newly-edited record with fresh autonumber value is selected.
iActive = 1
'Else if vOldValue is not null, it is an existing record.
'* Not the current record since it can't be both existing and new.
End If
End If
End If
End If
End If
'* Set these values on EACH CALL, since their values will be retained
'* on subsequent calls.
With boxCurrent
.BackStyle = 0 'iActive
.BorderStyle = iActive
End With
End Sub
Private Sub Form_AfterDelConfirm(Status As Integer)
Me.Repaint
End Sub
Private Sub Form_AfterInsert()
If IsNull(vCurrentAutonumber) Then
'* If a new record is saved while staying on that record,
'* the Form_Current() handler is not called and so the
'* vCurrentAutonumber would not be updated with the newly
'* saved value. But now Me.NewRecord is false, so the
'* currently record would not be updated properly unless
'* vCurrentAutonumber is explicitly updated here.
On Error Resume Next
vCurrentAutonumber = Me.ID.Value
'* Force repaint (see comment in Form_Current)
boxCurrent.BackColor = vbBlue
End If
End Sub
'Private Sub Form_BeforeInsert(Cancel As Integer)
'* Attempted to set some variable or property in this event handler
'* --something to indicate to Detail_Paint() which record is the
'* new record being edited. But no matter what I set here, the
'* change is present and identical for each call of Detail_Paint(),
'* so for the most part this technique was not useful.
'* The only alternative is to set one of the data fields, because
'* those DO change for each each to Detail_Paint().
'* IF THE PRIMARY KEY IS NOT AN AUTONUMBER FIELD (OR IF ANOTHER
'* DATA FIELD IS AVAILABLE TO MANIPULATE), ONE COULD FLAG A NEWLY
'* EDITED RECORD BY SETTING SUCH A FIELD HERE AND INSPECTING
'* it in Detail_Paint(). Personally, I avoid dummy fields just for
'* making Access work well and my primary key is Autonumber so it cannot
'* bet set to a known new value.
'End Sub
Private Sub Form_Current()
On Error Resume Next
vCurrentAutonumber = Me.ID.Value
If Err.Number <> 0 Then vCurrentAutonumber = Null
On Error GoTo 0
'*** FORCE REPAINT of record detail section
'* If not forced, records are not necessarily repainted for every type of
'* UI event. For instance, changing records using the record selectors
'* has different behavior than clicking inside a record, but either way
'* the current record has changed and so should be repainted.
'* But calling Me.Repaint is not sufficient to actually repaint the form.
'* Even if the Detail_Paint event is called, the actual visible elements
'* are not always repainted (bug?). It seems that only changing some
'* visible feature/control of the form will force an actual repaint.
boxCurrent.BackColor = vbBlue
End Sub
Private Sub Form_Load()
vCurrentAutonumber = Null
End Sub
答案 1 :(得分:0)
OP在这里。 Cade指出原始解决方案的链接指向了一个可能无法再打开的97 db。此外,不幸的是,我的原始代码很久以来就消失了。
但是,我最近使用不需要VBA的条件格式化方法做了类似的事情。这是在Access 2016中的连续表格:
每当您单击该区域时,该复选框将打开/关闭,触发背景中文本框的条件格式以更改颜色。 这样做的一个限制是它使整个记录成为只读。我从未遇到速度问题,并且在选择和取消选择多个记录时它可以正常工作。
答案 2 :(得分:0)
连续表格的另一种方式......
[ID_xxx]=[TempVars]![CurrentRecordID]
并设置所需的格式,例如背景色
Private Sub Form_Current()
10 On Error GoTo Form_Current_Error
'=============================================================
20 TempVars!CurrentRecordID = Me.MatterID.Value
30 Me.fldDateEngagedEnquiry.Requery
'================================================================
MyExit:
40 On Error GoTo 0
50 Application.Screen.MousePointer = 0 'reset to default mouse pointer
60 Exit Sub
Form_Current_Error:
70 MsgBox "Code Line Number: " & Erl & vbCrLf & vbCrLf & "Error " & Err.Number & vbCrLf & vbCrLf & " (" & Err.Description & ") in procedure " & vbCrLf & vbCrLf & " Form_Current of Sub Form_frmMyMatters_SVR"
80 GoTo MyExit
End Sub