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

Showing posts with label Queries. Show all posts
Showing posts with label Queries. Show all posts

Combining Active and Backup Database Records in Union Query

Combining Active and Backup Database Records in a Union Query.

Microsoft Access database has a maximum size limit of 2GB. To maintain performance and avoid reaching this limit, older records (such as previous year’s transactions) can be safely archived into a backup database for future reference. Once these records are backed up, they can be deleted from the active database. Run the Compact & Repair Utility to optimize performance for day-to-day operations.

However, there are situations where older data is required for analysis—for example, preparing budgets, setting sales targets, or comparing trends.  In such cases, we may need to reintegrate archived records with the current master table in the active database to perform meaningful analysis.

The Union Query Solution.

We can merge records from both the active Table and backup table (with the same name) in a Union Query.

A simple example is given below:

SELECT Export.* 
FROM Export
UNION ALL SELECT Export.*
FROM Export IN 'G:\NEW FOLDER\DB1.MDB';

In the example above, you can see that the names of the tables exported to the active database and the backup database(DB1.MDB) are the same. No need to link the table to the active database to get data from the backup database.

Share:

RUNSQL Action in MACRO and VBA

RUNSQL Action in Macros and VBA.

Microsoft Access beginners are often confused about the difference between the RunSQL action in a Macro and the 'DoCmd.RunSQL' method in Visual Basic for Applications (VBA). Regardless of where it is used—in a macro or VBA—you must provide the SQL statement of an Action Query or a Data Definition Query. These are the only types of queries supported.

If you’re unsure which queries fall under these categories, refer to the following list:

Action Query Types.

Action Query Types
Query Type Statement
Append INSERT INTO
Delete DELETE
Make-Table SELECT ... INTO
Update UPDATE

Data Definition Queries.

Data-Definition Query Types
Query Type Statement
Create a table CREATE TABLE
Alter a table ALTER TABLE
Delete a table DROP TABLE
Create an Index CREATE INDEX
Delete an Index DROP INDEX

Using the SQL Statement of any other Query type in the RUNSQL Action will result in errors. In Macro, the length of an SQL statement is 256 characters or fewer.

The 'DoCmd.RunSql' method of VBA can execute an SQL statement with a maximum length of 32768 characters or less.

Note: You are not allowed to give an existing Query Name as a parameter to this command. But in VBA, you can load the SQL Statement of a predefined query into a String Variable and use it as the parameter to the DoCmd.RUNSQL command. 

Example-1:

Public Function DelRecs()
'Existing Delete Query’s SQL is used in this example
Dim db As Database, qryDef As QueryDef
Dim strSQL As String

'Read and save the SQL statement from 'Query48'
'and load into strSQL string variable
Set db = CurrentDb
Set qryDef = db.QueryDefs("Query48")
strSQL = qryDef.SQL

'Execute the SQL statement after
'disabling warning messages
DoCmd.SetWarnings False
DoCmd.RunSQL strSQL
DoCmd.SetWarnings True

'Using DoCmd.OpenQuery Command to run a Delete Query
DoCmd.SetWarnings False
DoCmd.OpenQuery "Query48", acViewNormal
DoCmd.SetWarnings True

End Function

The RunSQL action in a Macro allows you to modify or delete records across multiple records in one step. Before executing an Action Query, Microsoft Access displays a warning message appropriate to the action (such as update or delete) and waits for the user’s response to either proceed or cancel.

Once you have thoroughly tested the Action Query, you can instruct Microsoft Access to temporarily suppress warning messages during the RunSQL execution. After the query completes, you should re-enable the warning messages so that Access can continue to alert you about unexpected errors or issues as they occur.

The SetWarnings action in a Macro (or the DoCmd.SetWarnings method in VBA) is used to set or reset the System warning messages. This is particularly useful when data processing for a report involves one or more Action Query steps within a Macro.

In the Macro design example shown below, the first action is SetWarnings, with its parameter set to No, which suppresses the warning messages when the RunSQL executes the Action Queries in the next step. The third action is another SetWarnings, this time with its parameter set to Yes, which enables System warning messages. This ensures that Microsoft Access can once again handle and report any unexpected errors as they occur.


Example-2:

Create a Table with the Data-definition SQL

Warning: Double-check that you are not using any existing table name for this sample run.

Public Function DataDefQuery()
Dim strSQL As String

strSQL = "CREATE TABLE Books  (Title TEXT(50) NOT NULL, Author TEXT(50) NOT NULL, PublishDate DATE, Price CURRENCY)"

DoCmd.RunSQL strSQL

End Function

The OpenQuery Action in Macro and DoCmd.OpenQuery Method of VBA uses the name of a predefined Query (of any type) to open it in any of the following Views:

  • Design View
  • Datasheet View
  • Print Preview
  • Pivot Table
  • Pivot Chart
Share:

Adding Data directly into External Databases

Adding Data directly into External Databases.

The Back-End/Front-End database design is a common practice in Microsoft Access. The back end may consist of Access, dBase, SQL Server, Excel, or Paradox databases, with their tables linked to the front end (FE). Once the tables are linked, they behave just like native tables within Access—you can design queries, forms, and reports on them, and manage everything from the FE.

But what if we want to work without directly linking these tables to the FE? For example, can we create a query in the current database that uses an external table (not linked) from another Access database?

We have already explored this topic earlier and confirmed that it is indeed possible. You can check the following blog posts for practical demonstrations of this technique applied to different types of external data sources:

  1. Opening External Data Sources
  2. Opening dBase Files directly
  3. Opening an Excel Database directly
  4. Display Excel Values directly on Form
  5. Database Connection String Property
  6. Source ConnectStr Property and ODBC
  7. Link External Tables with VBA
  8. Lost Links of External Tables
  9. MS-Access Live data in Excel
  10. MS-Access Live data in Excel-2

As you can see from the list above, methods 1 through 6 show different ways to retrieve external data without external tables linked to the current database.

When working with dBase or FoxPro tables, the folder path where the table resides is treated as the database name.

If you’ve already read the second article, Opening dBase Files Directly, you should now have a good idea of what we are about to explore—namely, how to send output data into external databases without linking them to Microsoft Access.

Sample SQL for External dBase Table.

Before we dive into output operations, let’s take a closer look at a sample SQL statement that retrieves data from a dBase table through a query—without linking the table to the Access database.

Note: If you don’t already have a dBase table to test with, you can easily create one by exporting one or more of your Access tables into a separate folder on your disk. You don’t need to install a dBase application on your machine—the required ODBC driver files are already included with Microsoft Office.

