Example Apps for Businesses, Schools & Developers

Page 1 Page 2 Page 3

Version 2.3           Approx 1.3 MB (zipped)                 First Published 16 Feb 2024                 Last Updated 23 Feb 2024


Section Links (this page):
          Introduction
          Download
          Using the Example App
          How Does the Example App Work?
          More Continuous Forms Examples
          Feedback


Introduction                                                                                                                  Return To Top

This is the second part of the ninth article in my series showing how functionality can be added to continuous forms.

In the first part of this article, I discussed the built-in freeze fields feature in datasheets and then built similar functionality in continuous forms.

The approach used for continuous forms required a main form with 2 subforms. The left subform is fixed. The right subform can be scrolled horizontally, sorted and filtered.

Design View - Version 1.3
Whilst that worked well, that approach also had certain issues / limitations including:

a)   The fixed columns in the left subform are locked and the subform cannot be sorted or filtered directly.
b)   The ActiveX vertical scrollbar is disabled to prevent errors when the right subform is filtered or sorted
c)   Clearing the sorts & filters works correctly using the form buttons BUT not using the ribbon.

This article demonstrates a much improved approach with a continuous form and no subforms. All the above issues have been solved.
As far as I am aware, this type of solution has never been published before. I hope you find it useful!

I am very grateful to Xevi Battle for suggesting this approach using ideas from my earlier article: Hide & Restore Selected Columns in Continuous Forms
A significant part of the code used is also due to Xevi. Many thanks



Download                                                                                                                      Return To Top

Click to download:   FreezeColumns_v2.3     ACCDB file     Approx 1.4 MB (zipped)


Using the Example App                                                                                               Return To Top

The app opens to a startup form:

CStartForm
Click Continue to open the main (continuous) form. In this case the first three columns are fixed

MainForm1
This is the form in design view. It is just a standard continuous form with an ActiveX horizontal scrollbar.

Design View - Version 2.2
The form allows you to specify the number of frozen columns (any value between 0 and 8). If set to zero, all columns are scrollable as in a standard continuous form.
You can also optionally choose to lock the frozen columns so the text in those columns cannot be edited. The text in the locked columns is shaded RED.
In this screenshot, SEVEN columns have been frozen and the text in those columns LOCKED.

7 Columns Frozen & Locked
The next screenshot shows the same setup after scrolling both horizontally and vertically

7 Columns Frozen, Locked & Scrolled
All columns can also be sorted and filtered whether or not the text is locked:

4 Columns Frozen, Sorted & Filtered
Sorts and filters can be removed using either the form buttons or the ribbon

Clear Sorts & Filters
This is the same form after removing both sorts and filters and then scrolling both horizontally & vertically.

Sorts & Filters Cleared


How Does the Example App Work?                                                                           Return To Top

The app requires no APIs and works in both 32-bit & 64-bit Access. The only non standard features are:
a)   an
ActiveX scrollbar for horizontal scrolling of the columns that are not frozen (fixed)
b)   VBA code to create a dictionary and array list of the column names, widths and positions
      To do both of these, you need two additional references (Microsoft Scripting Runtime / MSCore library) if using early binding. Alternatively, use late binding:

Early Binding

References - Early Binding
Late Binding

References - Late Binding



The type of binding used and related code is defined in the declarations section of modManageColumns

Option Compare Database
Option Explicit

'#Const EarlyBind = True       'Use Early Binding
#Const EarlyBind = False       'Use Late Binding

'Early Binding comments* * * *
'The ArrayList is part of the library 'System.Collections * * * * * * * * * * * * * * * * * * * * * *
'You'll find it in the file       \WINDOWS\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb (32 bit)
'                                                \WINDOWS\Microsoft.NET\Framework64\v4.0.30319\mscorlib.tlb (64 bit)
'------------------------------------------------------------------------
'The dictionary is an element in the Microsoft Scripting Runtime library.
'That library is the file       \Windows\system32\scrrun.DLL or in a similar directory
' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

