Export nested tables to new back end - vba

I have an Access back end database with 7 nested, related tables: Clients, Projects, Project Goals, Goal Impediments, Impediment Causes, Possible Solutions and Required Actions or Resources. Each client may have multiple Projects. Each Project may have multiple records in Goals to Actions.
I want to export one Client Project with its nested tables into an empty back end with exactly the same structure, so the Client, supplied with front and back end, can review the information and make changes. If the client has made changes, I want to import the changes back into the master database, replacing the existing data.
Clients has the usual personal information. Projects has eight fields including a linked ID to Clients. Each Table from Goals to Actions has an Auto numbered primary key, an ID field linked to the primary key of table above, a 100 character short description, a long field for Notes, a number for priority or weighted importance and a Yes/No field for Resolved or Completed. Each may have between 1 and 10 records. There are 94 records in the sample record set I am working with.
It is easy enough to extract the Project and its related data from the database with a query; but I am having trouble coming up with the most efficient way to insert it into the empty back end. I started a few subroutines under an Export button to transfer the data table by table, so I could handle the changed relationships caused by the renumbered the primary keys; but I would like to do the entire process in one fell swoop, if possible. I created a huge back end file with one flawed attempt at a While NOT rsSource.EOF – Wend routine. Any suggestions gratefully received.
******************************** Code **********************************
Private Sub Command316_Click()
' SelectedClient and SelectedProject are Public Integer variables
' To be used in For...Next loops
Dim i, iNumRecs, intGoal, intImped, intCause, intSolution, intAction As Integer
Dim SQLstr As String
'Open source database
Dim dbSource As Database
Set dbSource = CurrentDb
'Open dest database
Dim dbDestination As Database
Set dbDestination = DAO.OpenDatabase("C:\Prosolve\Temp\Prosolve_BE.accdb")
' Select Project to be transferred
' Might be easier to work with if everything NOT selected at once
SQLstr = "SELECT Clients.ClientID, Clients.ContactFirstName, Clients.ContactLastName, Clients.Address, Clients.City, Clients.StateOrProvince, Clients.PostalCode, "
SQLstr = SQLstr + "Clients.Country, Clients.EmailAddress, Clients.CompanyName, Clients.PhoneNumber, Clients.CellNumber, Clients.BillingRate, Clients.TaxPayable, Clients.Discount, "
SQLstr = SQLstr + "Projects.ProjectID, Projects.ClientID, Projects.ProjectName, Projects.ProjectOwner, Projects.ProjectDescription, Projects.EmployeeID, Projects.Priority, Projects.TotalBilled, "
SQLstr = SQLstr + "Goals.GoalID, Goals.ProjectID, Goals.Goal, Goals.Notes, Goals.Owners, Goals.Gpriority, "
SQLstr = SQLstr + "Impediments.ImpedID, Impediments.IgoalID, Impediments.Impediment, Impediments.Notes, Impediments.Iweight, Impediments.Resolved, "
SQLstr = SQLstr + "Causes.CauseID, Causes.cimpedID, Causes.cause, Causes.Notes, Causes.cweight, Causes.resolved, "
SQLstr = SQLstr + "Solutions.SolutionID, Solutions.ScauseID, Solutions.Solution, Solutions.Notes, Solutions.Sweight, Solutions.Implemented, "
SQLstr = SQLstr + "Actions.ActionID, Actions.AsolutionID, Actions.Action, Actions.Notes, Actions.Priority, Actions.Completed "
SQLstr = SQLstr + "FROM ((Clients INNER JOIN Projects ON Clients.ClientID = Projects.ClientID) "
SQLstr = SQLstr + "INNER JOIN ((Goals INNER JOIN Impediments ON Goals.GoalID = Impediments.IgoalID) "
SQLstr = SQLstr + "INNER JOIN (Causes INNER JOIN Solutions ON Causes.causeID = Solutions.ScauseID) "
SQLstr = SQLstr + "ON Impediments.ImpedID = Causes.cimpedID) ON Projects.ProjectID = Goals.ProjectID) "
SQLstr = SQLstr + "INNER JOIN Actions ON Solutions.SolutionID = Actions.AsolutionID "
SQLstr = SQLstr + "WHERE Clients.ClientID = " & SelectedClient & " AND Projects.ProjectID = " & SelectedProject & " ;"
'Open source recordset
Dim rsSource As Recordset
Set rsSource = dbSource.OpenRecordset(SQLstr, dbOpenDynaset)
'Open dest recordset
Dim rsDestination As Recordset
Set rsDestination = dbDestination.OpenRecordset("Clients", dbOpenDynaset)
'Loop through source recordset
'While Not rsSource.EOF
'Look for record in dest recordset
rsDestination.FindFirst "ContactFirstName = '" & rsSource.Fields("ContactFirstName") & "'"
'& " AND ContactLastName = " & rsSource.Fields("ContactLastName") & ""
'If not found, copy record
'Works okay
If rsDestination.NoMatch Then
rsDestination.AddNew
rsDestination.Fields("ContactFirstName") = rsSource.Fields("ContactFirstName")
rsDestination.Fields("ContactLastName") = rsSource.Fields("ContactLastName")
rsDestination.Fields("Address") = rsSource.Fields("Address")
rsDestination.Fields("City") = rsSource.Fields("City")
rsDestination.Fields("StateOrProvince") = rsSource.Fields("StateOrProvince")
rsDestination.Fields("PostalCode") = rsSource.Fields("PostalCode")
rsDestination.Fields("Country") = rsSource.Fields("Country")
rsDestination.Fields("EmailAddress") = rsSource.Fields("EmailAddress")
rsDestination.Fields("CompanyName") = rsSource.Fields("CompanyName")
rsDestination.Fields("PhoneNumber") = rsSource.Fields("PhoneNumber")
rsDestination.Fields("CellNumber") = rsSource.Fields("CellNumber")
rsDestination.Fields("BillingRate") = rsSource.Fields("BillingRate")
rsDestination.Fields("TaxPayable") = rsSource.Fields("TaxPayable")
rsDestination.Fields("Discount") = rsSource.Fields("Discount")
rsDestination.Update
Else
MsgBox "Record alreasy exists"
End If
'Works okay
Set rsDestination = dbDestination.OpenRecordset("Projects", dbOpenDynaset)
rsDestination.FindFirst "ClientID = 1"
If rsDestination.NoMatch Then
rsDestination.AddNew
rsDestination.Fields("ClientID") = 1
rsDestination.Fields("ProjectName") = rsSource.Fields("ProjectName")
rsDestination.Fields("ProjectOwner") = rsSource.Fields("ProjectOwner")
rsDestination.Fields("ProjectDescription") = rsSource.Fields("ProjectDescription")
rsDestination.Fields("EmployeeID") = rsSource.Fields("EmployeeID")
rsDestination.Fields("Priority") = rsSource.Fields("Projects.Priority")
rsDestination.Fields("TotalBilled") = rsSource.Fields("TotalBilled")
rsDestination.Update
Else
MsgBox "Record alreasy exists"
End If
' Try to find number of Goals for a For ... Next procedure
' Not counting Goals in Query. Will cause problems later when 2 or more client have same ProjectID
iNumRecs = DCount("ProjectID", "Goals", "ProjectID = " & SelectedProject & "")
'Here we need to copy all goals for projectID = 1 from 1 to number of goals'
' Once this is done successfully the process can be repeated for tables below it
'Loop through source recordset
'Currently copies 6 x first goal. rsSource.Movenext not working.
Set rsDestination = dbDestination.OpenRecordset("Goals", dbOpenDynaset)
rsDestination.FindFirst "ProjectID = " & SelectedProject & ""
If rsDestination.NoMatch Then
For i = 1 To iNumRecs
rsDestination.AddNew
rsDestination.Fields("ProjectID") = SelectedProject
rsDestination.Fields("Goal") = rsSource.Fields("Goal")
rsDestination.Fields("Notes") = rsSource.Fields("Goals.Notes")
rsDestination.Fields("Owners") = rsSource.Fields("Owners")
rsDestination.Fields("Gpriority") = rsSource.Fields("Gpriority")
rsDestination.Update
rsSource.MoveNext
Next
Else
MsgBox "Record alreasy exists"
End If
MsgBox "Procedure successfully completed to this point"
End Sub
******************************** End Code **********************************