SELECT Employees.* FROM Employees IN 'C:\MydBase'[DBASE IV;];

The SELECT query shown above will return all records from the Employees.dbf table located in the dBase database folder C:\MydBase. The text [DBASE IV;] specifies the database type and version. The clause

IN 'C:\MydBase' [DBASE IV;];

creates a direct connection to the Employees.dbf table—without establishing a permanent physical link. In other words, the data from Employees.dbf is accessible only through this query and not as a linked table in Access.

Up to this point, we were experimenting with how to bring data from external databases into Access without linking them. Now, let’s take it a step further and explore how to update or add data to these external databases.

Updating Data into an External dBase Table.

A sample SQL that updates an external dBase Table is given below:

UPDATE Products IN 'C:\MydBase'[DBASE 5.0;] SET Products.TARGET_LEV = 45 WHERE (((Products.TARGET_LEV)=40) AND ((Products.REORDER_LE)=10));

With the above SQL, we are updating the Products stock Target level to 45 from 40. For items with Re-order Level (Minimum Stock Level) of 10, the current stock quantity target level is 40.

Appending Data into an External dBase Table.

Let us append Records from the current MS Access Database Products_Tmp Table to the Products.dbf Table of C:\MydBase dBase Database.  The sample SQL is given below:

INSERT INTO Products
  SELECT Products_Tmp.*
  FROM Products_Tmp IN 'C:\MydBase'[DBASE 5.0;];

IN Clause and Query Property Setting

Source Database and Source Connect Str Properties.

Let us examine the Property Sheet of one of the above Queries to check whether the SQL IN Clause setting is there.

  1. Open one of the above Queries in Design View.

  2. Display the Property Sheet of the Query. Press F4 or ALT+Enter to display the property sheet and make sure that it is the Query Property Sheet. Under the Title of the Property Sheet, there will be a description: Selection Type Query Property.

  3. You may click an empty area to the right of the Table on the Query Design surface to make sure that the Property Sheet displayed is the Query's Property Sheet, not the Table or Query Column Property Sheet. Check the sample image given below.

  4. Check the Source Database and Source Connect Str Property Values. If you find it difficult to memorize the correct syntax of the IN Clause in SQL, then you can populate the respective values in these Query properties as shown. This will automatically insert the Connection String with the correct syntax in the SQL.

  5. You can find the correct syntax for Access, Excel, Paradox, and ODBC connection strings for IBM iSeries machines, SQL Server, etc., from the above-quoted Articles.

Caution:

While the above methods offer convenient ways to work with external tables without permanently linking them to an Access database, relying on this approach too heavily can cause problems down the line if not managed carefully. To avoid confusion or data management issues, it is essential to maintain proper documentation of these Queries and keep them safely for future reference.

Constant Location Reference Issues?

Let’s consider the case of an external Microsoft Access database. The SQL example below demonstrates how to append data directly to the Employees table of another Access database located on a LAN Server. This type of operation is commonly performed on a scheduled basis—daily, weekly, or at other regular intervals.

INSERT INTO Employees IN 'T:\Sales\mdbFolder\Database1.accdb' 
SELECT Employees_tmp.*
FROM Employees_tmp;

Everything works smoothly, and over time, you may even forget about this particular query—or others like it. After six months, suppose you decide to shift or copy the databases from their current folder into a new location on the server (say, T:\Export\mdbFolder), while leaving a copy in the old folder as a backup. The database seems to function perfectly in the new location; no errors appear, and the users are satisfied.

However, some of your queries still contain the original connection strings hard-coded in their SQL statements. Since these were never updated to the new folder in the query, the queries continue to update the old database copy in ...\Sales..., instead of the intended ...\Export... location. When users eventually report data discrepancies, it may not immediately occur to you that the culprit is the IN clause of your SQL. By the time you discover the oversight, you may already have wasted hours—or even days—troubleshooting the wrong problem.

Despite this drawback, the method remains useful when external databases are needed only occasionally. If the frequency of use is minimal, it is often better than keeping the external tables permanently attached to the front-end.

Share:

Dynamic Dlookup in Query Column

Dynamic Dlookup in Query Column.

If we need only a single value in a Query Column from a related Table, we often use the DLookup() function.

Normally, the standard approach is to add the related table to the query design surface.  Establish a relationship between the Primary Key of the main table and the Foreign Key of the other table, and then pull the required field value into the query column.

However, in certain cases, this method can lead to complications. To illustrate, let’s look at an interesting scenario where DLookup() is used in a query column.

Suppose we use the following expression to pick up the Sales Tax Rate for each sold item from the tblTaxRates table, so that the tax value can be calculated on the sales amount:

DLookup("TaxRate2005", "tblTaxRates", "[Product Code] = '" & [ProductCode] & "'")

Here’s the catch: the tax rate changes every year as part of the government’s annual budget revisions. The company maintains a history of these changes by adding a new tax rate field for each year, with the year as a suffix—e.g., TaxRate2005, TaxRate2006, TaxRate2007, and so on.

A sample image of the tblTaxRates table is shown below:

In the Query, we assign a consistent column name TaxRate, and insert the DLookup() Function as its expression. For example:

TaxRate: DLookup("TaxRate2005","tblTaxRates","[Product Code]='" & [ProductCode] & "'")

Here, the function may refer to TaxRate2005, TaxRate2006, or TaxRate2007, depending on the year being processed. But the query output column name remains the same, TaxRate.

This consistency is useful when designing reports. On the report, we can place a control bound to the TaxRate field. Since the query always produces a column named TaxRate, the report design does not need to be modified each time the tax year changes.

Check the sample Query result image given below:


Applying Different Tax Rates

Now, consider a practical scenario:

  • Some orders were placed in December, when the previous year’s tax rate still applied.

  • Other orders were placed after the budget, when the new tax rate came into effect.

When preparing invoices, this means:

  • Older invoices must use the TaxRate2005 field.

  • Newer invoices must use the TaxRate2006 field.

In other words, the first parameter of the DLookup() function needs to change each time:

DLookup("TaxRate2005","","") DLookup("TaxRate2006","","")

(The table name and criteria are omitted for simplicity.)

Obviously, we cannot expect the user to open the query design and manually update the field name every time they need to print invoices from a different year.

