Learn Microsoft Access Advanced Programming Techniques, Tips and Tricks.

Showing posts with label msaccess forms. Show all posts
Showing posts with label msaccess forms. Show all posts

DIRectory and File Copy Utility

Introduction.

Last week, we explored how to use the Dir() DOS command to read files from the disk one by one and display their names in the Debug window.

Building on that, we will now create a VBA utility that uses the Dir() command together with the very useful FileCopy statement (note that it is a statement, not a function) to read and transfer files from one folder to another location on the disk. The files can be of any type—for example, *.pdf, *.docx, *.xls, or *.* (all files).

This utility will read the files from a folder specified in a text box, list them in a list box using the Dir() command, and allow you to copy either all the listed files or only the selected ones to a target folder specified in another text box.

The Utility Form.

The design view image of a Form created for this purpose is given below for reference:

The form design is simple, consisting of two text boxes, one list box, three command buttons, and a label control to display messages from the utility program. You can download this utility form as part of a sample database at the end of this article.

These are the names of the Controls on the Form:

  1. Top Text box: Source

  2. Text Box 2:  Target

  3. List Box:  List1

  4. Top Command Button: cmdDir

  5. Second Command Button: cmdSelected

  6. Last Command Button: cmdClose

  7. Bottom empty Label Name: msg

Note: If you are designing this form yourself, make sure that the same control names are used as described above. The VBA code you will copy into the module references these exact names.

In addition to the main controls, there is a Label control below the first (source) text box that provides examples of how to specify the source file path correctly.

Another label control at the bottom of the form displays messages during input validation and shows error notifications while the VBA code is executing.

An Image of a sample run of the FileCopy Statement is given below:

filecopy_run0

Right-click to open Large Image in New Tab/Window.

You can create this user interface using the control names provided above. Once the form is designed with the correct control names, open the VBA window for the form and copy the following code into its VBA module:

The Form Module Code.

Option Compare Database
Option Explicit
Dim strSource1 As String
Dim strSource2 As String, strMsg As String

Private Sub cmdClose_Click()
On Error GoTo cmdClose_Click_Error

If MsgBox("Close File Copy Utility?", vbOKCancel + vbQuestion, "cmdClose_Click()") = vbOK Then
   DoCmd.Close acForm, Me.Name, acSaveYes
End If

cmdClose_Click_Exit:
Exit Sub

cmdClose_Click_Error:
MsgBox Err.Description, , "cmdClose_Click()"
Resume cmdClose_Click_Exit
End Sub

Private Sub cmdDir_Click()
'=========================================================
'Author : a.p.r.pillai
'Date   : June 2018
'Purpose: Take directory listing
'Rights : All Rights Reserved by www.msaccesstips.com
'=========================================================
Dim strSource As String, strMsg As String
Dim i As Integer, x As String
Dim j As Integer, strfile As String
Dim strList As ListBox, LList As String

On Error GoTo cmdDir_Click_Err
msg.Caption = ""

'Read Source location address
strSource = Nz(Me!Source, "")
If Len(strSource) = 0 Then
    strMsg = "Source Path is empty."
    MsgBox strMsg,vbOKOnly + vbCritical, "cmdDir_Click()"
msg.Caption = strMsg
    Exit Sub
End If

'check for the last back-slash location
'this can be used to split the folder name
'and file name type values separately.