#If EarlyBind Then

      Public dict As New Scripting.Dictionary
      Public oArrayList As New ArrayList
      Public oArrayListOrdered As New ArrayList
#Else
      Public dict As Object
      Public oArrayList As Object
      Public oArrayListOrdered As Object
#End If


The Form_Open event creates both the dictionary and array list

Private Sub Form_Open(Cancel As Integer)
'Uses Dictionary to store column names, positions & widths
'Xevi Batlle

'Set values if using late binding
#If EarlyBind Then
      'no code needed here
#Else
      Set oArrayList = CreateObject("System.Collections.ArrayList")
      Set oArrayListOrdered = CreateObject("System.Collections.ArrayList")
      Set dict = CreateObject("Scripting.Dictionary")
#End If

      'Create dictionary to store control names, sizes & postions
      For Each ctl In Me.Controls
            If ctl.ControlType = acLabel Or ctl.ControlType = acTextBox Then
                  dict.Add ctl.Name & "_Left", ctl.Left
                  dict.Add ctl.Name & "_Width", ctl.Width
            End If
      Next

      'Store labels in an ArrayList to order them by Left Position
      For Each ctl In Me.Controls
            If ctl.ControlType = acLabel And ctl.Tag = "DetachedLabel" Then
                  oArrayList.Add Format(ctl.Left, "000000") & ctl.Name       ' Assign this format to sort Left position as string
            End If
      Next

      oArrayList.Sort
      For I = 0 To oArrayList.Count - 1
            oArrayListOrdered.Add Mid(oArrayList.Item(I), 7)
      Next I

End Sub


The Form_load event sets up the initial formatting depending on conditions saved in tblSettings:

Private Sub Form_Load()

      'set combo values depending on values saved in tblSettings
      Me.cboFrozenColumns = GetCountFrozenColumns
      Me.cboLockFrozen = GetLockFrozenColumnsStatus

      'clear existing filters and sorts
          strWhere = ""
      strOrderBy = ""
      Me.FilterOn = False
      Me.OrderByOn = False

      AssignScrollBarValues Me     'set horizontal scrollbar position depending on number of frozen columns
      ShowAllColumns Me     'move horizontal scrollbar fully to left so all columns visible
      PaintFrozenColumns Me    'format frozen columns light grey (with red text if locked)

End Sub


There are several procedures referenced in Form_Load which are called from modManageColumns:

Function GetCountFrozenColumns()
'Colin Riddington
      GetCountFrozenColumns = Nz(DLookup("ItemValue", "tblSettings", "ItemName='CountFrozenColumns'"), "3")
End Function
'---------------------------------------------------

Function GetLockFrozenColumnsStatus()
'Colin Riddington
      GetLockFrozenColumnsStatus = Nz(DLookup("ItemValue", "tblSettings", "ItemName='LockFrozenColumns'"), "No")
End Function

'---------------------------------------------------

Function GetControlNameFromLabel(labelName As String)
'Colin Riddington
      GetControlNameFromLabel = Left(labelName, Len(labelName) - 6)
End Function
'---------------------------------------------------

Sub AssignScrollBarValues(frm As Form)
'Xevi Batlle

      With frm.MainScrollBar
            .Max = oArrayListOrdered.Count - 1
            .Min = frm.cboFrozenColumns

            .Value = frm.cboFrozenColumns
            .Left = dict(oArrayListOrdered(GetCountFrozenColumns) & "_Left")
            .Width = frm.InsideWidth - .Left - 500
      End With

End Sub
'---------------------------------------------------

Sub PaintFrozenColumns(frm As Form)
'Xevi Batlle / Colin Riddington

      For I = 0 To oArrayListOrdered.Count - 1
            labelName = oArrayListOrdered(I)
            controlName = Left(labelName, Len(labelName) - 6)
            frm(controlName).Locked = False
            If frm(controlName).BackColor <> colPaleGreen And frm(controlName).BackColor <> colPaleYellow Then
                  If I < GetCountFrozenColumns Then
                        frm(controlName).BackColor = colPaleGrey
                        frm(controlName).ForeColor = IIf(GetLockFrozenColumnsStatus = "Yes", colDarkRed, colDarkGrey)
                        If GetLockFrozenColumnsStatus = "Yes" Then frm(controlName).Locked = True
                  Else
                        frm(controlName).BackColor = vbWhite
                        frm(controlName).ForeColor = colDarkGrey
                  End If
            End If
      Next I