The solution is straightforward:

  1. Create a small Form with a Text Box (or, better yet, a Combo Box that lists available tax rate fields).

  2. Provide a Command Button on the form.

  3. The user enters (or selects) the required tax rate field name and clicks the button.

  4. The code behind the button dynamically updates the query, refreshes it, and then opens the Report that depends on it.

This approach lets the user control which TaxRate field the DLookup() uses, without ever touching the query design.

The Textbox name is Tax on the form.  Our Dlookup() function in the Order Details Query column will look as given below:

TaxRate:DLookup([Forms]![InvoiceParam]![Tax], _
”tblTaxRates”,”[ProdCode]= '” & [Product Code] & “'”)

In the criteria, the ProdCode field of the tblTaxRate table should match the (Product Code) field of the Products Table linked to the Order Details Table to return the tax rate for each item on the Order Details table.

The sample SQL of the Query.

SELECT [Order Details].[Order ID],
 Products.[Product Code],
 Products.[Product Name],
 [Order Details].Quantity,
 [Order Details].[Unit Price],
 [Quantity]*[Unit Price] AS SaleValue,
 Val(DLookUp([Forms]![InvoiceParam]![Tax],"TaxRates", _
 "[ProdCode]='" & [Product Code] & "'")) AS TaxRate,
 [SaleValue]*[TaxRate] AS SaleTax,
 [SaleValue]+[SaleTax] AS TotalSaleValue
FROM Products INNER JOIN [Order Details] _
ON Products.ID = [Order Details].[Product ID];

The Command Button Click Event Procedure can run the following code to open the Sales Invoice Report after refreshing the change on the Form:

Private Sub cmdRun_Click()
Me.Refresh
DoCmd.OpenReport "SalesInvoice", acViewPreview
End Sub
Technorati Tags:
Share:

Change Query Top Values Property with VBA-2

Continued from Last Week's Topic.

With last week’s introduction, we have seen various ways the Top Value and other properties change the SQL string of a SELECT Query.  Now we will learn how to redefine the Query for the Top Values and other property changes.

As I mentioned earlier, three types of queries, SELECT, APPEND, and MAKE-TABLE, only have the Top Values property.  SELECT and MAKE-TABLE queries have almost identical SQL strings with DISTINCT, TOP nn, and PERCENT clauses appearing immediately after the SELECT clause at the beginning of the SQL String.

A sample SQL string of a MAKE-TABLE query is given below:

SELECT TOP 15 PERCENT SalesReportQ.* INTO chart
FROM SalesReportQ
ORDER BY SalesReportQ.Total DESC;

Unlike SELECT and MAKE-TABLE Queries, APPEND Queries have the Top Values property settings inserted somewhere in the middle of the SQL string immediately after the SELECT clause. Check the sample SQL of the Append Query given below:

INSERT INTO Table3 ( xID, Field1, Field2 )
SELECT DISTINCT TOP 17 PERCENT Table2.ID, Table2.Field1, Table2.Field2
FROM Table2
ORDER BY Table2.ID DESC;

Our VBA program scans through the SQL String to find the TOP Values property Clauses in the SQL String(wherever they appear), removes the existing settings, and inserts changes as per input from the User.

First, we will create a form for the User to input the Query 'Top Values' property values and click a Command Button to redefine the SQL.

An image of a sample form is given below:

Two TextBoxes named Qry and TopVal, for Query name and Top values parameters, respectively, and a CheckBox named Unik for Unique value selection.  The Top Values TextBox can be set to a number or a percentage (15%).  If the Unik checkbox is set, then the query suppresses duplicate records based on the selected field values in the Query.

After setting the Query property values in the controls, the user should click the Command Button to Redefine the selected query SQL in the Query Name control.  The Command Button's name is cmdRun (the Caption: Modify Query). When the Command Button is clicked, the cmdRun_Click() Event Procedure is run (the VBA Code is given below) and validates the input values in the controls above and calls the QryTopVal() function (with parameters: query name, Top Values property value, and Checkbox value) to redefine the Query based on the user inputs.

Form Module Code.

Private Sub cmdRun_Click()
Dim strQuery, strTopVal, bool As Boolean
Dim msg As String

On Error GoTo cmdRun_Click_Err

msg = ""
strQuery = Nz(Me![Qry], "")
If Len(strQuery) = 0 Then
   msg = "  *>>  Query Name not found." & vbCr
End If
strTopVal = Nz(Me![TopVal], 0)
If strTopVal = 0 Then
   msg = msg & "  *>>  Top Property Value not given."
End If
bool = Nz(Me![Unik], 0)
If Len(msg) > 0 Then
    msg = "Invalid Parameter Values:" & vbCr & vbCr & msg
    msg = msg & vbCr & vbCr & "Query not changed, Program Aborted...."
    MsgBox msg, , "cmdRun_Click()"
Else
    'Call the QryTopVal() Function to redefine the Query
    QryTopVal strQuery, strTopVal, bool
End If

cmdRun_Click_Exit:
Exit Sub

cmdRun_Click_Err:
MsgBox Err.Description, , "cmdRun_Click()"
Resume cmdRun_Click_Exit
End Sub

Copy and paste the VBA Code into the Form Module and save the Form. Don't forget to name the Command Button as cmdRun.

The Main Function QryTopVal().

The main function QryTopVal() checks the validity of the Query Type (SELECT,  APPEND, or MAKE-TABLE) and reads the Query SQL.  Checks for the existence of Top Values and other Property settings; if they exist, then removes them.  Redefines the query based on the Top Values and other property inputs.

Copy and paste the following VBA code for QryTopVal() into the Standard Module and save it:

Public Function QryTopVal(ByVal strQryName As String, _
                       ByVal TopValORPercent As String, _
                       Optional ByVal bulUnique As Boolean = False)
'--------------------------------------------------------------------
'Author : a.p.r. pillai
'Date   : Jun 2011
'Remarks: All Rights Reserved by www.msaccesstips.com
'Valid Query Types:
'  0 - SELECT
' 64 - APPEND
' 80 - MAKE TABLE
'--------------------------------------------------------------------
Dim strSQL1 As String, strSQL2 As String, strTopValue
Dim db As Database, qrydef As QueryDef, sql As String
Dim loc, qryType As Integer, locTop
Dim txt(1 To 3) As String, num
Dim J, xt, msg As String

On Error GoTo QryTopVal_Err

txt(1) = "DISTINCT"
txt(2) = "TOP"
txt(3) = "PERCENT"

Set db = CurrentDb
Set qrydef = db.QueryDefs(strQryName)
qryType = qrydef.Type

