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

Showing posts with label msaccessprocess. Show all posts
Showing posts with label msaccessprocess. Show all posts

Indexing and Sorting with VBA

Indexing and Sorting with VBA.

A table is usually created with a Primary Key or an Index to organize its records in a specific order for viewing or processing. A Primary Key or Index can include one or more fields to ensure that each record has a unique key value, especially when a single field alone cannot guarantee uniqueness.

For example, if you open the Employees table in the Northwind.mdb sample database (located in *C:\Program Files\Microsoft Office\Office11\Samples*), and switch to Design View, you’ll see that the EmployeeID field is defined as the Primary Key.

To create an Index manually and define it as a Primary Key:

  1. Open the Table in Design View.

  2. Click on the left side of the Field Name to select it.

  3. Click on the Indexes Toolbar Button.

  4. You may give any suitable name in the Index Name Field, replacing the PrimaryKey text, if you would like to do so.

If the values in the selected field are not unique, you can include additional fields—up to a maximum of ten—to create a composite key that ensures uniqueness for the Primary Key.

To do this, click and drag over the adjoining fields to select them, or hold down the Ctrl key and click individual fields to select non-adjacent ones.

This process creates a Primary Key Index for the table. You can define multiple indexes in a table, but only one Primary Key can be active at any given time.

Creating an Index with VBA.

We can activate an existing index in a table or create a new one through VBA and use it for data processing.

In this exercise, we’ll learn how to:

  1. Create a new index named myIndex for a table through VBA.

  2. Activate the required index for data processing.

  3. Delete the index once processing is complete.

Before creating a new index, we’ll first check whether it myIndex already exists in the table’s Indexes collection.

  • If it exists, we’ll activate it.

  • If not, we’ll create it, activate it, and proceed with processing.

For this example, we’ll use the Orders and Order Details tables from the Northwind.mdb sample database. The Order Details table will be organized in Order-Number Sequence. The total value of all items for each order is calculated and updated in the corresponding record of the Orders table.

The Data Processing Steps

The following are the data processing steps, which we follow in the VBA Routine to update the Orders Table with order-wise Total Value from the Order Details Table:

  1. Open the Orders Table for Update Mode.

  2. Open the Order Details Table for Input.

  3. Check for the Index name myIndex in the Order Details Table. If found, then activate it; otherwise, create myIndex and activate it as the current Index.

  4. Initialize the Total to Zero.

  5. Read the first record from the Order Details Table.

  6. Calculate the Total Value of the item using the Expression: Quantity * ((1-Discount%)*UnitPrice).

  7. Add the Value to the Total.

  8. Read the next record and compare it with the earlier Order Number. If it is the same, then repeat steps 6 and 7 until the Order Number changes, or there are no more records to process in the Order Details Table.

  9. Find the record with the Order Number in the Orders Table.

  10. If found, then edit and update the Total to the TotalValue field in the Orders Table.

  11. Check for the End of File (EOF) condition of the Order Details Table.

  12. If False, then repeat the Process from Step 4 onwards; otherwise, Close files and stop running.

