Accessing all records in a field - ms-access

Just started using VBA and I'm trying to access all the data in a dummy table I set up called Employees.
This is the code im trying:
Sub getRecords()
Dim dbs As Database
Dim rst As Recordset
Dim sql As String
Set dbs = CurrentDb
sql = "SELECT * FROM Employees"
Set rst = dbs.OpenRecordset(sql)
End Sub
The ultimate aim here is to print the contents to the screen — would this involve breaking down the record set into different components? If so what components could make up a typical record set?
The table format is as follows:
Emp_Id - Number
Emp_Name - Text
Emp_Email - Text

You can iterate through the fields:
Sub getRecords()
Dim dbs As Database
Dim rst As Recordset
Dim sql As String
Set dbs = CurrentDb
sql = "SELECT * FROM Employees"
Set rst = dbs.OpenRecordset(sql)
Do while not rst.eof
For each fld in rst.Fields
Debug.Print fld, fld.name
Next
rst.MoveNext
''You can also edit or add
rst.Edit
rst!Emp_Name = "Something"
rst.UpDate
Loop
End Sub
I would avoid calling variables names that are also properties, such as SQL.
For updates, you are usually best to use an Action query and Execute againt a database object:
db.Execute "UPDATE aTable SET aField = 'Some text'", dbFailOnError

You'll need to start by looping through the records. Try:
Do While Not rst.EOF And Not rst.BOF
...
Loop
To do that. BOF and EOF relate to the beginning and end of the recordset respectively. If there's no data in the table then the whole loop will be skipped.
From there you can look at the fields individually by either using an index to relate to the position of the field in the select list, or by referring to the field name, like so:
Do While Not rst.EOF And Not rst.BOF
Debug.Print rst.Fields("myfield")
Debug.Print rst.Fields(0)
Loop
That's a starting point. Intelisense should really help you with this.
PS: always remember to close your recordset objects afterward to reclaim the memory:
rst.Close()
Set rst = Nothing
Kind regards,
Paul.

Related

access vba - grab the results in the code

I am working on an access application and I am trying to do the following:
the user insert input to a search, and then I search in my db, and I want to manipulate the results (generate an html file and put the results in there).
so I have a form with one input, there the user insert something he wants to search.
then it redirects to another form, with following on_load code:
Private sub form_load()
dim str as string
set frm = screen.activeForm 'gets the last form
str = frm!search 'the input the user entered
task = "SELECT * FROM results WHERE (condition)" 'some query with the db and the input
Me.recordSource = taks
end sub
this form gets the results and prints them.
now, I see the results on my form. but, what I want is: to get the results and manipulate them in the code, for example, make an array with all the results ids and not to print it to the user.
is that possible?
You should open a Recordset with your query, loop on it's results,and apply your logic within the loop.
For instance, you can call my sub below after your :
Me.recordSource = taks
For_Instance taks ' Call my sub and pass it your SQL instruction
And here's the sub in question that you purt in your form and containing your logic:
Private Sub For_Instance(strSQL As String)
Dim DB As dao.Database
Dim RST As dao.Recordset
Dim lngID As Long
Dim strMyField As String
Dim lngCount As Long
Dim i As Long
Set DB = CurrentDb
Set RST = DB.OpenRecordset(strSQL)
If RST.BOF Then Exit Sub ' no records found, stop.
' If you want to know how many record you have prior to loop, do:
RST.MoveLast
lngCount = RST.RecordCount
Debug.Print "There are " & lngCount & " to process."
' Let's loop on your recordset now...
' first, reposition on first record:
RST.MoveFirst
' Then start to loop
While Not RST.EOF
' This is where you do your stuff with the records
' You can grab the data that is in the current line of you recordset like this:
' RST!name_of_the_field
' name_of_the_field refers to your column names
' Suppose you have a column named ID with type long, to get the current ID, do:
lngID = RST!ID
' Suppose you have a column named MyField with type string
strMyField = RST!MyField
' and do whatever you want
' And finally you go to the next record and continue your stuff
RST.MoveNext
i = i + 1
Wend
' When you arrive here, you have processed all your records
MsgBox "All done, I have processed " & i & " records"
'Close your recordset
RST.Close
'Clean your objects
Set RST = Nothing
Set DB = Nothing
End Sub
Something like this will let you connect vba to your database and get the data out:
Sub vbaRecords()
Dim db As DAO.Database
Dim rst As DAO.Recordset
Dim SQLstr As String
Set db=CurrentDb
SQLstr = "SELECT * FROM results WHERE (condition)" ' You'll need to flesh this out to have the same condition as you've used previously.
Set rst = db.OpenRecordset(SQLstr)
' Then you can move around the recordset. Assuming you want to start at the beginning:
rst.MoveFirst
' Then you can access individual items
vbitem1 = rst!item1
' You can also loop through the different records, if there's more than 1 (your condition can narrow this down)
do until rst.EOF
' Grab items from each record in here and do something with them
rst.MoveNext
Loop
' Then close and end the connections
rst.Close
db.Close
Set rst = Nothing
Set db = Nothing
End sub
Just open a recordset using the same SQL:
SELECT * FROM results WHERE (condition)
and browse the records as needed.
Read up on the Recordset class. You can use it like this to get the results of the query into an object:
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("SELECT * FROM results WHERE (condition)", dbOpenDynaset, dbFailOnError + dbSeeChanges)
From there you can run through it, query and manipulate it as you like.

