Access 2007-2016
Access 2000-2003
Access Seminars
TechHelp Support
Tips & Tricks
Access Forum
Course Index
Topic Glossary
Insider Circle
Home   News   Tips   Glossary   Templates   Forums   Help   Logon   Order   Contact Us  
Courses - Microsoft Access 320
Description: Advanced Access Recordsets
Running Time: 93 minutes
Pre-Requisites: Access 313 very strongly recommended
Previous Lesson: Access 313
Next Lesson: Access 321
Main Topics: Recordsets, References, DAO, ADO, Loops, EOF, BOF, MoveNext, dbOpenRecordset, SQL
Versions: This course is valid for Access 2000 through 2003. If you are using Access 2007 or 2010, you will still benefit from this course. You will find that the concepts are the same, but there are cosmetic differences between the versions.


Order before 4/28/2019 to get a FREE upgrade to our Access 2010 version!
Click here for details


This series of classes (320-329) is all about Recordsets. Every class will focus on Recordset creation. Our goal is to add Inventory Control (Products In, Products Out, and Purchase Orders) to our PC Resale database that we've been building since Access 101. In today's class we're going to start with the basics of recordsets.

You will first learn what a Recordset is, how to create a Recordset, different uses for Recordsets. In a nutshell, a Recordset is a way to access the data and structure of a table or query from Visual Basic programming. Knowing how to work with Recordsets opens up a whole new world of possibilities for your database development.

You will learn about DAO, ADO, references, and the different object libraries.


You will learn how to create a Recordset object in VBA code to detemine information about your database.


You will learn how to create a Recordset to loop through all of the records in a table.


You'll learn about variables and their scope.


You'll learn how to create buttons to move around inside a Recordset manually with MoveNext and MovePrevious.


We'll learn how to use a Recordset and the FindFirst method to search for records inside of your table.


Access 320 - Course Outline

1. Recordset Basics
What is a Recordset?
Why use Recordsets?
Example Uses For Recordsets
Turn Off VBA Project Explorer
Tools > References
What is a Library?
Microsoft DAO 3.6 Object Library
Microsoft ActiveX Data Objects 2.1 Library
DAO vs. ADO, Brief Discussion

2. Our First Recordset
Create a Database Object
Create a Recordset Object
db.Name, rs.Name
Closing Our Objects
Freeing Memory (Set to Nothing)
Creating a Status Box
Display Field Data: FirstName
When to use ! vs .
Ways to Refer to Fields
rs![First Name]
Create Unbound Text Boxes
Store RS Data Into Text Boxes

3. Moving Around, Part 1
Move X
EOF End of File
BOF Beginning of File
Endless Loops
Create a Counter
Dim Variables Outside of Subs
Variable Scope
Opening Recordset With Form Opened
Closing Recordset When Form Closed

4. Moving Around, Part 2
Buttons to Move Around Recordset
Dealing with Hitting EOF/BOF
RecordCount Property

5. Finding Records, Part 1
Types of Recordsets

6. Finding Records, Part 2
Wildcard Search
Dynamic SQL For FindFirst
Do Loop



Student Interaction: Microsoft Access 320

Richard on 1/1/2008:  Recordset basics, creating a recordset, moving around in recordsets, finding records.
BRYAN binkerd on 7/1/2009: on lesson 02, first recordset time frame 0736, I understand the StatusText = S & vbnewline but I don't understand the "& StatusText" that follows the statement.
Richard Rost on 7/2/2009: Bryan, that's just to continue with whatever previous StatusText was there before. It's like saying:

X = A + X

It takes X, adds A to the beginning, and then whatever X was there before. It's so you can keep a long listing of continuous "status" information.

bryan binkerd on 7/3/2009: thanks for the clarification. You rock.
Richard Rost on 7/3/2009: Thanks, Bryan. I try. :)
Margaret Cattarin on 7/30/2009: Richard,
I have started a db for conducting a community survey. I am having difficulty bringing the responder information, questions, responses, etc. together for a tabulated summary report. Is this something that could be accomplished with Record Sets?

Thank You!

