Record count in Access table using VBA - ms-access

I'm trying to get the record count of a table, and if count is greater than 17, create a new table.
Dim rst As DAO.Recordset
strSQL = "Select * from SKUS"
Set rst = db.OpenRecordset(strSQL)
If rst.RecordCount > 17 Then
Set tdf = db.CreateTableDef("161-0363")
Set fld = tdf.CreateField("SKUS", dbText, 30)
tdf.Fields.Append fld
Set fld = tdf.CreateField("Count", dbInteger)
tdf.Fields.Append fld
db.TableDefs.Append tdf
End If
This code doesn't create a new table, but when I change the if statement to this, it works:
...
If rst.RecordCount > 0 Then
Set tdf = db.CreateTableDef("161-0363")
...
So the RecordCount is returning 1, I think. Why is this happening? I know for sure the table has 18 rows in it.
Can anyone help me out?

You have to force the recordset to move through all the rows to get an accurate count. Try this:
...
Set rst = db.OpenRecordset(strSQL)
rst.MoveLast
If rst.RecordCount > 17 Then
...
Unless you are doing something else with the recordset that you're not showing in your snippet, you can simplify your code by just doing a check of the record count using the domain count function:
If DCount("*", "SKUS") > 17 Then
If you plan to loop through the recordset after doing the RecordCount check, make sure you move back to the first record before you start your loop:
rst.MoveFirst

The problem with strsql is that when the string represents a parameter query the above code does not work.
In this case I would use a meter in the code as simplified below:
rs.movelast
X = rs.recordcount
Rs.movefirst
Do until rs.eof
For i = 1 to X
If i<=17 then
Do things
Else
Do things
End if
Next i
Loop

You need to move through the recordset to get an accurate count of records in DAO. Since the recordset is only used to get a count of the records, you can just do rst.MoveLast and then the rst.RecordCount will be accurate.
Depending on the type of recordset being used (ex: forward only) the rst.MoveFirst line suggested by others above may not always work. If you're not touring through all the records individually, just do the .MoveLast without the .MoveFirst.
...
Set rst = db.OpenRecordset(strSQL)
rst.MoveLast
If rst.RecordCount > 17 Then
...

Related

VBA Do While Loop

Good Morning,
I am building a database that will be used for scheduling employee work assignments. Below is the code that I am using to create the actual daily work assignments. The intent is that this will loop through each employee in the company and if they are in a work status it will also read their assigned schedule version. Then if the employee is in a work status the db will list their work assignments for each day.
The issue that I am encountering is that this only reads the first employee in the table and gives every other employee the work assignments that the first employee should have. Again, the intent is that the code will look at each employees, one at a time, and append the correct assignments to tbl_employee_work_assignments based on each employees status and schedule version.
Can someone help me understand how to do this correctly, please?
Many Thanks!!!
Private Sub btn_build_assignment_schedule_Click()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("tbl_employees")
DoCmd.SetWarnings False
DoCmd.RunSQL "DELETE * FROM tbl_employee_work_assignments"
Do While Not rs.EOF
Dim X As String
Dim Y As String
X = employee_schedule_version.Value
Y = employee_status.Value
DoCmd.SetWarnings False
DoCmd.RunSQL "DELETE * FROM tbl_employee_work_assignments"
Select Case True
Case X = 1 And Y = 1
db.Execute "qry_append_schedule_1"
Case X = 2 And Y = 1
db.Execute "qry_append_schedule_2"
Case X = 3 And Y = 1
db.Execute "qry_append_schedule_3"
Case X = 4 And Y = 1
db.Execute "qry_append_schedule_4"
End Select
rs.MoveNext
Loop
rs.Close
End Sub
Based on the very limited information provided and making a few assumptions, I would hazard a guess that your code should be changed to something along the lines of the following:
Private Sub btn_build_assignment_schedule_Click()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("tbl_employees")
DoCmd.SetWarnings False
DoCmd.RunSQL "DELETE FROM tbl_employee_work_assignments"
With rs
Do Until .EOF
If !employee_status = "1" Then
Select Case !employee_schedule_version
Case "1": db.Execute "qry_append_schedule_1"
Case "2": db.Execute "qry_append_schedule_2"
Case "3": db.Execute "qry_append_schedule_3"
Case "4": db.Execute "qry_append_schedule_4"
End Select
End If
.MoveNext
Loop
.Close
End With
End Sub
This assumes that employee_status and employee_schedule_version are string-valued fields in your table tbl_employees.
Without knowing the structure of your table tbl_employees and the SQL behind your queries qry_append_schedule_1, qry_append_schedule_2, etc. it is difficult to advise.