Prepare for a Trial Run.

  1. To try the above method, Import Orders and Order Details Tables from 'C:\Program Files\Microsoft Office\Office11\Samples\Northwind.mdb' (Access 2003) or 'C:\Users\User\My Documents\Northwind 2007.accdb' (Access 2007; if not available, then you must create from Local Templates)

  2. Open the Orders Table in Design View.

  3. Add a new Field named Total Value with a Numeric (Double) data Type in the Orders Table.

    You may display the Index List of this Table to view its Primary Key Index on the Order ID field.

  4. Save the Orders Table.

  5. Open the VBA Editing Window (Alt+F11).

  6. Create a new Standard Module from the Insert Menu.

  7. Copy and Paste the following VBA Routine and save the Module.

    The CreateIndex() Function.

    Public Function CreateIndex()
    Dim db As Database, fld As Field, tbldef As TableDef
    Dim idx As Index, rst As Recordset, PreviousOrderID As Long
    Dim CurrentOrderID As LongDim xQuantity As Long, xUnitPrice As Double
    Dim xDiscount As Double, Total As Double, rst2 As Recordset
    
    On Error Resume Next
    
    Set db = CurrentDb
    Set rst = db.OpenRecordset("Order Details", dbOpenTable)
    'Check for presence of myIndex, if found set as current
    rst.Index = "myIndex"
    If Err = 3800 Then
    'myIndex not found
        Err.Clear
        GoSub myNewIndex
    End If
    
    On Error GoTo CreateIndex_Err
    
    Set rst2 = db.OpenRecordset("Orders", dbOpenTable)
    rst2.Index = "PrimaryKey"
    PreviousOrderID = rst![Order ID]
    CurrentOrderID = PreviousOrderID
    Do Until rst.EOF
        Total = 0
        Do While CurrentOrderID = PreviousOrderID
            xQuantity = rst![quantity]
            xUnitPrice = rst![unit price]
            xDiscount = rst![discount]
    
            Total = Total + (xQuantity * ((1 - xDiscount) * xUnitPrice))
            rst.MoveNext
            PreviousOrderID = CurrentOrderID
            If Not rst.EOF Then
                CurrentOrderID = rst![Order ID]
            Else
                Exit Do
            End If
        Loop
        rst2.Seek "=", PreviousOrderID
        If Not rst2.NoMatch Then
            rst2.Edit
            rst2![totalvalue] = Total
            rst2.Update
        End If
        PreviousOrderID = CurrentOrderID
    Loop
    
    rst.Close
    rst2.Close
    
    'Delete temporary Index
    Set tbldef = db.TableDefs("Order details")
    tbldef.Indexes.Delete "myIndex"
    
    CreateIndex_Exit:
    Exit Function
    
    myNewIndex:
    rst.Close
    Set tbldef = db.TableDefs("Order Details")
    Set idx = tbldef.CreateIndex("myIndex")
    
    Set fld = tbldef.CreateField("Order ID", dbLong)
    idx.Fields.Append fld
    Set fld = tbldef.CreateField("Product ID", dbLong)
    idx.Fields.Append fld
    tbldef.Indexes.Append idx
    tbldef.Indexes.Refresh
    Set rst = db.OpenRecordset("Order Details", dbOpenTable)
    rst.Index = "myIndex"
    Return
    
    CreateIndex_Err:
    MsgBox Err.Description, , "CreateIndex()"
    Resume CreateIndex_Exit
    
    End Function
  8. Click somewhere in the middle of the VBA Routine and press F5 or click the Run Command Button to execute the Code and update the Orders Table.

At the beginning of the code, we attempt to activate one of the indexes (myIndex) in the Order Details table. Since myIndex has not yet been created, this action triggers an error. The error is trapped, and control is passed to a subroutine that creates myIndex and adds it to the table’s Indexes collection. The new index is then activated in preparation for data processing. 

The next steps calculate Order-wise Total Values and update them in the Orders Table.

At the end of the process, myIndex is deleted from the Indexes Collection of the Order Details Table.

Earlier Post Link References:

Share:

MS-Access And Data Processing-2

Continued from Last Week's Post.

This is the continuation of an earlier article published on this subject last week. Click here to visit that page.

Last week, we explored sample data processing methods and attempted to solve the same problem from different angles to arrive at the same result. Reports are the primary output delivered to the User, with critical information for analyzing business activities and making informed business decisions. Transforming raw data into a meaningful design as a Report is a real challenge for any Project.

If you attain some working knowledge of different types of Queries available in MS Access, you can do most of these tasks without touching the VBA Code. Depending upon the complexity of processing steps, you can use several Queries, create intermediate temporary Tables, and use those tables as the source for other Queries to overcome issues that may arise as hurdles in the processing steps.

We will examine this issue to help you understand the challenges involved in producing the final report. Complex data-processing tasks of this kind can be automated by arranging the individual steps in a macro and executing it from a command button or a VBA subroutine.

Process Flowcharts.

It is essential to create and maintain flowcharts for processes that involve multiple queries and tables, clearly showing the input and output at each step, to the final report data. Over time, you may build hundreds of queries in a database for different reports and forget how a particular one was structured. If a user later points out an error in the output, a well-documented flowchart helps you to easily trace each step and identify where the problem occurred.