Richard Rost on 7/31/2009: Margaret, tell me more about what your report needs to look like. Have you tried a CROSSTAB query?
Margaret Cattarin on 7/31/2009: Richard,
I have a Response form for each of the households that return the survey. The main form has the name and information that I need to fill in, such as #of persons in household, combined income, #Over 65 and #Under 18.
The Sub form has information that I can pick from drop down boxes (gender, years at address, marital status, and comments.

This is the point where I am stuck. I would really like to generate two reports. The first would list all of the survey responses sorted by household.

The second needs to have the counts or sums of each response (count of male, count of female, sum of persons Over 65, Rate of Return, % Moderate Income, % Low Income, Average Income, etc.).

If you can get me to that point, I think that I will be able to set the detail section of the report as not visible and then put all of the calculations in the report footer.

I tried a crosstab query, but I don't know how to use this in a report.

Any help you can give me will be very much appreciated.

Richard Rost on 8/3/2009: Margaret, why not just GROUP the report based on each respondent, and then put the calculations in the footer of the group? You can use the =SUM(Field) or =COUNT(Field) functions in that footer to calculate your values.
Bert Jansen on 11/23/2009: Dear Richard,How can you make a report of the StatusText?
AC 320
Time index 12.43

Richard Rost on 11/25/2009: Bert, I don't understand your question. Can you please clarify? What do you mean by "report of the StatusText?"
Bert Jansen on 11/25/2009: Dear Richard, I mean if I want to print all the data in the statustext you've created like "Anne wilson 45",How can I do that?
AC320 Time index 12.43

Richard Rost on 12/13/2009: If you actually want to PRINT the statustext data, then I would recommend creating a status TABLE, binding that control (the big text box) to a field in your table, and then storing it that way. Then you can print it if you want by making a report based on it.
 Chris on 3/28/2010: AC320.2 TS 4:32 - I noticed that you create the object db and rs and then you destroy it (Clean it up) backward - i.e. set rs to nothing then the same with db. I assume by this that there is a particular order of creation and tidying. It this assumption correct?

Reply from Richard Rost:

This just goes back to my C/C++ programming days.

In C/C++ you have to remember to manually clean up any variable pointers and other objects yourself, and in the correct order, otherwise you end up with craziness in your programs. Things called NULL POINTERS (pointers to nothing) can wreck havoc in your programs.

Think of object variables like plastic containers. If you declare a variable to a database object, that's a big container. If you then declare a variable to a recordset, then that's a container INSIDE a bigger container. It's dependent on the database object to exist.

Well, if you destroy the database pointer first, then the recordset pointer really doesn't reference anything useful since it's parent is gone. It's a small container floating out in space with nothing holding on to it. :)

HOWEVER, none of this really matters in VB or VBA because Visual Basic is very good at cleaning up after you. The guys who created VB realized that most people using it aren't professional programmers, so they made it so the language cleans up most things like this for you... unlike in C/C++ where you have to do all of the housekeeping yourself... it's a trade-off for more power to control variables right down to their memory address.

Anyhow... to answer your question, it's good FORM to clean up dependent variables before their parents, but it's not 100% necessary in VB. In fact, by default, whenever you exit a sub or function, VB will clean up that memory for you... but don't get used to it. Try to remember to clean up your variables on your own. It's a good habit to be in if you do ever decide to move on to "grown up" programming languages. :)

Salvatori Costa on 5/15/2011: any idea why the rs.movenext doesn't work in Access 2010

Reply from Richard Rost:

It certainly should. Make sure you're using DAO and not ADO as your recordset type. Check your REFERENCES in the VBA editor.

 Dana Michaels on 11/27/2011: when I click Microsoft DAO 3.6 Object Library and try to save changes - I am presented with the error "Name conflicts with existing module, projet or object libarary.

Reply from Richard Rost:

Make sure you don't have any other DAO or ADO modules checked. If that still doesn't work, what version of Access are you working with?

Scott Adkins on 12/29/2011: This is a cool class. With this status log, I would like to use it to do error checking on a form. What I am looking for is null or -0 values. When it checks the text box and finds a null or 0, can it highlight that entry and ... hyperlink it to the field that needs fixing?
Alex Hedley on 12/30/2011: Hi Scott,
You could use an after update event on the text box and just use the check for null or 0 to change the background colour:
TEXTBOXNAME.BackColor = vbRed

What do you mean hyperlink to the control?
You can use a GoToControl command:


Scott Adkins on 2/26/2012: Richard, I just noticed this. When you copy a text box, and then paste it, the pasted box shows up where the mouse pointer is. When I paste it, it shows up on the upper right corner. Is there a way to fix this?
 JIm Gray on 3/2/2012: Richard,
How about using an If EOF exit sub statement? I used this way back when I learned FORTRAN...

Reply from Richard Rost:

You could do it that way too. In programming, there are always 3 ways to do everything. This is the way I like to do it. Post here how YOU would write it, so everyone else could see.

Kevin  O'Malley on 3/15/2012: I get a run time error 3077: Syntax error (missing operator) in expression whenever I try to use the Age feature (time: 8:05). When I debug it highlights "rs.FindNext MySQL". It only does this if I try to search by age using the combo box. Any idea what is going wrong?

Reply from Richard Rost:

