SELECT Queries in Access VBA - ms-access

I have an Access database consisting of two tables, Individuals & Pairs. Individuals consists two columns; 'Bird_ID' and 'Parents_Pair_number' and Pairs consists of three columns; 'Pair', 'Female_ID' and 'Male_ID'. 'Parents_Pair_number' and 'Pair' have a Many-to-one relationship. Via this relation one can check the parents of an individual.
But now I was thinking of making automatized family trees using a form. My plan was to make a field (Bird_ID_Field) in which you can find a certain individual and that other fields such as Father, Mother, Fathers father etc. etc. would auto-fill based on that entry.
I tried to auto-fill the Father_ID (Field) using the following VBA code:
Dim strSQL As String
Dim strBird_ID As String
If Bird_ID_Field <> "" Then
strBird_ID = Bird_ID_Field
strSQL = "SELECT Pairs.[Male_ID] " & _
"FROM Pairs " & _
"WHERE PAIR = (SELECT Individuals.[Parents_Pair_number] FROM Individuals WHERE Individuals.[Bird_ID]= '" & strBird_ID & "');"
DoCmd.OpenQuery strSQL
Father_ID = strSQL
End If
But after updating the Bird_ID_Field I get the following error: Microsoft Access can't find the object ''.
Do you have any idea what's wrong?
Thanks in forward!
Jeroen

You should use recordsets:
Dim rst As Recordset
Dim strSQL As String
If Nz(Bird_ID_Field,"") <> "" Then
strBird_ID = Nz(Bird_ID_Field, "")
strSQL = "SELECT Pairs.[Male_ID] " & _
"FROM Pairs " & _
"WHERE PAIR = (SELECT Individuals.[Parents_Pair_number] FROM Individuals WHERE Individuals.[Bird_ID]= '" & strBird_ID & "');"
Set rst = CurrentDb.OpenRecordset(strSQL)
If rst.RecordCount > 0 Then
Father_ID = rst![Male_ID]
End If
End If
rst.Close
Set rst = Nothing
And also I would recommend to use JOIN for tables joining instead of subquery.

Related

How to get bigdata from one table and insert into another in VBA?

I have table with columns like key,English Phrase and that phrase with other 40 languages.See in following image :
I want to break the records of these table by it's language column like following image:
I did this using the following code:
Sub InsertIntoMasterPhrases()
Dim objRecordsetMaster As ADODB.Recordset
Set objRecordsetMaster = New ADODB.Recordset
Dim objRecordset As ADODB.Recordset
Set objRecordset = New ADODB.Recordset
objRecordsetMaster.ActiveConnection = CurrentProject.Connection
objRecordset.ActiveConnection = CurrentProject.Connection
objRecordsetMaster.Open ("SELECT [Master Table].* FROM [Master Table];")
While objRecordsetMaster.EOF = False
objRecordset.Open ("Select [SAP_LANGUAGE to LANG].[LANGUAGE NAME], [SAP_LANGUAGE to LANG].[LANGUAGE] " & _
"From [SAP_LANGUAGE to LANG]")
While objRecordset.EOF = False
key = objRecordsetMaster.Fields("Key").Value
englishPhrase = objRecordsetMaster.Fields("English Phrase").Value
language = objRecordset.Fields("LANGUAGE").Value
translation = objRecordsetMaster.Fields(languageName).Value
If (GetRecordsExist(CStr(key), CStr(englishPhrase), CStr(language)) = "") Then
Query = "INSERT INTO [Language Sample](Key,English,Translation,Language)VALUES ('" & key & "','" & englishPhrase & "','" & translation & "','" & language & "');"
CurrentDb.Execute Query
End If
objRecordset.MoveNext
Wend
objRecordset.Close
objRecordsetMaster.MoveNext
Wend
objRecordsetMaster.Close
End Sub
//Checking records already exist in table
Function GetRecordsExist(key As String, english As String, language As String) As String
Dim db As Database
Dim Lrs As DAO.Recordset
Dim LGST As String
Set db = CurrentDb()
Set Lrs = db.OpenRecordset("SELECT KEY FROM [Language Sample] where KEY='" & key & "' and English='" & english & "' and Language = '" & language & "'")
If Lrs.EOF = False Then
LGST = "Found"
Else
LGST = ""
End If
Lrs.Close
Set Lrs = Nothing
GetRecordsExist = LGST
End Function
In the Master table i have 15000 records and when its breaking 15000 records it becomes 15000 * 40 = 600000. above code inserting almost 10000 records per minutes and after few hour it' hangs up . But also it don't produce any error then i have to restart the access. Kindly help how can i do it in better way.
Alternative 1:
Use a large UNION query to append many records with one SQL statement, as described here:
How to simulate UNPIVOT in Access 2010?
You will probably want to split it into several chunks (e.g. 5 or 10 languages at a time), or Access might choke on the query.
Alternative 2:
Instead of running INSERT statements for each record, use a DAO recordset with .AddNew. This is faster by magnitudes, see this answer:
https://stackoverflow.com/a/33025620/3820271