Last week, I posed a question: how can we display Revenue, Expenses, and Profit/Loss on a month-by-month basis if the sample data includes separate Year and Month fields? The image below shows the sample source table (Transactions2).

The image of the Report Output Created and presented to you last week is shown below:

We can transform the sample data in the first image above into the Report output form in the second image in two steps. The numbers appearing as a Suffix to the Column headings represent the Month Value. For example, Revenue1 is January Revenue, and Profit/Loss2 is February.

We can arrive at the above result in two steps, and the SQL String of those two Queries is given below:

Query Name: Method2_1

TRANSFORM Sum(Transactions2.Amount) AS SumOfAmount
SELECT Transactions2.Location,
 Transactions2.Year
FROM Transactions2
GROUP BY Transactions2.Location,
 Transactions2.Year
PIVOT IIf([type]="R","Revenue","Expenses") & [Month];
  1. Copy and paste the above SQL String into the SQL Editing Window of a new Query and save it with the name Method2_1.
  2. Open the Query and view the output as it is transformed with the Cross-Tab Query.

    Query Name: Method2_2

    SELECT Method2_1.Location,
     Method2_1.Year,
     Method2_1.Revenue1,
     Method2_1.Expenses1,
     [Revenue1]-[Expenses1] AS [Profit/Loss1],
     Method2_1.Revenue2,
     Method2_1.Expenses2,
     [Revenue2]-[Expenses2] AS [Profit/Loss2]
    FROM Method2_1;
    
  3. Copy and paste the above SQL String into the SQL Editing Window of a new Query and save it with the name Method2_2.

    We are using the first Query as input to the second Query for the final Report output.

  4. Open the Method 2_2 Query and view the output.

Even though we can get the desired results with the two queries, the second query must be modified each time new monthly data records are added to include the new Profit/Loss column. Since the Profit & Loss Report is based on this query, it also needs to be updated to include the corresponding Revenue, Expenses, and Profit columns for the new period.

This approach is not ideal, especially when the goal is to automate all database processes so that users can produce reports with a single click.

We can automate this data processing task permanently with the following few simple steps:

  1. Create a second Report Table with Revenue and Expenses Fields for all twelve months.

  2. Change the second Query created above (Method2_2) to an append query and add the output data of available months into the Report Table.

  3. Create a SELECT Query, using the Report Table as the source, to calculate Profit/Loss Values for all twelve months, only once. This is possible because we have all twelve months' data fields in the Report Table, even if some of them will have only zero values till December.

  4. Design the P&L Report with all twelve months' Revenue, Expenses, and Profit/Loss Fields using the Query created in Step 3 as the source.

Once you implement this method, you don't have to make any changes to the Queries or Reports when new data records are added to the Source Table. All you have to do is automate this process, like deleting the old data (for this action, we will need a Delete Query) from the Report Table and bringing in fresh Report data from the source table Transactions2.