If qryType = 0 Or qryType = 64 Or qryType = 80 Then
   xt = qrydef.sql

   GoSub ParseSQL

   loc = InStr(1, TopValORPercent, "%")

   If loc > 0 Then
      TopValORPercent = Left(TopValORPercent, Len(TopValORPercent) - 1)
   End If

   If Val(TopValORPercent) = 0 Then
      sql = strSQL1 & strSQL2
   Else
      sql = strSQL1 & IIf(bulUnique, "DISTINCT ", "") & "TOP " & TopValORPercent & IIf(loc > 0, " PERCENT ", "") & strSQL2
   End If

   qrydef.sql = sql
   msg = "Query Definition of " & strQryName & vbCr & vbCr & "Changed successfully."
   MsgBox msg, , "QryTop()"
Else
   msg = strQryName & " - Invalid Query Type" & vbCr & vbCr
   msg = msg & "Valid Query Types: SELECT, APPEND and MAKE-TABLE"
   MsgBox msg, , "QryTop"
End If

QryTopVal_Exit:
Exit Function

ParseSQL:
For J = 1 To UBound(txt)
  xt = Replace(xt, txt(J), "", 1)
Next
  
  locTop = InStr(1, xt, "SELECT")
  num = Val(Mid(xt, locTop + 7))
  num = " " & Format(num) & " "
  strSQL1 = Left(xt, locTop + 7)
  xt = Right(xt, Len(xt) - (locTop + 7))
  xt = Replace(xt, num, "", 1, 1)
  strSQL2 = " " & xt
  locTop = InStr(1, strSQL2, "ORDER BY")
  If locTop = 0 Then
    MsgBox "ORDER BY Clause not found in Query.  Result may not be correct.", , "QryTopVal()"
  End If
Return

QryTopVal_Err:
MsgBox Err & " : " & Err.Description, , "QryTopVal()"
Resume QryTopVal_Exit

End Function

You may try the Code with sample Queries.

Share:

Change Query Top Values Property with VBA

Change Query Top Values Property with VBA.

We have already learned how to use the Top Values property of Queries (applicable in SELECT, MAKE-TABLE, and APPEND queries) in an earlier post. If you haven’t seen it yet, I recommend taking a look at that article first [link here].

The Top Values property of a Query can only be set manually during design time. Unfortunately, you cannot directly change its value dynamically in VBA. You also cannot expect users to open the query in Design View each time they want a different set of results.

So, how do we handle situations where we need flexibility with these values?

Sample SQL with TOP Property Setting.

When we manually change the Top Values property, Microsoft Access automatically updates the SQL statement of the Query to reflect that change. Keeping this behavior in mind, we can use a little VBA trickery to manipulate the SQL directly, rather than searching for a property setting that doesn’t exist.

Before we move on to that approach, let us first examine what actually happens to the SQL definition of a Query when you set the Top Values property or other related properties.

Here is a sample SELECT Query with the Top Values Property value set to 25.

SELECT TOP 25 Orders.OrderID, Orders.EmployeeID, Orders.OrderDate, Orders.RequiredDate, Orders.Freight
FROM Orders
ORDER BY Orders.Freight DESC;

As shown in the example, when the Top Values property is set to 25, Access automatically inserts the text TOP 25 immediately after the SELECT clause in the SQL string. This indicates that the Query will return only 25 records. In the ORDER BY clause, the Freight column is sorted in descending order, so the output consists of the 25 records with the highest freight values in the table.

If, instead of a fixed number of records, you want a percentage of the total records—for example, 25%—then the Top Values property must be set to 25% rather than 25. In this case, the SQL text changes accordingly to:

SELECT TOP 25 PERCENT Orders.OrderID, Orders.EmployeeID, Orders.OrderDate, Orders.RequiredDate, Orders.Freight
FROM Orders
ORDER BY Orders.Freight DESC;

The next property that affects the record set is the Unique Values property (valid values: Yes or No). When this property is set to Yes, Access suppresses duplicate records in the output shown in the Datasheet. However, it evaluates only the fields included in the Query’s column list—other fields from the table that are not selected are ignored when checking for duplicates.

When this property is enabled, Access inserts the keyword DISTINCT in the SQL, immediately after the SELECT clause. The modified SQL will look like this:

SELECT DISTINCT TOP 25 PERCENT Orders.OrderID, Orders.EmployeeID, Orders.OrderDate, Orders.RequiredDate, Orders.Freight
FROM Orders
ORDER BY Orders.Freight DESC;

Another property you can set in a query is Unique Records (valid values: Yes or No). When this property is set to Yes, Access suppresses duplicate records in the output. Unlike the Unique Values property, this setting evaluates all fields in the source table, regardless of whether they are included in the query’s column list.

When enabled, the SQL changes by replacing the DISTINCT keyword with DISTINCTROW. This ensures that the uniqueness check is applied across the entire underlying table.

For example:

SELECT DISTINCTROW TOP 25 PERCENT Orders.OrderID, Orders.EmployeeID, Orders.OrderDate, Orders.RequiredDate, Orders.Freight FROM Orders ORDER BY Orders.Freight DESC;

We will exclude the Unique Records property from our VBA-based solution. As shown in the examples above, depending on the user’s requirements, we can dynamically add or remove any of these three elements—DISTINCT, TOP n, or PERCENT—to control the query output for reports.

Preparing for the VBA-based Solution.

Our methodology for modifying the SQL is straightforward. We will collect the required Query property values from the user through a TextBox and a Checkbox placed on a Form. Once the user enters the input and clicks a Command Button, the SQL will be redefined. This will invoke the following actions to redefine the Query:

  1. Open the Query Definition and read the existing SQL String.

  2. Scan the SQL string to check for the key text DISTINCT, TOP nn, and PERCENT.  If found, then remove them from the SQL String.

  3. Validate the input given by the User in the Textbox and checkbox, and insert appropriate SQL Clauses in the SQL String.

  4. Update the modified SQL in the Query definition.

This article has become too long now.  Explaining the above four steps and introducing the VBA Routines may make it even longer.  We will complete this topic in the next blog post.

Earlier Post Link References:


Share:

Top N Records in Query

Top N Records in Query.

We have seen the usage of different types of complicated Queries like the following:

Today, we will learn how to define and extract the top 100 records, or a certain percentage of the total records, based on the values in a particular Column.

Review of Rules of Queries.

