在MS Access窗体中,如何为所选记录的背景添加颜色?

时间:2010-03-11 18:34:25

标签: ms-access vba

我有一个看起来有点复杂的Access Form,带有连续显示(意味着一次显示多个记录)。我想更改所选记录的背景颜色,以便最终用户可以轻松判断他们所在的记录。

我想的可能是条件格式或类似的东西:

Private Sub Detail_HasFocus()
    Detail.BackColor(me.color)=vbBlue
End Sub

以及当该行失去焦点时类似的东西。这段代码片段显然不起作用,但它是我想要实现的那种代码。

3 个答案:

答案 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中的连续表格:

  1. 在数据集中,添加“是/否”字段。我们称之为Rcd_Selected。
  2. 制作一个文本框。同时将控制源设置为Rcd_Selected。
  3. 将Fore Color更改为#FFFFFF(这将是未选择的颜色)
  4. 将格式更改为&#39; True / False&#39;
  5. 设置已启用=是,已锁定=否
  6. 在功能区中,转到格式 - &gt;条件格式并创建一个新规则:其中字段值= True,将前颜色和背景颜色设置为所选颜色,然后单击启用。
  7. 通过拉伸整个“细节”部分上的文本框并将其移动到背面进行清理。
  8. 创建一个复选框字段。将控制源发送到Rcd_Selected。
  9. 拉伸整个“细节”部分的复选框,并将其移到前面。
  10. 每当您单击该区域时,该复选框将打开/关闭,触发背景中文本框的条件格式以更改颜色。 这样做的一个限制是它使整个记录成为只读。我从未遇到速度问题,并且在选择和取消选择多个记录时它可以正常工作。

答案 2 :(得分:0)

连续表格的另一种方式......

  1. 在Form的Form_Current事件中,将TempVar设置为等于当前记录ID的值,例如`     TempVars!CurrentRecordID = Me.ID_xxx.value     Me.ControlName.Refresh'这必须是下面第2步中有条件格式化的控件之一 NB。上面的第二行代码是触发条件格式所必需的。您只需要刷新一个有条件格式的控件。
  2. 条件格式规则表达式为:[ID_xxx]=[TempVars]![CurrentRecordID]并设置所需的格式,例如背景色
    1. 将步骤2应用于您希望在选择记录时有条件格式化的任何控件。
    2. 仅突出显示当前记录中的控件
  3. 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