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

Showing posts with label Reports. Show all posts
Showing posts with label Reports. Show all posts

Auto-Numbers in Query Column Version-2

Auto-Numbers in Query Column Version 2.

In January 2010, I published an article, “Function: QrySeq() – Auto-Numbering in Query Column,” on this website. Over the years, it has been well received by readers. While reviewing the article again, I thought the Function could be rewritten with less code and improved performance than a variant Array.

When the QrySeq() function is called for a record in the query, the program searches the Array of Unique Keys for the key value passed from the record as a Parameter. Once it finds a matching key, it retrieves the corresponding sequence number from the Array element and returns it to the calling record.

If the query contains a large number of records, this process can take considerable time because the program begins the search from the start of the Array each time it looks for a key value.

The New Version is Named: QryAutoNum()

Using a Collection Object instead of an Array.

You can find a detailed discussion of the Collection Object on the MS Access and Collection Object Basics Page.

Here, we will have a brief introduction to the Collection Object, including what it is and how it is used in VBA. The Collection Object is a versatile Object that can generally hold any type of value, including numeric or string values, Class Module Objects, or a collection of other Objects. The Collection Object is instantiated in VBA programs as follows:

'declare a Collection Object. Dim ABC as Collection 'create an instance of Collection Object in Memory Set ABC = New Collection 'We can Add built-in data types: Numeric, Strings etc ‘or Objects like Class Module Objects, ‘or other Collection Object as Items to the Collection Object.

'Use the Add method to add a Collection Item to the Object. ABC.Add 25 ABC.Add "ms-accesstips" 'When Collection Object Items added this way, ‘it can be retrieved only in the added order. For j = 1 to ABC.Count 'gets the count of Items Debug.Print ABC(J)’ retrieve in Item index Order. Next 'When ADDed an Item with a String Key 'we can use the Key value to retrieve the Items Randomly. 'But, usage of Key is optional. ABC.Add 25, "1" ABC.Add "ms-Accesstips", "2" x = "2" Debug.Print ABC(x) Result: ms-accesstips

We will use the Collection Object to store the Query Auto-numbers, with the corresponding Unique Key Values assigned as the Collection Object Keys. With this approach, we can retrieve the Auto-numbers directly, eliminating the need to work with Arrays and their more complicated data storage and retrieval steps.

The QryAutoNum() Function Code.

Option Compare Database
Option Explicit

Dim C As Collection

Public Function QryAutoNum(ByVal KeyValue As Variant, ByVal KeyfldName As String, ByVal QryName As String) As Long
'-------------------------------------------------------------------
'Purpose: Create Sequence Numbers in Query Column Ver.-2
'Author : a.p.r. pillai
'Date : Dec. 2019
'All Rights Reserved by www.msaccesstips.com
'-------------------------------------------------------------------
'Parameter values
'-------------------------------------------------------------------
'1 : Column Value - must be UNIQUE Numeric/String Type Values from Query Column
'2 : Column Name  - the Field Name in Quotes from where Unique Values taken
'3 : Query Name   - Name of the Query this Function is Called from
'-------------------------------------------------------------------
'Limitations - Function must be called with Unique Field Values
'            - as First Parameter
'            - Need to Save the Query, if changes made, before opening
'            - in normal View.
'-------------------------------------------------------------------
Static K As Long, Y As Long, fld As String
On Error GoTo QryAutoNum_Err

Y = DCount("*", QryName) ' get count of records for control purpose

'If KeyfldName Param is different from saved name in variable: fld
'or Value in K more than count of records in Variable: Y
'then it assumes that the QryAutoNum() is called from a different Query
'or a repeat run of the same Query. In either case the Control Variable
'and Collection Object needs re-initializing.
If KeyfldName <> fld Or K > Y Then
'initialize Control Variable
'and Collection Object
    K = 0
    Set C = Nothing
    'save incoming KeyfldName
    fld = KeyfldName
End If

'if KeyValue parameter is Numeric Type then convert
'it to string type, Collection Object needs it's Key as String Type.
If IsNumeric(KeyValue) Then
    KeyValue = CStr(KeyValue)
End If

K = K + 1
If K = 1 Then
Dim j As Long, db As Database, rst As Recordset
Dim varKey As Variant

Set C = New Collection

Set db = CurrentDb
Set rst = db.OpenRecordset(QryName, dbOpenDynaset)

'Add recordlevel AutoNumber with Unique KeyValue
'to Collection Object, in AutoNumber, KeyValue Pair
While Not rst.BOF And Not rst.EOF
    j = j + 1 ' increment Auto Number
    
    'Get key value from record
    varKey = rst.Fields(KeyfldName).Value
    
    'if numeric key convert it to string
    If IsNumeric(varKey) Then
      varKey = CStr(varKey)
    End If
    
    'Add AutoNumber, KeyValue pair to Collection Object
    C.Add j, varKey
    
    rst.MoveNext
Wend
    rst.Close
    Set rst = Nothing
    Set db = Nothing

'Retrieve AutoNumber from Collection Object
'using the KeyValue.  Works like Primary Key of Table
    QryAutoNum = C(KeyValue)
Else
    QryAutoNum = C(KeyValue)
End If

If K = Y Then 'All record level AutoNumbers are Returned
    K = K + 1 ' increment control variable
End If

QryAutoNum_Exit:
Exit Function

QryAutoNum_Err:
MsgBox Err & " : " & Err.Description, , "QryAutoNum"
Resume QryAutoNum_Exit

End Function

Sample Source Query SQL.

With the Northwind Products Table.