You need to know only a few rules to work with this type of Query.

  1. You can select several Columns of data from the source for output.

  2. You must sort one or more columns of data in ascending or descending Order, and the leftmost sorted column will pick the top valuation records.

  3. If the output contains duplicate records (i.e., two or more records with identical values in all columns), you can set the Unique Values property to Yes, which is equivalent to using a DISTINCT clause in the SQL SELECT statement, to suppress the duplicates.

  4. If the query has more than one Table/Query as the source, and duplicate records are found in the output, set the Unique Records Property to Yes (DISTINCTROW clause in the SELECT statement) to suppress duplicates.

Create a Sample Query.

  1. Create a new database or one of your existing databases.

  2. Import the Order Details and Products Table from the Northwind.mdb sample Database. There is a Combobox in the Order Details Table that retrieves the Product Name from the Products Table. The Product Code in the Order Details Table is linked to the Product Code in the Products Table. Open a new Query in SQL View (without selecting a Table/Query from the displayed list).

  3. Copy and paste the following SQL String into the SQL window, and save the Query as Order_DetailsQ.

    SELECT TOP 100 [Order Details].ProductID, [Order Details].UnitPrice
    FROM [Order Details]
    WHERE ((([Order Details].OrderID) Between 10248 And 10300))
    ORDER BY [Order Details].UnitPrice DESC;
  4. Open the Query in Design View and check the order of field placement and the Sort Field.

  5. Right-click an empty area above the column grid to display the Query Shortcut Menu, select the Properties… option to display the Property Sheet. Check the image below:

  6. Ensure that the Top Values Property is set to 100 to filter the Query to 100 records with the highest Unit Price values.

  7. Change the Query View into Datasheet View to display the output records.  See the image given below:

    The Order Details table contains multiple records of the same product under different OrderIDs. In this example, we have intentionally excluded the OrderID field from the data columns, using it only in the criteria to select records with OrderIDs between 10248 and 102300, which also results in some duplicate records. As shown in the image above, several duplicate product records appear in the output. This scenario provides an opportunity to experiment with the Unique Values property settings to remove duplicates.

    Eliminating Duplicate Records.

  8. Change the Top Values property to All, and the Query to Datasheet View. The output will be about 150 records for OrderID Range between 10248 and 102300.

  9. Change the Query in Design View and display its Property Sheet.

  10. Set the Top Values property to 100 and the Unique Values property to Yes.

  11. Change the Query in the Datasheet View and inspect the output.

    Now the duplicate records are suppressed (29 records removed), leaving only 71 records in the output. The next property, Unique Records, can be set to Yes to achieve the same result when fields from two or more tables or queries are joined in a query design. This is useful when the output contains duplicate records due to a one-to-many relationship between the tables.

    We have specified 100 records in the Top Values Property, but the Unique Values property setting reduced the number of records to 71 after suppressing duplicates. 

  12. Change the Top Values Property setting from 100 to 25% and change the View to Datasheet.

Using the Percentage setting, the output returns only one-fourth of the total records. With Unique Values set to Yes, this yields 18 records, out of a total of 71. With Unique Values set to No, it returns 39 records, which is approximately one-fourth of the total 150 records.

The Top Values Property sets can be a specific number or a percentage of Total Records.

Share:

Sub-Query in Query Column Expressions

Sub-Query in Query Column Expressions.

Queries are the primary data processing tools in database systems. They work behind the scenes, shaping raw data into meaningful outputs such as reports and summaries. Many Microsoft Access users, especially beginners, try to build a report’s output data by chaining multiple tables/queries together in a single query, expecting the final result in just one or two steps. This approach often leads to difficulties in producing the correct output.

A better method is to start by planning the report—define its layout, required contents, grouping, and summarizing needs. If multiple related tables are involved, break down the process into smaller, manageable steps. Begin by joining a few tables or queries to create a new query, then use that query as input for the next step. You can also create intermediate tables and build further queries on top of them to refine the data. In this process, make use of action queries such as Make-Table, Append, or Update to prepare and organize the data effectively.

When the Report Requirement is Complicated.

When a report’s contents are complex and cannot be built in a single step, my preferred approach is to create a Report Table. Data is brought into this table piece by piece from the source tables using queries or VBA routines, and then added or updated as needed before opening the report. Once the Report Table is populated, the report design becomes straightforward, since it is bound to a single, well-structured dataset.

These preparation steps can be fully automated with Macros or VBA.

To make the process flexible, necessary report parameters—such as date ranges or filter criteria—are stored in a Parameter Table. A Parameter Form is provided to capture or update these values. From this form, users can either:

  • Re-run the procedure to refresh the Report Table with new parameter values, or

  • directly open the report in Preview/Print mode if the data has already been prepared.

Using a Sub-Query in the Criteria Row.

Here, we will explore how to use Subqueries within Queries to filter records or incorporate data from other tables or queries.

Let us look at a simple Query that uses a sub-query in the criteria section to filter data from the Orders Table.   In the Orders table, there are about 830 Orders, and the OrderIDs range from 10248 to 11077.  We need to filter certain Groups of Orders (say Order Numbers 10248, 10254, 10260, 10263, 10267, 10272, 10283) for review.

The following is the sample SQL query that filters the above Orders without the use of a Sub-Query:

SELECT Orders.*
FROM Orders
WHERE (((Orders.OrderID) In (10248,10254,10260,10263,10267,10272,10283)));

The above query works, but it has a limitation that whenever we want to filter a different set of Orders, we must manually modify the Criteria line by replacing the existing Order Numbers with the new ones. Clearly, we cannot expect end users to perform this task themselves.

A better approach is to provide users with a simple option to enter the required Order Numbers into a dedicated table (let’s call it ParamTable, with a single field: OrderNumber). This way, the query can automatically detect any changes to the table values at runtime. Users can type the desired Order Numbers directly into a Datasheet Form, and then click a Command Button to run the query with the updated values.

To achieve this, we need to use a subquery in the criteria row of the main query. The subquery compares the OrderNumber values in the ParamTable with those in the Orders table, ensuring that only matching records are returned.

We will modify the Query in the Criteria Row to insert a subquery to get the values from the ParamTable and use the OrderNumber field values as Criteria. 

The modified SQL String of the Query is given below:

SELECT Orders.*
FROM Orders
WHERE (((Orders.OrderID) In (SELECT OrderNumber FROM OrderParam)));

The Sub-Query string in the Criteria Row is in Bold in the SQL above.

The Sub_Query in a Query Column.