You are constructing a giant source recordset with a join of all tables. So this recordset will have a large number of records (94 in your example), but the various tables you are exporting have less records.
This works when you know you only have to insert a single record into the target recordset (Clients, Projects), but it won't work if there is a variable number of records.
With Goals, you limit their number with the DCount and the For loop, but you simply get the first 6 records of the giant source. Because of the joins, this will usually be 6 times the same goal.
You should create a separate source recordset for all tables, each with a WHERE clause on client/project. Then you can copy all records from source to destination.
A much easier method would be:
Run INSERT statements for all tables directly into the target DB.
INSERT INTO [Goals] IN 'C:\Prosolve\Temp\Prosolve_BE.accdb'
SELECT *
FROM Goals
WHERE Goals.ProjectID = 1;
Note that this works also for AutoNumber columns.
And note that the hard part is still ahead of you: importing the changed data won't be so easy. How hard depends on whether the client can only change existing data, or can also add/delete records.

Related

Run time error: 3021 No current record found in multiple table recordset loop

I have a form that is filled with questions for different equipment. The user selects the equipment type then answers the questions for each category of tools. Each tool category is a table. Please see picture for example.
I am attempting my to add a new record into each table using a autonumber from the LineKey table as my ID, my primary keys. However I am getting a:
3021 error `No current record found'
when I am looping through each table adding the new record. If I run the code it errors out in the first loop at rec.Edit. If I walk through the code with breaks it goes through the first table loop but then errors out at rec.Edit for the second table. I am not sure what I am missing here.
CODE:
Private Sub btnUpDatabase_Click()
Dim i As Integer, j As Integer, e As Integer, ID As Integer
Dim db As Database
Dim rec As Recordset
Dim Value As String
Set db = CurrentDb
'Create Record ID "Key" in lineKey table
Set rec = db.OpenRecordset("SELECT * FROM LineKeys")
rec.AddNew
rec("Line") = Me.txtLine.Value
rec("Part Number") = Me.txtPartNumber.Value
rec("Equipment") = Me.cmbEquip.Value
rec.Update
Set rec = CurrentDb.OpenRecordset("Select ##Identity")
ID = rec(0)
Set rec = Nothing
Select Case cmbEquip.Value
Case "OP10 Lathe"
Dim strArray(0 To 6) As String
strArray(0) = "Tool Holders"
strArray(1) = "Chuck Jaws"
strArray(2) = "Jaw Grippers"
strArray(3) = "Drawbars"
strArray(4) = "Actuators"
strArray(5) = "Chatter Pin"
strArray(6) = "Chatter Pin Spring"
j = 0
For e = 0 To 6
Set rec = db.OpenRecordset("SELECT * FROM [" & strArray(e) & "]")
rec.AddNew
rec.Fields("ID") = ID
For i = 1 To 7
rec.Edit
rec.Fields("A" & i & "") = Me.Controls("cmb" & j & i & "").Value
rec.Update
Next
j = j + 1
Set rec = Nothing
Next
End Select
Set rec = Nothing
Set db = Nothing
End Sub
Possibly, you are conflating the .AddNew and .Edit processes where the first was not fully closed and hence record locked.
Consider replacing the .Edit and move the .Update outside the nested For loop. So you are updating an entire row in one call and not individual columns iteratively in a loop. Also you can simplify your outer array looping:
For each e In Array("Tool Holders", "Chuck Jaws", "Jaw Grippers", "Drawbars", _
"Actuators", "Chatter Pin", "Chatter Pin Spring")
Set rec = db.OpenRecordset("SELECT * FROM [" & e & "]")
rec.AddNew
rec.Fields("ID") = ID
For i = 1 To 7
rec.Fields("A" & i & "") = Me.Controls("cmb" & j & i & "").Value
Next i
rec.Update
j = j + 1
Set rec = Nothing
Next e
Once again, I advise not storing separate, similarly-structured tables by different values of a typology such as tool categories. Incorporate all into one Tool table without many (if any) looping. In this way, you do not change your schema for new categories and storage is more efficient as many rows are inexpensive compared to many tables.

Repeated number when sequencing a list of subform items VBA code issue in Access 2010

I am new to VBA code so I may have not taken the most practical of approaches on the following situation. I have Items that is a subform to Purchase_Orders. One of the fields in Items is PO_Line_item. This has to be a sequence of numbers (from 1) where PO_ID is the same. If several items have the same PO_ID have then I need this sequence. I cannot use the Item_ID as they may not always be added in succession.
here's the code I used:
Private Sub Form_BeforeUpdate(Cancel As Integer)
Dim db As Database
Dim rs As DAO.Recordset
Dim currentItem As String
Dim seq As Long
Dim sql As String
sql = "SELECT * " & _
"FROM Items " & _
"WHERE PO_ID = " & Me.Parent.PO_ID
Set db = CurrentDb
Set rs = db.OpenRecordset(sql, dbOpenDynaset)
rs.MoveFirst
currentItem = ""
With rs
Do While Not .EOF
If currentItem = "" Then
seq = 1
currentItem = seq
Else
seq = currentItem + 1
currentItem = seq
End If
Me.PO_Line_Item = seq
.MoveNext
Loop
End With
Set rs = Nothing
Set db = Nothing
End Sub
This works great if I stay on the record, I get items 1 then 2 then 3. however if I return the form and input another item record then I get a repeat of the last PO_Line_Item. i.e. 1,2,3,(return to form)3,4.
If anyone knows why this is happening, or if there is an alternative method that I can use that will work as well; then ideas are welcome. Thanks in advance.
You don't need a recordset loop to find the number of elements - use SQL COUNT() instead.
sql = "SELECT COUNT(*) " & _
"FROM Items " & _
"WHERE PO_ID = " & Me.Parent.PO_ID
Or even shorter with the Access DCount function:
' Number of existing records (may be 0)
seq = DCount("Item_ID", "Items", "PO_ID = " & Me.Parent.PO_ID)
' assign the next number
Me.PO_Line_Item = seq + 1

MS Access - Execute SQL statement receives error

I get an error:
"Object doesn't support this property or method"
...when I try to run this code:
Dim db As DAO.Database
Dim mySQL As String
Set db = currentdb
mySQL = "SELECT tbl1.pID, tbl1.sID, tbl1.Type, tbl1.Description, tbl1.Amount, tbl1.Delete, tbl1.Approve, tbl2.sName FROM tbl2 INNER JOIN tbl1 ON tbl2.sID = tbl1.sID WHERE pID = " & Forms.frmEdit1.cboP & " And Delete = False;"
db.Execute mySQL, dbFailOnError
Set db = Nothing
It seems like the error is somewhere in the last line (that's where it fails when I use the immediate window) I also tried the single quotes around 'False'.
EDIT: Recordsource that worked
SELECT tbl1.[pID],
tbl1.[sID],
[tbl1].Type,
[tbl1].Description,
[tbl1].Amount,
[tbl1].Delete,
tbl1.Approve,
tbl2.sName
FROM tbl2 INNER JOIN tbl1 ON tbl2.sID = tbl1.sID
WHERE pID = Forms![frmEdit1].cboP
And [Delete] = False;
Logically, sending a SELECT statement to Execute is saying, 'select values according to this criteria but don't let me know the results', which doesn't make much sense. Populating an unbound subform needs to be done manually - that's what makes it 'unbound':
Sub LoadByID(Optional ByVal ID)
Dim RS As DAO.Recordset, SQL As String
If IsMissing(ID) Then ID = Forms!frmEdit1.cboP
SQL = " SELECT tbl1.sID, tbl1.Type, tbl1.Description, " + _
" tbl1.Amount, tbl1.Delete, tbl1.Approve, tbl2.sName " + _
" FROM tbl2 INNER JOIN tbl1 ON tbl2.sID = tbl1.sID " + _
" WHERE pID = " & ID & " And [Delete] = False;"
Set RS = CurrentDb.OpenRecordset(SQL)
' Assuming no match is an error; if it isn't, rewrite accordingly
If RS.EOF Then Err.Raise 999, "LoadByID", "Er, no selection..."
txtID.Value = RS!ID
txtDescription.Value = RS!Description
' and so on...
End Sub
I've allowed specifying the ID not through the combo box to make the method easier to test. Also, note that if the form is supposed to allow editing, then you will need more code to then save any changed values.
Edit
The above was assuming only one return record. If more than one, loop like this:
Sub LoadByID(Optional ByVal ID)
Dim RS As DAO.Recordset, SQL As String
If IsMissing(ID) Then ID = Forms!frmEdit1.cboP
SQL = " SELECT tbl1.sID, tbl1.Type, tbl1.Description, " + _
" tbl1.Amount, tbl1.Delete, tbl1.Approve, tbl2.sName " + _
" FROM tbl2 INNER JOIN tbl1 ON tbl2.sID = tbl1.sID " + _
" WHERE pID = " & ID & " And [Delete] = False;"
Set RS = CurrentDb.OpenRecordset(SQL)
' add code to clear current display here...
While Not RS.EOF
' add code to load the individual values here...
RS.MoveNext
Wend
End Sub

When inserting data from a query to a table, does the query run for each record inserted?

I'm inserting data problematically into tables. When I do this from another table, it's swift, only slowed very slightly if there are a lot of records. Even then, it's a matter of seconds.
When I insert from a query to a table, it goes into minutes - roughly a minute for every 1,000 records inserted.
The source query itself, when just run as a select query, takes maybe 1 - 2 seconds. Is the query running for every record that's inserted? I'd hoped that it would run once for the whole data set. Or is there something else that's causing the function to run so slowly when compared to inserting "flat" data from another table.
The VBA I'm using is fairly innocuous:
CurrentDb.Execute "SELECT [Extra Value Concatenation].* _
INTO [" & strTableName & "] FROM [Extra Value Concatenation];"
and the source query is below - it uses Allen Browne's Concatenate function.
SELECT [Extra Fields - Fee Protection Insurance Concatenate].ContactID,
ConcatRelated('[Fee Protection Insurance]',
'[Extra Fields - Fee Protection Insurance Concatenate]',
'ContactID = ' & [ContactID])
AS [Fee Protection Insurance]
FROM [Extra Fields - Fee Protection Insurance Concatenate];
EDIT: In answer to Fionnuala's comment, but I couldn't format it properly in the comments.
Using fictional data, here's roughly what I want.
T1 contains client records.
ContactID Name
1 Example Limited
2 Another Company Limited
T2 contains extra fields. ContactID is there as a foreign key, and may be duplicated if multiple records are held.
ContactID FieldValue
1 Value 1
1 Value 2
2 Value 3
2 Value 4
2 Value 5
When I left join the tables, the duplicates from T2 show up, so I get
ContactID Name FieldValue
1 Example Limited Value 1
1 Example Limited Value 2
2 Another Company Limited Value 3
2 Another Company Limited Value 4
2 Another Company Limited Value 5
when what I want is
ContactID Name FieldValue
1 Example Limited Value 1; Value 2
2 Another Company Limited Value 3; Value 4; Value 5
Hence concatenating the data in a temporary table seemed like a good idea, but is slowing everything down. Is there another way I should be looking at my query?
I have written a pretty basic module that should accomplish this for you very quickly compared to your current process. Note you will need to re-name your project to something other than "Database" on the project navigation pane for this to work
I have assumed that table1 and table2 are the same as you have above
table3 is simply a list of all records in table 1 with a blank "FieldValues" field to add
the required "value1, value2" etc. This should result in Table3 being populated with your desired result
IMPORANT: For anyone using recordset .edit and .update functions make sure you remove record level locking in the access options menu, it can be found under the "client settings" section of Access options, failing to do so will cause extreme bloating of your file as access will not drop record locks until you compact and repair the database. This may cause your database to become un-recoverable once it hits the 2gb limit for windows.
Function addValueField()
'Declarations
Dim db As Database
Dim rs1 As DAO.Recordset
Dim rs2 As DAO.Recordset
Dim qry As String
Dim value As String
Dim recordcount as Long
Set db = CurrentDb()
'Open a select query that is a join of table 1 and table 2
'I have made Contact ID a foreign key in the second table
qry = "SELECT Table1.[Contact ID], Table1.Name, Table2.FieldValue FROM Table1 INNER JOIN Table2 ON Table1.[Contact ID] = Table2.[Contact ID(FK)] ORDER BY [Contact ID];"
Set rs1 = db.OpenRecordset(qry, dbOpenDynaset)
'Table 3 was filled with each record from table1, with a 3rd "Field Value" field to
'be filled with your Value 1, Value 2 etc.
qry = "SELECT * FROM Table3 ORDER BY [Contact ID]"
Set rs2 = db.OpenRecordset(qry, dbOpenDynaset)
'Ensure you have enough file locks to process records
recordcount = rs1.recordcount
DAO.DBEngine.SetOption DAO.dbMaxLocksPerFile, recordcount + 1000
rs1.MoveFirst
rs2.MoveFirst
'Here we test to see if "Name" is the same in both recordsets, if it is, add the FieldValue
'to the FieldValue in Table3, otherwise move to the next record in table 3 and compare again
Do While Not rs1.EOF
If IsNull(rs2![FieldValue]) = True Then
If rs2![FieldValue] = "" Then
rs2.Edit
rs2![FieldValue] = rs1![FieldValue]
rs2.Update
rs1.MoveNext
Else
rs2.Edit
rs2![FieldValue] = rs2![FieldValue] & "; " & rs1![FieldValue]
rs2.Update
rs1.MoveNext
End If
Else
rs2.MoveNext
End If
Loop
rs1.close
rs2.close
db.close
set db = nothing
set rs1 = nothing
set rs2 = nothing
End Function
You are using a user defined function (UDF) ConcatRelated, so the UDF runs for each record, otherwise, usually Access SQL works in the normal way.
Building on pegicity's answer, my eventual code was:
Option Compare Database
Sub Concatenate(strTableToConcatenate As String, strFieldToConcatenate As String, strIDField As String)
Dim rsSource As DAO.Recordset
Dim rsDestination As DAO.Recordset
Dim qry As String
Dim strSourceTable As String
Dim i As Integer
Dim strFieldName As String
Dim strValue As String
Dim intConcatenateID As Integer
Dim intSortID As Integer
strSourceTable = strTableToConcatenate & " (Concatenate)" 'Creates a duplicate copy of the table to be concatenated and empties the original table'
DeleteTable (strSourceTable)
DoCmd.CopyObject , strSourceTable, acTable, strTableToConcatenate
qry = "DELETE FROM [" & strTableToConcatenate & "]"
CurrentDb.Execute (qry)
qry = "ALTER TABLE [" & strTableToConcatenate & "] ALTER COLUMN [" & strFieldToConcatenate & "] memo" 'Changes the DataType of the field to be concatenated to Memo, as the result may be considerably longer than the original data'
CurrentDb.Execute (qry)
i = 0
intCurrentID = 0
qry = "SELECT * FROM [" & strSourceTable & "] ORDER BY [" & strIDField & "], [" & strFieldToConcatenate & "]"
Set rsSource = CurrentDb.OpenRecordset(qry, dbOpenDynaset)
qry = "SELECT * FROM [" & strTableToConcatenate & "]"
Set rsDestination = CurrentDb.OpenRecordset(qry, dbOpenDynaset)
For Each fld In rsSource.Fields 'Finds the column number of the fields you are sorting by and concatenating from your source table.'
strFieldName = rsSource.Fields(i).Name
If strFieldName = strFieldToConcatenate Then
intConcatenateID = i
ElseIf strFieldName = strIDField Then
intSortID = i
End If
i = i + 1
Next
If rsSource.recordcount <> 0 Then
rsSource.MoveFirst
intCurrentID = rsSource.Fields(intSortID).Value
strConcatenateValue = ""
While Not rsSource.EOF 'The source recordset is sorted by your designated sort field, so any duplicates of that field will be next to each other. If the row below has the same id as the row above, the sub continues to build the concatenated value. If the row changes, it adds the concatenated value to the destination record set.'
If intCurrentID = rsSource.Fields(intSortID).Value Then
strConcatenateValue = strConcatenateValue & "," & rsSource.Fields(intConcatenateID).Value
rsSource.MoveNext
Else
rsDestination.AddNew
i = 0
If Len(strConcatenateValue) > 0 Then
strConcatenateValue = Right(strConcatenateValue, Len(strConcatenateValue) - 1)
End If
For Each fld In rsSource.Fields
strFieldName = rsSource.Fields(i).Name
If strFieldName = strFieldToConcatenate Then
strValue = strConcatenateValue
ElseIf strFieldName = strIDField Then
strValue = intCurrentID
Else
strValue = rsSource.Fields(i).Value
End If
rsDestination.Fields(strFieldName) = "" & strValue & ""
i = i + 1
Next
rsDestination.Update
intCurrentID = rsSource.Fields(intSortID).Value
strConcatenateValue = ""
End If
Wend
End If
rsSource.Close
rsDestination.Close
Set rsSource = Nothing
Set rsDestination = Nothing
End Sub

VBA Access SQL SELECT Query only returning one record

I'm working with VBA in Access 2010 and I have an odd problem. I'm trying to pull records from a table, but my SELECT query is only returning a single record.
There are three records in the table, but the recordset is only getting the first one.
Here's my code.
Dim cc As String
Dim DB As Database
Dim rst As recordset
Dim sqlstr As String
Dim e As Integer
cc = CmbClass.Text
If cc = "" Then Exit Sub
sqlstr = "SELECT * FROM Students" 'WHERE CCode ='" & cc & "'"
Set DB = CurrentDb
Set rst = DB.OpenRecordset(sqlstr)
'Debug.Print rst.Fields(0)
e = rst.RecordCount
Debug.Print e
If e = 0 Then Exit Sub
The value of e is continually 1, not 3. As you can see I originally had a more complex SQL string, but I've cut it down to the most basic while trying to troubleshoot, yet the problem persists. Does anyone know why this is happening?
Thanks,
Tam.
From memory you need to issue a rst.MoveLast before you can reliably get the record count like this:
sqlstr = "SELECT * FROM Students" 'WHERE CCode ='" & cc & "'"
Set DB = CurrentDb
Set rst = DB.OpenRecordset(sqlstr)
rst.MoveLast
e = rst.RecordCount
Also you might want to consider using SELECT COUNT(*) FROM Students and reading the value from the recordset instead of moving through the records to get the count. Using this query should be more efficient.
Another method is DCount.
e = DCount("*","Students","CCode ='" & cc & "'")
no playing around with recordsets until you really need to