SELECT Products.ID, 
Products.Category, 
Mid([Product Name],18) AS PName, 
Sum(Products.[Standard Cost]) AS StandardCost, 
QryAutoNum([ID],"ID",
"Product_AutoNumQ") AS QrySeq
FROM Products
GROUP BY Products.ID, Products.Category, Mid([Product Name],18)
ORDER BY Products.Category, Mid([Product Name],18);

Review of VBA Code Line-By-Line.

In the Global Area of the Module, we have declared a Collection Object, the Object Variable C.

The QryAutoNum() Function declaration is the same as our earlier QrySeq() with three parameters.

  1. Unique Key-Value, either Numeric or String, as the first Parameter.
  2. The Key-Value Field’s Name in String Format.
  3. The Query Name in String Format.

The returned AutoNumber is in a Long Integer format.

Three Static Variables,  K and Y, are declared as Long Integers, and fld was declared as a String Variable.

All three Variables control the Code execution Paths, and determine when to initialize Collection objects and control variables.

The DCount() Function takes a count of records in the Query in Variable Y.

If the KeyFldName differs from the previously saved field name in the fld variable, the function assumes that the call originates from a new Query Record. If the field name is the same, but the value of the variable K is greater than Y, the function assumes that the earlier Query is calling QryAutoNum() again as part of a repeated run. In either case, the control variable K is reset to zero, and the Collection Object containing the existing Items is cleared from memory. The new Key field name from the KeyFldName variable is then saved in the fld variable for subsequent validation.

Next, if the KeyValue parameter is numeric, it is converted to String format using the statement KeyValue = CStr(KeyValue). The Item Key of the Collection Object must be in String format.

The variable K is then incremented by one. When K = 1, the function assumes that this is the first call to the function, originating from the first record of the Query. In this case, the main processing of the function begins.

The local temporary Variables are declared here, and their values are not preserved between calls of this function from different records of the query.

The Collection Object declared in the Standard Module’s  Global area is instantiated in memory with the statement Set C = New Collection.

The Query recordset is opened to read records. The local variable J will create Auto-numbers and add them to the Collection Object for each record.  The Unique Key-Value, read from the recordset into variable varKey, is added to the Collection Object as its Key Value.

If the varKey variable value is Numeric Type, then it is converted to String format.

The Auto-Number Value in Variable J and the string value in variable varKey are added to the Collection Object in the following statement, as its Item value, Key pairs:

C.Add J, varKey

This process is repeated for all the records in the Query.  The Auto-Numbers are generated for all records and added to the Collection Object.  All this work is done during the first call of the function from the first record of the query.

Did you notice that we are reading the Unique Key value of each record directly from the record set within the While . . . Wend Loop to add them to the Collection Object?  After adding the Auto-Numbers for all records, the record set and Database Objects are closed.

Remember, we are still on the first call of the function from the first record of the query, and the first parameter variable KeyValue still holds the first record Key Value.

The next statement QryAutoNum = C(KeyValue) retrieves the Collection Object’s first Item Auto-Number Value 1, using the Unique Key Value in parameter variable KeyValue, and returns it to the function calling record. This will happen only once because the variable K will be greater than one on subsequent calls of this function.

Function calls from the second record onward take the Else path of the If K = 1 Then statement. They retrieve the AutoNumber from the Collection Object using the KeyValue passed as a parameter and return it to the corresponding record in the Query.

This process is very fast because the required Item can be retrieved directly using the Collection Object Key, rather than searching through the Array from the beginning each time to locate the required Key.

When the Auto-number values for all records have been returned, the value of the control variable K equals Y. The record count of the Query was obtained and stored in the variable Y at the beginning of the program. At this point, K is incremented by 1, making its value greater than Y. Because K and Y are Static Variables, their values are retained in memory after the last record call has completed. If the same Query is run a second time, these variable values can be tested to determine whether the variables need to be reset and the existing Collection Object cleared from memory, allowing the entire process to start afresh.

If the QryAutoNum() function is called from the same Query again, the Static Variables and Collection Object are cleared from memory, preparing for a fresh run of the Function for the same Query or for a different Query.

The sample Report image, generated using the above Query, is shown below for reference

You can use the Query as the source for a Report or Form. 

A sample demo database is attached. 


  1. Auto-Numbering in Query Column
  2. Product Group Sequence with Auto-Numbers.
  3. Preparing Rank List.
  4. Auto-Number with Date and Sequence Number.
  5. Auto-Number with Date and Sequence Number-2.
Share:

Sub-Report Summary Value in Main Report Calculations

Sub-Report Summary Value in Main Report Calculations.

How to bring the sub-report summary value to the main report and use it in calculations?

But first, we need a ready-made report for our project.

Download links for the sample database are provided below. Choose the version you need. The demo database is created in Microsoft Access 2007 format and is fully compatible with later versions.