Advanced Filter Criteria in Access

The issue is simple but I just cant figure it out.
I have two tables in access, one with records and another with "key words". I need to filter the records containing certain "key words". In other words, use one table field as a filter criteria for the other, but without linking them because the "key words" table just contains random words instead of a whole record.
In excel I can run an advanced filter on my records and just specify as criteria the list of key words (and using wildcards), but in acces I havent found a way to filter according to another table fields.
Any ideas about it?
You may need to create a function that spits out custom SQL with all the keywords in it. Here is an example to get you started.
Public Function fGetTrashRecords()
'add your own error handling
Dim SQL As String
Dim rst As DAO.Recordset
Dim rstTrash As DAO.Recordset
Dim db As DAO.Database
Set db = CurrentDb
Set rst = db.OpenRecordset("SELECT sKeyWord FROM tblBadKeyWords", dbOpenSnapshot)
If Not rst Is Nothing Then
rst.MoveFirst
Do While Not rst.EOF
SQL = SQL & " strFieldContaingKeyWord LIKE *'" & rst!sKeyWord & "'* OR"
rst.MoveNext
Loop
If SQL > "" Then SQL = Left(SQL, Len(SQL) - 2) 'get rid of the last OR
rst.Close
Set rst = Nothing
End If
If SQL > "" Then
Set rstTrash = db.OpenRecordset("SELECT * FROM tblHasKeyWords WHERE " & SQL, dbOpenDynaset, dbSeeChanges)
If Not rstTrash Is Nothing Then
rstTrash.MoveFirst
Do While Not rstTrash.EOF
Debug.Print rstTrash!ID
rstTrash.MoveNext
Loop
rstTrash.Close
Set rstTrash = Nothing
End If
End If
Set db = Nothing
End Function

Rewrite field names in multiple tables - skipping over missing fields

