Microsoft Access VBA Tutorials for self-paced learning, Class Modules, SQL Techniques, and AI Integration Guides.

Working with Chart Object in VBA

Chart Object and VBA.

Working with the Microsoft Access Chart Object in VBA can be quite complex — but it’s also a fascinating and rewarding process. Once the code is properly developed, it can be reused across different Access databases to create charts with a consistent look and feel in just a few minutes.

There are numerous chart types, chart areas, and object groups available, each with a wide range of configurable properties. Some of these properties, such as Auto Scaling, are specific to certain chart types — for example, 3D charts.

Note: Before proceeding, ensure that the following essential reference libraries are attached to your database. This will prevent VBA runtime errors when working with chart-related code.

Attaching System Reference Libraries.

  1. Open the Visual Basic Editor by selecting Tools → Visual Basic Editor or choosing Code from the View menu.

  2. From the Tools menu, select References.

  3. In the Available References dialog box, check the following libraries:

    • Microsoft Office 12.0 Object Library

    • Microsoft Excel 12.0 Object Library

These libraries are also required to run the demo database provided for download at the end of this page.

After some research and experimentation, I developed a VBA routine that can dynamically modify and format Microsoft Access charts with a clean, professional appearance. I hope you’ll enjoy working with it as much as I did. A sample result is shown in the image below.

Formatting Chart Elements.

The resizing of the chart and formatting of its Report various elements — including the Chart Title, Axis Titles, Chart Area, Plot Area, Chart Bars with Gradient Colors, Legends, Grid Lines, Data Labels, and the alignment of Data Labels — are all controlled through VBA code. Placing a chart object on a report with minimal property settings is done manually as a starting point.

When the program is run, it presents three options for the chart type:

  • Bar Chart

  • Line Chart

  • Pie Chart

The same chart object is dynamically transformed into the selected type, using sample values from a table for demonstration purposes. The Pie Chart uses the first record from the table, and its data handling differs from the Bar and Line Charts. In this example, the Pie Chart is included for demonstration only and is not treated as a separate, fully detailed case.

Color Numbers

The following Color index numbers can be used in different combinations in the Program to get different gradient shades.

Preparing for Trial Run.

Follow the simple steps explained below, and get prepared for the trial run.

  1. Create a Table with the following Structure and save it with the name Table1.

  2. Add the sample records with the values shown above.

  3. Open a new Report in Design View.
  4. Select Object from the Insert Menu and select Microsoft Graph 2000 Chart (or Microsoft Graph Chart in MS-Access 2003) from the Object Type List.

    The inserted chart object with default values will be in an activated state, displaying the default values in the Data Grid.

  5. Click outside the chart in the Detail Section of the Report to deactivate and deselect the Chart.

  6. Click on the Chart again to select it and display the Property Sheet (View ->Properties)

  7. Change the following Property Values as given below:

    • Name: Chart1

    • Row Source Type: Table/Query

    • Row Source: Table1

    • Column Heads: Yes

    Even though the following properties can be changed manually, these are changed through the Code:

    • SizeMode : 3 (Zoom)
    • Column Count: Number of Columns in the Source Data

    • Left: 0.2917?

    • Top: 0.2708?

    • Width: 5.5729?

    • Height: 4.3854?

    2D Chart Area Zones.

    An MS Access 2D Chart Object has 3 different areas:

    1. the outer Frame
    2. Chart Area where Chart Title, Axis Titles, and Legend Values appear.

    3. Plot Area where the chart Data Series Values, Data Labels, Gridlines, Scale, and Category Values appear in the Bar or Line Charts.

    If the Size Mode property is set to Clip (value 0), resizing the chart using the last four properties (Left, Top, Width, Height) will only adjust the outer frame, leaving the inner sections — the Chart Area and Plot Area — unchanged. If the property is set to Stretch or Zoom (values 1 or 3, respectively), the inner chart sections will resize to fit within the outer frame. Zoom is the preferred setting, as it maintains the correct aspect ratio of the chart during resizing, preventing distortion.

    The Column Count property is determined from the Row Source table or query.

    The program also validates the Row Source Type property. If it is not set to Table/Query, it will be corrected. However, if the Row Source property does not contain a valid table name or SQL string, the program will terminate and display an error message.

  8. Save the Report with the Name myReport1.
  9. The VBA Code.

  10. Copy and Paste the following VBA Code into the Global Module and save the Module.
    Public Function ChartObject(ByVal ReportName As String, ByVal ChartObjectName As String)
    '------------------------------------------------
    'Author : a.p.r. pillai
    'Date   : June-2008/Revision on 12/2019
    'Source Code : from Microsoft Access Help
    'and modified certain parameters
    '------------------------------------------------
    Dim Rpt As Report, grphChart As Object
    Dim msg As String, lngType As Long, cr As String
    Dim ctype As String, typ As Integer, j As Integer
    Dim db As Database, rst As Recordset, recSource As String
    Dim colmCount As Integer
    Const twips As Long = 1440
    
    'On Error GoTo ChartObject_Err
    
    cr = vbCr & vbCr
    
    msg = "1. Bar Chart" & cr
    msg = msg & "2. Line Chart" & cr
    msg = msg & "3. Pie Chart" & cr
    msg = msg & "4. Quit" & cr
    msg = msg & "Select Type 1,2 or 3"
    
    ctype = "": typ = 0
    Do While typ < 1 Or typ > 4
     ctype = InputBox(msg, "Select Chart Type")
     If Len(ctype) = 0 Then
        typ = 0
     Else
     typ = Val(ctype)
     End If
    Loop
    
    Select Case typ
        Case 4
            Exit Function
        Case 1
           lngType = xlColumnClustered
        Case 2
           lngType = xlLine
        Case 3
           lngType = xl3DPie
    End Select
    
    DoCmd.OpenReport ReportName, acViewDesign
    Set Rpt = Reports(ReportName)
    
    Set grphChart = Rpt(ChartObjectName)
    
    grphChart.RowSourceType = "Table/Query"
    
    recSource = grphChart.RowSource
    
    If Len(recSource) = 0 Then
       MsgBox "RowSource value not set."
       Exit Function
    End If
    
    'get number of columns in chart table/Query
    Set db = CurrentDb
    Set rst = db.OpenRecordset(recSource)
    colmCount = rst.Fields.Count
    rst.Close
    
    With grphChart
        .ColumnCount = colmCount
        .SizeMode = 3
        .Left = 0.2917 * twips
        .Top = 0.2708 * twips
        .Width = 5.5729 * twips
        .Height = 4.3854 * twips
    End With
    
    grphChart.Activate
    
    'Chart type, Title, Legend, Datalabels,Data Table
    With grphChart
         .chartType = lngType
        ' .chartType = xlColumnClustered
        '.AutoScaling = True
        ' only for 3D type
        .HasLegend = True
        .HasTitle = True
        .ChartTitle.Font.Name = "Verdana"
        .ChartTitle.Font.Size = 14
        .ChartTitle.Text = "Revenue Performance - Year 2007"
        .HasDataTable = False
        .ApplyDataLabels xlDataLabelsShowValue
    End With
    
    'apply gradient color to Chart Series
    If typ = 1 Or typ = 2 Then
        For j = 1 To grphChart.SeriesCollection.Count
          With grphChart.SeriesCollection(j)
            '.Interior.Color = RGB(Int(Rnd(j) * 200), Int(Rnd(j) * 150), Int(Rnd(j) * 175))
            .Fill.OneColorGradient msoGradientVertical, 4, 0.231372549019608
            .Fill.Visible = True
            .Fill.ForeColor.SchemeColor = Int(Rnd(1) * 54) + 2
            If typ = 1 Then
               .Interior.Color = msoGradientVertical
            End If
            .DataLabels.Font.Size = 10
            .DataLabels.Font.Color = 3
            If typ = 1 Then
                .DataLabels.Orientation = xlUpward
           Else
                .DataLabels.Orientation = xlHorizontal
            End If
         End With
        Next j
    End If
    
    If ctype = 3 Then
     GoTo nextstep 'skip axes for pie chart
    End If
    
    'Y-Axis Title
    With grphChart.Axes(xlValue)
        .HasTitle = True
        .HasMajorGridlines = True
        With .AxisTitle
            .Caption = "Values in '000s"
            .Font.Name = "Verdana"
            .Font.Size = 12
            .Orientation = xlUpward
        End With
    End With
    
    'X-Axis Title
    With grphChart.Axes(xlCategory)
        .HasTitle = True
        .HasMajorGridlines = True
        .MajorGridlines.Border.Color = RGB(0, 0, 255)
        .MajorGridlines.Border.LineStyle = xlDash
        With .AxisTitle
            .Caption = "Quarterly"
            .Font.Name = "Verdana"
            .Font.Size = 10
            .Font.Bold = True
            .Orientation = xlHorizontal
        End With
    End With
    
    With grphChart.Axes(xlValue, xlPrimary)
         .TickLabels.Font.Size = 10
    End With
    With grphChart.Axes(xlCategory)
         .TickLabels.Font.Size = 10
    End With
    
    nextstep:
    
    With grphChart
        .ChartArea.Border.LineStyle = xlDash
        .PlotArea.Border.LineStyle = xlDot
        .Legend.Font.Size = 10
    End With
    
    'Chart Area Fill with Gradient Color
    With grphChart.ChartArea.Fill
        .Visible = True
        .ForeColor.SchemeColor = 2
        .BackColor.SchemeColor = 19
        .TwoColorGradient msoGradientHorizontal, 2
    End With
    
    'Plot Area fill with Gradient Color
    With grphChart.PlotArea.Fill
        .Visible = True
        .ForeColor.SchemeColor = 2
        .BackColor.SchemeColor = 10
        .TwoColorGradient msoGradientHorizontal, 1
    End With
    
    grphChart.Deselect
    
    DoCmd.Close acReport, ReportName, acSaveYes
    DoCmd.OpenReport ReportName, acViewPreview
    
    ChartObject_Exit:
    Exit Function
    
    ChartObject_Err:
    MsgBox Err.Description, , "ChartObject()"
    Resume ChartObject_Exit
    End Function
    

    Running the Code.

  11. Open the VBA Module that you have pasted the code into if you have closed it.

  12. Run the code from the Debug Window (press Ctrl+G to display the Debug Window) using the following syntax:

    ChartObject "myReport1", "Chart1"

    Or call the function from the On_Click() Event Procedure of a Command Button on a Form.

  13. Select Chart Type 1, 2, or 3 for Bar Chart, Line Chart, or Pie, respectively.