First, take a look at the following images:

  1. Print Preview of the finished report.
  2. Original Report Preview. 
  3. Changes were made to the Report in Design View to get the result shown in the first image above.


    Download Links.

  4. Sample Database Download Links for Microsoft Access 2007 and 2003 Versions are given below.


  5. Download the suitable sample database.

    In short, our task is to add the sub-report category total to the Footer Section of the Sales by Category sub-report. Get the summary value of each category for the main report header.  Calculate the percentage of each category of product sales value on Grand-Total Sales Value (or Percentage = Category Sales Value / Total Sales value of all Categories * 100).  We can do this by adding a few text boxes to both reports and writing a few expressions in them.

    The Sub-Report Changes.

    Let us start with the Sales by Category Sub-report first.

  1. Open the downloaded database.

  2. Open Sales by Category Sub-report in Design View.

  3. Right-click on the Report Footer bar and select Properties to display the Property Sheet.

  4. Select the Height Property and change the property value to 0.33” or 0.838 cm.

  5. Select the Text Tool from the Toolbar above and draw a text box on the Report Footer area below the Product Sales column.

  6. Write the expression =Sum([ProductSales]) in the Control Source property of the text box. Change the Name property value to SubTotal.

  7. Modify the Caption property value of the child label to read as Sub-Total.

  8. Save and close the Sales by Category Subreport.

    The Main Report Changes.

  9. Open the Sales by Category main report in Design View.

  10. Create a TextBox on the Header Section of the Report, to the right of the report heading.

  11. While the text box is in selected state, display the property sheet (F4).

  12. Write the expression =Sum([ProductSales]) in the Control Source property. Change the Name property value to TotalSales. Change the Caption property of the child label to Total Sales.

    Note: The expression calculates the total product sales value across all categories on the main report. When used in the sub-report, however, the same expression calculates the sales value of the current product category (for example: Beverages). This gives us two values: the SubTotal for a specific category in the sub-report, and the TotalSales for all categories in the main report.

    With these values, we can calculate the percentage contribution of a particular category using the formula:

    Percentage=SubTotalTotalSales×100\text{Percentage} = \frac{\text{SubTotal}}{\text{TotalSales}} \times 100

    However, since SubTotal is calculated in the sub-report, it cannot be referenced in the parent (main) report. To use it in the main report—especially when there are multiple sub-reports—we must explicitly specify the location of the control or expression within the sub-report.

  13. Create a text box below the Category Header bar to the right of the Category Name heading, and relocate the TextBox under the Total Sales calculation control on the Report Header.

  14. Right-click on the Control Source Property of the text box and select the Build option from the displayed list to open the expression builder control.

    • Click on the = symbol to insert it into the expression editor window.

    • Double-click on the + symbol on the left side of the Reports option to expand and show other options.

    • Double-click on Loaded Reports.

    • Double-click on the Sales by Category main report to display the Sub-Report's name.

    • Click on Sales by Category Subreport to display its control names in the next column.

    • Find the Subtotal control in the list and double-click on it.

      The reference to the SubTotal control in the subreport can be written as:

      [Sales by Category Subreport].[Report]![SubTotal]

      This reference can be inserted directly using the Expression Builder. Alternatively, if you already understand how to write the reference correctly, you can type it directly into the Control Source property without going through the Expression Builder.

      With practice and by studying Microsoft Access’s addressing conventions, you will quickly become comfortable writing these references manually for use in Reports or Forms.

    • Click Ok to return to the TextBox Control Source property, with the Subtotal Reference, and write the rest of the expression to calculate the percentage.

    • Type /[TotalSales] at the end of the subtotal reference. Have you noticed the slash on the left side of the expression snippet?

    • Select Percent from the Format Property drop-down list. With these settings, we don’t have to write the *100 part in the expression.

    • Change the Caption of the child label to Category %. Change the TextBox and Child label Font Size to 12 points and Font weight Bold.

    Report Sample Print Preview

    Our Report is almost finished, but we need a little more change, and that comes next after we preview the progress of our work so far

  15. Save the changes we have made to the Report, and open it in Print Preview to see how the changes appear on the Report.

    The Report should look like the image below.

  16. Move the Report to the next page.

    The Total Sales value of the Report Header Section is not appearing on the second page.

    By default, the Report Header section prints only on the first page of the report, and the Report Footer section prints only on the last page. This means that any headings or calculations placed in the Report Header will not appear on subsequent pages.

    However, we often want the report heading and certain calculated values to appear on every page. Content placed in the Page Header section is repeated across all pages, making it the ideal place for such information.

    The challenge is that aggregate functions Sum(), Count (), and similar expressions do not work in the Page Header section. For example, we cannot place a SUM() calculation there. But we do want the calculated result from the Total Sales control (defined in the Report Footer or another valid section) to appear consistently at the top of every page.

    To achieve this, we make the following adjustments:

    Move the report heading from the Report Header to the Page Header, so it prints on every page.

    Reference the Total Sales control (which performs the calculation in a valid section, such as the Report Footer) from within the Page Header. By pointing to the existing Total Sales control, its value can be displayed in the Page Header even though aggregate functions cannot be calculated there directly.

    With this approach, both the heading and the calculated Total Sales value will appear consistently on every page of the report.

    The Final Changes.

    • Open the report in design view.

    • Drag the Category Name header bar down to get enough space for the Page Header Section, then cut and paste the Report Heading there.

    • Highlight the report heading and the report date controls (leave the Total Sales textbox alone), cut, and paste into the Page Header Section.

    • Select the Total Sales text box, copy and paste it into the Page Header Section, and move the position below the text control on the Report Header Section.

    • Write the expression = [TotalSales] (the Name of the Total Sales calculation text box on the header section) in the Control Source property (overwriting the existing expression) of the copied text box.

      This will display the value of the Header Section text box, where the Total Sales value is calculated.  

    • Select the Header Section text control and the child label and set their Visible property to No to keep it hidden when the report is previewed or printed.

    • Save the report with the changes.

      Print Preview the Report.

    • Open the Sales by Category report in Print Preview, move the pages forward, and check the headings and category percentage values.

  17. Next time you want to do something like this, you can do it in a few minutes.

Share:

Alphabetized Customer List

Alphabetized Customer List.