VB6, MS Access, DAO - Display all records WHERE column-name IS NOT NULL

I need a bit of help with this, so what I am trying to do is to display all records WHERE column-name IS NOT NULL. What I have is:
Dim rs As Recordset
Dim sqlStr As String
Set WS = DBEngine.Workspaces(0)
DbFile = (App.Path & "\mydb.mdb")
strSql = "SELECT * FROM MyDatabaseName"
Set rs = db.OpenRecordset(strSql)
rs.MoveFirst
Do While Not rs.EOF
lblResult.Caption = ("cust Name: " & rs!SurName & " cust Surname: " & rs!FirstName)
rs.MoveNext
Loop
MsgBox ("End ")
What I have tried is
strSql = "SELECT * FROM MyDatabaseName WHERE column-name IS NOT NULL"
But I get an error 3131. Any help is appreciated. Also how can I display the result in a ListBox insted of Label.
Simple fix: enclose column names in square brackets when using special characters, like the - substraction operator:
strSql = "SELECT * FROM MyDatabaseName WHERE [column-name] IS NOT NULL"
The rest of your SQL seems valid.
If you want a list box with the results of this query as the list, just set its row source equal to this query, and set its row source type equal to Table/Query. No need for any VBA.
If you want to put everything in a label, use:
Do While Not rs.EOF
lblResult.Caption = lblResult.Caption & "cust Name: " & rs!SurName & " cust Surname: " & rs!FirstName & VbCrLf
rs.MoveNext
Loop

How to locate data source for unbound control?

I've inherited some Access VBA code and there are controls on a form (such as a listbox named lstOrderID, mentioned below) which have no RowSource property set (an empty string). I look in the code and find statements like this in various places:
Forms!frm_Customer.lstOrderID = rstCust!OrderID ' set from a record set
Forms!frm_Customer.lstOrderID.Requery
Me.lstOrderID = Me.lstOrderID.ItemData(0) ' set to first item in self
But nowhere in the code is lstOrderID.RowSource being set.
How can Requery be called on a listbox that has no RowSource?
How can a listbox be set to a single value (rstCust!OrderID) from a record set, unless this is a list of values (although the debugger shows an integer in lstOrderID.Value)?
Here is more code:
Dim rstCust As Recordset
Set db = CurrentDb
Set rstCust = db.OpenRecordset("SELECT * FROM Orders WHERE CustID=" & ID & _
"AND Datetaken =Date() " & _
"AND VendorID='" & Forms!frm_Customer.cboVendorID & "'")
Forms!frm_Customer.lstOrderID = rstCust!OrderID
rstCust.Close
db.Close
Another section:
Dim rstCust As Recordset
Dim blStatus As Boolean
Dim strSql As String
Set db = CurrentDb
strSql = "SELECT Orders.OrderID " & _
"FROM Orders " & _
"WHERE (((Orders.DateTaken)=#" & Date & "#) " & _
"AND ((Orders.VendorID)='" & Forms!frm_Customer.cboVendorID & "') " & _
"AND ((Orders.CustID)=" & ID & "));"
Set rstCust = db.OpenRecordset(strSql)
Forms!frm_Customer.lstOrderID = rstCust!OrderID
Forms!frm_Customer.lstOrderID.Requery
Forms!frm_Customer.lstOrderID = rstCust!OrderID
rstCust.Close
db.Close
Also this:
Me.lstOrderID.Requery
Me.lstOrderID = Me.lstOrderID.ItemData(0)