Let me see your code building the SQL statement.

Kevin on 3/15/2012:
If Not IsNull(LastName) Then
If MySQL <> "" Then
MySQL = MySQL & " AND "
End If
MySQL = "LastName LIKE '*" & LastName & "*'"""
End If

If Not IsNull(Age) Then
If MySQL <> "" Then
MySQL = MySQL & " AND "
End If
MySQL = MySQL & "Age " & AgeEq & " " & Age
End If

Reply from Richard Rost:

I want to make you figure this one out on your own. It's one of those "so easy once you see it" moments that EVERYONE has. Get ready for a facepalm...

HINT: You're missing an equal sign.

Can you figure out where?

Kevin on 3/15/2012: For the life of me I do not see it. I have compared line for line to the video and I can't see where I am missing an = sign.

Also, when are you suppose to use a single quote vs. double quotes?

Reply from Richard Rost:

Kevin, repost your entire section of code again (the whole sub). I might have trimmed too much of it when I was answering your question before... and before I give you the WRONG answer, I want to make sure of something first. I was thinking you were missing an equals sign in the line:

MySQL = MySQL & "Age " & AgeEq & " " & Age

But I forgot that in that class I created a combo box with the different equality/inequality signs in it (=,<,>,etc.). So make sure that combo box is working correctly first. If that's not it, I need to see your code again.

Hey, it's been a few YEARS since that class came out. I can't remember every detail of every class. :)

Kevin on 3/16/2012: Here is the entire code:

Private Sub Command18_Click()

Dim db As Database
Dim rs As Recordset
Dim MySQL As String

Status "---------"

Set db = CurrentDb
Set rs = db.OpenRecordset("CustomerT", dbOpenDynaset)

MySQL = " "
If Not IsNull(FirstName) Then
MySQL = "FirstName LIKE '*" & FirstName & "*'"
End If

If Not IsNull(LastName) Then
If MySQL <> "" Then
MySQL = MySQL & " AND "
End If
MySQL = MySQL & "LastName LIKE '*" & LastName & "*'"
End If

If Not IsNull(Age) Then
If MySQL <> "" Then
MySQL = MySQL & " AND "
End If
MySQL = MySQL & "Age " & AgeEq & " " & Age
End If

If MySQL = "" Then Exit Sub

Counter = 0
rs.FindFirst MySQL

Do While rs.NoMatch = False
Status "FOUND: " & rs!FirstName & " " & rs!LastName & " " & rs!Age
Counter = Counter + 1
rs.FindNext MySQL

If Counter = 0 Then
Status "No Match Found"
End If

Set db = Nothing
Set rs = Nothing

End Sub

I even tried replacing the with:

MySQL = MySQL & "Age >= 20" & Age

but that didn't work either. I double checked that I created the combo box the same as the video. Does this have anything to do with the fact I am using 2010? Why does the debug feature highlight the "rs.FindFirst MySQL" line

Thanks Rick. I love all the courses and appreciate how fast you get back to me. Happy St. Pat's day!

Reply from Richard Rost:

Your SQL looks fine... except you wouldn't want to say:

MySQL = MySQL & "Age >= 20" & Age

This should be just:

MySQL = MySQL & "Age >= 20"

No need to add on Age to the end of that again. Can you send me your database? ZIP it up and email it to Remove any sensitive data.

Alex Hedley on 3/17/2012: Hi Kevin
Doing a little debugging is always useful
Debug.Print or update a label/textbox on a form making it equal to MySQL to see exactly what your string is made up of, could be missing a space or something or as rich says the dropdown values

 Sissoko on 3/20/2012: this may help others..
Dim Db As Database
Dim rs As Recordset
Dim Rs2 As Recordset
Dim SqlStr As QueryDef

Set Db = CurrentDb
Set SqlStr = Db.CreateQueryDef("", "SELECT ItemTTemp.* " & _
" FROM ItemTTemp " & _
" WHERE ItemTTemp.OPTION=" & 1 & ";")

Set rs = SqlStr.OpenRecordset

Set Rs2 = Db.OpenRecordset("itemt", dbOpenDynaset)
Do Until rs.EOF

Rs2!itemref = rs!itemref
Rs2!itemname = rs!itemname
Rs2!itemprice = rs!itemprice

Mikki Swanson on 12/5/2012: I'm using access 2010 as well and I'm showing the same error for
rs.FindNext MySQL
line. Why is that?

Thanks so much

Zachary Marsett on 6/10/2013: Richard,
For some reason my recordset is going to the last record I have saved in my table. As I change the last record in the table, sure enough that's what comes up in the FirstName box. I can't figure out how I'm messing up the syntax. Here's the code I have saved:
Private Sub Command0_Click()
Dim db As dao.Database
Dim rs As Recordset