Designing a Report Table.

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

    The Data Fields R1 to R12 and E1 to E12 will hold Revenue and Expenses Values for the period from January to December, respectively.

    Note: Don't forget to set the Default Value Property of all Number Fields with 0 values as shown in the Property Sheet below the Field Structure. This will prevent adding data fields with Null Values when data is not available for those fields. Remember, when you write expressions using Numeric Fields with Null values combined with fields with values, the end result will be Null.

    We have modified the first Query above to simplify the data field names.

  2. Copy and paste the following SQL String into a new Query's SQL Editing Window and save it with the name Method3_1.
    TRANSFORM Sum(Transactions2.Amount) AS SumOfAmount
    SELECT Transactions2.Location,
     Transactions2.Year
    FROM Transactions2
    GROUP BY Transactions2.Location,
     Transactions2.Year
    PIVOT [type]&[Month];
    
  3. Copy and paste the SQL string given below into a new Query and save it with the name Method3_2.
    INSERT INTO PandLReportTable
    SELECT Method3_1.*
    FROM Method3_1;
  4. Copy and paste the following SQL String into a new Query and save it with the name PandLReportQ.
    SELECT PandLReportTable.Location,
     PandLReportTable.Year,
     PandLReportTable.R1,
     PandLReportTable.E1,
     [R1]-[E1] AS P1,
     PandLReportTable.R2,
     PandLReportTable.E2,
     [R2]-[E2] AS P2,
     PandLReportTable.R3,
     PandLReportTable.E3,
     [R3]-[E3] AS P3,
     PandLReportTable.R4,
     PandLReportTable.E4,
     [R4]-[E4] AS P4,
     PandLReportTable.R5,
     PandLReportTable.E5,
     [R5]-[E5] AS P5,
     PandLReportTable.R6,
     PandLReportTable.E6,
     [R6]-[E6] AS P6,
     PandLReportTable.R7,
     PandLReportTable.E7,
     [R7]-[E7] AS P7,
     PandLReportTable.R8,
     PandLReportTable.E8,
     [R8]-[E8] AS P8,
     PandLReportTable.R9,
     PandLReportTable.E9,
     [R9]-[E9] AS P9,
     PandLReportTable.R10,
     PandLReportTable.E10,
     [R10]-[E10] AS P10,
     PandLReportTable.R11,
     PandLReportTable.E11,
     [R11]-[E11] AS P11,
     PandLReportTable.R12,
     PandLReportTable.E12,
     [R12]-[E12] AS P12
    FROM PandLReportTable;
    
  5. Design a Report using PandLReportQ as the Source File, similar to the sample design image given below.

    The sample report currently displays columns for January and February only. However, you can easily extend the same design to include all twelve months. The value from the Year field is used to generate the report headings, ensuring the headings are automatically updated each year when the report is printed—without requiring any manual modifications to the report design.


    The Report in Print Preview.

    We will now automate the Report preparation process so that the Profit and Loss (P&L) Report reflects the updated data whenever new Revenue and Expense entries are added to the source table.

    As part of this automation, we’ll create a Delete Query to clear the existing data from the PandLReportTable before inserting the latest, revised records.

  6. Create a new Query with the following SQL String and name the Query as PandLReportTable_Init.
DELETE PandLReportTable.*
FROM PandLReportTable;

Isn't it easy enough to prepare the P & L Report with the above simple Queries and with a supporting Report Table for any number of Locations that you add to your main Source Table, Transactions2? As you can see now, you don't need any complicated programs to prepare this Report.

Action Queries in Macro.

If you look at the Queries we have created, you can see that only two are action queries among them (Delete and Append Queries). We can put these two Queries into a Macro to automate the P&L Report preparation procedure. But first, let us examine the logical arrangement of this Report preparation procedure with a Process Flow Chart.

In Step 1, the PandLReportTable_Init Delete Query clears all previously generated report data from the PandLReportTable.

In Step 3, the Append Query (Method3_2) takes the output from the CrossTab Query in Step 2 and appends it to the PandLReportTable.

We have already defined expressions in the PandLReportQ (SELECT Query) to calculate the Profit/Loss values. The report automatically retrieves all available data from this query, while other columns will remain blank until new records are added to the Transactions2 source table.

To streamline the process, both Action Queries can be combined into a Macro (or a VBA Subroutine) so the user can generate an updated P&L report each month simply by clicking a CommandButton — producing results within seconds.

The sample image of the Macro with the Action Queries in the sequence is given below for reference:


If you can further simplify this procedure, please share that idea with me, too.

Share:

MS-Access and Data Processing

MS Access and Data Processing.

Designing Forms and Reports in Microsoft Access can be learned quickly by experimenting with the available Design Tools. However, data processing presents an entirely different challenge, as it requires flexibility and varies from one project to another.

Table and Query designs are critical and must be carefully planned to ensure efficient information retrieval and prevent data duplication. Establishing appropriate relationships between tables is equally important for combining and processing related information from multiple tables.

If these principles are ignored — if you design casually and enter data as you might in Microsoft Excel — you’ll likely face serious difficulties when you try to prepare reports later.

A good example of proper database design and relationships can be found in the sample database:

C:\Program Files\Microsoft Office11\Samples\Northwind.mdb

Open the Northwind sample database and select Relationships from the Tools menu to view the structure of the various tables and how they are organized and related to one another. Use this as a reference and guide when planning your own projects.

Each field name shown in bold represents a Primary Key in its respective table. These keys establish one-to-many relationships between tables, ensuring that the required information can be accessed efficiently from related tables when generating reports.

