Advanced Filter Criteria in Access - ms-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

Related

Microsoft Access 2010 interdependencies in Forms (fill out one cell, automatically fill another)

In excel, I know this is the VLOOKUP function, however, being a beginner at Access, I have no clue how to do this.
I have halls (from A to H), who all have their own teamleader (eg A-->Ben, B-->Michael, C-->Dave, etc). I would like to select just the hall, and the teamleader will automatically show up in the next field on the form. At the end, all will be registered in a table.
I have currently build this equation to fill out a specific value in a cell (dependent on the value of another cell), but it is giving an error message. What am I doing wrong?
Option Compare Database
Dim db As DAO.Database
Dim rst As DAO.Recordset
Private Sub Hal_AfterUpdate()
Set db = CurrentDb
'SELECT Voormannen.Voorman, Voormannen.Hal
'FROM Voormannen
'WHERE (((Voormannen.Hal)=[Formulieren]![DSM formulier]![Hal]));
strSQL = "SELECT Voormannen.Voorman, Voormannen.Hal FROM Voormannen WHERE [Voormannen]![Hal]=[Forms]![DSM formulier]![Hal]"
Set rst = db.OpenRecordset(strSQL)
rst.MoveFirst
Me.Tekst304 = rst![Voorman]
rst.Close
Set rst = Nothing
Me.Refresh
End Sub
Assuming your SQL string returns a correct dataset, try replacing this:
Me.Tekst304 = rst![Voorman]
with this:
Me.Tekst304.Text = rst("Voorman")
If your SQL string does not return a correct dataset, try changing it to this:
strSQL = "SELECT Voorman, Hal FROM Voormannen " & _
"WHERE Hal = '" & Forms![DSM formulier]!Hal.Text & "'"
You need to surround your control reference with ampersands (&) otherwise VBA doesn't know you're referencing a control.

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.

Accessing all records in a field

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.

Code To Loop Through and Edit Recordsets

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.

VBA - Accessing a collection of values

I have two access forms. frm_Main and frm_Sub which has data conditionally displayed depending on the selections of the main form. I need to write a select all function for items displayed in frm_Sub. In VBA is there a way that I can get a list of the id's currently being displayed in frm_Sub?
for example, if I do this
me.controls("Svc_Tag_Dim_Tag_Num").value
I get the value for one of rows in the frm_Sub, is there a way to get all of the values?
Maybe I can ask a different way. I have a form that is displayed as a listview, in VBA, is there a way to get all the values from a specific column?
Another option is to write a function that concatenates the PKs of the recordset that the subform displays. Say your main form is Company and your subform lists Employees. You'd have a LinkMasterFields and LinkChildFields properties of the subform control would be CompanyID (PK of the Company table, FK of the Employees table).
Thus, to get the same set of records as is displayed in the subform when the parent is on a particular Company record:
Dim db As DAO.Database
Dim strSQL As String
Dim rst As DAO.Recordset
Dim strEmployeeIDList As String
Set db = CurrentDB
strSQL = "SELECT Employees.* FROM Employees WHERE CompanyID="
strSQL = strSQL & Me!CompanyID & ";"
Set rs = db.OpenRecordset(strSQL)
If rs.RecordCount > 0 Then
With rs
.MoveFirst
Do Until .EOF
strEmployeeIDList = strEmployeeIDList & ", " & !CompanyID
.MoveNext
Loop
End With
strEmployeeIDList = Mid(strEmployeeIDList, 3)
End If
rs.Close
Set rs = Nothing
Set db = Nothing
Now, why would you do this instead of walking through an already-opened recordset (i.e., the subform's RecordsetClone)? I don't know -- it's just that there may be cases where you don't want your lookup to be tied to a particular form/subform. You could fix that by making your function that concatenates accept a recordset, and pass it a recordset declared as I did above, or pass it the subform's RecordsetClone. In that case, you could use the concatenation function either way, without being tied to the form/subform.
If I understand your question you should be able to access the ID value in the control using Column(x) where x indicates the control's row source column starting from 0. For example, if ID is in column 0 with width 0 in. it will be hidden from view but VBA can "see" it as me.controls.["Svc_Tag_Dim_Tag_Num"].column(0).
To get at the sub-form's record source directly from outside the form's class module you could create a function something like:
Public Function test_get_sub_form_record_set() As String
Dim dbs As Database
Dim rst As Recordset
Dim xcat As String
Set dbs = CurrentDb()
Set rst = [Forms]![Your Main Form Name]![Your Sub-form Name].[Form].RecordsetClone
If rst.RecordCount > 0 Then
rst.MoveFirst
xcat = rst!ID
rst.MoveNext
Do While Not rst.EOF
xcat = xcat & ", " & rst!ID
Loop
Else
xcat = ""
End If
test_get_sub_form_record_set = xcat
rst.Close
Set dbs = Nothing
End Function
This would be included in a separate module and when called would return a concatenated, comma separated list of ID's.