Split Recordset Every 50 Records

I know how to use access VBA to get the total count of records in the recordset. Which is what I do below, but I am in need of taking my main rs and splitting the rs into sub-recordsets every 50 records. Meaning if rs.RecordCount = 200 - then I would want to create, rs1, rs2, rs3, rs4 and the recordCount of each should be 50.
How can I dynamically split a recordset into sub-recordsets as desecribed above? This is how I get the count in the primary recordset
Set rs = CurrentDb.OpenRecordset("Select firen, daja, globaltwo", dbOpenDynaset)
With rs
If Not .EOF And Not .BOF Then
.MoveLast
.MoveFirst
Do While Not .EOF
qty = rst.RecordCount
Debug.Print qty
Loop
End If
End With
rs.Close
Set rs = Nothing
You might want to see if the OLEDB provider supports paging. See this https://support.microsoft.com/en-us/help/202125/how-to-page-through-a-recordset-from-asp
The given link to an Access 97 database which suggest access does support this even though the code is an Active Server Page the PageSize property is still available to VBA clients.

Create queries based on information in a table

I have some knowledge of Access and VBA programming, but I stress some. I haven't really used Access since college.
I have a table called Location with 2 fields: Postcode and a Group Code. This list has 1,693,353 records.
I have another table called Group with 2 fields: Group Name and Group Code.
There are about 300 different Authority Records.
I need to make a table/query for each Group and have the different location postcodes in the tables.
I know that I could go through and make 300 different queries all with the Group code as the criteria and that would match them up, but that means making 300 different queries.
What I would like to know is if there is a way of automating this process. I'm not asking for people to create it for me (unless they want to) but if there are any guides or tutorials that people could recommend for learning Access VBA that would help as well.
This query will contain all your groups (I've named it SQL_Group)
SELECT GroupName, Postcode FROM [Group] INNER JOIN Location ON Group.GroupCode = Location.GroupCode will create your groups.
This code will cycle through each group:
Public Sub FilterQuery()
Dim qdf As DAO.QueryDef
Dim rst As DAO.Recordset
Dim rst_Groups As DAO.Recordset
Dim rst_Filtered As DAO.Recordset
Dim db As DAO.Database
Set db = CurrentDb
Set qdf = db.QueryDefs("SQL_Group")
Set rst = qdf.OpenRecordset
Set rst_Groups = db.OpenRecordset("Group")
With rst_Groups
If Not (.BOF And .EOF) Then
.MoveFirst
Do While Not .EOF
rst.Filter = "GroupName = '" & rst_Groups.Fields("GroupName") & "'"
Set rst_Filtered = rst.OpenRecordset
With rst_Filtered
If Not (.BOF And .EOF) Then
.MoveFirst
Do While Not .EOF
Debug.Print .Fields("GroupName") & " : " & .Fields("PostCode")
.MoveNext
Loop
End If
.Close
End With
.MoveNext
Loop
End If
.Close
End With
Set rst_Filtered = Nothing
Set rst = Nothing
Set rst_Groups = Nothing
End Sub

MS-Access RecordCount Returns a valid number, but .GetRows only pulls one record

Ok I am trying to dynamically get recordCount and pass that to .GetRows but it doesnt work as it only pulls in one records into the array. If I just statically put a number into the .GetRows method it works fine, but this is obviously not ideal.
This Works
Set rs = CurrentDb.OpenRecordset("SELECT * FROM Client", dbOpenDynaset, dbSeeChanges)
aRR = rs.GetRows("random number")
For i = 0 To rs.RecordCount - 1
For j = 0 To rs.Fields.Count - 1
Debug.Print ; aRR(j, i)
Next j
Next i
This does not
Set rs = CurrentDb.OpenRecordset("SELECT * FROM Client", dbOpenDynaset, dbSeeChanges)
With rs
rs.MoveLast
Debug.Print ; rs.RecordCount
Q = rs.RecordCount
aRR = rs.GetRows(Q)
End With
For i = 0 To rs.RecordCount - 1
For j = 0 To rs.Fields.Count - 1
Debug.Print ; aRR(j, i)
Next j
Next i
I have tried multiple things I have found on the web but clearly I must be missing something? Is there an easy approach to this or do i need to requery with a DISTINCT clase, and pass the return value within that record set to a new variable?
GetRows also uses the recordset's pointer. With rs.MoveLast you put that pointer to the last row. That's why only one row gets returned. Addrs.MoveFirst after setting Q to resolve this.
Like Phesago mentioned, Access will only return the recordcount based on which record in the recordset it's looking at. As a general practice when working with recordsets, I always begin with the following template:
Private Sub CreateRecordset()
Dim rs As Recordset
Dim sql As String
sql = "SELCT * FROM tblSomeTable"
Set rs = CurrentDb.OpenRecordset(sql, dbOpenDynaset, dbSeeChanges)
With rs
If Not .EOF And Not .BOF Then
.MoveLast
.MoveFirst
Dim i As Integer
For i = 0 To rs.RecordCount - 1
'do whatever actions desired
Next
End If
End With
End Sub

How to search a field in a table in Access

Using VBA, how can I search for a text string, for example "CHIR", in a table called "ServiceYES", in the field "Service".
After that, I would like to save the neighboring field for all the rows that "CHIR" exists in the table "ServicesYES". The "ServiceYES" table is below:
I basically, want to find all the "CHIR" in "Service" column and then save the names which are on the left of the CHIR, eg "FRANKL_L", "SANTIA_D" as an array.
Thanks for all your help in advance.
Start by creating a SELECT query.
SELECT Code_Perso
FROM ServicesYES
WHERE Service = 'CHIR';
Use SELECT DISTINCT Code_Perso if you want only the unique values.
Add ORDER BY Code_Perso if you care to have them sorted alphabetically.
Once you have a satisfactory query, open a DAO recordset based on that query, and loop through the Code_Perso values it returns.
You don't need to load them directly into your final array. It might be easier to add them to a comma-separated string. Afterward you can use the Split() function (assuming you have Access version >= 2000) to create your array.
Here's sample code to get you started. It's mostly standard boiler-plate, but it might actually work ... once you give it "yourquery".
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strItems As String
Dim varItems As Variant
Set db = CurrentDb
Set rs = db.OpenRecordset("yourquery", dbOpenSnapshot)
With rs
Do While Not .EOF
strItems = strItems & "," & !Code_Perso
.MoveNext
Loop
.Close
End With
If Len(strItems) > 0 Then
' discard leading comma '
strItems = Mid(strItems, 2)
varItems = Split(strItems, ",")
Else
MsgBox "Oops. No matching rows found."
End If
Set rs = Nothing
Set db = Nothing
I tested this and it seems to work. This function will pull all records where ServiceYes='CHIR' and dump the Code_Person value into an array which it will return:
Function x() As String()
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset( _
"Select * from ServiceYES where Service='CHIR'")
Dim Arr() As String
Dim i As Integer
While rst.EOF = False
ReDim Preserve Arr(i)
Arr(i) = rst.Fields("Code_Person")
i = i + 1
rst.MoveNext
Wend
x = Arr
End Function
Sample Usage:
Debug.Print x()(0)
Paolo,
Here is something I threw together in a few minutes. You can add it to the VBA editor in a module. It uses a trick to get the RecordCount property to behave properly. As for returing the array, you can update the function and create a calling routine. If you need that bit of code, just post a comment.
Thanks!
Option Compare Database
Function QueryServiceYES()
Dim db As Database
Dim saveItems() As String
Set db = CurrentDb
Dim rs As DAO.Recordset
Set rs = db.OpenRecordset("SELECT Code_Perso, Service, Favorites " & _
"FROM ServiceYES " & _
"WHERE Service = 'CHIR'")
'bug in recordset, MoveFirst, then MoveLast forces correct invalid "RecordCount"
rs.MoveLast
rs.MoveFirst
ReDim Preserve saveItems(rs.RecordCount) As String
For i = 0 To rs.RecordCount - 1
saveItems(i) = rs.Fields("Code_Perso")
rs.MoveNext
Next i
'print them out
For i = 0 To UBound(saveItems) - 1
Debug.Print saveItems(i)
Next i
rs.Close
Set rs = Nothing
db.Close
Set db = Nothing
End Function