The above notes are a reminder for your future projects. To illustrate the importance of proper table design, consider the sample image of a poorly structured table shown below. In that design, Location Names and Description values are directly entered in the same table — a mistake that leads to data duplication and maintenance difficulties.

Instead, each of these — Location and Description — should be maintained in separate lookup tables, each with its own unique code. You can then use Combo Boxes in the Transactions table structure and insert them in the fields, ensuring data consistency and eliminating redundancy, as demonstrated in the corrected design below.


Approaching the Data Processing Task.

In this exercise, we will explore and learn the data processing steps required to derive meaningful information from the table shown above.

The second field, Type, contains transaction category codes — R for Revenue and E for Expenses. These codes were intentionally included in the table design to allow us to group transactions by category and tabulate the Revenue and Expense values. The Description field lists the actual Account Heads under which each transaction is recorded.

Our task is to prepare a Location-wise Profit and Loss (P&L) Statement. To achieve this, we need to sum all Revenue values and subtract the total of all Expense values for each location. The final result should display the Profit or Loss amount alongside the corresponding Location Name, as shown in the sample report image below.

Now, here’s a question to consider:
How many queries or steps do you think are needed to produce this report?

Surprisingly, the entire process can be completed in just a few well-designed steps — ultimately yielding the final Profit/Loss summary by Location.

The first thought that comes to one's mind is: how can you subtract the value of one row from another? If that’s what you’re thinking, you’re already on the right track.

Now, let’s talk about the number of steps. If you say it takes four steps, I won’t consider that the best approach — but if it gets the correct result, that’s fine. After all, the end result is what really matters to the User.

If you can solve it in three steps, I’ll be curious to see your method. If you can do it in two steps, then you clearly have a solid grasp of MS Access techniques. And if you can do it in one step, then you are an MS Access expert.

If you’re truly interested in this challenge, here’s my suggestion:
Stop reading here, and try it out on your own database. Create the Transactions Table with the structure and sample data given above. Work through the problem, then compare your solution with the examples provided.

And if you solve it differently but still arrive at the correct result, please share your approach — it could give everyone a fresh perspective!

One-step solution

  1. Copy the following SQL String into the SQL Editing Window of a new Query and save it with a name you prefer.
    SELECT Transactions.Location,
     Sum(IIf([type]="E",-[Amount],[Amount])) AS Profit
    FROM Transactions
    GROUP BY Transactions.Location;
    
  2. Open the Query in Normal View, and you will see the result of the Query as shown in the second Image given above.

The Two-Step Solution.

  1. Create a Query with the following SQL String and name the Query as Query_Step1.
    SELECT Transactions.*,
     IIf([Type]="E",-[Amount],[Amount]) AS Amt
    FROM Transactions;
    

    The Query output will look like the image given below:

    Tip: The Query Amt Column is formatted to display Negative Values in Color and in brackets. Open the Query in Design View. Highlight the Column and click the Properties Toolbar Button or select Properties from the View Menu to display the Property Sheet of the Column. Type 0.00;[Red](0.00);0.00;0.00 into the Format Property and save the Query. If you open the Query now, the output will appear in color.

    The Format Property Values are expressed in four segments separated by semicolons. The first segment dictates how to display positive values, the second segment stands for Negative values, the third segment says what to display when the field value is zero, and the fourth segment displays zero when the Field/Column contains Null. The third and fourth segments can be set as a literal string,  0.00;[Red](0.00); "Zero"; "Null" to display these values rather than 0.00. You can set the Field Format Property values on the Table Structure, on Forms, or on Reports. You don't need to use all four segments of the Format Property Values all the time.

  2. Create another Query with the following SQL String, using Query_Step1 as Source Data, and save the Query with the name PL_Report:
    SELECT Query_Step1.Location,
     Sum(Query_Step1.Amt) AS Amount
    FROM Query_Step1
    GROUP BY Query_Step1.Location;
    
  3. Open the PL_Report Query in the normal view, and the result will be the same as the second image given above.

Three-Step Solution.