End Sub
'---------------------------------------------------

Sub ShowAllColumns(frm As Form)
'Xevi Batlle

      For I = 0 To oArrayListOrdered.Count - 1
            labelName = oArrayListOrdered(I)
            controlName = GetControlNameFromLabel(labelName)
            widthControl = dict(oArrayListOrdered(I) & "_Width")
            leftPosition = dict(oArrayListOrdered(I) & "_Left")
            frm(labelName).Left = leftPosition
            frm(labelName).Visible = True
            frm(controlName).Left = leftPosition
            frm(controlName).Visible = True
            leftPosition = leftPosition + widthControl
      Next I

End Sub


The Form_Current event checks if any sorts and filters have been applied and sets or clears the format conditions as appropriate for relevant columns

It then runs PaintFrozenColumns again to format frozen columns light grey (with red text if locked)

Private Sub Form_Current()

      If Me.FilterOn = True Then
            strWhere = Me.Filter
            CheckFilterFormat Me     'highlight filtered columns
            Me.cmdClearFilter.Enabled = True
      Else
            ClearFilterFormat Me
            Me.cmdClearFilter.Enabled = False
      End If

      If Me.OrderByOn = True Then
            strOrderBy = Me.OrderBy
            CheckSortFormat Me     'highlight sorted columns
            Me.cmdClearSort.Enabled = True
      Else
            ClearSortFormat Me
            Me.cmdClearSort.Enabled = False
      End If

      PaintFrozenColumns Me

End Sub


NOTE:
The CheckFilterFormat / ClearFilterFormat / CheckSortFormat / ClearSortFormat code is in modManageColumns
It is identical to that described in earlier articles such as: Hide & Restore Selected Columns in Continuous Forms

I hope you find this approach useful for your own applications

To use this approach in your own apps, you need to import the following items:
a)   Table tblSettings
b)   All three standard modules: modFunctions / modManageColumns / modNavPane
b)   Use late binding or add the two references listed above

The form code should be easily transferable to your own forms with little or no changes required.

As a test, I created a second form frmStudentAddresses (not included in the example app) with similar layout.

Student Address Form
I then copied all the code from frmMain with no changes. It worked perfectly first time!

UPDATE 23 Feb 2024
However, I completely forgot about navigation using the tab (or shift+tab) keys as I rarely use this method myself.
The result was that tabbing completely ignored the frozen columns and the whole form was scrolled horizontally. This is clearly far from satisfactory.

That issue is addressed in the third part of this article. It wasn't difficult to get the code to work when tabbing but shift+tab proved more tricky.

The solution used makes use of class module code by A.P.R. (Ramachandran) Pillai to streamline the code and make it easily transferable to other forms.


More Continuous Form Examples                                                                              Return To Top

The following articles provide further examples of functionality added to continuous forms:

•   Highlight Current Record
•   Highlight Selected Control or Column
•   Highlight Filtered Columns
•   Add Multiselect Filter   (2 pages)
•   Paint Me Transparent       (Selectively Hide Controls)
•   Sort columns
•   Hide duplicate values in a column   (as for reports)
•   Hide & Restore Selected Columns   (2 pages)
•   Freeze Columns   (3 pages)
•   Move and Resize Columns   (2 pages)


Feedback

Please use the contact form below to let me know whether you found this article interesting/useful or if you have any questions/comments.

Please also consider making a donation towards the costs of maintaining this website. Thank you



Colin Riddington           Mendip Data Systems                 Last Updated 23 Feb 2024



Return to Example Databases Page Page 2 of 3 1 2 3 Return To Top