If you are new to Microsoft Access report design, this simple tutorial on creating an alphabetized customer list will give you a clear understanding of the basics. It provides valuable insight into the steps involved in designing a report. We will need the following steps to complete our task:

  1. Prepare the Customers' source data in a SELECT Query for the report.

  2. Open a new report in Design View.

  3. Insert the SELECT Query name into the Record Source Property of the Report.

  4. Use the Data Grouping and Sorting option of the Report to organize and display A, B, C, etc., in the Group Header.

  5. Design the Report.

  6. Preview the Report.

A Sample Report.

Sample alphabetized list of customers. Report Preview is given below:


Designing A Report.

Get Some Sample Data.

But first, we need some ready-made sample data for our Report

Let us start by importing the Customers Table from the Northwind sample database.

  1. Click on the External Data Menu.

  2. Click the Access Tool button to display the Import control dialog box to specify the Source and destination of data.

  3. Click on the Browse... button to locate the Northwind sample database, select the file, and click Open.

    The selected file pathname is inserted into the File Name control in the dialog box.

    The first option is already selected as the default to import one or more required Access Objects from the selected Access database.

  4. Click OK to open the selected Access Database and expose its Tables, Queries, Reports, etc.

  5. Click the Tables tab, select the Customers table, and click Ok to import the selected table.

    The next step is to create a SELECT Query using the Customers table as the Source.

  6. Click on the Create menu and select Query Design from the Other group.

  7. Click the Close button to close the Show Table Dialog Box without selecting any object from the displayed list.

  8. You will find the SQL View option on the left of the Toolbar; select it to display the Query's SQL editing window.

    You will find the SQL statement SELECT in the window.

  9. Copy the SELECT Query Code given below and paste it into the SQL window, overwriting the existing SELECT statement.

    SELECT Left([First Name],1) AS Alpha, [First Name] & " " & [Last Name] AS CName
    FROM Customers
    ORDER BY Left([First Name],1), [First Name] & " " & [Last Name];
    

    In the SQL string shown above, we are working with only two columns of data. The first column, named Alpha, contains a single character from each row—the leftmost character of the customer’s first name—extracted using Microsoft Access’s built-in String function Left(). Access also provides other useful string functions in this category, such as Right(), Mid(), and more.

    The second column, named CName, contains the customer’s full name, created by joining the first and last names together with a space in between. When building query expressions like this, it is always good practice to assign simple, meaningful names to the calculated columns. This makes it much easier to remember and reference them later in reports or forms. If you don’t provide explicit names, Access will automatically assign generic names such as Expr1, Expr2, and so on, which can be confusing when working with queries.

    In the ORDER BY clause of the query, both columns are sorted in ascending (A-Z) order, first the Alpha column, then the CName column.

  10. Save the Query named Customer ListQ.

  11. Open the Customer ListQ in the datasheet view and check the data.

    A sample image of what we are going to create is given below for reference:

The Design Task.

Let us design the Report.

  1. Select Report Design from the Create menu.

    An empty Report is open in Design View, with its Property Sheet. The first priority is to define the CustomerListQ Query as the Record Source of our report. If the Property Sheet is not displayed, then click on the Property Sheet toolbar button to display it.

  2. Select the Data Tab on the Property Sheet.

  3. Click the Record Source Property, and click the drop-down list at the right end of the property.

  4. Find CustomerListQ Query (use the slider, if necessary) and select it from the drop-down list to insert it into the Record Source property.

  5. Click the Group & Sort Toolbar button in the Group & Totals Group under the Design Menu, if it is not in the selected state, to display the Group and Sort controls under the Report Footer Section.

  6. Click the Add a Group control displayed in the Group, Sort, and Total shown below the empty report.

  7. Click on the Alpha column name displayed in the Query columns list.

    You can see that the Alpha Group Header is between the Page Header and Detail Sections of the empty report.

    We must sort the customer names by their first character (A, B, C order) so that all names appear under the first Alpha Character. 

    Note: All Names starting with the letter A will appear under Group A, all names starting with the letter B will list on the Report under Group B, and so on.

  8. Click Add a Sort control and select CName from the list.

    Now, let us create the Report Heading, Group headings (A, B, C, and so on), and customer names to appear under each group.

  9. Click the Label control to select it, draw a rectangle for the Heading Text "CUSTOMER LIST", select Bold and Italic formatting styles, and set the font size to 16.

  10. Select the TextBox control and draw a text box on the Alpha Header Section of the report.

  11. Click the Data Tab on the Property Sheet and select Alpha from the Control Source drop-down list. Change the font style to Bold and character size to 16.

  12. Select the child label of the text box and delete it.

  13. Create another text box in the Report Detail Section, below the Alpha Header control.

  14. Select the CName Column name from the drop-down list in the Control Source property under the Data Tab in the TextBox Property Sheet.

  15. Reduce the Detail Section height by dragging the Page-Footer section to the height of the TextBox.

  16. Save the Report as Customer List.

    Print Preview the Report.

  17. Open the Customer List report in Print Preview to view.

If the Heading, Group heading, and customer list are not properly aligned to the left in your report, as shown in the first image at the top, align all the controls to the left.

Share:

How to Use Form Filter on Report

How to Use Form Filter on a Report.

Normally, we use a query or a processed data table as the record source for a report when printing selected items, such as customer invoices or customer ledger statements.

But what if you want to print only the current record displayed on a form?

Let’s begin with a simple method before moving on to using the form filter with the report. For this, we’ll need some sample data, a form, and a report to work with.