You may have already encountered the type of subquery shown above, but now we will explore a different approach: employing a subquery as an expression in a query column. This allows us to bring in values from another table related to the Query source table. Although this technique is not commonly used, it can be extremely valuable in complex scenarios where conventional joins or query structures fall short.

When several tables are used in a Query with LEFT JOIN or RIGHT JOIN relationships, it becomes difficult to link all the related tables this way to incorporate summary values of one table. This is more so when one-to-many relationships are involved.

We will use the Orders and Order Details Tables from the Northwind.mdb sample database for our example. Import both these tables from the Northwind.mdb sample database from C:\Program Files\Microsoft Office\Office11\Samples\Northwind.mdb.

The sample Query (in normal style) uses both Tables in the Query, linked to the OrderID Field of both tables to create an Order-wise Summary from the Order Details Table.

SELECT Orders.OrderID,
 Orders.CustomerID,
 Sum((1-[Discount])*[UnitPrice]*[Quantity]) AS OrderVal
FROM Orders INNER JOIN [Order Details] ON Orders.OrderID = [Order Details].OrderID
GROUP BY Orders.OrderID, Orders.CustomerID;

The same result can be achieved without placing the Order Details Table in the Query design. We will write an expression in a separate Column using a subquery to pull the Summary Order-wise Total Value directly from the Order Details Table. Here is the example SQL String:

SELECT Orders.*,
    (SELECT  Sum((1-[Discount])*[UnitPrice]*[Quantity]) AS OrderValue
     FROM [Order Details] AS ODetails WHERE ([ODetails].[OrderID] = [Orders].[OrderID])
GROUP BY [ODetails].OrderID) AS OrderVal, [OrderVal]*0.12 AS Tax
FROM Orders;

In the Orders table, each order can have multiple related records in the Order Details table. By using a subquery (a totals query), we can calculate the total sales value for each order. The result of this calculation is then displayed in the corresponding row of the output. In other words, the subquery functions as an independent expression in its own column, running separately for each row in the Orders table.

The new column name OrderValue, created, can be part of other expressions, and we have calculated the Tax value, 12% of Order Value, in a separate column.

Let us take a closer look at the Sub-Query.

  1. The SELECT clause uses only one output column (Sum((1-[Discount])*[UnitPrice]*[Quantity]) AS OrderValue), and the expression is named OrderValue.  You should not use more than one column in the SELECT clause.

  2. In the FROM clause, the Order Details Table is given a new name (ODetails), and the name is used to qualify the OrderID field in the WHERE clause.  The OrderID field appears in both the Orders and Order Details Tables.

  3. The WHERE clause in the Subquery is necessary to match the OrderIDs of the tables and place the calculated value of the Order row matched Records.

Earlier Post Link References:

Share:

Memo field and data filtering

Memo field and data filtering.

When designing tables, we carefully organize information to make it easy to retrieve through searches, filters, and queries. For example, in the Employees table of the Northwind.mdb sample database, an employee’s name is split into three separate fields—Title, FirstName, and LastName—so that each piece of information can be managed individually. These fields are also defined with specific lengths, based on the size of the source data.

However, when recording details such as an employee’s qualifications or work experience, we cannot predict the length of the text. In such cases, the Memo field type is used. A memo field allows free-form text of varying lengths, making it ideal for storing descriptive information.

That said, memo fields are not used directly in reports or queries because their contents are unstructured and more difficult to work with. Still, they do provide some flexibility in filtering records—for example, by searching for specific text that may appear anywhere within the field.

Let’s look at a few examples of working with memo field data from the Employees table in the Northwind.mdb sample database.

Prepare for a Trial Run.

  1. Import the Employees Table from the sample database C:\Program Files\Microsoft Office\Office\Samples\Northwind.mdb.

  2. Open the Employees Table in the datasheet view.

  3. Move the horizontal scrollbar at the bottom to the right, so that the Notes Memo Field contents are visible to you.

  4. Point the mouse at the left border of the table at the intersection of two rows, and the mouse pointer turns into a cross.

  5. Click and drag down to increase the row size so that the Notes field contents can be viewed properly.

    If you review the qualification details stored in each employee record, you’ll notice that many employees hold a BA degree. However, the text “BA” does not appear in a fixed position within the memo field—it may occur anywhere in the description. So how can we filter all employee records that include a BA degree?

    To begin, let’s try this directly in Datasheet View before moving on to writing a query that filters data based on text in a memo field.

  6. Highlight the letters BA in any record, and Right-click on the highlighted text.

    A shortcut menu is displayed, and the suggested options for filtering data from the Memo Field are Contains "BA" or Does Not Contain "BA".

  7. Click the Contains 'BA' option to filter records with the text "BA" matching anywhere in the memo field.

If you want to filter records this way for printing a Report, then we must create Queries to filter data based on the text in the Memo Field.  You can use the Like Operator with AND, OR logical operators.

Copy and paste the following SQL Strings into the SQL Editing Window of new Queries and save them with the suggested names:

Query Name:  Employee_BAQ

SELECT Employees.LastName, Employees.FirstName, Employees.Notes
FROM Employees
WHERE (((Employees.Notes) Like "*BA*"));

The output of this query will also include the record of an employee with an MBA degree because the text "BA" appears within "MBA". To exclude this record, modify the criteria by inserting a space immediately after the first asterisk, as in "* BA*".

Query Name:   Employee_BA_BSCQ

SELECT Employees.LastName, Employees.FirstName, Employees.Notes
FROM Employees
WHERE (((Employees.Notes) Like "* BA*")) OR (((Employees.Notes) Like "*BSC*"));

The above query is an example use of the logical operator OR to filter data having BA or BSC.

Query Name:   Employee_BA_BSCQ

SELECT Employees.LastName, Employees.FirstName, Employees.Notes
FROM Employees
WHERE (((Employees.Notes) Like "* BA*" And (Employees.Notes) Like "*psychology*"));

The above example demonstrates the logical operator AND and filters records of employees with BA in Psychology.

Earlier Post Link References:

Share:

Auto Numbering In Query Column

Auto Numbering In Query Column.

We know how to create an Auto-number Field in a Table to generate Unique Sequence numbers for the records added to the Table. We know how to insert line numbers sequentially for data lines on Reports.

On The Reports.

On Reports, create a TextBox in the Detail Section of the Report, write the expression =1 in the Control Source Property, and change the Running Sum Property Value to Over All or Over Group. 