The Program will open the Report myReport1 in Design View, modify the Graph Chart for the selected Type, save it, and then reopen it in Print Preview. You may minimize the VBA Window (Alt+F11) to view the Chart. Since the Report is saved after the changes, you may open it manually in Design View or Print Preview.

When you run the Bar Chart or Line Chart Code, the Gradient Scheme Color Codes are selected randomly, which will apply different shades of Gradient Colors every time.

NB: Any suggestions for improvement are welcome.

Download the Demo Database.

Download Demo Database

  1. MS-Access and Graph Charts
  2. MS-Access and Graph Charts-2
  3. Working With Chart Object in VBA
  4. Column Chart and VBA
  5. Pie Chart Object and VBA
  6. Missing Lines in Line-Chart
  7. Pie Chart and Live Data on Form
  8. Scaling Chart Object
  9. Cross-Tab Union Queries for Chart
Share:

Linking with IBM AS400 Tables

Linking with IBM AS400 Tables.

IBM iSeries (AS400) DB2 tables can be converted into dBase format, downloaded, and then linked or imported into MS Access databases. The downloading process is typically initiated and run from the AS400 menus. If multiple steps are required before transferring the output file to the local drive, this process can be automated using macro scripts. Keystrokes can be recorded and modified so that the target file is saved to a specific location on the local machine, with a predefined name, allowing it to remain linked to the Microsoft Access database.

You need the necessary Access privileges to the iSeries (AS400) mainframe tables, and you can link the table directly to your MS Access database using an ODBC-based procedure.  We will explore this aspect shortly.

Typically, Reports are generated on the AS400 and delivered to users as hard copies or exported as text-based spool files if a soft copy is required. These files can be downloaded in text file format or imported into Microsoft Excel—though Excel may not always parse numbers, dates, or other formats correctly. AS400 tables can also be downloaded directly into Excel. If the number of rows exceeds 65,535 (the limit for an Excel worksheet), multiple worksheets will be created automatically to accommodate all the data.

Linking to IBM iSeries DB2 Tables.

Let us review the steps for linking IBM iSeries DB2 Tables in an MS Access database. The example images are created from the Windows 2000 Workstation.

Creating ODBC System DSN.

  1. Select Start Menu -> Settings -> Control Panel -> Administrative Tools -> double-click on Data Sources (ODBC).

    The ODBC Data Source Administrator Settings will be displayed. See the Image given below. The Following Steps will walk you through the procedure:

  2. Select the System DSN Tab on the ODBC Data Source Administrator.

  3. Click the 'Add...' Button to display a list of Data Source Drivers.

  4. Select Client Access ODBC Driver (32-bit) from the displayed list in the Create New Data Source Control and click Finish.

  5. Type a name in the Data Source Name Control. I have entered the name myData as the Data Source Name. We have to look for this name when we attempt to link the Table to MS-Access.

  6. Click on the Server Tab.

  7. Type the specific iSeries Folder Name where your data table resides in the Library List Control. If more than one Library File, separate them with Commas.

  8. Select the Read-Only (Select statements only) option under Connection Type to ensure that we have no intention to modify the data in the iSeries Table.
  9. Click the Apply button followed by the OK Button. The System Data Source Name myData appears in the System DSN Tab. See the image below.

  10. Click OK to close the ODBC Configuration Main Control (the Apply button remains disabled in this case).

Linking to MS-Access Database.

  1. Open your MS-Access Database.

  2. Select File -> Get External Data -> Link Table or Import Option.

  3. Select ODBC Databases in the Files of Type control in the Common Dialog Control and click the Link (or Import) Button, as the case may be.

  4. Select the Machine Data Source Tab on the ODBC Control and find the Data Source Name myData that you have created, select it, and click OK.

    You will be prompted for AS400 User ID and Password. Key in your User ID and password, and then click OK.

    The Tables list will open up, showing all the Table Names available in the AS400 iSeries Machine, prefixed with the Library Name followed by a period.

  5. Select the Table(s) to Link and Click OK.

    The Fields of the selected Table will be displayed, suggesting that one or more fields be highlighted for indexing if needed.

  6. Highlight the field(s) if you would like to create a Unique Index for the Table; otherwise, click OK without selecting any.

The selected Table will be linked (or imported as the case may be) into your Database.

The AS400 Login Issue.