I have an Access database with nearly 200 tables each with about 150 field. I need to change most of the field names and am writing some VBA code to programatically update the names to what I assign. The problem is that not all tables have exactly the same fields (some fields are missing from certain tables). Is there a way that I can write the change in the code, but just skip the change for a particular field if it doesn't exist in a particular table?
The basic code that I am using comes from this site: http://windowssecrets.com/forums/showthread.php/125845-Change-Field-name-in-Table-with-VBA
And here is my actual code. I'm brand new to VBA, so please be gentle.
Option Compare Database
Option Explicit
Public Sub changeFieldName()
Dim db As DAO.Database
Dim table As DAO.TableDef
Set db = CurrentDb
For
Set table = db.TableDefs("table")
table.Fields("Field1").Name = "name1"
table.Fields("Field2").Name = "name2"
if(IsNull(table.Fields("FieldDoesn'tExist").Name = "name")) Then End If
Set table = Nothing
Next
db.Close
Set db = Nothing
MsgBox "Changed"
End Sub
The "Then End If" statement doesn't work, but I don't know what to use here
Thanks for any help!
Paul
The way I'd approach it would be to put the old and new names into their own table named [NameMap]:
oldName newName
-------- --------
oldName1 newName1
oldName2 newName2
and then loop through that list to apply the name changes. The On Error Resume Next statement would allow the routine to continue if the table did not have a field whose name corresponded to one of the [oldName] values
Option Compare Database
Option Explicit
Public Sub changeFieldNames()
Dim cdb As DAO.Database, rst As DAO.Recordset, tbd As DAO.TableDef
Set cdb = CurrentDb
Set tbd = cdb.TableDefs("SampleTable")
Set rst = cdb.OpenRecordset("SELECT oldName, newName FROM NameMap", dbOpenSnapshot)
Do Until rst.EOF
On Error Resume Next
tbd.Fields(rst!oldName).Name = rst!newName
On Error GoTo 0
rst.MoveNext
Loop
rst.Close
Set rst = Nothing
Set tbd = Nothing
Set cdb = Nothing
End Sub

openrecordset only showing one result

When I use a recordset to read from a table everything works fine and the recordcount function shows me the correct amount, but when I use this simple query or any query I always get 1 as a recordcount.
Here's whats working
Option Compare Database
Option Explicit
Public Sub LoadQ2()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("test")'test is the name of my table which contains 13 rows
With rs
Debug.Print .RecordCount
.Close
End With
Set db = Nothing
Set rs = Nothing
End Sub
and here's whats not working
Option Compare Database
Option Explicit
Public Sub LoadQ2()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strSQL As String
strSQL = "SELECT test.number_id FROM test"
Set db = CurrentDb
Set rs = db.OpenRecordset(strSQL)
With rs
Debug.Print .RecordCount
.Close
End With
Set db = Nothing
Set rs = Nothing
End Sub
I should get the same result with both recordcount right?? Also I'd like to see the line I have in the recordset in the debug is it possible to print the content of the recordset in the debug window??
To print the contents of the recordset, you can do one of these two options..
debug.print rs.fields(0) & ", " & rs.fields(1)
or
debug.print rs("ColumnNameHere") & ", " & rs("AnotherColumnName")
.... found the answer
before doing the Debug.Print .RecourdCount i added .MoveLast and got the right number of recordcount
Looks like recordcount just means at what record that he is not how many records
Just to complement as you already found the answer yourself :)
The Dynaset data type (default for DAO recordset) doesn't fully populate until you go through all its records - since the need to do a .MoveLast before checking how many records it actually has.
I presume that DAO just returns 1 for the recordcount as an easy way to check beforehand if the recordset is empty or not (e.g. recordcount > 0) without having to go through the hassle of moving between records.

Code to loop through all records in MS Access