Set db = CurrentDb
Set rs = db.OpenRecordset("ChildT")

While Not rs.EOF
FirstName = rs!FirstName


Set db = Nothing
Set rs = Nothing

Is there something wrong right in front of me that I'm not noticing?

Reply from Richard Rost:

If you don't specify a sort order in your recordset, you cannot be guaranteed that the records will be in any particular order. If you want to FORCE them to sort in order, you need to say something like:

Set rs = db.OpenRecordset("SELECT * FROM ChildT ORDER BY ChildID")

Mark Stute on 4/26/2014: Hi Richard, I have come across databases that use the term "Bookmark" in VB code. Do you cover the use of Bookmark in any of your lessons?

Reply from Richard Rost:

Not really. Perhaps in a future lesson.

Richard Lanoue on 6/22/2014: I upgraded my Access Computer and now work with access 2010....
It won't make me select MS DAO 3.6.
Do they have something that is equivalent?

Margarita Apostolova on 1/20/2015: To Kevin:
Kevin, first I got the same error message because I put quotes around the AgeEq control. Once you remove them, the problem was fixed. Please see below.

If Not IsNull(Age) Then
If MySQL <> "" Then
MySQL = MySQL & " AND "
End If
MySQL = MySQL & "Age" & " " & "AgeEq" & " " & Age

End If

Mohamed Salim on 8/2/2016: Hello Mr Richard. I've Been watching your lessons for 2 years now and i'am really doing great thanks to you. I'am facing a strange issue here. Everything works fine in my Database using rs, except that when I use rs.movenext it would move only one record. I really used your method exactly but it won't skip records like how it should do. Please help me out. Thanks

Reply from Alex Hedley:

So when you click the button again it doesn't keep moving to the next record and the next?

Mohamed Salim on 8/6/2016: Yea when i click the button again, it won't keep moving to the next record and the next. Note that i use Access 2016, and i saw many people who have Access 2010 + facing the same issue. Whereas the other methods like Add,delete,update are working just fine. Thank you for your concern and looking forward for a solution.

Reply from Alex Hedley:

You could try
DoCmd.GoToRecord , , acNext

Mohamed Salim on 8/6/2016: Mr Alex, actually my comment was a follow up with my first question, which was about the recordset Rs.movenext that it wont skip records and its only skip one record as a click the button. So i replied yes it wont skip records and i use Access 2016. So is there a way to fix this issue? I just want to skip record by record as a click a button. Thanks.

Reply from Alex Hedley:

I usually have a
If NOT rs.EOF Then rs.MoveFirst


Do While Not rst.EOF
'Work with your recordset

Mohamed Salim on 8/11/2016: Hello Computer Learning Zone family. I'am stuck. I have built a complete Recordset code except that when I want to Rs.Movenext, it won't keep going to the next record and the next record, and its only moves for one record then stop. How I can make it work to move to next record as I keep clicking next!However, The other methods works fine like Add,Eddit,Delete. Note that I have access 2016. Thank you.

Reply from Alex Hedley:

Linked question

Gioia Heiser on 2/10/2018: For access 2013, 2016 and Office 365 which version DAO library should we use?

Reply from Alex Hedley:

Which versions do you have available?

Gioia Heiser on 3/9/2018: I have only one: Microsoft DAO 3.6 Object Library however when I check the box to add it I get "Error in Loading DLL". I'm using Office 365 on a 64 bit Windows 10 Home Machine. The only other references I have loaded are: Visual Basic for Applications, Microsoft Access 16.0 Object Library and OLE Automation.

Reply from Alex Hedley:

"Error in loading DLL" error message when you run a Microsoft Access wizard in Access
MS Article

This may help, do at own risk.


You may want to read these articles from the 599CD News:


Visual Basicindex
Account Login
Online Theater
Lost Password
Free Upgrades
Insider Circle
Student Databases
Change Email
Latest News
New Releases
User Forums
Topic Glossary
Tips & Tricks
Search Our Site
Waiting List
Production Schedule
Collapse Menus
Live Chat
Customer Support
WalkThru Tutorials
Consulting Services
About Us
Affiliate Program
Richard Rost
Free Lessons
Mailing List
Video Tutorials
MYOLP Memberships
Idiot's Guide to Excel
Volume Discounts
Payment Info
Terms of Sale
Gift CDs
Live Chat
General Info
Support Policy
Contact Form
Email Us
Mailing Address
Phone Number
Fax Number
Course Survey
Facebook    Twitter

Google Plus    LinkedIn

Blog RSS Feed    YouTube Channel
Richard Rost Microsoft MVP