If the table remains linked, whenever you attempt to use the table after opening your MS-Access Database, it will prompt for the AS400 iSeries UserID and Password.  The login is valid for the current Session of the Access Database only.

If you don't want this to happen in the middle of some process, it is better to invoke the login immediately after opening the Database. To do this, create a Query, Form, or Report that uses the linked iSeries Table, and opens it with an Autoexec Macro or the Form in Startup. Even better, create a VBA routine to open the linked table that invokes the login procedure and the User Logon at the beginning of the current session. This will cover the rest of the Session time.

Share:

Repairing Compacting Database with VBA

Repairing and compacting the database.

Repairing and compacting the database is an essential maintenance task in Microsoft Access to keep the database size optimized and prevent performance issues. During regular use, MS Access creates temporary work objects within the database, causing the file size to grow over time.

If the database is used by a single user, this is not a major concern. You can simply enable the Compact on Close option in Access settings to automate this process:

  • Go to Tools → Options → General Tab

  • Check the box labeled Compact on Close

With this enabled, Access will automatically compact and repair the database each time it is closed.

However, if the database is shared on a network, enabling this feature can cause problems. Compacting requires exclusive access to the database, which means no other users can be connected while the process runs. If multiple users attempt to close the shared database, Access will attempt to compact it and fail, potentially leading to instability or corruption over time.

Granting Exclusive Access through Tools → Security → User and Group Permissions → Permissions Tab prevents multiple users from accessing the database concurrently, but that defeats the purpose of a shared system.

Access requires exclusive access during compacting because the process actually deletes the original database file and re-creates it. The compacting operation involves the following internal steps:

Database Compacting Steps.

  1. Select Tools -> Database Utilities -> Compact and Repair Database. Closes the Current Database.

  2. Creates a temporary Database named db1.mdb in the current folder.

  3. Transfers all the Objects (Tables, Forms, Reports, etc.), except the work objects, into db1.mdb.

  4. Deletes the original Database.

  5. Renames the db1.mdb file to the original name.

  6. Opens the newly created Database.

When No Database is active.

If no database is open when you select the Compact and Repair option, Microsoft Access prompts you to select the source database from your disk. It then asks you to specify the name and location for saving the compacted database. Access does not automatically overwrite the original database. Instead, it creates a new compacted copy, allowing you to decide whether to retain or replace the original file. Renaming the files is recommended for clarity and effective version control.

When compacting a database stored on a server, disk quota limitations can become a constraint. The user performing the operation must have available disk space equal to at least twice the size of the database, or more, within their allocated quota. This additional space is required because Access creates the compacted copy before the original database is removed or replaced.

In multi-user environments where multiple databases are shared across network folders, manually compacting each database can be time-consuming and inefficient. In such situations, a dedicated VBA-based Compacting Utility Program is invaluable. Such a utility can automatically compact multiple databases sequentially by following the same logical procedure described earlier (Steps 1 through 7), with minor modifications to efficiently process multiple databases.

The Compacting Utility that we create has the following advantages:

  • Uses Local Disk Space for the work file, instead of Network disk space, and runs the compacting process faster.

  • Can select more than one Database for compacting.

  • Takes a safe Backup on the Local Drive.

  • No failures due to the non-availability of enough Disk Space under the User's Disk Quota.

We will create a small Database with a Table to hold a list of Database Path Names, a Form, and two VBA Programs on the Form Module.