I need a code to loop through all the records in a table so I can extract some data. In addition to this, is it also possible to loop through filtered records and, again, extract data? Thanks!
You should be able to do this with a pretty standard DAO recordset loop. You can see some examples at the following links:
http://msdn.microsoft.com/en-us/library/bb243789%28v=office.12%29.aspx
http://www.granite.ab.ca/access/email/recordsetloop.htm
My own standard loop looks something like this:
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("SELECT * FROM Contacts")
'Check to see if the recordset actually contains rows
If Not (rs.EOF And rs.BOF) Then
rs.MoveFirst 'Unnecessary in this case, but still a good habit
Do Until rs.EOF = True
'Perform an edit
rs.Edit
rs!VendorYN = True
rs("VendorYN") = True 'The other way to refer to a field
rs.Update
'Save contact name into a variable
sContactName = rs!FirstName & " " & rs!LastName
'Move to the next record. Don't ever forget to do this.
rs.MoveNext
Loop
Else
MsgBox "There are no records in the recordset."
End If
MsgBox "Finished looping through records."
rs.Close 'Close the recordset
Set rs = Nothing 'Clean up
In "References", import DAO 3.6 object reference.
private sub showTableData
dim db as dao.database
dim rs as dao.recordset
set db = currentDb
set rs = db.OpenRecordSet("myTable") 'myTable is a MS-Access table created previously
'populate the table
rs.movelast
rs.movefirst
do while not rs.EOF
debug.print(rs!myField) 'myField is a field name in table myTable
rs.movenext 'press Ctrl+G to see debuG window beneath
loop
msgbox("End of Table")
end sub
You can interate data objects like queries and filtered tables in different ways:
Trhough query:
private sub showQueryData
dim db as dao.database
dim rs as dao.recordset
dim sqlStr as string
sqlStr = "SELECT * FROM customers as c WHERE c.country='Brazil'"
set db = currentDb
set rs = db.openRecordset(sqlStr)
rs.movefirst
do while not rs.EOF
debug.print("cust ID: " & rs!id & " cust name: " & rs!name)
rs.movenext
loop
msgbox("End of customers from Brazil")
end sub
You should also look for "Filter" property of the recordset object to filter only the desired records and then interact with them in the same way (see VB6 Help in MS-Access code window), or create a "QueryDef" object to run a query and use it as a recordset too (a little bit more tricky). Tell me if you want another aproach.
I hope I've helped.
Found a good code with comments explaining each statement.
Code found at - accessallinone
Sub DAOLooping()
On Error GoTo ErrorHandler
Dim strSQL As String
Dim rs As DAO.Recordset
strSQL = "tblTeachers"
'For the purposes of this post, we are simply going to make
'strSQL equal to tblTeachers.
'You could use a full SELECT statement such as:
'SELECT * FROM tblTeachers (this would produce the same result in fact).
'You could also add a Where clause to filter which records are returned:
'SELECT * FROM tblTeachers Where ZIPPostal = '98052'
' (this would return 5 records)
Set rs = CurrentDb.OpenRecordset(strSQL)
'This line of code instantiates the recordset object!!!
'In English, this means that we have opened up a recordset
'and can access its values using the rs variable.
With rs
If Not .BOF And Not .EOF Then
'We don’t know if the recordset has any records,
'so we use this line of code to check. If there are no records
'we won’t execute any code in the if..end if statement.
.MoveLast
.MoveFirst
'It is not necessary to move to the last record and then back
'to the first one but it is good practice to do so.
While (Not .EOF)
'With this code, we are using a while loop to loop
'through the records. If we reach the end of the recordset, .EOF
'will return true and we will exit the while loop.
Debug.Print rs.Fields("teacherID") & " " & rs.Fields("FirstName")
'prints info from fields to the immediate window
.MoveNext
'We need to ensure that we use .MoveNext,
'otherwise we will be stuck in a loop forever…
'(or at least until you press CTRL+Break)
Wend
End If
.close
'Make sure you close the recordset...
End With
ExitSub:
Set rs = Nothing
'..and set it to nothing
Exit Sub
ErrorHandler:
Resume ExitSub
End Sub
Recordsets have two important properties when looping through data, EOF (End-Of-File) and BOF (Beginning-Of-File). Recordsets are like tables and when you loop through one, you are literally moving from record to record in sequence. As you move through the records the EOF property is set to false but after you try and go past the last record, the EOF property becomes true. This works the same in reverse for the BOF property.
These properties let us know when we have reached the limits of a recordset.