Sample Trial Run.

  1. Import the Order Details and Products Table from the Northwind sample database.

  2. Use the Report Wizard to design a Report, using the Order Details Table as Record Source (sample report view below), and save the Report as Rpt_OrderDetails.

  3. Use the Form Wizard to design a multiple-item (continuous) Form using the Order Details Table (sample data view image is below) and save it as Frm_OrderDetails.

  4. Open the Form Frm_OrderDetails in the design view.

  5. Select the Command Button Tool from the Toolbox and draw a Command Button on the Header Section of the Form.

  6. Display the Command Button Property Sheet (Design -> Tools -> Property Sheet or F4), select the Property Sheet All Tab

  7. Change the Name Property Value to cmdRpt and change the Caption Property Value to Run Report (see the Form image above).

  8. Select the Event Tab of the Property Sheet.

  9. Select the OnClick event property [Event Procedure] from the drop-down list, and click the Build (...) button at the right edge of the property to open the VBA window with the Command Button Click Event Procedure empty Subroutine stub.

  10. Copy and paste the middle line of Code between the empty Subroutine stub.

    Private Sub cmdRpt_Click()
    
       DoCmd.OpenReport "Rpt_OrderDetails", acViewPreview, , "[order id] = " & Me![order id]
    
    End Sub
    
    

    The last parameter to the 'DoCmd.OpenReport' command is a Filter condition to select the current record's Order ID number to filter all records with the same Order ID number. We have omitted the third parameter from using a Query as the Report Source Data.

    The filter condition "[Order ID] = " & Me![Order ID] states that "take all the records with the current record Order ID Number as source data" for the Report.

  11. Save the form Frm_OrderDetails and open it in normal view.

  12. Click on any record with the same Order ID as more than one record under the same Order or any record you like.

  13. Click on the Run Report Command Button to open the Rpt_OrderDetails with the selected record.

The above example uses only a single record or several records with the same Order ID to print the Report. 