The Design Task.

  1. Create a new Database with the name CompUtil.mdb.

  2. Create a Table with the following structure.

    Table: FilesList
    Field Name Type Size
    ID AutoNumber  
    dbPath Text 75
  3. Save the Table with the name FilesList and key in the full path names of your Databases running on the Server, and close the table. Do not use the UNC type server addressing method: 

    "\\ ServerName\FolderName\DatabaseName" 
  4. Open a new Form and create a List Box using the FilesList Table. See the design given below. Draw two Label Controls below the List Box and two Command Buttons below that, side by side.

  5. Resize the Controls and position them to match the design given above. The finished design in Normal View is shown below. The Labels below the List Box are kept hidden and will appear only when the Program runs.

    Change the Property Values of the Form and controls, so that your Form and design look exactly like the design given above.

  6. Click on the List Box and display the property sheet (View -> Properties).

  7. Change the List Box's Property Values as given below:

    • Name: dbList
    • Row Source Type: Table/Query
    • Row Source: SELECT [FilesList].[ID], [FilesList].[dbPath] FROM [FilesList]
    • Column Count: 2
    • Column Heads: No
    • Column Widths: 0.2396";1.4271"
    • Bound Column: 2
    • Enabled: Yes
    • Locked: No
    • Multiselect: Simple
    • Tab Index: 0
    • Left: 0.3021"
    • Top: 0.7083"
    • Width: 3.2083"
    • Height: 1.7708"
    • Back Color: 16777215
    • Special Effect: Sunken
  8. Resize the child Label Control, attached to the List Box, to the same size and position it above the List Box. Change the Caption to Database List.

  9. Click on the first Label Control below the List Box, display the Property Sheet, and change the following Properties:

    • Name: lblMsg
    • Visible: No
    • Left: 0.3021"
    • Top: 2.5"
    • Width: 3.2083"
    • Height: 0.5"
    • Back Color: 128
    • Special Effect: Sunken
  10. Display the Property Sheet of the second Label Control and change the following Properties:

    • Name: lblstat
    • Visible: No
    • Left: 0.3021"
    • Top: 3.0417"
    • Width: 3.2083"
    • Height: 0.1667"
    • Back Style: Transparent
    • Back Color: 16777215
    • Special Effect: Flat
    • Border Style: Transparent
  11. Change the following properties of the left-side Command Button:

    • Name: cmdRepair
    • Caption: Repair/Compact
    • Tab Index: 1
    • Left: 0.3021"
    • Top: 3.25"
    • Width: 1.4271"
    • Height: 0.2292"

  12. Change the following properties of the right-side Command Button:

    • Name: cmdClose
    • Caption: Quit
    • Tab Index: 1
    • Left: 2.0833"
    • Top: 3.25"
    • Width: 1.4271"
    • Height: 0.2292"
  13. Change the Properties of the Form. Click on the left top corner of the Form where the left-side and Top design guides (Scales) meet. When you click there, a blue square will appear, indicating that the Form is selected. Display the Property Sheet and click on the All Tab. If that is not the current one, change the following Properties:

    • Caption: External Repair/Compact Utility
    • Default View: Single Form
    • Views Allowed: Form
    • Allow Edits: Yes
    • Allow Deletions: No
    • Allow Additions: No
    • Data Entry: No
    • Scroll Bars: Neither
    • Record Selectors: No
    • Navigation Buttons: No
    • Dividing Lines: No
    • Auto Resize: Yes
    • Auto Center: Yes
    • Pop up: Yes
    • Modal: Yes
    • Border Style: Dialog
    • Control Box: Yes
    • Min, Max Buttons: None
    • Close Button: Yes
    • Width: 3.9063"
  14. Click on the Detail Section of the Form, and change the Height Property:

    • Height: 3.7917"
  15. Create a Header Label at the top with the Caption Compacting Utility, and set the Font Size to 18 Points.

    NB: If you would like to create a Heading with 3D-style characters, as the sample shown above, visit the Page Create 3D Heading on Forms and follow the procedure explained there. You can do it later.

  16. Select the Rectangle Tool from the Toolbox and draw a Rectangle around the Controls as shown on the Design.

    Form Class Module Code.

  17. Display the VBA Module of the Form (View -\> Code), Copy, and paste the following code into it, and save the Form with the name Compacting.
    Private Sub cmdClose_Click()
    If MsgBox("Shut Down...?", vbYesNo + vbDefaultButton2 + vbQuestion, _"cmdQuit_Click()") = vbYes Then
        DoCmd.Quit
    End If
    End Sub
    
    Private Sub cmdRepair_Click()
    Dim lst As ListBox, lstcount As Integer
    Dim j As Integer, xselcount As Integer
    Dim dbname As String, t As Double, fs, f
    Dim ldbName As String, strtmp As String
    
    'create a temporary folder C:\tmp, if not present
    On Error Resume Next
    Set fs = CreateObject("Scripting.FileSystemObject")
    Set f = fs.GetFolder("c:\tmp")
        If Err = 76 Or Err > 0 Then
           Err.Clear
           fs.createfolder ("c:\tmp")
        End If
    
    On Error GoTo cmdRepair_Click_Err
    
    Me.Refresh
    Set lst = Me.dbList
    lstcount = lst.ListCount - 1
    
    xselcount = 0
    For j = 0 To lstcount
    If lst.Selected(j) Then
        xselcount = xselcount + 1
    End If
    Next
    
    If xselcount = 0 Then
       MsgBox "No Database(s)Selected."
       Exit Sub
    End If
    
    If MsgBox("Ensure that Selected Databases are not in Use. " _
    & vbCrLf & "Proceed...?", vbYesNo + vbDefaultButton2 + vbQuestion, "cmdRepair_Click()") = vbNo Then
       Exit Sub
    End If
    
    For j = 0 To lstcount
        If lst.Selected(j) Then
          dbname = lst.Column(1, j)
           dbname = Trim(dbname)
           ldbName = Left(dbname, Len(dbname) - 3)
           ldbName = ldbName & "ldb" 'for checking the presense of lock file.
           If Len(Dir(ldbName)) > 0 Then 'database is active
              MsgBox "Database: " & dbname v vbCrLf & "is active. Skipping to the Next in list."
              GoTo nextstep
           End If
    
           If MsgBox("Repair/Compact: " & dbname & vbCrLf & "Proceed...?", vbQuestion + vbDefaultButton2 + vbYesNo, "cmdRepair_Click()") = vbYes Then
                Me.lblMsg.Visible = True
                Me.lblStat.Caption = "Working, Please wait..."
                Me.lblStat.Visible = True
                DoEvents
    
                dbCompact dbname 'run compacting
    
                Me.lblStat.Caption = ""
                DoEvents
    
    nextstep:
                t = Timer
                Do While Timer <= t + 7 'delay loop
                   DoEvents 'do nothing
                Loop
            End If
        End If
    Next
    
       Me.lblMsg.Visible = False
       Me.lblStat.Caption = ""
       Me.lblStat.Visible = False
    
    strtmp = "c:\tmp\db1.mdb" 'Delete the temporary file
    If Len(Dir(strtmp)) > 0 Then
      Kill strtmp
    End If
    
    Set fs = Nothing
    Set f = Nothing
    Set lst = Nothing
    
    cmdRepair_Click_Exit:
    Exit Sub
    
    cmdRepair_Click_Err:
    MsgBox Err.Description, , "cmdRepair_Click()"
    Resume cmdRepair_Click_Exit
    End Sub
    

    Private Function dbCompact(ByVal strdb As String)
    Dim t As Long
    Dim xdir As String, strbk As String
    Const tmp As String = "c:\tmp\"
    
    On Error GoTo dbCompact_Err
    
    If Len(Dir(tmp & "db1.mdb")) > 0 Then
        Kill tmp & "db1.mdb"
    End If
    
    t = InStrRev(strdb, "\")
    If t > 0 Then
       strbk = Mid(strdb, t + 1)
    End If
    strbk = tmp & strbk
    
    xdir = Dir(strbk)
    If Len(xdir) > 0 Then
       Kill strbk
    End If
    'Make a Copy in c:\tmp folder as safe backup
    Me.lblMsg.Caption = "Taking Backup of " & strdb & vbCrLf _
    & "to " & tmp
    DoEvents
    
       DBEngine.CompactDatabase strdb, strbk
    
    Me.lblMsg.Caption = "Transferring Objects from " & strdb & vbCrLf _
    & "to " & tmp & "db1"
    DoEvents
    
       DBEngine.CompactDatabase strdb, tmp & "db1.mdb"
    
    ' Delete uncompacted Database and Copy Compacted db1.mdb with
    ' the Original Name
    
    lblMsg.Caption = "Creating " & strdb & " from " & tmp & "db1.mdb"
    DoEvents
    
        If Len(Dir(strdb)) > 0 Then
            Kill strdb
        End If
    
        DBEngine.CompactDatabase tmp & "db1.mdb", strdb
    
    lblMsg.Caption = strdb & " Compacted Successfully." & vbCrLf & "Database backup copy saved at Location: " & tmp
    DoEvents
    
    dbCompact_Err_Exit:
    Exit Function
    
    dbCompact_Err:
    MsgBox Err & " : " & Err.Description, , "dbCompact()"
      Resume dbCompact_Err_Exit
    End Function
    

    You can set the Compacting Form to open at Startup. Select Startup from the Tools Menu. Select Form Compacting in the Display Form/Page Control. To hide the Database Window, remove the check mark from the Display Database Window Option.

    The Trial Run

  18. Open the Compacting Form in Normal view. Select one or more Databases from the List Box for Compacting.

  19. Click the Repair/Compact Command Button.

When you run the program for the first time, it checks for the folder C:\tmp. If that folder is not found, the program automatically creates it. This directory serves as the working area for the Compacting Utility—regardless of whether the program is executed from the server or a local drive. All backup copies of the compacted databases are stored in this location for safekeeping.

Before initiating the compacting process, the program performs a status check on each selected database to ensure that no users are currently accessing it. If a database is found to be in use, the program will display a notification message. The compacting operation is skipped for that particular database, preventing potential file conflicts or data corruption.

The Label Controls that we have created and kept hidden under the List Box will be made visible. It will be updated with the program's current activity information at different stages of the Compacting Procedure.

Any suggestions for improvement of this Program are welcome.

The Demo Database is upgraded to MS-Access Version 2016 and can be downloaded from the link below.

Share:

Database Open Close Event Alerts

Logging Database Events.

When your application is installed on a network and shared by multiple users, it’s often useful to monitor database activity, such as which user opens or closes the database, and when these events occur.

In some cases, your database may not be secured (i.e., anyone with access to the shared location can open it). Even if it’s primarily intended for a few trusted users whose Workstation IDs or Network IDs you already know, it’s still possible for unauthorized users to explore it out of curiosity.

To address this, you can implement a monitoring and alert system within the database. When someone opens the database, the system records their workstation or network ID, along with the login time. If an unauthorized user attempts to open it, the system can immediately send a message to that workstation. The intruder will receive a warning message to close the database immediately. This action makes it clear that their activity is being monitored, discouraging future unauthorized access attempts.

You can also use the same mechanism for legitimate administrative purposes. For example:

  • To receive an alert when someone opens the database during maintenance work, so you can prevent data conflicts.

  • To detect when the current active user has closed the database, allowing you to safely make updates.

  • To send a message to an active user directly from your system — for example, requesting to close the database so you can apply fixes, or notifying them that maintenance tasks are complete,  without needing to contact them by phone or in person.

It’s both interesting and highly practical to automate certain administrative tasks and receive timely feedback from your databases. This allows you to plan and execute maintenance or coordination activities more efficiently, keeping in touch with both your Users and Databases.

All of these capabilities become possible once your databases can send alert messages directly to your workstation whenever users open or close them. For implementation details, refer to the article titled Sending Alerts to Workstations Based on Process-Related Activities within a Database.” Once you know each user’s workstation ID, you can even send messages back to their PCs directly from your desktop whenever you need to communicate with them.

You can also explore the related article Who Is Online,” where we discuss alternative approaches to these same monitoring concepts.

If you manage multiple applications across the network, you may occasionally receive too many alert messages. That’s not a problem; you can easily turn specific alerts on or off without having to modify any of your databases individually.

At first glance, this might sound like a large or complex project, but it’s actually quite simple to implement. You can set it up in just about ten minutes, and you’ll immediately see it in action. All you need is a Windows network environment in your office, nothing more.

The Alert Message Contents

The Alert Messages must be loaded with the following information when received:

  • User Workstation-ID
  • Date and Time
  • Database PathName
  • Status info (Open/Close)
  • User Network ID
  • MS-Access User ID

Our Network Administrator was kind enough to set my Last Name (PILLAI) as my WorkStation-ID. The images of sample Network Messenger Alerts that come to my WorkStation are given below as a sample. 

The Database Open Event Alert Message.

Database Close Event Alert Message

All we need for this interesting Trick is a VBA Routine (given below) and 3 text files. The VBA Program must be copied to the Global Module of your Database and called from the Main Switchboard (Control Screen) in the On Open and On Close Event Procedures.

If you have a Library Database already attached to your Databases from a Network Location, then place the main Code in the Library Database only. Then you need to install only two lines of code in the On Open and On Close Event Procedures in the Main Switchboard Form (Control Screen) in your Databases.

Prepare for a Trial Run.

But for now, let us try it in one of your Databases installed in a Network Location shared by Users. When you are ready to implement it in other Databases, you can do so following the same procedure. The Names and usage of the three Text files (all of them are Optional), created for your control purposes, are given below:

File-1: AccsCtrl.txt - List of Databases where the Message Alert Programs are running.

File-2: AccLog.txt - Message Alert Log entries for reference purposes.

File-3: Message.BAT - For sending messages and alerts from your PC to your Database Users' Workstation.

  1. Copy and paste the following VBA Code into a Global Module of your Project or Library Database and save it:

    The OpenCloseAlert() Function

    Public Const accmsgtxt As String = "h:\inhsys\comlib\AccsCtrl.txt"
    Public Const acclogtxt As String = "h:\inhsys\comlib\AccsLog.txt"
    
    Public Function OpenCloseAlert(ByVal mstat As String)
    '-----------------------------------------------------------
    'Author: a.p.r. pillai
    'URL   : www.msaccesstips.com
    'Date  : 20/05/2008
    'All Rights Reserved by www.msaccesstips.com
    '-----------------------------------------------------------
    Dim t As Double, WorkStationID As String * 15
    Dim netUserName As String * 15, accUserName As String * 15
    Dim str As String, loc As Integer, AlertMsg As String
    Dim AlertFlag As String,  flag As Boolean
    Dim chk As String, dbpath As String, m_stat As String * 1
    Dim status As String * 8, dttime As String * 22
    
    On Error GoTo OpenCloseAlert_Err
    
    dbpath = CurrentDb.Name
    m_stat = mstat
    str = Dir(accmsgtxt)
    If Len(str) = 0 Then
    'accsctrl.txt File Not Found   
    'ignore ON/OFF flag checking   
    'proceed to Alert Message Section
       GoTo nextstep
    End If
    
    'open the control file and check the Status
    Open accmsgtxt For Input As #1
    AlertFlag = " ": flag = False
    Do While Not EOF(1)
    Input #1, chk
    If flag = False And Left(chk, 5) = "ALERT" Then
       flag = True
       chk = UCase(chk)
       loc = InStr(6, chk, "OFF")
       If loc > 0 Then     'Turn off Alerts from All Databases
         Exit Function
       Else
         GoTo readnext
       End If
    End If
    
    loc = InStr(1, chk, dbpath)
    If loc > 0 Then'database file found, take the flag value
      AlertFlag = Right(Trim(chk), 1)
      Exit Do
    End If
    readnext:
    Loop
    Close #1
    
    If AlertFlag = "0" Or Len(AlertFlag) = 0 Then   'Turn off Alert in this Database
       Exit Function
    End If
    
    nextstep:
    
    WorkStationID = Environ("COMPUTERNAME")
    netUserName = Environ("USERNAME")
    accUserName = CurrentUser
    
    status = IIf(Left(mstat, 1) = "O", "OPEN", "CLOSE")
    dttime = Format(Now(), "mm/dd/yyyy hh:nn:ss")
    
    AlertMsg = LCase(CurrentDb.Name) & " OPEN/CLOSE Status : " & vbCr & vbCr & "STATUS............: " & IIf(Left(mstat, 1) = "O", "OPEN", "CLOSE") & vbCr & "WORKSTATION ID....: " & WorkStationID & vbCr & "NETWORK USERNAME..: " & netUserName & vbCr & "ACCESS USERNAME...: " & accUserName & vbCr 
    
    'insert your Workstation ID replacing the text
     Call Shell("NET SEND  " & AlertMsg, vbHide)
    
    str = Dir(acclogtxt)
    If Len(str) = 0 Then
      GoTo OpenCloseAlert_Exit
    Else
      Open acclogtxt For Append As #1
      Print #1, status; dttime; WorkStationID; netUserName; accUserName; CurrentDb.Name
      Close #1
    End If
    
    OpenCloseAlert_Exit:
    Exit Function
    
    OpenCloseAlert_Err:
    MsgBox Err.Description, , "OpenCloseAlert()"
    Resume OpenCloseAlert_Exit
    End Function
    

    The first two lines of the code must be placed in the Global Declaration area of the Module, below the Option Declarations, as indicated below.

    Option Compare Database
    Option Explicit
    Public Const accmsgtxt As String = "h:\inhsys\comlib\AccsCtrl.txt"
    Public Const acclogtxt As String = "h:\inhsys\comlib\AccsLog.txt"
    
  2. Copy the following lines in the VBA Module of the Main Switchboard (Control Screen) Form or copy only the middle line into their respective Event Procedures, if they already exist:

    Private Sub Form_Open(Cancel As Integer)
         OpenCloseAlert "Open"
    End Sub
    
    Private Sub Form_Close()
         OpenCloseAlert "Close"
    End Sub
    
  3. We will create the Text Files AccsCtrl.txt and AccsLog.txt in a common location on the Server, where all your Application Users have Access Rights. Change the Server Path h:\inhsys\comlib in the Constant Declaration lines to the common location Path on your Server. Do not use UNC Path specification \\Server\Folder\database.

    Note: The term Path represents the location address of a file without the File Name, but Path Name denotes the location Address including the File Name and File Name Extension.

    Create Text Files.

  4. Open Windows Notepad (Start -> Program Files -> Accessories -> Notepad). Copy and paste the following lines into the blank Notepad File:
    ALERT=ON
    H:\FolderName\FolderName\MYDB1.MDB=1
    G:\FolderName\MYDB2.MDB=0
    
  5. Change the second and third lines to point to your Databases on a Server already in use by others. Save the Text File with the name AccsCtrl.txt at the Location on the Server specified in the constant declaration line path given above. Databases can be in any location on the Server.

  6. Select New from the Notepad File Menu to open a new text File. Save the empty text file in the same location on the Server named AccsLog.txt. The Log details of the Alert Messages that you receive will be saved in this file, too. You can open and view history when needed.

    This file can be created programmatically if it doesn’t already exist. However, I decided to leave that choice to you, depending on whether you want to do it or not. If you have multiple applications running with this alert mechanism enabled, the log file may grow rapidly, consuming a significant portion of your disk quota.

    You can experiment with it to observe the frequency of logged events and determine whether ongoing logging is necessary. It’s also a good practice to periodically review and manage the file’s contents — either by deleting older entries or by archiving them to another file on your local drive to keep disk usage under control.

  7. Create Desktop Shortcuts to these Files so that you can open them quickly, and edit or view the contents when needed. Right-click on the Desktop, highlight New, and select Shortcut from the displayed menu. Browse to the location of the AccsCtrl.txt file and select it, click OK, click Next, then click Finish.

    Let us look into the Logic of the Main Program OpenCloseAlert() and how the File AccsCtrl.txt is interpreted and controls the Program execution.

    • If you have not created the File AccsCtrl.txt at all (as per the declaration Public Const accmsgtxt As String = "h:\inhsys\comlib\AccsCtrl.txt" In the specified location, you will still receive the Alert Messages, but you cannot control them by switching them off or on at will.

    • If you have created the File AccsCtrl.txt but forgot to add the Database Path Name with flag 1 at the end, then the Alerts will not trigger for that Database.

    • If the first line in this file is ALERT=OFF, then further lines in this file will not be processed and will turn off the Alerts from all Databases.

    • Any value after the word ALERT= other than OFF (ON or anything else except space) will be ignored, and will proceed with the individual Database level flag checking. We opted out of checking the ON flag setting because we are doing it at the individual database level to trigger the Alerts. Besides, this line was introduced to switch off all alerts from all databases with one change. If you prefer to control with an individual file-level flag setting (which is explained below), you don't need to put this line at all in this File.

    • If you place the ALERT=OFF statement after a few lines of the Database Path Names (see Step 4) in the Text File, then the program always checks the lines above this statement and executes the program OpenCloseAlert(). This depends on the logic setting (1 or 0) at the Database level. But, Path Names after this line are ignored and never checked.

    • We have added two sample Database Path Names after the first line with Alert status flag =1 and =0 at the end (1= Alerts ON, 0=Alerts OFF). You may add any number of Databases in this way, with flag value 0 or 1 after the equal (=) sign, after installing the Program OpenCloseAlert() in the Database.

    • When the program encounters the Database Path Name, it extracts the last character from that line to check the status. Ensure that you are not adding any other characters after 0 or 1 except white spaces.

    • If the flag is 0, then the Alert Message will be turned off for that Database. Any other value will send it.

    • By adjusting the values in this file, you can control Alerts coming to you without touching any of your Databases.
    • If you have not created the Logfile AccsLog.txt, the program will not generate any error, but the message history will not be maintained. You can delete old records from this file to keep the file size small on the Server.

    • Create copies of these Files periodically as a backup and keep them in a safe place for restoring, if the active one gets corrupted or deleted by mistake.

    The DOS Batch File.

  8. We will create a DOS Batch File on your Desktop for sending messages to your Database Users as and when the need arises. Open Windows Notepad and write the following line:

    NET SEND WorkstationID messagetext
    
  9. Note: The NET SEND <messageCommand works under the Windows XP Operating System only. Later versions of Windows use the MSG Command.   C:\MSG /? - The Command displays the details of different Parameters that can be used with this Command.

    Write the network of a known machine in place of the text 'WorkstationID' and a test message, replacing the text 'message text--.'

  10. Select Save As from the File menu and browse to your Desktop (C:\Documents and Settings\your network ID\Desktop) and save it, named MESSAGE.BAT. Select All Files in the Save As Type control before saving it. The MESSAGE.BAT name will appear on your Desktop.

  11. Since this file is on your Desktop, you can always right-click it, select Edit from the displayed menu, open it in Notepad, change the WorkStationID and message text, and close it.

  12. Double-click on the Desktop icon of the MESSAGE.BAT File to send the message after making changes. Batch Files are treated as programs, and if you have any security issues, please check with your System Administrator. Alternatively, you can send Network messages directly from the DOS Prompt. Open Run from the Start Menu. Type cmd and click OK. Type the NET SEND command followed by WorkstationID and your Message Text, giving a space between the WorkstationID and the Message, then press the Enter Key.

When you implement this method correctly, you can keep track of your Databases, and the log file (AccsLog.txt) will record the history of activities. If you need, you can link this Text File to a Database for analysis purposes and find out the frequency and User-level time spent, and so on.

When you communicate with your Database Users, asking them to open or close the Database, they will also know that you are watching over their activities. You can open and check the AccsLog.txt file contents to find out who is active and for how long, etc.

You must consider securing your Databases for the internal security of Objects and for regulating access rights to different categories of Users if you have not done so already. Read the Pages Microsoft Access Security for details on this very powerful feature. It may take some time to understand all the twists and turns of this feature. But if you start using it, you can learn it by experimenting. Believe me, if you are a serious MS-Access Developer, you must learn it. Doesn't matter how long it takes to understand the rules. You can post your doubts over Security issues in the Comments Section. I will extend all possible help that I can give you.

The Trial Run.

Now the stage is all set for trial Runs. Ask one of your Application Users to open the above Database from their Workstation. You must get a Pop-up message, similar to the sample image given above, during both Opening and Closing events. Ask more Users to open the same Database from their PCs, too. You must get Alerts from each instance of the same Database.

You can implement the same Code in other Databases and add their Path Names in the AccsCtrl.txt file.

Share:

List Box and Date Part Two

Continued from LIST BOX AND DATE PART ONE

When working with date values in List Boxes, we’ve seen that it’s often necessary to convert the selected values into a compatible format before using them in data processing tasks. In this section, we’ll explore two additional examples that use different date expressions. Although the resulting output remains the same, the methods of specifying the date parameters will vary.

Typically, we can filter data using a date range — by entering a start date and an end date in text boxes on a report parameter form, or by entering these values directly into parameter queries to extract records from a source table or query. However, in the examples that follow, we’ll approach this task differently to gain a deeper understanding of how to work with date-related expressions in Microsoft Access VBA.

Modifying the Form.

  1. Open the Form LISTBOXDATE that we have created in the earlier example in Design View.

  2. Make a copy of the List Box and paste it into the same area of the Form. Drag and place it on the right side of the Combo Box. See the sample image given below:

  3. Place the child Label on the top and display its Property Sheet (View --> Properties). Change its Caption Property to List (Type-2).

  4. Click on the List Box and display the Property Sheet (if you have closed it), and change the following Properties:

    • Name = List2
    • Row Source Type = Value List
    • Row Source = 01;"Jan";02;"Feb";03;"Mar";04;"Apr";05;"May";06;"Jun";07;"Jul";08;"Aug";09;"Sep";10;"Oct";11;"Nov";12;"Dec"
    • Column Count = 2
    • Column Heads = No
    • Column Width = 0";1.5"
    • Bound Column = 1
    • Default Value = 1
    • Multi Select = None

    At this point, let’s focus on a few important property settings of the List Box.
    First, check the Row Source property. In this example, the List Box items are entered as value pairs, such as 01; "Jan" for January, and so on for the other months. The Column Count property is set to 2, meaning the List Box contains two columns — the numeric value (e.g., 01) in the first column and the corresponding month abbreviation (e.g., Jan) in the second.

    However, when the List Box is displayed, only the second column (Jan, Feb, etc.) appears. This is because of the Column Widths property, which is set to 0";1.5". The first column has a width of  0 inches, effectively hiding it from view.

    Even though it’s hidden, the Bound Column property is set to 1, which means that when a user selects a month, the value from the first (hidden) column — such as 01 — is actually the one returned by the List Box.

    Finally, the Default Value property is set to 1, ensuring that if the user doesn’t make a selection, “Jan” (the first item in the list) is chosen automatically.

  5. Create two TextBoxes to the left of the List Box and below the other TextBoxes. Change the Caption of the child Labels to Method-2 and Method-3.

  6. Change the Property Values of the first Text Box that you have drawn now to the following Values:

    • Name = Method2
    • Control Source = =Format(DateSerial([cboyear],[List2],1),"mmm-yyyy")
  7. Change the Property Values of the second Text Box to the following Values:

    • Name = Method3
    • Control Source = =[cboYear]*100+[List2]
  8. Create a Command Button to the right of the existing two buttons and change the Property Values as shown below:

    • Name = cmdDisplay2
    • Caption = Display-2
  9. Create another Command Button and place it to the right, and change the Property Values as given below:

    • Name = cmdDisplay3
    • Caption = Display-3
  10. Display the VBA Code Module of the Form (View -> Code), and add the following VBA Code into the Module by copying and pasting it below the existing Code:

    Private Sub cmdDisplay2_Click()
    Me.Refresh
    DoCmd.OpenQuery "Display2_listbox", acViewNormal
    End Sub
    
    Private Sub cmdDispaly3_Click()
    Me.Refresh
    DoCmd.OpenQuery "Display3_listbox", acViewNormal
    End Sub
    
  11. Open a New Query in Design View without selecting any file from the displayed list. Open the SQL editing Window (View -> SQL View), copy and paste the following SQL String, and save the Query with the name DISPLAY2_LISTBOX:

    SELECT Orders.*
    FROM Orders
    WHERE (((Format([orderdate],"mmm-yyyy"))=[Forms]![LISTBOXDATE]![Method2]));
    
  12. Open another New Query in Design View, copy and paste the following SQL String into the SQL editing window, and save it with the name DISPLAY3_LISTBOX:
    SELECT Orders.*
    FROM Orders
    WHERE (((Format([orderdate],"yyyymm"))=[Forms]![LISTBOXDATE]![Method3]));
    

    Test Runs

  13. Open the LISTBOXDATE Form in Normal View and click on the Command Button Display-2. The Query DISPLAY2_LISTBOX will open up with filtered output data using the current value in the Text Box with the name Method2. Select different Values in the Year Combo Box and the new List Box and try it again. Check the accuracy of the filtered data.

    NB: If the Query displays an error, then try to link the essential Library Files to your Project. Visit the Page Command Button Animation for details of Library Files and follow the procedures explained there. The Orders Table doesn't have all twelve months of data except for the Year 1997. Check for the Range of months available in the 1996 and 1998 years' data in this Table and select a month for available data for testing.

    Every time you select different Values in the List Box and the Combo Box, the value in the TextBox with the names Method2 and Method3 also changes. Close the Datasheet View of the Query before clicking the Command Button with a different selection of values.

  14. Click on the Command Button Display-3 to open the Query DISPLAY3_LISTBOX with the filtered output using the Text Box named Method3 Value.

NB: You must change the Visible Property of these TextBoxes to No to keep them hidden from your Application Users. Study the expressions written in the TextBoxes and their corresponding Formula written in the Query Column to compare both values.

The List Box Settings

We used the Multi-Select Property of the List Boxes in the first two articles, Selected List Box Items and Dynamic Query, and Create List from Another List Box With Simple and Extended value settings,  but here we turned it off.

When you open the Form containing the List Boxes (with their Multi-Select property set to either Simple or Extended) for the first time, the Text Boxes that depend on expressions using values from these List Boxes will automatically display results based on the Default Value property, if one is defined. However, once you start interacting with the List Box—by clicking on an item—the Text Boxes may display #Error or become blank.

When the Multi-Select property is set to Simple, you can select or deselect items by clicking them one at a time.
When it is set to Extended, you can:

  • Select a range of adjacent items by clicking the first and last items while holding down the SHIFT key, or by clicking and dragging the mouse across the list (without using SHIFT).

  • Select non-adjacent items by holding the CTRL key and clicking on each desired item individually — just as you would in Simple mode.

We used the Multi-Select Property value equal to None (default setting) because our examples presented here work on a single item from the List Box.

Share:

List Box and Date Part One

Date Selection ListBox.

One of our dedicated readers, Mr. Nick Els from South Africa, has proposed an insightful idea for an Article focusing on the practical applications of ListBoxes with date-related settings. This marks the beginning of a two-part series dedicated to exploring this specific topic. Please review our previous posts on Selected List Box Items and Dynamic Query, and create a List from Another List Box for a comprehensive understanding leading up to this series.

Descriptive names of the Months or their numerical form combined with Year Values from Combo Boxes or List Boxes can be used in various ways to compare with Date Field values in Queries for filtering data. I have mentioned the term variety because all methods require creating expressions at the Query level or in Text Boxes on Forms to reformat the values into a compatible type before they are compared. We will split this article into two parts instead of overcrowding it with all of them here.

List Boxes can be created in Data Entry Forms, Main Switchboards (Control Screen) for opening Forms or Reports, or on Report Parameter Forms for use in Queries for Data Processing tasks, and so on. One or more Values from List Boxes can be selected and used directly with queries or VBA Routines to filter data from underlying tables, as we did in the earlier examples with List Boxes.

A reference to the selected List Box item can be set directly in a Query Criteria Row or extracted the selected value into a Text box with the help of a formula (like =[List1] in the Control Source property) and referenced it in the Query to Filter Values from the underlying Table.

There are a few important aspects to understand about the Multi-Select property settings of List Boxes,  their advantages, limitations, and how they affect expressions that reference selected items in Text Boxes or Query Criteria. These topics will be explored in greater detail in the second part of this article, rather than delving too deeply into them here, and risking unnecessary complexity at this stage.

Get Northwind Sample Tables.

  1. Download the following four tables from the Northwind.mdb sample database. For now, we will be using only the Orders table. However, since the Orders table contains references to other tables, missing those related tables in your project may cause errors when opening queries based on the Orders table.

    If you’re unsure where the Northwind.mdb sample database is located, refer to the page Saving Data on Forms Not in a Table for location details and reference instructions.

    If you prefer to use a Table from your own project, you may do so, but you have to edit the expressions to change the Table Name and Field Names presented here before they are used with your Table.

    • Orders
    • Customers
    • Employees
    • Shippers
  2. Copy and paste the following SQL String into the SQL Editing window of a new Query and save the Query with the name OrderYearQ.

    SELECT Year([OrderDate]) AS OrderYr
    FROM Orders
    GROUP BY Year([OrderDate]);
    
  3. Open a New Form in Design View. If the Toolbox is not visible, then select Toolbox from the View Menu.

    Designing a Form with a List Box.

  4. De-select the Control Wizard (top-right control on the Toolbox) if it is in the selected state. Select the ListBox Tool and draw a ListBox as shown in the design below.

  5. Click on the Child Label attached to the List Box and display the Property Sheet (View -> Properties), change the Caption Property to List1 (Type-1), and position the Label above the List Box.

  6. Select the List Box, display the Property Sheet (if you have already closed it), and change the following property values as indicated against each one:

    • Name = List1
    • Row Source Type = Value List
    • Row Source = "January";"February";"March";"April";"May";"June";"July";"August";"September";"October";"November";"December"
    • Column Count = 1
    • Column Widths = 1.5"
    • Bound Column = 1
    • Default Value = "January"
    • Multi Select = None
  7. Turn on the Control Wizard that we have disabled in Step 5. Select the Combo Box Tool and draw a Combo Box at the top and to the right of the List Box. Select the OrderYearQ Query that we have created in Step 1 from the Queries List.

  8. Change the following Property Values of the Child Label and the Combo Box:
    • Child Label: Caption = Year
    • Combo Box: Name = cboYear
    • Column Count = 1
    • Column Heads = No
    • Column Widths = 0.5"
    • Bound Column = 1
    • List widths = 0.5"
    • Default Value = =DMin("orderyr","orderyearQ")+1
  9. Create a Text Box below the Combo Box and change its Child Label Caption to Method-1. Select the Text Box and change the following Properties:
    • Name = Method1
    • Control Source = =Format(DateValue("01" & "-" & [List1] & "-" & [cboyear]),"yyyymm")

    The Visible Property of this Control can be set to No to hide it from Users if needed.

  10. Create two Command Buttons below the List Box.
  11. Change the first Command Button's Name Property to cmdDisplay0 and change the Caption Property to Display-0.
  12. Create a second Command Button to the right of the earlier one and change the Name Property to cmdDisplay1 and the Caption Property to Display-1.

    The Form Class Module Code.

  13. Display the VBA Module of the Form (View -> Code), copy and paste the following VBA Code into the Module, and save the Form with the name LISTBOXDATE.
    Private Sub cmdDisplay0_Click()
    Me.Refresh
    DoCmd.OpenQuery "Display0_listbox", acViewNormal
    End Sub
    
    Private Sub cmdDisplay1_Click()
    Me.Refresh
    DoCmd.OpenQuery "Display1_listbox", acViewNormal
    End Sub
    

    Note: You must save the Form with the above name for our examples. We will be setting references to the List Box, Combo Box, and Text Box on this Form to use their current values in Query Criteria Rows.

    Sample Queries.

  14. Open a new Query in Design View without selecting any of the Files displayed. Display the SQL Window (View -> SQL View), copy and paste the SQL string given below, and save it with the name DISPLAY0_LISTBOX.
    SELECT Orders.*,
     Format([orderdate],"mmmm") AS MTH,
     Year([ORDERDATE]) AS XYEAR
    FROM Orders
    WHERE (((Format([orderdate],"mmmm"))=[Forms]![LISTBOXDATE]![List1]) AND ((Year([ORDERDATE]))=[Forms]![LISTBOXDATE]![cboYear]));
    
  15. Create another Query with the following SQL string and save it with the name DISPLAY1_LISTBOX.
    SELECT Orders.*
    FROM Orders
    WHERE (((Format([OrderDate],"yyyymm"))=[Forms]![LISTBOXDATE]![Method1]));
    

    Test Runs.

  16. Open the Form LISTBOXDATE in Normal View.

  17. By default, January is selected in the List Box, and the Year 1997 is set in the Year Combo Box as the default value.

    The Text Box below the Combo Box displays the result of the formula that we have written using the List Box's current selection of the month and the Combo Box value combined.

    The two Queries that we have created use different methods to reference the contents of the List Box and the Combo Box.

  18. Select a month from the List Box. Select a different Year in the Combo Box, if needed (but be careful with the month selection because not all twelve months' data are available except for the year 1997 in the Orders Table).
  19. Click on the Command Button with the Caption Display-0. The DISPLAY0_LISTBOX Query will open in Datasheet view with the data corresponding to the Month and Years settings in the List box and the Combo box, respectively. Close the Datasheet View of the Query before trying it out with the different settings.

    NB: If the Query displays an error, then link the essential Library Files to your Project. Visit the Page Command Button Animation for details of Library Files and follow the procedures explained there.

  20. Open the first Query DISPLAY0_LISTBOX in the design view and check the criteria settings that we have created to compare the Order Date with the settings on the Form.

    We have created two columns with expressions for converting the Order Date Value into the descriptive name of the Month in the first column, and extracting the Year Value in the second Column. On the criteria row, we have set a direct reference to the selected month in the ListBox, and the second column criteria are set with a reference to the current value of the ComboBox.

  21. Click the Command Button with the Caption Display-1.

It will open the second Query DISPLAY1_LISTBOX with the same result. But this query has only one column with an expression to compare the value with the Text Box contents on the Form. The Text box has the formula =Format(DateValue("01" & "-" & [List1] & "-" & [cboyear]), "yyyymm") to combine both Month and Year values, from the List Box and the Combo box respectively, together and referenced from the Query criteria row.

Study the expressions written in the Queries and in the Form controls and try to understand how they work. You may create TextBoxes and Queries using the same ListBox and ComboBox values and try them out, which will give you more insight into these methods.

Share:

PRESENTATION: ACCESS USER GROUPS (EUROPE)

Translate

PageRank

Post Feed


Search

Popular Posts

Blog Archive

Powered by Blogger.

Labels

Forms Functions How Tos MS-Access Security Reports msaccess forms Animations msaccess animation Utilities msaccess controls Access and Internet MS-Access Scurity MS-Access and Internet External Links Queries Array Class Module msaccess reports Accesstips msaccess tips WithEvents Downloads Objects Menus and Toolbars MsaccessLinks Process Controls Art Work Collection Object Property msaccess How Tos Combo Boxes ListView Control Query VBA msaccessQuery Calculation Dictionary Object Event Graph Charts ImageList Control List Boxes TreeView Control Command Buttons Controls Data Emails and Alerts Form Custom Functions Custom Wizards DOS Commands Data Type Key Object Reference ms-access functions msaccess functions msaccess graphs msaccess reporttricks Command Button Report msaccess menus msaccessprocess security advanced Access Security Add Auto-Number Field Type Form Instances ImageList Item Macros Menus Nodes Recordset Top Values Variables msaccess email progressmeter Access2007 Copy Excel Expression Fields Join Methods Microsoft Numbering System RaiseEvent Records Security Split SubForm Table Tables Time Difference Utility WScript Workgroup Wrapper Classes database function msaccess wizards tutorial Access Emails and Alerts Access Fields Access How Tos Access Mail Merge Access2003 Accounting Year Action Animation Attachment Binary Numbers Bookmarks Budgeting ChDir Color Palette Common Controls Conditional Formatting Data Filtering Database Records Defining Pages Desktop Shortcuts Diagram Disk Dynamic Lookup Error Handler Export External Filter Formatting Groups Hexadecimal Numbers Import Labels List Logo Macro Mail Merge Main Form Memo Message Box Monitoring Octal Numbers Operating System Paste Primary-Key Product Rank Reading Remove Rich Text Sequence SetFocus Summary Tab-Page Union Query User Users Water-Mark Word automatically commands hyperlinks iSeries Date iif ms-access msaccess msaccess alerts pdf files reference restore switch text toolbar updating upload vba code