代码之家  ›  专栏  ›  技术社区  ›  PowerUser

在MS Access窗体中,如何对所选记录的背景进行着色?

  •  2
  • PowerUser  · 技术社区  · 14 年前

    我有一个看起来有点复杂的访问表单,它有一个连续的显示(意味着一次显示多个记录)。我想更改 仅选定记录 因此最终用户可以很容易地分辨出他们在哪个记录上。

    我在考虑一个条件格式或者类似的东西:

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

    当那一排失去焦点时也会发生类似的事情。这段代码显然行不通,但这是我想要实现的代码。

    3 回复  |  直到 6 年前
        1
  •  0
  •   C Perkins    7 年前

    这里有一个完整的解决方案,可以正确地处理新编辑的记录,并处理访问用户界面的问题(即,重新绘制失败、不一致的行为取决于如何选择记录——通过鼠标或键盘或记录选择器等)。我包含冗长的注释,因为access需要彻底的解释,因为它有许多不一致和/或错误。我尝试过更精简的解决方案,但如果没有强制访问以重新绘制表单的技巧,或者没有在detail_paint()事件处理程序中确定当前记录的复杂方法,那么它的性能肯定不好。

    该代码用于带有绑定到id autonumber字段的文本框的访问表单。表单还有一个名为boxcurrent的矩形控件,该控件将被更新以突出显示当前选定的记录(它有一个明亮的宽边框)。我发现矩形控件提供了比设置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
    
        2
  •  0
  •   PowerUser    7 年前

    这里是OP。凯德指出,最初的解决方案的链接指向一个'97分贝,可能无法再打开。另外,不幸的是,我的原始代码已经消失很久了。

    但是,我最近做了类似的事情,使用了不需要vba的条件格式方法。这是access 2016的一个连续表单:

    1. 在数据集中,添加“是/否”字段。我们称之为rcd_u selected。
    2. 制作文本框。同时将控制源设置为RCD_selected。
    3. 将前景色更改为ffffff(这将是未选定的颜色)
    4. 将格式更改为“true/false”
    5. 设置启用=是,锁定=否
    6. 在功能区中,转到“格式”->“条件格式”并创建一个新规则:如果“字段值”为“真”,请将“前颜色”和“后颜色”设置为选定的颜色,然后单击“启用”。
    7. 通过在整个细节部分上拉伸文本框并将其移到后面来进行清理。
    8. 勾选复选框字段。已将控制源发送到选定的rcd。
    9. 将复选框拉伸到整个细节部分并将其移到前面。

    每当您单击该区域时,复选框将打开/关闭,触发背景中文本框的条件格式以更改颜色。 其中一个限制是它使整个记录成为只读的。我从未遇到过速度问题,当选择和取消选择多个记录时,它会工作。

        3
  •  0
  •   GregR    7 年前

    还有一种连续形式的方法…

    1. 在窗体的form_current event中,将tempVar设置为等于当前记录ID的值,例如` 坦普瓦尔斯!当前记录id=me.id_xxx.value me.controlname.refresh'在下面的步骤2中,这必须是条件格式的控件之一 铌。上面的第二行代码是触发条件格式所必需的。您只需要刷新一个条件格式的控件。
    2. 条件格式规则表达式为: [ID_xxx]=[TempVars]![CurrentRecordID] 并设置所需的格式,例如背景色
      1. 将步骤2应用于在选择记录时要按条件格式化的任何控件。
      2. 只突出显示当前记录上的控件

    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