Display multiple specific records in a report

Let's say I have a single table called "Customers". It contains 2 fields:
Name
Address
I want users to be able to select multiple records by selecting their names. For example something like having a list box containing all the names of the records in the database. I want users to be able to select multiple items like:
Dave Richardson
Bob Smith
Sophie Parker
And then only display records with these names in the report.
You can use the WhereCondition option of the DoCmd.OpenReport Method to filter your report as needed.
Const cstrReport As String = "YourReportNameHere"
Dim custNames As String
Dim lItem As Variant
Dim strWhereCondition As String
With Me.yourListBoxName
For Each lItem In .ItemsSelected
custNames = custNames & ",'" & Replace(.ItemData(lItem), "'", "''") & "'"
Next
End With
If Len(custNames) > 0 Then
custNames = Mid(custNames, 2)
strWhereCondition = "[Name] IN (" & custNames & ")"
End If
DoCmd.OpenReport ReportName:=cstrReport, View:=acViewPreview, _
WhereCondition:=strWhereCondition
Note this approach has features in common with PaulFrancis' answer. In fact, I copied his code and modified it. The key difference is that this approach does not require you to revise a saved query in order to filter the report.
The setup I would I have is, a Form with a SubForm and a ListBox, the Listbox will have the names of all your customers. So the RowSource would be,
SELECT
customerNameFieldName
FROM
yourTableName;
The Multi Select property will be setup to Extended. Then a button will have the following code that will generate the SQL for the SubForm's recordsource.
Private Sub buttonName_Click()
Dim lItem As Varaint, strSQL As String
Dim custNames As String, whereStr As String
Dim dbObj As dao.Database
Dim tmpQryDef As QueryDef
Set dbObj = CurrentDb()
For Each lItem In Me.yourListBoxName.ItemsSelected
custNames = custNames & "'" & Me.yourListBoxName.ItemData(lItem) & "', "
Next
Id Len(custNames) <> 0 Then
custNames = Left(custNames, Len(custNames) - 2)
whereStr = "WHERE customerNameFieldName IN (" & custNames & ")"
End If
strSQL = "SELECT someFields FROM someTable " & whereStr
Set tmpQryDef = dbObj.QueryDefs("Summary 3 Q1")
tmpQryDef.SQL = strSQL
DoCmd.OpenReport "yourReportName", acViewNormal
Set dbObj = Nothing
Set tmpQryDef = Nothing
End Sub
So now the SubForm will have the RecordSource based on all the information you have selected in the ListBox.

Simple access query

I'm trying to create a query in Access.
Let's say, for example, I have four fields: Numbers 1-26, Letters A-Z, 26 Names, and 26 Cities, so one record might be: 2, B, Jane, New York
I want to create and save a new query with:
the numbers field, the letters field, and the names field. I want the letters field to be filtered on "A" or "B", and the names field to have an expression so it's always 0.
This will become a loop, so it'll create 13 queries (A/B, C/D, etc).
It seems like having this process in VBA as opposed to the Access macro builder would be better since not only do I have to loop this process, but there are also 2 similar tables (same field names, different values) that I need to run it on.
You can run your queries in VBA using a recordset and then work with the data from there:
Sub YourQueries(ByVal pstrCol1 As String, ByVal pstrCol2 As String, ByVal pstrCol3 As String, ByVal pstrCol4 As String)
Dim rs As Recordset
Dim strSQL As String
' Change types above to match what's actually in the table
strSQL = "SELECT YourColumn1, YourColumn2, YourColumn3, YourColumn4 "
strSQL = strSQL & " WHERE "
strSQL = strSQL & "YourColumn1='" & pstrCol1 & "'"
strSQL = strSQL & " AND YourColumn1='" & pstrCol1 & "'"
strSQL = strSQL & " AND YourColumn1='" & pstrCol1 & "'"
strSQL = strSQL & " AND YourColumn1='" & pstrCol1 & "'"
Set rs = CurrentDb.OpenRecordset(strSQL, dbOpenSnapshot)
While Not rs.EOF
For i = 0 To 3
Debug.Print rs.Fields(i) & " is Column" & Format(i)
Next i
rs.MoveNext
Wend
rs.Close
Set rs = Nothing
End Sub