If you need more clarity on how the results are formed in the final report, then try this method.

  1. You can use the first Query under the two-step solution as the first step here.
  2. Use the following SQL String, which uses the first step Query's output as source data, and create the second step Query with the name Query_Step2:
    SELECT Query_Step1.Location,
     Query_Step1.Type,
     Sum(Query_Step1.Amt) AS Amt
    FROM Query_Step1
    GROUP BY Query_Step1.Location, Query_Step1.Type
    ORDER BY Query_Step1.Location, Sum(Query_Step1.Amt) DESC;
    

    The second Query result is given below.

  3. Create a third Query for the final result, with the SQL String given below, using the second step Query (Query_Step2) as Input:
SELECT Query_Step2.Location,
 "Profit/Loss" AS Description,
 Sum(Query_Step2.Amt) AS Amt
FROM Query_Step2
GROUP BY Query_Step2.Location;

The Query output is below with a three-column result, replacing the Type Column with Description.

Doing It Differently

How about doing it differently and arriving at the following Result with Queries in two Steps?

  1. Create the first Query Method2_1 with the following SQL String:
    TRANSFORM Sum(Transactions.Amount) AS SumOfAmount
    SELECT Transactions.Location
    FROM Transactions
    GROUP BY Transactions.Location
    PIVOT IIf([Type]="R","Revenue","Expenses");
    
  2. Create the Report Query Method2_2 with the following SQL String that uses Method2_1 as Source:
    SELECT Method2_1.Location,
     Method2_1.Revenue,
     Method2_1.Expenses,
     [Revenue]-[Expenses] AS [Profit/Loss]
    FROM Method2_1;
    
  3. Open the Method2_2 Query in Normal View and check the output carefully.

    As demonstrated in the examples above, there are often multiple ways to approach a problem in MS Access and still arrive at the same result.

    If your solution requires several steps to the final Report output, it’s good practice to create the process step flowchart. This way, if you later notice an issue with the Report, you can follow the flowchart to backtrack and identify the source of the error.

A sample Flow Chart of the Three-Step Solution is given below:

If the Transactions Table has Year and Month Fields and both locations have January and February 2009 data records, how can you create the Month-wise Report?

Try it out on your own, and check it out with my examples next week. A sample image of the output is given below for reference.

Share:

Seriality Control Finding Missing Numbers

Seriality control: Finding Missing Numbers.

In accounting and auditing, it is standard practice to maintain strict control over the usage of important documents such as checkbooks, receipt vouchers, payment vouchers, and local purchase orders. These documents usage is closely monitored to prevent misuse that could negatively impact the company’s operations or reputation.

These documents are usually printed in books containing 20, 50, or 100 sheets, each bearing sequential serial numbers. All transactions involving these documents are recorded along with their corresponding serial numbers.

Periodic audit checks verify that the serial numbers recorded in the system match the continuity of used documents in hand. Any missing numbers, whether due to cancellation, loss, or other reasons, are investigated and properly documented.

To illustrate this process, we’ll create a sample program that identifies and lists missing serial numbers from recorded transactions. For this, we’ll need the following tables containing the necessary information:

Preparing for Trial Run

  1. Parameter Table: with Start-Number and End-Number values. Uses this number range to find missing numbers by tagging the available transactions in the Table.

  2. Transaction Table: where the actual transaction details of the Documents are recorded, and our program should check and bring out the missing cases.

  3. Missing_List Table: where the missing list of Numbers will be created.

  4. Copy the following VBA Code and paste it into a new Global Module in your Database.

The VBA Code

Option Compare Database
Option Explicit

Type Rec
    lngNum As Long
    flag As Boolean
End Type

Public Function MissingNumbers()
'------------------------------------------------------
'Author : a.p.r. pillai
'Date   : 05/10/2008
'URL    : www.msaccesstips.com
'All Rights Reserved by www.msaccesstips.com
'------------------------------------------------------
Dim db As Database, rst1 As Recordset, rst2 As Recordset
Dim lngStart As Long, lngEnd As Long
Dim ChequeNo As Long, j As Long, ChqSeries() As Rec
Dim NumberOfChqs As Long, k As Integer, bank As String
Dim strSeries As String

On Error GoTo MissingNumbers_Err

'initialize the Report Table
DoCmd.SetWarnings False
DoCmd.RunSQL "DELETE Missing_List.* FROM Missing_List;"
DoCmd.SetWarnings True

