I know I'm over thinking this, but I want to check a single value/field within a single record. For instance, I want to know if the value of the "closedDate" field in the record with the primary key of 33 is null or not.
I was thinking something like:
dim db as DAO.Database
dim rs as DAO.Recordset
set db = CurrentDb
set rs = db.OpenRecordset("record_holdData")
If not isNull(rs.Fields("closedDate")) then
'do nothing
Else
'add a close date
End If
But I don't think this is right. It doesn't specify the record number. In the application, the form is opened by being bound to the record in question, but I don't think CurrentDb takes that into consideration and rather references the entire table.
So my question is, how do open the recordset in this fashion and reference this field in that particular record only?
You found the answer you wanted, but I would use the DLookup Function instead.
Dim db As DAO.Database
Dim strWhere As String
Dim varClosedDate As Variant
Set db = CurrentDb
strWhere = "id = 33"
varClosedDate = DLookup("closedDate","record_holdData",strWhere)
If IsNull(varClosedDate) = True Then
'use today's date as closedDate
db.Execute "UPDATE record_holdData Set closedDate = Date() WHERE " & strWhere
End If
I was under the impression that the argument for the .OpenRecordset() method was to be a table name only. But it turns out you can send it a query too:
set rs = db.OpenRecordset("select * from record_holdData where id = 33")
Related
How can I iterate a record set that returns a field of type field2?
Is there a way to tell how many objects are in the field2 type?
Let me describe the relevant aspects of my table:
The table fields has field NMR which contains a list of possible options a user can select in another table. In the Experiments table, the field NMR is a combobox with populates the options from the other table.
The way I do this is in the Experiments table design, I have set the field this way:
Now in one of my forms, I need to read the value in Experiments!NMR which can be a multiple selections allowed combobox. The recordset rs!NMR is of type Field2.
To get the values, you iterate using an integer (i.e. rs!NMR(0) would return the first selected option). The problem is I don't know how to get the field count and calling !NMR(i) where i is greater than the number of elements will invoke a Run time error '3265', Object doesn't exist in this collection.
Their exist a size method only returns the field width size (4?) and the documentation states this is the size of the data type within the field2 object.
There doesn't seem to be a count method associated with field2 as using !NMR.Count invokes runtime error 438, Object doesn't support this method.
Code:
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim qry As String
qry = "SELECT * FROM Experiments"
Set db = CurrentDb
Set rs = db.OpenRecordset(qry, dbOpenSnapshot)
With rs
Do While Not .EOF
Dim i As Integer
For i = 0 to !NMR.Count ' or SOMETHING - this is the problem
' this is irrelevant, I need to know how to iterate the list
Next i
.MoveNext
Loop
End With
rs.Close
db.Close
Set rs = Nothing
Set db = Nothing
I've also tried logic control such as
Do While(!NMR(i) <> vbNullString) since the individual components are strings, but no luck. This issues the same 3265: Item isn't found error. Same for a loop with this check Do While Not IsNull(!NMR(i))
Is there a way to tell how many objects are in the Field !NMR?
You need to assign the complex Field2 to a Recordset2 object and loop through it.
Sub Whatever()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim rsComplex As DAO.Recordset2
Dim qry As String
qry = "SELECT * FROM Experiments"
Set db = CurrentDb
Set rs = db.OpenRecordset(qry, dbOpenSnapshot)
Do While Not rs.EOF
Set rsComplex = rs("NMR").Value
rsComplex.MoveLast
rsComplex.MoveFirst
Dim i As Integer
For i = 0 To rsComplex.RecordCount - 1 ' Asker modified
Debug.Print rsComplex(0)
rsComplex.MoveNext
Next i
rsComplex.Close
Set rsComplex = Nothing
rs.MoveNext
Loop
rs.Close
db.Close
Set rs = Nothing
Set db = Nothing
End Sub
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
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.
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.
I have found how to loop through recordsets with the following link:
Code to loop through all records in MS Access
However, I want to know if it is possible if I can remove a record from the recordset if it doesn't meet criteria that I specify in the loop.
EDIT
I am now getting an error with the following code:
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("fieldHistory", dbOpenTable)
where fieldHistory is the name of the query recordset I want to open. Why am I getting this error? The last line of code there is the source of the error and Access simply states "Invalid operation"
Yes, you can use the DAO recordset's Delete method to delete the current record. This example will delete rows where the fname value is "xxx".
Public Sub DeleteRecordsetRow()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("tblDiscardMe", dbOpenTable)
Do While Not rs.EOF
If rs!fname = "xxx" Then
rs.Delete
'* the next line would trigger *'
'* error 3167: "Record is deleted." *'
''Debug.Print rs!fname
End If
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
Notice that immediately after rs.Delete (i.e. before MoveNext), the deleted row is still "current", but you can't access its values. You can uncomment the Debug.Print line to examine this further.
Edit:
Since your record source is a query rather than a table, try this to narrow down the reason you're getting an error with OpenRecordset.
Public Sub foo20110527a()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("fieldHistory")
If Not (rs.BOF And rs.EOF) Then
rs.MoveLast
MsgBox "RecordCount: " & rs.RecordCount
Else
MsgBox "No records"
End If
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
Since you used English (rather than English-like technical terms), your intent isn't very clear. You ask if you can "...remove a record...", which can mean either that you want to Delete it (in which case you already have a good answer form HansUp), or that you want to filter it out so that you don't see it, while leaving it in the underlying database.
If your intent is the latter (filtering), you have two choices:
Use a SQL statement with a WHERE clause in the original OpenRecordset call.
Use the Recordset's .Filter property before you enter the loop.
Access comes with adequate (if not stellar) Help on either topic.