If you need sequence numbers starting with 1 for each Group separately, depending on the Sorting and Grouping settings on the Report, then the Over Group option must be set in the Property.  Otherwise, set the Overall All option for continuous numbers from the start of the Report to the End.

If you want to create a Running Sum value of a Field, like Quantity or Total Price, then set the Running Sum Property value as explained above. For more details on Running Sum as well as creating Page-wise Totals on Access Reports, visit the Page with the Title: MS-Access Report and Page Totals.

In The Query Column.

However, asking for auto-numbering in a query column might seem unusual—unless the query results are meant for display purposes or the output requires sequence numbers for a specific reason.

Products Category Group-level sequence numbers or for creating a Rank List for students based on their obtained marks, and so on.

Or after filtering the records in the Query, the Auto-number field values are out of sequence.

This requirement was actually raised by a participant in an online MS Access Users Forum. No one, including myself, was able to suggest a definitive solution, only some alternatives. I offered a solution of my own, even though I wasn’t entirely satisfied with it either.

The Access User who raised the question in the Forum asked for a solution via email.

This prompted me to revisit the topic and experiment with a few simple methods. Eventually, I developed a function that accomplishes the task, and I’m sharing it here so that you can try it out too.

Need Trial and Error Runs.

It is important to understand how to use the QrySeq() function in a new query column to generate sequence numbers. The function must be called with specific parameter values, often derived from the query’s own columns. Before presenting the VBA code for the function, the details of its parameters are explained below.

Usage of the Function in the Query Column is as shown below:

Syntax: Target Column Name: QrySeq([Field Value], "Field Name", "Query Name")

SRLNO: QrySeq([ORDERID], "[ORDERID]", "QUERY4")

The QrySeq() Function needs three Parameters.

  1. The First Parameter must be Unique Values available from any Column in the Query.

  2. The second Parameter is the Column Name of the first parameter in Quotes.

  3. The third Parameter is the Name of the Query from which you call the Function.

The query from which the QrySeq() function is called should include a column of unique values, such as an AutoNumber or a Primary Key field. If such a column is not readily available, you can create one by combining two or more existing fields—for example:

NewColumn: [OrderID] & [ShipName] & [RequiredDate] & [Quantity] 

Ensure that this concatenation produces unique values for all records, and then pass this column ([NewColumn]) as the first parameter to the function.

The first Parameter Column Name must be passed to the Function in Quotes ("[NewColumn]") as the second parameter.

The Name of the Query must be passed as the third parameter.

NB: Ensure that you save the Query first, after every change to the design of the Query, before opening it in Normal View, to create the Sequence Numbers correctly.

The QrySeq() Function Code.

The simple rules are in place, and it is time to try out the Function.

  1. Copy and Paste the following VBA Code into a Standard Module in your Database:

    Option Compare Database
    Option Explicit
    
    Dim varArray() As Variant, i As Long
    
    Public Function QrySeq(ByVal fldvalue, ByVal fldName As String, ByVal QryName As String) As Long
    '-------------------------------------------------------------------
    'Purpose: Create Sequence Numbers in Query in a new Column
    'Author : a.p.r. pillai
    'Date : Dec. 2009
    'All Rights Reserved by www.msaccesstips.com
    '-------------------------------------------------------------------
    'Parameter values
    '-------------------------------------------------------------------
    '1 : Column Value - must be unique Values from the Query
    '2 : Column Name  - the Field Name from Unique Value Taken
    '3 : Query Name   - Name of the Query this Function is Called from
    '-------------------------------------------------------------------
    'Limitations - Function must be called with a Unique Field Value
    '            - as First Parameter
    '            - Need to Save the Query after change before opening
    '            - in normal View.
    '-------------------------------------------------------------------
    Dim k As Long
    On Error GoTo QrySeq_Err
    
    restart:
    If i = 0 Or DCount("*", QryName) <> i Then
    Dim j As Long, db As Database, rst As Recordset
    
    i = DCount("*", QryName)
    ReDim varArray(1 To i, 1 To 3) As Variant
    Set db = CurrentDb
    Set rst = db.OpenRecordset(QryName, dbOpenDynaset)
    For j = 1 To i
        varArray(j, 1) = rst.Fields(fldName).Value
        varArray(j, 2) = j
        varArray(j, 3) = fldName
        rst.MoveNext
    Next
    rst.Close
    End If
    
    If varArray(1, 3) & varArray(1, 1) <> (fldName & DLookup(fldName, QryName)) Then
        i = 0
        GoTo restart
    End If
    
    For k = 1 To i
    If varArray(k, 1) = fldvalue Then
        QrySeq = varArray(k, 2)
        Exit Function
    End If
    Next
    
    QrySeq_Exit:
    Exit Function
    
    QrySeq_Err:
    MsgBox Err & " : " & Err.Description, , "QrySeqQ"
    Resume QrySeq_Exit
    
    End Function

    The Sample Trial Run.

  2. Import the Orders Table from C:\Program Files\Microsoft Office\Office11\Samples\Northwind.mdb sample database.

  3. Copy and Paste the following SQL String into the SQL Editing View of a New Query and save the Query with the Name: AutoNumberQuery:

    SELECT Orders.*, QrySeq([OrderID],"OrderID","AutoNumberQuery") AS SRLNO
    FROM Orders;
    
  4. Select Save from the File Menu or click the Save Toolbar Button.

  5. Open the Query in the normal view.

Check the SRLNO Column for Sequence Numbers.

In this case, the OrderID field in the Orders table already contains unique values, so we can generate sequence numbers directly in the SRLNO column without any additional steps.

However, if the query does not contain a single column with unique values, we must create one by combining two or more existing query columns. This newly created column with unique values can then be passed to the QrySeq() function.

Let us try such an example with the Orders Table.

  1. Copy and paste the following SQL String into a new Query and save the Query with the name AutoNumberQuery2.
    SELECT Orders.*, [ShipName] & [RequiredDate] AS NewColumn, _
    QrySeq([NewColumn],"NewColumn","AutoNumberQuery2") AS SRLNO
    FROM Orders;
  2. Open the Query in Datasheet View to check whether the Serial Numbers were created correctly.

Ensuring Accuracy.