i = InStrRev(strSource, "\")

'get the folder name part into the variable
strSource1 = Left(strSource, i)

'take file type (*.docx, *.exl, *.txt etc.) value into a separate
'variable temporarily
If Len(strSource) > i Then
    strSource2 = Right(strSource, Len(strSource) - i)
End If

'define Listbox object
Set strList = Me.List1

'Read the first file from the folder
strfile = Dir(strSource, vbHidden)
If Len(strfile) = 0 Then
    strMsg = "No Files of the specified type: '" & strSource2 & "' in this folder."
    MsgBox strMsg, vbCritical + vbOKOnly, "cmdDir()"
    msg.Caption = strMsg
    Exit Sub
End If

j = 0
LList = ""
Do While Len(strfile) > 0
   If Left(strfile, 1) = "~" Then 'ignore backup files, if any
      GoTo readnext:
   End If
    j = j + 1 'File list count
    LList = LList & Chr(34) & strfile & Chr(34) & ","
    
readnext:
    strfile = Dir() ' read next file
Loop

LList = Left(LList, Len(LList) - 1) ' remove the extra comma at the end of the list
strList.RowSource = LList 'insert the files list into the listbox RowSource property
strList.Requery 'refresh the listbox
msg.Caption = "Total: " & j & " Files found."

Me.Target.Enabled = True

cmdDir_Click_Exit:
Exit Sub

cmdDir_Click_Err:
MsgBox Err.Description, , "cmdDir_Click()"
Resume cmdDir_Click_Exit

End Sub


Private Sub cmdSelected_Click()
'=========================================================
'Author : a.p.r.pillai
'Date   : June 2018
'Purpose: Copy Selected/All Files to Target Location
'Rights : All Rights Reserved by www.msaccesstips.com
'=========================================================

Dim lstBox As ListBox, ListCount As Integer
Dim strfile As String, j As Integer, t As Double
Dim strTarget As String, strTarget2 As String
Dim chk As String, i As Integer, yn As Integer
Dim k As Integer

On Error GoTo cmdSelected_Click_Err

msg.Caption = ""
'Read Target location address
strTarget = Trim(Nz(Me!Target, ""))

'validate Destination location
If Len(strTarget) = 0 Then
   strMsg = "Enter a Valid Path for Destination!"
   MsgBox strMsg, vbOKOnly + vbCritical, "cmdSelected()"
   msg.Caption = strMsg
   Exit Sub
ElseIf Right(strTarget, 1) <> "\" Then
      strMsg = "Correct the Path as '" & Trim(Me.Target) & "\' and Re-try"
      MsgBox strMsg, vbOKOnly + vbCritical, "cmdSelected()"
      msg.Caption = strMsg
      Exit Sub
End If

'Take a count of files in listbox
Set lstBox = Me.List1
ListCount = lstBox.ListCount - 1

'take a count of selected files, if any, for copying
i = 0
For j = 0 To ListCount
If lstBox.Selected(j) Then
  i = i + 1
End If
Next

'identify user's response for copy
If (i = 0) And (ListCount > 0) Then
       strMsg = "Copy all Files..?"
       Me.cmdSelected.Caption = "Copy All"
Else
       strMsg = "Copy Selected Files..?"
       Me.cmdSelected.Caption = "Copy Marked files"

End If

'Me.cmdSelected.Requery

'get copy option from User
yn = MsgBox(strMsg, vbOKCancel + vbQuestion, "cmdSelected_Click()")

'Run Copy selected option
If (i = 0) And (yn = vbOK) Then
    GoSub allCopy
ElseIf (i > 0) And (yn = vbOK) Then
    GoSub selectCopy
Else
    Exit Sub
End If

'disable Copy button to stop a repeat copy of the same files.
'Remarks: User can make fresh selections from the same list
'To copy them to the same target locatiion.
'Or to a different location by specifying different Path
'in the Destination Text Box
Me.List1.SetFocus
Me.cmdSelected.Enabled = False

'Display copy status
strMsg = "Total " & k & " File(s) Copied." & vbCrLf & "Check the Target Folder for accuracy."
MsgBox strMsg, vbInformation + vbOKOnly, "cmdSelected_Click()"
Me.msg.Caption = strMsg

cmdSelected_Click_Exit:
Exit Sub

allCopy:
k = 0
For j = 0 To ListCount
    strfile = lstBox.ItemData(j)
   
    strSource2 = strSource1 & strfile
    strTarget2 = strTarget & strfile
    
    FileCopy strSource2, strTarget2
  'give enough time to copy the file
  'before taking the next file
  k = k + 1
  t = Timer()
  Do While Timer() > (t + 10)
    'do nothing
  Loop
Next
Return

selectCopy:
k = 0
For j = 0 To ListCount
   If lstBox.Selected(j) Then
        strfile = lstBox.ItemData(j)
        strSource2 = strSource1 & strfile
        strTarget2 = strTarget & strfile
        
            FileCopy strSource2, strTarget2
               'give enough time to copy the file
               'before taking the next file
               k = k + 1
                t = Timer()
                Do While Timer() > (t + 10)
                    'do nothing
                Loop
   End If
Next
Return


cmdSelected_Click_Err:
MsgBox Err.Description, , "cmdSelected_Click()"
Me.msg.Caption = Err.Description
Resume cmdSelected_Click_Exit

End Sub


Private Sub List1_AfterUpdate()
On Error GoTo List1_AfterUpdate_Error
Me.cmdSelected.Enabled = True
List1_AfterUpdate_Exit:
Exit Sub

List1_AfterUpdate_Error:
MsgBox Err.Description, , "List1_AfterUpdate()"
Resume List1_AfterUpdate_Exit
End Sub

You may save the Form with the name FileCopy.

Note: FileCopy is a VBA Statement, not a built-in Function.

You can copy different sets of files from the list displayed in the list box to different target folders by first deselecting any previous selections, selecting the desired files, and updating the destination folder address in the text box.

Download the Demo Database.

You may download the sample database with the VBA Code from the Link given below:

Download FileCopy2007.zip

Download (2003) FileCopy.zip


Share:

Microsoft Access Form Move Size Action

Introduction.

We design Access Forms that fits into the existing Application Window Width (to display/edit records), or design popup Forms with specific size without borders or scroll bars (can be moved out of the Application Window area too) or Modal type form (popup type forms with its Modal property value set to True) that must be closed, after taking suggested action on it, before you can work with other forms.

This type of form opens one over the other (when more than one form is open) on the Application Window. You must enable Overlapping Windows by selecting Office Button - - > Access Options - - > Current Database - - > Document Window Options - - > Overlapping Windows to open the forms in this way; otherwise, they will be opened in the Tabbed style in the Application Window.

The Pop-Up Forms.

Popup Forms will open on the exact location of the Application Window, from where you have saved it during design time. If you need more details on this topic, visit this Article Link: Positioning pop-up Forms.

We can open a Microsoft Access Form and move it to a particular location of the Application Window is in the resized state, if necessary, with the MoveSize Action on the Docmd Object.

The MoveSize Action.

Here, we will learn the usage of the MoveSize Action of the DoCmd Object in VBA.

View the YouTube Demo Video given below for reference. Select the 720p HD Option from the Settings for better quality viewing.

Demo Video

When the Supplier Code is selected on the Supplier List Form, the related Product List is displayed,  above the Supplier Form, to the right of the main form. The width of the Product List Form is not changed, but the height of it changes, depending on the number of items on it.

We need two tables, two Queries, and the Supplier List Form from the Northwind sample database to build this trick. You need to design a Form for the Product List. A Demo Database is given at the end of this Article to download and try out, right away.

The list of Tables, Queries, and Forms required to build this database is given below.

    Tables:

  • Suppliers
  • Products
  • Queries:

  • Suppliers Extended
  • ProductListQ
  • SQL Code:

    SELECT Products.[Supplier IDs], Right([Product Name],Len([product name])-17) AS Product, Products.[List Price], Products.[Quantity Per Unit]
    FROM Products
    WHERE (((Products.[Supplier IDs].Value)=[forms]![Supplier List]![id]));
    

    Forms:

  • Supplier List
  • Product List

Copy and Paste the following VBA Code into the Supplier List Form's VBA Module and save the Form:

Private Sub Company_Click()
Dim frm As Form, ProductForm As String, items As Integer
Dim mainFormHeight As Integer
Dim intHeader As Integer, intFooter As Integer
Dim intH As Integer, frmchild As Form, oneInchTwips As Integer

On Error GoTo Company_Click_Err

ProductForm = "Product List"
oneInchTwips = 1440 'Form's internal value conversion factor

mainFormHeight = Me.WindowHeight

For Each frm In Forms
  If frm.Name = ProductForm Then
    DoCmd.Close acForm, ProductForm
    Exit For
  End If
Next
DoCmd.OpenForm ProductForm
Forms(ProductForm).Refresh
items = DCount("*", "ProductListQ")

Set frmchild = Forms(ProductForm)
'Calc the required height of the chid-form
'based on number of items for selected supplier
intHeader = frmchild.Section(acHeader).Height
intFooter = frmchild.Section(acFooter).Height
'0.272 inch - product item row height
intH = intHeader + items * 0.272 * oneInchTwips + intFooter
intH = intH + oneInchTwips '- one inch margin from bottom
'Move and resize the height of the child form
'4.275 inches to the right from left of the Application Window
'1.25 inches - arbitrary value taken for bottom margin
DoCmd.MoveSize 4.275 * oneInchTwips, mainFormHeight - intH, , (items * 0.272 + 1.25) * oneInchTwips

Company_Click_Exit:
Exit Sub

Company_Click_Err:
MsgBox Err & ": " & Err.Description, , "Company_Click()"
Resume Company_Click_Exit

End Sub

Private Sub Form_Current()
Me.Refresh
End Sub

Note: Don't forget to change the Overlapping Windows option in the Access Option settings mentioned in paragraph two from the top.

  1. Open Supplier List Form.
  2. Click on the Supplier ID Field (with the Company column heading) of any record to open the  Supplier products List to display, in the Resized Product List Form, and move it to its specified location.

Download the Demo Database.


Download Demo MoveSize Demo.zip

Share:

Form Background with Gradient Color

Introduction

The Form background pictures are not only used for giving the Form a different look, but also for other useful purposes.

Assume that the user is entering data from a pre-printed document, such as a telephone bill or an electricity bill.  In such situations, it can be very effective to scan an image of the source document and use it as the background picture of the data entry form. The Data Fields can be positioned in appropriate locations on the image, matching the physical Document so that it will be easier for the user to find information on the Document and key in exactly the same locations on the Form.

Microsoft Access Form Wizard offers several images that can be used as background pictures, but I couldn’t find the one I wanted — a simple gradient background. So, I decided to create one myself and use it instead.


Creating a Sample Image

The steps are given below to create the image for the Form Background picture.

  1. Opened a new Microsoft Word Document and went through the following steps to create a Gradient bitmap image:

  2. Selected Format - - >Background - - > Fill Effects.

  3. Under Colors, options selected One Color.

  4. Clicked on the Color 1 drop-down control and selected a light color.

  5. Used the Darker/Lighter slider control to adjust the color tone.

  6. Selected the Horizontal Radio Button under Shading Styles.

  7. Clicked on one of the Style Variants.

  8. Clicked OK to apply the selected shade as the Background of the Word Document.

  9. Maximized the Word Document Window.

  10. Select the Prt Scrn key (at the top row, right side). The full-screen image is now captured and copied to the Clipboard.

  11. Opened the MS Paint Program. You can find this in Start -> Programs -> Accessories.

  12. Displayed the Toolbox (View -> Toolbox or press Ctrl+T).

  13. Selected the Select Tool (the one at the top right with a rectangle picture).

  14. Drawn a rectangle from the left top corner of the gradient image area to the right bottom corner to select the image large enough for my Form's width and height. If you find the width is not enough to cover your form, then change the Page Orientation of the Word Document into Landscape mode before capturing it in MS Paint.

  15. Use Ctrl+C to copy the selected area into the Clipboard.

  16. Clicked outside the selected area to deselect the earlier selection.

  17. Select Clear Image from the Image Menu (Ctrl+Shift+N) to clear the Canvas. Inspected the right Scroll Bar to check whether it is positioned at the top or not. It was positioned slightly down, so I dragged it up to the top. Similarly, adjusted the Scroll bar at the bottom to the position at the left end.

  18. Pressed Ctrl+V to paste the copied image from the Clipboard.

  19. Clicked outside the pasted image to deselect it.

  20. Dragged the Sizing control at the bottom of the Canvas up and stopped at the edge of the pasted image to eliminate the white area of the canvas.

  21. Similarly, adjust the right side of the image.

  22. Select Save from the File Menu to save the image with a name in a convenient location.

If you’ve been following along so far, we’re now ready to move on to the next stage — implementing the gradient image as a background picture. However, there are a few limitations when using images like this as a form background, but with a little trick, we can easily overcome them.

If you’re thinking about the increase in database size, you’re absolutely right to consider it. And if you’re already thinking about saving the image in JPEG or GIF format, then you’re one step ahead of me! Saving the image type as GIF in MS Paint won’t produce good-quality results. If you have access to software like Adobe Photoshop, you can create high-quality GIF images with much better control.

We’ll use the BMP image format with a few smart modifications to preserve excellent image quality without increasing the database size.

But first, let’s see how to apply the gradient image as the form’s background picture.

Inserting the Image on the Form Background

Before opening your database, you can check the current file size in Windows Explorer. It’s a good idea to compact the database first to get an accurate baseline size. After adding the background picture to a Form, inspect the database size again to see how much it has changed.

  1. Open your Database and open a Form in Design View or create a new one.

  2. Display the Property Sheet of the Form (View -> Properties).

  3. Find the Picture Property and click on it.

  4. Click on the build button (...) at the right side of the Property Sheet and click on it to browse to the location of the image you have saved and select the image.

  5. The next four Properties are used for formatting and displaying the Background Picture.

  • Picture Type
  • Picture Size Mode
  • Picture Alignment
  • Picture Tiling

Linked or Embedded Image Methods

The Picture Type property has two options, Embedded and Linkedwith Embedded as the default. The Embedded option allows opening the default image editor directly from within MS Access by double-clicking the image and editing the picture if needed. However, to support this functionality, Access stores not only the image but also additional information required to invoke the image editor. As a result, each embedded image can significantly increase the size of your database. Note that background images added this way cannot be edited by double-clicking them, unlike OLE object images inserted on a Form.

A better option is the Linked setting, which keeps the image stored externally, leaving your database size unaffected. However, in either case, the image file must remain available in the same location relative to your database if it is moved or shared.

The Picture Size Mode property provides three options. The default option, Clip, displays the picture at its actual size, positioned according to the Picture Alignment setting—Top Left, Top Right, Bottom Right, Bottom Left, Center, or Form Center. The Center option places the image both vertically and horizontally centered on the Form, while Form Center aligns it vertically centered along the left edge.

The Stretch/Zoom/Tile Picture Methods

The Stretch Picture Size Mode option will stretch the image to fit the dimensions of the Form, resulting in distortion of the image if it is a picture of something.

The Zoom Picture Size Mode option will attempt to maintain the right proportions of the image when stretched to match the dimensions of the Form. But both the Stretch and Zoom options will show stretch marks when the Form is restored to its original size. This is much evident when a .jpeg or GIF image is used.

The One Pixel Width Image

We can modify our earlier .bmp file to a one-pixel-width image and Tile it across the Form, which will give a good quality gradient picture effect, and the image size will also be small.

  1. Open the earlier saved .bmp image in the MS Paint Program.

  2. Select Attributes... from Image Menu.

  3. Change the Width value to 1, and no change in the Height value.

  4. Check Units selected are Pixels.

  5. Save the image with a different name.

  6. Change the name of the background image to the new image in the Picture property of the Form.

    Caution: Do not attempt to use the Picture Size Mode property options Stretch or Zoom; MS-Access may hang up.

  7. Set the Picture Tiling Property Value to Yes and save the Form.

  8. Open the Form in Normal View and enjoy your creation.

Share:

Drill-Down Inquiry Screen-2

Continuation of Last Week's Post.

Designing the Employee-Wise Order Summary Form

We will start by creating the top-level summary form that displays employee-wise order totals. This form will serve as the entry point for drilling down into the details of each employee’s sales performance.

  1. Create a New Form

    • Open your database and create a new blank form in Design View.

    • Set its Record Source property to the query or table that summarizes orders by Employee — for example:
      qryEmployeeOrderSummary
      This query should include fields such as:

      • EmployeeID

      • EmployeeName

      • TotalOrders

      • TotalSales

  2. Add Controls

    • Add a Combo Box (cboEmployee) to allow selection of an Employee.

    • Add Text Boxes to display summary values:

      • txtTotalOrders

      • txtTotalSales

    • Add Labels with appropriate captions (e.g., “Employee”, “Total Orders”, “Total Sales”).

  3. Form Properties

    • Set the Default View property to Single Form.

    • Set Allow Additions, Allow Deletions, and Allow Edits to No (this is a summary form, not for data entry).

    • Set the Border Style to Dialog and Pop Up to No.

  4. Add a Refresh Button

    • Insert a small Command Button (cmdRefresh) with the caption “Refresh Summary”.

    • Add the following VBA code in its Click event to requery the form data:

      Private Sub cmdRefresh_Click() Me.Requery End Sub

This completes the Employee Summary layer — the top level of your drill-down screen.
Next, we’ll design the second-level subform to display Order-Wise Details for the selected employee and link it dynamically to the summary form.

03_Employee_Summary Form

  1. Designing the Employee Summary Form

    1. Select the Source Query

      • Open the Database Window (or Navigation Pane in newer versions).

      • Locate and select the query named 03_Employee_Summary.
        This query should contain summary data for each employee, such as:

        • Employee ID

        • Employee Name

        • Number of Orders

        • Total Sales Amount

        • Region or City (if applicable)

    2. Create the Form Using the Form Wizard

      • From the Insert menu, choose Form Wizard.

      • Select 03_Employee_Summary as the record source.

      • Add the following fields in this order (or as per your data):

        • EmployeeID

        • EmployeeName

        • OrdersCount

        • TotalSales

      • When prompted for the form layout, choose Tabular Form (Continuous Form).

      • Complete the wizard and give the form a suitable name, such as Employee_Summary.

    3. Clean Up the Design
      The Form Wizard may add unnecessary design elements, like background images, grid lines, and shadowed controls.

      • Open the form in Design View.

      • Remove any background image (set the Picture property to None).

      • Select all controls and set:

        • Special EffectFlat

        • Back ColorWhite or Transparent

        • Border StyleSolid

      • Adjust the Form Header to include a descriptive title such as “Employee Summary” in a bold label.

    4. Enhance Readability

      • Align the text boxes neatly in columns.

      • Set the Alternate Back Color of the Detail section (e.g., a light grey) for easier row reading.

      • Format the TotalSales field as Currency.

      • Set OrderCount as a Number, with no decimal places.

    5. Save and Test the Form

      • Save the form as Employee_Summary.

      • Switch to Form View to verify that multiple employee records appear in a continuous list, as shown in the sample.


    Next Step:

    In the following section, we will design the Order Details Subform that will display order-level data for the employee selected in this summary form.

  2. Select all the data fields together by clicking on the left border of the Detail section. Alternatively, click anywhere within the Detail section and drag the mouse over all the controls to select them simultaneously.

  3. Display the Property Sheet (View ->Properties).

  4. Change the following Property Values:

    • Enabled = No
    • Locked = Yes
    • Tab Stop = No
    • Back Color = 12632256
    • Special Effect = Raised
  5. Expand the Detail Section of the Form down to get enough room to draw a lengthy Command Button.

  6. Draw a Command Button as wide as the full length of all the Fields above, so that we can cover the fields by placing it over them.

  7. Display the Property Sheet of the Command Button.

  8. Change the following Property Values:

    • Name = cmd1
    • Transparent = Yes
    • Hyperlink SubAddress = #
  9. We must make the Command Button's height the same as the Fields above. Click on the Command Button to select it, hold the Shift Key, and click on any one of the Fields above to select it along with the Command Button. Alternatively, you can click and drag over the Command Button and any one of the fields above.

  10. Select Format -> Size and select Shortest, if the Command Button's height is more than the field, or select Tallest to make the Command Button as tall as the fields above.

  11. Drag the Transparent Command Button and place it over the Fields above.

  12. To make sure that the Transparent Command Button stays above all the data fields, select Format -> Bring to Front.

  13. Now, reduce the Detail Section height, but leave a little gap above and below the Data Fields.

  14. Draw a Text Box in the Form Footer Section below in the same position as the TORDERS field in the Detail Section and write the following expression in the Control Source Property:

    =Sum([TORDERS]) 
  15. Change the Caption of the child label to Total Orders.

  16. Create a Label at the Header of the Form and change the Caption value to EMPLOYEE-WISE ORDERS SUMMARY. Change the font size to 12.

  17. Display the Code Module of the Form (View -> Code), copy and paste the following VBA lines into the Module:

    Private Sub cmd1_Click()
    Me.Parent.Refresh
    Me.Parent.Tabctl0.Pages(1).SetFocus
    End Sub
  18. Save the Form with the Name: 03_Employee_Summary.

04_Order_ListQ Form

  1. Select the Query 04_Order_ListQ and create a Tabular Form (continuous Form) as we did at the top.

  2. Change the design to look like the sample Image given below:

  3. Select all the fields as we did earlier and change the following Property Values:

    • Enabled = No
    • Locked = Yes
    • Tab Stop = No
    • Back Color = 16777215
    • Special Effect = Flat
  4. Follow Steps 6 to 8 given above.

  5. Change the following Properties of the Command Button:

    • Name = cmdOrder
    • Transparent = Yes
    • Hyperlink SubAddress = #
  6. Follow Steps 10 to 13 as explained above. Reduce the height of the Detail Section without leaving the gap above and below the fields.

  7. Create a Command Button at the Footer Section of the Form.

  8. Display the Property Sheet of the Command Button and change the following Property Values:

    • Name = cmdMain
    • Caption = Goto Main
  9. Expand the Header Section of the Form and drag the Field Headings down to get enough room to create a Heading for the Form.

  10. Add a Text Box above the Field Headings and write the following expression in the Control Source Property of the Text Box:

    = "Order List of " & [EmpName]
  11. Display the Code Module of the Form (View -> Code), copy and paste the VBA Code given below into the Module, and save the Form with the name 04_Order_ListQ.

Private Sub cmdMain_Click()
    Me.Parent.Tabctl0.Pages(0).SetFocus
End Sub

Private Sub cmdOrder_Click()
   Me.Parent.Refresh
   Me.Parent.Tabctl0.Pages(2).SetFocus
End Sub

05_Order_DetailQ Form

  1. Select the Query 05_Order_DetailQ and Create a Tabular Form.

    Here, we don't need the Transparent Command Button; change the Form design to look like the sample image below.

  2. Create a Text Box in the Form Footer below the Quantity field and write the following expression in the Control Source Property:

    =Sum([Quantity])
  3. Create another Text Box in the Form Footer below the ExtendedPrice Column and write the following expression in the Control Source Property:

    =Sum([ExtendedPrice])
  4. Create a Command Button in the Form Footer below the TextBoxes.

  5. Change the following Property Values of the Command Button.

    • Name = cmdBack
    • Caption = << Back

  6. Display the Code Module of the Form (View -> Code), copy and paste the following lines into the Module:

    Private Sub cmdBack_Click()
        Me.Parent.TabCtl0.Pages(1).SetFocus
    End Sub
  7. Save the Form with the Name 05_Order_DetailsQ.

Now, we are ready to design the Main Form Inquiry. Main to assemble all three Sub-Forms on a Tab Control and make the Tab Control Pages invisible.

Inquiry_Main Form

  1. Select the Parameter Table Date_Param, select Form from the Insert Menu, and select Design View from the displayed list.

  2. Select the Tab Control Tool from the Toolbox and draw a Tab Control on the Detail Section of the Form.

  3. Check the sample image given below. The Tab Control will have only two pages, but we need one more page.

  4. Click on the Tab Control to select it and select Tab Control Page from the Insert Menu.

    You may select each Page of the Tab Control, display its Property Sheet, and change the Caption Property value of Page1, Page2, and Page3 as Summary, Orders, and Order Detail, respectively, if needed. It is used for reference purposes only.

    The next step is to drag and drop the Sub-Forms (03_Employees_Summary, 04_Order_ListQ, and 05_Order_DetailQ) one by one, on the Tab Control Pages.

  5. Position the Database Window with the Forms Tab active and the Inquiry_Main Form with the Tab Control side by side.

  6. Drag and drop the 03_Employee_Summary Form on the Tab Control Page 1.

  7. You may delete the child label attached to the subform. Resize both the subform and the tab control to ensure that the contents are displayed properly on the screen. Save the form with the name Inquiry_Main, and open it in Normal View to verify how the information appears in the subform. Check whether any adjustment to the size of the form or tab control, either an increase or a decrease, is required or not. Leave some space between the tab control and the top of the Detail section of the form to insert a few text boxes for the StartDate and EndDate fields, along with two additional text boxes for control purposes. Also, make sure to leave some space for a heading above these controls.

  8. Once you are satisfied with the subform’s dimensions and overall design, click on the subform and open the Property Sheet. Take note of the following property values on a piece of paper — you will need them later to resize and position the other two forms that will be inserted into Page 2 and Page 3 of the Tab Control.

    • Top
    • Left
    • Width
    • Height
  9. Right-click on the Sub-Form and select Copy from the displayed Shortcut Menu.

  10. Select Tab Control Page2, press and hold the Shift Key, right-click on the Tab Control Page2, and select Paste from the displayed menu.

    The pasted control will be an empty form displaying the Source Object Name of the copied Form with a white background.

  11. Display the Property Sheet of the Form and change the Source Object Property value to 04_Order_ListQ. After this change, the Form will appear on the Tab Control Page 2.

  12. Change the dimension property values to match the ones you noted earlier. Since you copied the form (rather than dragging and dropping it from the Database Window), you only need to update the Top and Left property values — the Width and Height values should already be the same. If they differ, adjust them accordingly.

  13. Follow Steps 9 to 12 above to bring in the 05_Order_DetailQ Form to the third Page of the Tab Control.

  14. Display the Field List (View -> Field List) if it is not visible.

  15. Drag and drop StartDate and EndDate fields above the Tab Control, create labels above and left, and change their Caption values as shown in the design above.

  16. Create a Command Button to the right of the EndDate field and change its property values as given below:

    • Name = cmdRefresh
    • Caption = <<Refresh Screen

    The Date fields we created, along with two additional text boxes that we will add, will be referenced in the queries we designed earlier to filter the data displayed on the forms. Although the refresh action is not strictly required—since the data is refreshed automatically before the results are displayed—it serves as an additional feature that allows the user to manually refresh and update any recent changes.

  17. Create a Text Box to the right of the Command Button and display its property sheet, and change the following Property Values:

    • Name = EID
    • Control Source = =[03_Employee_Summary].Form!EmployeeID
    • Visible = No
  18. Create another Text Box below the earlier one and change the property values as given below.

    • Name = OID
    • Control Source = =[04_Order_ListQ].Form!OrderID
    • Visible = No
  19. Create a heading on top of the Form with the Caption Value SALES PERFORMANCE INQUIRY.

  20. Create a Command Button below the Tab Control and change the following property values:

    • Name = cmdQuit
    • Caption = Quit

    Now, we make the Tab Control disappear, and the Tab Control's appearance will change. It will not look like a Tab Control after the change.

  21. Click on the Tab Control, display the Property sheet, and change the following property values:

    Caution: After changing the property values, make sure to click the Save button on the toolbar or choose Save from the File menu to preserve your changes immediately. In Microsoft Office 2000, attempting any other action before saving may cause the form to lock up.

    • Back Style = Transparent
    • Multirow = No
    • Style = None
  22. Display the Code Module of the Form, copy, and paste the following few lines of code into the Module:
    Private Sub cmdQuit_Click()
      DoCmd.Close acForm, Me.Name
    End Sub
    
    Private Sub cmdRefresh_Click()
       Me.Refresh
    End Sub
    
    Private Sub EndDate_LostFocus()
    Me.Refresh
    End Sub
    
    Private Sub Form_Load()
    Me.TabCtl0.Pages(0).SetFocus
    End Sub
  23. We will finish the design by setting the Property Values of the Inquiry_Main Form. Display the Property Sheet of the Form and change the following Property Values:
    • 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 Re-size = Yes
    • Auto Center = Yes
    • Pop up = Yes
    • Modal = No
    • Border Style = Dialog
    • Control Box = Yes
    • Min Max Buttons = None
    • Close Button = Yes
    • Allow Design Changes = Design View Only
  24. Save the Form, open it in Normal View, and try out your creation.

    Note: If you encounter any issues while running your design, refer to the downloaded sample database. Compare your design with it to identify and correct any mistakes.

Share:

Drill-Down Inquiry Screen

Introduction

Following is an image of a three-layer Inquiry Screen, designed for the Management, to keep track of the Northwind Traders' staff-level Sales Performance:

The top section of the Form displays a salesperson-level summary of orders along with the percentage of total orders. The Form footer shows the combined total of all orders. When you click on a specific employee's record, the individual order-level summary for that employee will appear on the main screen, overlaying the previous summary view. Refer to the image below for illustration.

Several items can be ordered under a particular Order, and details of all items can be displayed by clicking on one of the Order records. Check the image given below.

The Form displays order-level details along with summary information in the footer, showing the total quantity of all orders and the total net value of all items after discounts. The command buttons at the footer of each sub-form allow you to switch back to the upper layer of the Form.

The date parameter values at the top can be adjusted to display information for a different period.

I want to assure you that there is no complex VBA code driving this design—only one or two lines are used here and there to refresh controls or switch between form layers. Beyond that, the entire screen operates using Queries and Forms.

Designing the Forms

We need several tables from the Northwind.mdb sample database to create six simple queries, three subforms, and a main form to organize them and present the information effectively to the user.

Note: If you would like to see the Inquiry Screen in action before designing it, you can download the demo at the bottom of this post. If you find it difficult to understand how it works or how to assemble all the components, you can return here and follow the step-by-step design instructions. This will help you see how simple or complex it is and understand how each element interacts with the others.

In this tutorial, we will also revisit the use of transparent command buttons, which were covered in an earlier article with the same title.

Due to the complexity of the design, this topic will be split across multiple posts. Although I could show you how to build it in just a few minutes, explaining the process with images and property settings requires more detail.

Downloading and exploring the demo database first will help you better understand the functionality and make the step-by-step design task more engaging.

The Design Task

So, let us start with the first part.

  1. Download the following Tables from C:\Program Files\Microsoft Office\Office11\Samples\Northwind.mdb (MSOffice2003 address, you can replace Office in place of Office11 if your Version of Access is 2000):
    • Employees
    • Orders
    • Order_Details
    • Products

    A Parameter Table.

  2. Create a Parameter Table with the following name and Structure:

    Parameter Table: Date_Param
    Srl. Field Name Data Type Size
    1. StartDate Date/Time  
    2. EndDate Date/Time  
  3. Open the Table and create a single record with the following StartDate and EndDate values, and save the record:

    Parameter Table: Date_Param
    StartDate EndDate
    01-01-1996 31-12-1996
  4. Open new Queries and copy the following SQL Strings into the queries' SQL Editing Module surface, and save them with the exact Name given for each one of them. Create the Queries in the same order as shown below, as they have dependencies on Queries created first.

  5. Query Name: 00_Orders_MainQ

    SELECT Orders.*
    FROM Orders, Date_Param
    WHERE (((Orders.OrderDate) Between [StartDate] And [EndDate]));
    
  6. Query Name: 01_OrderCount1

    SELECT Employees.EmployeeID,
      [FirstName] & " " & [LastName] AS EmpName,
       Count([00_Orders_MainQ].OrderID) AS TORDERS
    FROM Employees INNER JOIN 00_Orders_MainQ ON Employees.EmployeeID = [00_Orders_MainQ].EmployeeID
    GROUP BY Employees.EmployeeID, [FirstName] & " " & [LastName];
    
  7. Query Name: 02_OrderCount2

    SELECT Count([00_Orders_MainQ].OrderID) AS TOTALORDERS
    FROM 00_Orders_MainQ;
    
  8. Query Name: 03_Employee_Summary

    SELECT [01_OrderCount1].*,
          [TORDERS]/[TOTALORDERS] AS PCNT
    FROM 01_OrderCount1, 02_OrderCount2;
    
  9. Query Name: 04_Order_ListQ

    SELECT [00_Orders_MainQ].OrderID,
            UCase([FirstName] & " " & [Lastname]) AS EmpName,
           [00_Orders_MainQ].OrderDate,
            [00_Orders_MainQ].RequiredDate
    FROM Employees INNER JOIN 00_Orders_MainQ ON Employees.EmployeeID = [00_Orders_MainQ].EmployeeID
    WHERE ((([00_Orders_MainQ].EmployeeID)=[Forms]![Inquiry_Main]![EID]));
    
  10. Query Name: 05_Order_DetailQ

SELECT [FirstName] & " " & [LastName] AS EmpName,
        [Order Details].OrderID,
        [Order Details].ProductID,
        [Order Details].Quantity,
        [Order Details].UnitPrice,
        [Order Details].Discount,
        (1-[Discount])*[UnitPrice]*[Quantity] AS ExtendedPrice
FROM (Employees INNER JOIN 00_Orders_MainQ ON Employees.EmployeeID = [00_Orders_MainQ].EmployeeID) INNER JOIN [Order Details] ON [00_Orders_MainQ].OrderID = [Order Details].OrderID
WHERE ((([Order Details].OrderID)=[Forms]![Inquiry_Main]![OID]));

Continued Next Week.

Download


Download Demo InquiryDemo00.zip


  1. Multiple Parameters for Query
  2. Form Menu Bars and Toolbars
  3. Seriality Control - Missing Numbers
  4. Wave Shaped Reminder Ticker
  5. No Data and Report Error
Share:

Custom Calculator and Eval Function

Introduction.

When we think of a calculator, the image that usually comes to mind is the traditional type with buttons labeled 0–9 and the standard arithmetic operators. Windows already includes such a calculator under Accessories, which can even be switched to Scientific mode — so there’s no need to recreate that in MS Access.

Instead, we’re going to design a different kind of calculator — one that can evaluate defined expressions consisting of data field names, constants, arithmetic operators, and parentheses (to control the order of operations). This calculator will allow you to input an expression, have Access evaluate it, and display the result instantly.

There’s no need for a complex interface. All we require is:

  • A TextBox to enter the expression,

  • A Command Button to trigger the evaluation, and

  • A few lines of VBA code to process the calculation.

The result can be displayed either in a MsgBox or in another TextBox on the form.

Before we begin building the calculator, let’s look at one of Access’s most powerful yet underused built-in functions — the EVAL() function. This function will serve as the core engine of our custom calculator. With EVAL(), you don’t need to worry about following mathematical rules manually — such as evaluating parentheses first, then exponentiation, followed by multiplication and division (from left to right), and finally addition and subtraction. Simply pass the expression as a string to the EVAL() function, and it will return the correctly computed result.

EVAL() Function Usage

Try a few examples quickly to get a feel of it? Open the VBA Module Window (Alt+F11) and open the Debug Window (Ctrl+G). Type the following expressions in the Debug Window and press the Enter Key:

? EVAL("2+3*4/2")

Result: 8

? EVAL("(2+3)*4/2")

Result: 10

? EVAL("log(SQR(625))/log(10)")

Result: 1.39794000867204

? Eval("10^" & "Eval('log(Sqr(625))/log(10)')")

Result: 25

? EVAL("Datediff('yyyy',Forms!Employees!BirthDate,date())")

Result: 45 (the Employees Form must be open)

EVAL() the Expression Parser

From the above examples, we can see that you can write expressions in a TextBox using built-in functions, data field references, and numeric constants. The Eval() function then parses the expression and returns the result. This gives the user the flexibility to define and evaluate custom expressions dynamically, incorporating live data from form fields into their calculations.

Tip: The Eval() function can do much more than just evaluate formulas. It can also run other functions, trigger the Click event of a command button, or execute a macro programmatically. For additional details and examples of how Eval() can be used, open the Microsoft Access Help window in the VBA editor and search for “Eval Function.”

The sample Demo Project.

I have created a sample database (available for download at the bottom of this post) designed for an auto dealership that offers credit facilities to customers at nominal interest rates of 6%, 7%, or 8%, repayable in 24, 36, or 60 installments, respectively. The salesperson is responsible for determining the most suitable repayment plan for each customer, including the percentage of down payment, installment schedule, and applicable interest rate.

To encourage sales, the salesperson is also authorized to offer customers a discount of up to 20% on the Maximum Retail Price (MRP), based on negotiation and customer eligibility.

An image of the Form he uses to run these calculations is given below:

This is a stand-alone form (which can optionally be linked to a table) containing unbound text boxes. Each text box is labeled with its corresponding name displayed to the left. When writing expressions, it is essential to properly qualify the control names, for example:
Forms!CustomCalculator!Balance

Note that shorthand references such as Me!Balance are not accepted in this context. This can make it somewhat cumbersome to build expressions, especially when multiple field names are involved in a formula.

The VBA Code

We have created a small VBA routine that recognizes text box names enclosed in square brackets [ ], retrieves their corresponding values, and substitutes them into the expression before passing it to the Eval() function.

For easier expression entry, a combo box containing arithmetic operators and text box names (in square brackets) is provided on the form. The colored display control below shows, for informational purposes, the expression after the text box references have been replaced with their actual values. just before it is submitted to the Eval() function.

When the Calculate Command Button is clicked, the result of the calculation is displayed in the Text Box with a dark background and the label Result. The VBA Code is given below:

Private Sub cmdCalc_Click()
'-----------------------------------------------------------
'Author : a.p.r. pillai
'Date    : November, 2008
'URL     : www.msaccesstips.com
'All Rights Reserved by www.msaccesstips.com
'-----------------------------------------------------------
Dim str As String, loc1 As Integer, chk As Integer
Dim strout As String, loc2 As Integer, loc3 As Integer
Dim strin As String
Const sqrleft As String = "["
Const sqrright As String = "] "

On Error GoTo cmdCalc_Click_Err

'change the reference if different
str = Me![Expression]

loc1 = InStr(1, str, sqrleft)
If loc1 > 0 Then
   strin = Left(str, loc1 - 1)
   strout = Left(str, loc1 - 1)
   loc2 = InStr(loc1, str, sqrright)
End If
Do While loc2 > 0
   strin = strin & Mid(str, loc1, (loc2 - loc1) + 1)
   strout = strout & Me(Mid(str, loc1, (loc2 - loc1) + 1))
   loc1 = InStr(loc2 + 1, str, sqrleft)
   If loc1 > 0 Then
     loc2 = InStr(loc1, str, sqrright)
      If loc2 = 0 Then
         MsgBox "Errors in Expression, correct and retry. "
         Exit Sub
      Else
         strout = strout & Mid(str, Len(strin) + 1, loc1 - (Len(strin) + 1))
         strin = strin & Mid(str, Len(strin) + 1, loc1 - (Len(strin) + 1))
      End If
   Else
     loc3 = loc2
     loc2 = 0
   End If
Loop

If Len(str) > loc3 Then
   strout = strout & Mid(str, loc3 + 1)
End If

'this line can be removed if not required
Me![parsed] = strout

'change the reference, if different
Me![result] = Eval(strout)

cmdCalc_Click_Exit:
Exit Sub

cmdCalc_Click_Err:
MsgBox Err.Description, , "cmdCalc_Click()"
Resume cmdCalc_Click_Exit
End Sub

Private Sub cmdReset_Click()
Me![Expression] = Null
Me![parsed] = Null
End Sub

Note: There is no validation check included in the Code to detect misspelled names or unbalanced parentheses, etc. These shortcomings will automatically generate an error when the EVAL() function executes. The user will be able to review the expression, make corrections, and re-try.

Download

You can implement this program on any Form with a small change in str = Me![Expression] and Me![result] = Eval(strout) lines in the Code, if different names are used. Customize the Combo Box contents based on your input Field Names.


Share:

Data Editing And Security Issues

Introduction.

Data entry and editing are among the most crucial activities for keeping a database accurate and up to date. These steps ensure that the information remains reliable and ready for generating meaningful reports and analysis. To make data entry easier and more efficient for users, it is good practice to include combo boxes, check boxes, and calculated fields—for example, automatically determining a Payment Due Date as 30 days after the Material Delivery Date.

Another key consideration is data security. Here, the focus is not on preventing unauthorized external access—MS Access already provides robust built-in security features for that—but rather on protecting the data from accidental modifications or deletions by authorized users during routine operations.

For example, suppose our Employee database includes a Memo field that stores detailed information about each employee’s educational background and prior work experience. Normally, when the cursor (insertion point) moves into a field, the entire content of that field becomes highlighted and selected. At this stage, if the user’s attention is momentarily diverted and a key is pressed accidentally, the entire content of the field may be deleted. If the user does not immediately notice this or forgets to restore the data using Ctrl + Z (Edit → Undo Typing), the information could be lost permanently.

Protecting from unintended Changes.

We will focus on this specific behavior of the cursor and explore how to provide a level of protection against such inadvertent data loss. The way the cursor behaves when entering a field is determined by the settings found under the Keyboard tab of the Options dialog box (available from the Tools menu). Under the Behavior Entering Field section, you will find three different options, as shown in the image below:

The first option, Select Entire Field, is the default setting. However, choosing one of the other two options is generally more advisable to prevent the kind of data loss we are focusing on. Of the remaining two, my preferred choice is Go to End of Field. The reason is simple—when this option is selected, even if you accidentally press the Delete key or any other key, the insertion point is positioned at the end of the field content, and the existing information remains safe.

Since this is a global setting in Microsoft Access, any manual changes you make here will affect all forms in every database opened on your machine. Conversely, a database you design on your system will not carry these settings when opened on another computer in a multi-user environment. Moreover, you may not want this behavior applied to every form in your database.

The best approach, therefore, is to enable this feature programmatically through a VBA routine and restore the default settings when leaving that particular form. In a shared network environment, users may have different default settings for the “Behavior Entering Field” option on their own machines, so it’s important not to change these preferences permanently.

Following is the numeric value of each Behavior Entering Field Option setting:

Behavior | Description | Option Values.
  1. Select Entire Field - 0
  2. Go to Start of Field - 1
  3. Go to End of Field - 2

When opening a form that requires this modified cursor behavior, we will follow specific steps to enable it during the form’s initialization. Then, when the form is closed, we will restore the default settings to ensure that the global behavior of Access remains unchanged.

  1. Save the current default setting of Behavior Entering Field before it is changed.

  2. Change the setting to Go to the end of Field behavior for the current session of the Form.

  3. Reset it back to the saved value in Step 1 above, before closing the Form.

We can achieve this with the following Event Procedures in the Form Module:

Option Compare Database
Dim DefaultBehavior As Integer

Private Sub Form_Load()
    DefaultBehavior = Application.GetOption("Behavior Entering Field")
    Application.SetOption "Behavior Entering Field", 2
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Application.SetOption "Behavior Entering Field", DefaultBehavior
End Sub

Copy and paste the above Code into the Form's Code Module and save the Form. The Dim DefaultBehavior As Integer statement must be placed in the Global area of the Module as shown above.

Try out the New Setting

Open the Form in normal View and try moving the cursor from one field to the other by tapping the Tab Key or the Enter Key. The insertion point will position at the end of the field contents.

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 Class Module External Links Queries Array msaccess reports Accesstips WithEvents msaccess tips Downloads Objects Menus and Toolbars Collection Object MsaccessLinks Process Controls Art Work Property msaccess How Tos Combo Boxes Dictionary Object ListView Control Query VBA msaccessQuery Calculation 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 RaiseEvent Recordset Top Values Variables Wrapper Classes msaccess email progressmeter Access2007 Copy Excel Export Expression Fields Join Methods Microsoft Numbering System Records Security Split SubForm Table Tables Time Difference Utility WScript Workgroup 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 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