Set db = CurrentDb
'Load Cheque Book Start and End Numbers
'from parameter table
Set rst1 = db.OpenRecordset("Parameter", dbOpenDynaset)
Do While Not rst1.EOF
    bank = rst1!bank
    lngStart = rst1!StartNumber
    lngEnd = rst1!EndNumber
' calculate number of cheques
    NumberOfChqs = lngEnd - lngStart + 1
    strSeries = "Range: " & lngStart & " To " & lngEnd

'redimention array to hold all the cheque Numbers
'between Start and End numbers
    ReDim ChqSeries(1 To NumberOfChqs) As Rec

'Generate All cheque Numbers between
'Start and End Numbers and load into Array
    k = 0
    For j = lngStart To lngEnd
        k = k + 1
        ChqSeries(k).lngNum = j
        ChqSeries(k).flag = False
    Next

'Open Cheque Payment Transaction Records
    Set rst2 = db.OpenRecordset("Transactions", dbOpenDynaset)

'Flag all matching cheque Numbers in Array
    k = 0
    rst2.MoveFirst
    Do While Not rst2.EOF
        ChequeNo = rst2![chqNo]
        If ChequeNo >= lngStart And ChequeNo <= lngEnd And rst2![bnkCode] = bank Then
            j = (ChequeNo - lngStart) + 1
            ChqSeries(j).flag = True
        End If
        rst2.MoveNext
    Loop
    rst2.Close

'create records for unmatched items in Report Table
    Set rst2 = db.OpenRecordset("Missing_List", dbOpenDynaset)
    k = 0
    For j = lngStart To lngEnd
        k = k + 1
        If ChqSeries(k).flag = False Then
            With rst2
                .AddNew
                !bnk = bank
                ![MISSING_NUMBER] = ChqSeries(k).lngNum
                ![REMARKS] = "** missing **"
                ![CHECKED_SERIES] = strSeries
                .Update
            End With
        End If
    Next
    rst2.Close

rst1.MoveNext
Loop
rst1.Close

Set rst1 = Nothing
Set rst2 = Nothing
Set db = Nothing

MissingNumbers_Exit:
Exit Function

MissingNumbers_Err:
MsgBox Err & " : " & Err.Description, , "MissingNumbers()"
Resume MissingNumbers_Exit
End Function

To try out the above program, create the first two tables with the same Field Names and data types as suggested by the sample data given above, and enter the same data or similar records of your choice, excluding some serial numbers from the range of values in the Parameter Table.

Create the third Table (Missing_List) with the same Field Names and data types as the sample records shown above, but without adding any records to it.

VBA Code Analysis

In the global area of the Module, we have created a User-Defined Data Type Rec with two elements, lngNum to hold the Serial Number and Flag to mark when a match is found in the Transaction Table, with Long Integer and Boolean data types, respectively. After creating the new data type in the Global area, we have declared an empty array variable ChqSeries() as Rec with the newly created data type within the Program.

The program opens the Parameter Table, starts with the first record, calculates the number of records within the given range, and re-dimensions the array to hold all the numbers between the lngStart and lngEnd parameter values.

In the next step, the program generates all the serial numbers between lngStart and lngEnd and fills the chqSeries().lngNum array. The Flag element value is set to False.

Next, open the Transaction Table and scan through it for matching Bank Code and for Cheque Numbers between lngStart and lngEnd, and when a match is found, the 'chqSeries().Flag' is marked as True for that entry within the array, and this process continues until the end of the file is reached.

In this process, if the 'chqSeries().Flag' is not marked as True, then the Serial Number corresponding to that entry is found missing in the Transaction Table. In the next step, scan through the Array elements and check for entries with 'chqSeries().Flag' = False, and write them out in the Missing_List.

Note: This method is not the most efficient method when handling a large volume of transactions. In such cases, it is advisable to filter the data in the Transaction table using a parameterized query and use the filtered dataset in place of the full Transaction table.

This needs extra steps in the program to create a Dynamic Query before the following statement: Set rst2 = db.OpenRecordset("Transactions", dbOpenDynaset), replacing Transactions with the Query name.

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