Several Items Selection.

  1. Next, we’ll add more flexibility by using the Form Filter property. This allows us to filter the data on the form—such as by selecting one or more Order IDs—before opening the report for printing.

    Instead of hardcoding the criteria, for example:

    "[Order ID] = " & Me![Order ID]

    in the DoCmd.OpenReport command, we can reference the form’s Filter property directly.

    With this approach, the user can filter records based on any column value on the form (such as Order ID, Quantity, or Unit Price) and then use the resulting dataset to print the report.

  2. Make a copy of the form Frm_OrderDetails and paste it with the name Frm_OrderDetails2.

  3. Open the Form Frm_Orderdetails2 in Design View.

  4. Click on the Command Button to select and display its property sheet (F4).

  5. Select the Event Tab and select the OnClick property.

  6. Click on the Build (. . .) button to open the VBA window.

  7. Copy the following code and paste over the existing lines of code in the Form Module:

    Private Sub cmdRpt_Click()
        If Me.Filter = "" Then
            MsgBox "Apply a filter to the Form first."
        Else
            DoCmd.OpenReport "Rpt_OrderDetails", acViewPreview, , Me.Filter
        End If
    End Sub
  8. Check the last parameter setting in the DoCmd.OpenReport statement. We are asking the Report to use whatever criteria setting is available in the current Form’s (Me) Filter Property Value (like ('[Order Details].[Order ID] In (30,31,32)') to pick records for the Report. Save the Form and open it in its normal view.

  9. Click on the Command Button to open the Report.

    When you click the command button, you may see a message prompting you to “Apply a filter to the form first.” This happens because the program checks whether the form’s Filter property contains a filter condition—similar to the example we used earlier, or the sample shown in Step 7.

    Note: Once a filter is applied, the filter condition remains stored in the form’s Filter property, even after the filter action is turned off. The actual filtering is controlled by another property: FilterOn, which can be set to either True or False. When you toggle the filter action on the form, the FilterOn property changes accordingly, but the filter criteria text in the Filter property is not cleared. You will only see the above message if the Filter property is completely empty.

  10. Click on the Order ID column on any record.

  11. Click on the Filter Toolbar button (see the image below) to display the Filter selection control.

    The selected field values (Order ID numbers) List is displayed, showing that values are check-marked, indicating that all the values are selected.

  12. Click on the Select All Option to deselect all items.

  13. Now, select the Order ID Numbers 30, 31 & 32, and click OK to close the Filter Control.

    The form now shows only records of Order IDs 30, 31 & 32.

  14. Click the Run Report Command Button on the Header Section of the Form to open the Report in Print Preview with the records filtered on the Form.

  15. Close the Report.

    Try it with a different Field.

  16. Place the cursor on the Quantity Field on any record on the Form.

  17. Click on the Filter Toolbar Button to display the Filter Control.

  18. Select the items with Quantity values 100, 200 & 300, click the OK button to close the control and filter the selected records.

  19. Open the Report by clicking the Run Report Command Button and check the report contents.

  20. Close the Report.

  21. Click on the Toggle Filter Toolbar button.  The Filter action is reset, and all the records are back on the Form (or the FilterOn Property Value is set to False).

  22. Now, click on the Run Report Command Button to preview the Report. 

The Report shows the last filtered records, rather than all records from the Form.  When we toggle the filter, Microsoft Access sets the FilterOn Property Value to False, nullifying the effect of the filter action on the form, without removing the filter condition string inserted in the Filter Property, because the User may click the Toggle Filter button again to bring back data filtered by the last set filter condition. Our program keeps repeatedly using the filter setting because the Filter Property value is not empty, and we are not checking the status of the FilterOn Property setting.

But we can solve this issue with a few changes in our program as follows:

Private Sub cmdRpt_Click()
    If Me.FilterOn Then
        DoCmd.OpenReport "Rpt_OrderDetails", acViewPreview, , Me.Filter
    Else
        DoCmd.OpenReport "Rpt_OrderDetails", acViewPreview
    End If
End Sub

Change the program as shown above. Try the effect of the Filter and Toggle Filter on the Form and Report.

Technorati Tags:
Share:

Creating Watermark on MS-Access Reports

Creating Watermarks in MS-Access Reports.

No matter what kind of database design you create for your company, the ultimate output that external users expect is reports—whether in text format or as charts. Charts can be presented in simple 2D Designs, or in more polished 3D designs with gradient colors. While appearance can make reports more attractive, what truly matters is that the information presented is meaningful and serves its purpose.

Think of it like a song: the lyrics may be the same whether sung by an amateur in the bathroom or by a professional singer, but the audience will always prefer the professional version. The same principle applies to reports.

You can throw together a report in a few minutes. Or you can carefully design it, paying attention to every detail—control placement, sizing, font style, highlighting, headings, footers, and summary lines. This may take hours of refinement, but the result is worth it when you present the report and see your boss’s nod of approval.

Now, speaking of controls and enhancements—why not take it one step further? For instance, you can add a watermark (such as a company logo or name) to the report’s background. This small touch gives your report a professional polish. If you have a light grayscale image of your company logo (in .bmp format), you can easily print it as a watermark to enhance the presentation.

Incorporating a Watermark on the Report.

  1. Open the Report in Design View.
  2. Display the Report's Property Sheet (F4).
  3. Look for the Picture Property and select the Property.
  4. Click on the Build button (...), at the right end of the property, to browse for the Watermark image on the disk and select it.
  5. With the following three property settings of the Report, you can display and print the watermark image in various ways:
    • PictureAlignment = 2 (center)
    • PictureTiling = False 
    • PictureSizeMode = 3 (zoom)

When you load the Watermark picture in the background, with the above property settings, the Report Print Preview looks like the image given below:

Print the Report on the Printer or convert it to MS-Access Snapshot format (file extension: .snp) or into PDF.

The above work can be automated to define and assign the Watermark Image at the run-time of the Report, with the VBA Code given below:

The ReportWaterMark() Function.

Public Function ReportWaterMark()
Dim rpt As Report, txtRpt As String
Dim imgPath As String

txtRprt = ""
imgPath = ""

Do While txtRpt = "" Or imgPath = ""
  If txtRpt = "" Then
   txtRpt = Nz(InputBox("Give Report Name:", "Report Water Mark"), "")
  End If
  If imgPath = "" Then
   imgPath = Nz(InputBox("Watermark Image PathName:", "Report Water Mark"), "")
  End If
Loop

DoCmd.OpenReport txtRpt, acViewDesign

Set rpt = Reports(txtRpt)
With rpt
    .Picture = imgPath
    .PictureAlignment = 2
    .PictureTiling = False
    .PictureSizeMode = 3
End With
DoCmd.Close acReport, txtRpt, acSaveYes
Set rpt = Nothing

DoCmd.OpenReport txtRpt, acViewPreview

End Function

Copy the code, paste it into a Standard VBA Module, and save the Code.  You can run this program from a Command Button Click Event Procedure like:

Private Sub cmdWMark_Click()
    ReportWaterMark
End Sub

When you run the main program, it will prompt you for two inputs: the report name and the location of the watermark image (including the file name). Be sure to note down this information before running the program. You only need to run the program once for a given report; the image will remain as the background picture till you run it again to replace the image with a different one.

Try the following property settings to see how they appear in the Report Print Preview:

.PictureAlignment = 0
    .PictureTiling = True
    .PictureSizeMode = 0

.PictureAlignment = 2
    .PictureTiling = False
    .PictureSizeMode = 1
Technorati Tags:
Share:

Continued on Page 2 on Report

Continued on Page 2 of the report.

Normally, MS-Access reports can span several pages, and it is often useful to display the current page number along with the total number of pages. To achieve this, a TextBox is added to the Report Page Footer section. In the Control Source property of this TextBox, you can enter an expression like the following:

=”Page: “ & [page] & “ of “ & [pages]

Result: Page 1 of 15

OR

="Page: " & [page] & " / " & [pages]

Result: Page: 1 / 15

Report Date is also added in the page footer area like ="Date: " & format(date(), ”dd/mm/yyyy”)

We often find ourselves repeatedly writing these expressions whenever a new report is designed. If you are a VBA enthusiast, you can automate this process by creating small, reusable User-Defined Functions (UDFs) in your application. By calling the function from a Text Box’s Control Source property, you can quickly insert the required information into your report. I have created two such functions for this purpose—if you’d like to take a look, click here.

This approach is especially efficient for developers aiming to standardize functionality across multiple Access applications, much like the concept discussed in your blog post on the MS-Access Reference Library.

Returning to the page indicator, we aim to display page continuity information in the Report’s Page Footer, but with a slight variation. A report may consist of a single page or multiple pages. When the report spans more than one page, the footer on the first page should display: “Continued on Page 2.”

On subsequent pages (page 2, page 3, etc.), the label should update accordingly—for example, “Continued on Page 3”, and so on—up to the second-to-last page. This label should not appear on the final page. If the report consists of only a single page, the label should be omitted entirely.

Using the first example at the beginning of this article, a single-page report will simply print as “Page 1 of 1.”

Try out the Page Footer Setting

  1. To try our new page labels, open one of your Reports with a few pages.

  2. Create a Text Box wide enough to display the label Continued on Page 99, at the Page Footer of the Report.

  3. Write the following expression in the Control Source Property of the Text Box.

  4. =IIf([Pages]>1 And [Page]<[Pages],"Continued on Page " & [Page]+1,"")

  5. Save the Report and open it in Print Preview.

  6. Check the last page of the Report.  This label should not appear there.

  7. Try this out on a single-page Report.

NB: [page], [pages] are System Variables and should be used in the expression without change. &hypen;

Earlier Post Link References:

Share:

Easy-Read Reports

Easy-Read Reports.

When computer reports, accounting ledger statements, or purchase invoices are printed with closely spaced lines, readability improves if alternate lines are shaded with a light background color. Traditionally, pre-printed stationery was used for this purpose. Line printers typically print six lines of data within a one-inch vertical space. To emphasize headlines, the double-strike each character for enhanced printing style,  the only advanced feature available in line printers.

Line-printer-based reports were designed on graph-paper-like sheets, with carefully written code to position headings, data lines, and summaries precisely on the pre-printed stationery.

An A4 sheet (8.5 × 11 inches) provides 66 print lines. Of these, one inch at the top and half an inch at the bottom are reserved as margins, while the alternate data lines are shaded in green—see the sample image below.

A4-size paper has 80 print positions across when a 10-character-per-inch (pitch) font size is used. This can be increased to 96 characters if a 12-character-per-inch character size is used.

The above details provide a general background about computer stationery. Reports designed for line printers were created with these specifications in mind. When necessary, you can design reports for plain paper by setting the section height and the text box control height to one-sixth an inch, matching the line spacing used by traditional line printers.

Light Shading of Alternate Report Data Lines

We will use a simple trick to print alternate lines with a shaded background, making the report easier to read. There is no need for pre-printed stationery, as the shading will be applied dynamically during printing.

You can design a Quick Report and add a few lines of VBA code in the report’s class module. If you already have a report with closely spaced detail lines, you may skip directly to step 3 below.

  1. Import Products Table from MS-Access sample database Northwind.mdb

  2. Use the Report Wizard to design a Tabular Report with the Products Table, like the sample image given below:

  3. Open the Report in Design View.

  4. Select all the controls on the Detail Section of the Report and drag them to the right to get enough space to draw a TextBox on the left side to display Serial Numbers on the Report Lines.  Drag the heading lines and position them to the right.

  5. Insert a TextBox on the left side and write the '=1' expression in the Control Source Property.  Change the Name Property Value to SRL.

  6. Change the Running Sum Property Value to Over All.

  7. Create a Label control in the Page Header above the TextBox and write the Caption to SRL (for Serial Number).

  8. Select all the Controls in the Detail Section and display the Property Sheet (F4 or Alt+Enter).

  9. Change the Top Property Value to 0.  All the controls are shifted to the top edge of the Detail Section.

  10. Select the Rectangle Tool from the Toolbox and draw a rectangle around all the text boxes in the Detail Section (see the design view image above).

  11. Display the Rectangle (F4) Property Sheet and change the Name Property Value to Box1.

  12. Select the Send-to-Back option from the Arrange Menu to position the rectangle behind the text box controls.

  13. Reduce the Detail Section height so that there is no empty space below the TextBox controls.

  14. Display the VBA Code Module of the Report (ALT+F11).

  15. Copy and paste the following lines of VBA Code into the Code Module and save the Report:

    The Report Module VBA Code.

    Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
    Dim xSrl
    xSrl = [SRL]
    If xSrl / 2 = Int(xSrl / 2) Then
       [Box1].BackColor = &HCCC8C2
    Else
       [Box1].BackColor = &HFFFFFF
    End If
    End Sub
    
  16. Open the report in Print Preview.  You will find the result as shown in the report image at the top of this page.

Share:

Percentage on Report Summary

Percentage on Report Summary.

Earlier, we solved this problem using a Query in the blog post Percentage on Total Query. This time, let’s see how to achieve the same result on a Report. Our task is to display each detail line’s value as a percentage of the report’s summary total.

The approach is simple:

  1. Create a Report that lists the detailed values and includes a report-level summary (such as the total).

  2. Insert a Text Box in the Detail section.

  3. In the Text Box’s Control Source, write an expression that divides the detail value by the Report Summary total.

This way, each record line will show its proportional contribution to the overall total directly on the Report.

Design a Sample Report to Try.

  1. Import the Order Detail Table from Microsoft Access Sample Database: C:\Program Files\Microsoft Office\Office11\Sample\Northwind.mdb

  2. Open a new Query in SQL View, without selecting a Table from the displayed list.

  3. Copy and paste the following SQL String into the SQL editing window of the new Query:

    SELECT [Order Details].[Order ID], Sum([Order Details].Quantity) AS TQuantity, Sum([Order Details].[Unit Price]) AS UnitPrice, Sum([Unit Price]*[Quantity]) AS TotalPrice
    FROM [Order Details]
    GROUP BY [Order Details].[Order ID];
    
  4. Save the Query named OrderSummary.

  5. Design a Report with the Detail Section and Report Footer summary controls using the OrderSummary as the Source.

  6. Click the TextBox at the Report Footer to select it.

  7. Display the Property Sheet (F4 or ALT+Enter) of the Text Box.

  8. Change the Name Property Value to GTPrice (stands for Grand Total Price).

  9. Write the expression =Sum([TotalPrice]) in the Control Source Property.

  10. Select the Text Box at the right end of the Detail Section and display its Property Sheet.

  11. Write the expression =[TotalPrice]/[GTPrice] in the Control Source Property.

  12. In the Format Property, select the Percent format from the drop-down list.

  13. Type 2 in the Decimal Places Property.

  14. Save and Close the Report.

  15. Open the OrderSummary in Print Preview and check the detail line percentage value calculated on the Report Footer Grand Total Price.

Creating Page-Level Totals.

Want to know how to calculate and display Page-wise control totals? You can learn it from here.

Share:

Embedded Macros in Access2007

Embedded Macros in Access2007.

The only difference between stand-alone macros and embedded macros is that embedded macros do not appear in the Navigation Pane under the Macros group. Instead, they are written directly within a Form, Report, or a control’s event property. When you copy a Form or Report, its embedded macros go with it.

Let’s now explore how embedded macros are created.

Creating Embedded Macros.

  1. Open Microsoft Access 2007.

  2. Open a Report in Design View.

  3. Press F4 or Alt+Enter to display the Property Sheet of the Report.

  4. Click on the Event Tab of the Property Sheet.

  5. Click on the On Load Event Property to select it.

  6. Click on the Build (...) button on the right side of the property.

  7. The Macro Builder option is already in selected state. Click the OK Command Button to accept it.

    The Macro is open in Design View.  The title bar of the macro indicates Catalog:Report: On Load (the Report Name: Object Type: Event Type), where the macro will be embedded. 

  8. Select MsgBox Action and type my Embedded Macro in the Message Action Argument.

  9. Type the On Load Info in the Title Argument of MsgBox Action.

  10. Click on the Close Toolbar button to save and close the Macro.

  11. Save and Close the Report.

  12. Right-click the Report in the navigation pane and select Open to open the Report in Report View.  The embedded macro will run, and you will see the message.

  13. You can modify the macro by following steps 2 to 6.  You can add several actions in the Macro if needed.

Share:

Report Design in Access2007

Report Design in Access2007.

In Microsoft Access 2007, two new design-time features are available: Report View (different from Print Preview) and Layout View, in addition to the traditional Design View and Print Preview. These new views make working with reports more interactive.  In earlier versions of Access, only Design View and Print Preview were available.

Report View looks similar to Print Preview but offers additional functionality. You can search within the report, copy data to the clipboard, filter records, and even view summarized values of the filtered data. If you’d like to preserve the filtered records so that they appear each time the report is opened, simply set the Filter On Load property to Yes.

Layout View is somewhat similar to Design View, but with one important difference—you can make design adjustments while viewing the actual report contents. In this view, you can rearrange fields, add or remove fields, adjust field sizes, and modify data field properties, with the changes immediately reflected in the report output.


The Report View Feature.

  1. Let us try out the above features; Open Microsoft Access 2007.

  2. Open one of your Databases.

  3. Import the Order Details Table from the Northwind.mdb sample database.

  4. Click on the Table to select it.

  5. Click the Report Option from the Create Menu to create a Report with the basic design and save it named Order Details.

  6. Right-click the Order Details Report in the navigation pane, select Open to open the report in Report View.

Now, let us try search, filter, and copy operations in the Report View mode.

  1. Click on the OrderID field in the first record on the Report to select it.

  2. Click on the Find Toolbar button (the field-glass icon) under the Home menu.

  3. Type 10251 in the Find What control and click the Find Next Command Button.  The first record with OrderID number 10251 is highlighted.  You can repeat the search operation by clicking on the Find Next Command Button.

  4. Let us incorporate the filter action; click the Cancel Button to cancel the Find operation and close the dialog box.

  5. Click on the Filter Toolbar Button.  The following filter control will be displayed over the report.

  6. Click the Select All option to remove all the check marks.

  7. Put check marks on OrderID Numbers 10251 and 10255.

  8. Click the OK Command Button to filter records with the selected OrderIDs on the Report.

  9. You can click the Toggle Filter Toolbar button to display all the records or filter the records again.

To copy selected records from the Report to the Clipboard:

  1. Click and hold the left mouse button at the left border of the topmost record in the report, and drag over a few records to highlight and select them.

  2. Click the Copy toolbar button in the Home Menu to copy the highlighted records onto the Clipboard.  These copied Report records can be pasted into Excel, Word, etc.

If you want to see the same set of filtered records every time you open the Report, then you must change the Report Property Value.

  1. Select the Design View option from the View Menu.

  2. Select the Property Sheet option to display the Report Property Sheet.

  3. Click on the Data Tab of the Property Sheet.

  4. Set the Filter on the Load property value to Yes.

  5. You can add or remove OrderID numbers in the IN clause of the Filter condition in the Filter property value if needed.

  6. Save the changes and close the Report.

  7. Open the Report in Print Preview and check whether the filter action is in effect.

  8. Close the Report.

The Layout View Feature.

Now, it is time to try out the Layout View options.

  1. Right-click on the Order Details Report in the navigation pane.

  2. Select Layout View from the displayed shortcut menu.

  3. Click and hold on the OrderID heading, and drag and drop it after the Discount Column.  You can do this with the column header, and also on any row of records.

  4. Click any row in the Discount column to select the column.

  5. Press the Delete key to remove the column from the Report.

    Let us try to bring that column back into the Report from the Source Table Field List.

  6. Click on the Add Existing Fields Toolbar Button from the Format Menu.

  7. Drag the Discount Field and drop it between the Unit Price and OrderID fields.

  8. While the Discount Field is still in selected state, click on the Arrange Menu to display its Toolbar.

  9. Click on the Property Sheet Tool to display the Property Sheet of the Discount Field.

  10. Click on the Format Tab of the Property Sheet.

  11. Change the Decimal Places property value to 2 and change the Width Property value from 1 inch to 0.75 inches.

The interactivity feature is very powerful in the designing process of Microsoft Access Reports and makes the design task easier and more interesting, too.

Technorati Tags:
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