When a query contains hundreds or thousands of records, it is impractical to manually verify that the column values passed to the QrySeq() function are truly unique and that the generated serial numbers contain no duplicates. Instead, we can use a Total Query to count serial numbers that appear more than once. For this, we use the AutoNumberQuery2 as the source, which allows us to quickly identify any duplicate serial numbers in the dataset.

  1. Create a new Query that uses the following SQL String and name the new Query as DuplicatesCheckQ:
    SELECT AutoNumberQuery2.SRLNO,
     Count(AutoNumberQuery2.SRLNO) AS CountOfSRLNO
    FROM AutoNumberQuery2
    GROUP BY AutoNumberQuery2.SRLNO
    HAVING (((Count(AutoNumberQuery2.SRLNO))>1));
    
  2. Open DuplicatesCheckQ Query in Normal View.

The result will show that the SRLNO column contains the same number appearing more than once in the records. This indicates that the column values of the QrySeq() function are not unique and contain duplicates.

This can be rectified only by adding more Column Values to the NewColumn expression to eliminate the chance of ending up with duplicates.

This method serves as an alternative when an AutoNumber or Primary Key field is not available, and it does not guarantee 100% accuracy. When additional records are added to the source table, the method may fail again. In such cases, the only solution is to combine more fields in the NewColumn expression to reduce the likelihood of duplicates and ensure uniqueness.

To correct the query above, include the [Freight] column in the NewColumn expression. Alternatively, you can copy and paste the following SQL string into the AutoNumberQuery2 query, overwriting the previous SQL, and then save the query.

SELECT Orders.*,
 [ShipName] & [RequiredDate] & [Freight] AS NewColumn,
 QrySeq([NewColumn],
"NewColumn";,"AutoNumberQuery2") AS SRLNO
FROM Orders;

Open the DuplicatesCheckQ Query again to check for duplicates. If the result is empty, then the Sequence Numbers will be correct.

If you know a better solution, please share it with me. I’m not looking for a refinement of the existing code or method, but for a different approach that can achieve the same—or even better—results.

Improved Versions related to this topic:

Find New Auto-Numbers in Query Column Version-2 on this link.

For creating Running Sum Values in the Query Column, visit the following link:

Running Sum in MS-Access Query.

Next:

Autonumber with Date and Sequence Number.

Download


Download Demo QryAutoNum.zip



  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:

Multiple Parameters For Query

Multiple Parameters For Query.

Queries are an essential component of data processing, and we rely on them extensively in various ways. One of the main challenges when creating queries is how to filter data in a user-friendly manner, making the process seamless for the user. To address this, we employ several methods that allow users to easily pass values as criteria to the queries.

  1. You can create Parameter Queries by inserting variables, such as:[EnterSalesDate]', Into the Criteria row of a query. When run, the query will prompt the user to enter the parameter value, allowing them to filter records directly. To define the data type for a parameter variable, use the Parameters… option from the Query menu while in Design View.

  2. You can place TextBoxes or Combo Boxes on a Form, where the user can enter or select values before running a Report or viewing data. The underlying queries reference these controls in their Criteria rows—for example, Forms![MyForm]![myDateCombo]. Based on the values entered or selected, the queries filter the data accordingly, producing the desired results in Reports or data views.

  3. Another way to filter records is by specifying a range of values. For example, to retrieve Sales records for a particular period, the query criteria for the Sales Date might be : Between #01/01/2008# AND #03/31/2008# if constants are used. Alternatively, these values can be dynamically passed from TextBoxes on a Form, allowing the user to specify the date range interactively.

    In such cases, I prefer to create a small table—let’s call it a Parameter Table—with a single record and two fields: StartDate and EndDate. Then, I create a Datasheet Form for this table and embed it as a Sub-Form on the Main Form. This allows the user to conveniently enter the date range values directly into the table.

    This table is included in the main query, with the StartDate and EndDate fields placed in the Criteria row using the expression:

    Between [StartDate] AND [EndDate]

    It is important to note that the Parameter Table should contain only one record; otherwise, the main table’s results will be duplicated if the Parameter Table has multiple records. To prevent this, set the Allow Additions property of the Datasheet Form to No, so the user cannot inadvertently add more records.

    When the user clicks a button to generate the Report or other outputs based on this date range, the Parameter Sub-Form can be refreshed first to update the values in the table. After that, the query can be executed to reflect the latest StartDate and EndDate values.

  4. The above example retrieves all data between StartDate and EndDate. However, sometimes we need to filter specific, non-sequential values—for instance, Employee Codes 1, 5, 7, and 8. In such cases, we are forced to enter the codes manually in the Criteria row of the query, using one of several methods, as illustrated in the sample image below:

Query Parameter Input Methods.

I would like to share another method I use to let users select parameter values for reports—by simply checking boxes in a Parameter Table.

For example, assume that our company has several branch offices across the country, and management occasionally requests reports for selected branches. Since branch names remain constant, we can enable users to pick the required branches by placing check marks beside them. The check-marked entries can then serve as criteria for filtering data.

To illustrate this method more clearly (and to keep it simple), let’s use a list of months as an example. We will see how the selected months are used as criteria for the main query. The image below shows how this list of months appears to the user in a datasheet form, displayed as a subform on the main form.

We will need two queries for this process—one to filter the selected months from the list, and a second (the main query) that uses the results of the first query as parameters to filter data for the report.

The first query should return the values 3, 6, 9, and 12, based on the month selections shown in the image above. The following SQL statement can be used to achieve this result:

Query Name: Month_ParamQ

SELECT Month_Parameter.MTH
FROM Month_Parameter
WHERE (((Month_Parameter.[SELECT])=True));

When the user selects or deselects check marks on the parameter screen, these changes may not update in the underlying Month_Parameter table. To ensure the latest selections are reflected, we must refresh the Month_Parameter subform before opening the report that retrieves data from the main query (which uses the above query as its criteria).

To handle this, include the following statement in the On_Click() event procedure of the Print Preview command button:

Private Sub cmdPreview_Click()
     Me.Month_Parameter.Form.Refresh
     DoCmd.OpenReport "myNewReport", acViewPreview
End Sub

Now, how can the selected months filtered in the Month_ParamQ be used in the Main Query as a criterion? The third method we used earlier as a criterion in the first Image given above. I will repeat it below:

IN(1,5,7,8)

Here, we will compare the EmployeeID values with the numbers 1, 5, 7, 8, and select records that match any of these numbers as output.

Similarly, all we need to do here in the Main Query is to write this as a Sub_Query in the Criteria Row to use the Month Values from the Month_ParamQ. The above criteria clause, when written in the form of a sub-query, will look like the following:

IN(SELECT MTH FROM MONTH_PARAMQ)

The User doesn't have to type the Report Parameter values; they can select required items from a list, click a Button, and the Report is ready.

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