How to pass a SQL query result to variable with VBA Access - vba

I need to create a standalone function which checks whether a value is true or false. I have attempted to set up a SQL query that does this, but can't get the result to pass to the variable.
The query will always return only one record.
How can I pass the result of the SQL string as the returning value of the function?
UPDATED
Private Function HasBM(iMandate As Variant) As Boolean
'Returns boolean value for whether or not mandate has a benchmark
Dim sSQL1 As String
Dim sSQL2 As String
Dim db As Database
Dim rs As Recordset
sSQL1 = "SELECT tbl_Mandate_Type.BM_Included " & _
"FROM tbl_Mandate_Type INNER JOIN tbl_MoPo_BM ON tbl_Mandate_Type.Mandate_Type_ID = tbl_MoPo_BM.MandateType_ID " & _
"WHERE (((tbl_MoPo_BM.MoPo_BM_ID)="
sSQL2 = "));"
Set db = CurrentDb
Set rs = db.Execute(sSQL1 & iMandate & sSQL2)
HasBM = rs.Fields(0).Value
End Function
UPDATE 2: SOLUTION
Thanks for Magisch and HansUp I ended up getting two solutions that work:
DLOOKUP Solution by Magisch as I implemented it:
Private Function HasBM2(iMandate As Variant)
'Returns boolean value for whether or not mandate has a benchmark
Dim tmp As String
tmp = CStr(DLookup("tbl_MoPo_BM.MandateType_ID", "tbl_MoPo_BM", "tbl_MoPo_BM.MoPo_BM_ID = " & iMandate))
HasBM2 = DLookup("tbl_Mandate_Type.BM_Included", "tbl_Mandate_Type", "Mandate_Type_ID =" & tmp)
End Function
Second Solution using recordset as HansUp helped create:
Private Function HasBM(iMandate As Variant) As Boolean
'Returns boolean value for whether or not mandate has a benchmark
Dim sSQL1 As String
Dim sSQL2 As String
Dim db As Database
Dim rs As dao.Recordset
sSQL1 = "SELECT tbl_Mandate_Type.BM_Included " & _
"FROM tbl_Mandate_Type INNER JOIN tbl_MoPo_BM ON tbl_Mandate_Type.Mandate_Type_ID = tbl_MoPo_BM.MandateType_ID " & _
"WHERE (((tbl_MoPo_BM.MoPo_BM_ID)="
sSQL2 = "));"
Set db = CurrentDb
Set rs = db.OpenRecordset(sSQL1 & iMandate & sSQL2)
HasBM = rs.Fields(0).Value
rs.close
End Function

You can use the DLookup function native to access for this. Since you have an INNER JOIN in your SQL, you will have to use it twice, but it'll still work.
Use a temporary string variable to store the temporary output, like this:
Dim tmp as String
tmp = Cstr(DLookup("tbl_MoPo_BM.MandateType_ID","tbl_MoPo_BM","tbl_MoPo_BM.MoPo_BM_ID = " & iMandate)) 'This is to fetch the ID you performed the inner join on
HasBM = DLookup("tbl_Mandate_Type.BM_Included","tbl_Mandate_Type","Mandate_Type_ID =" & tmp) ' this is to get your value
Using your DoCmd.RunSQL will not suffice since its for action queries only (INSERT, DELETE, UPDATE) and incapable of returning the result.
Alternatively, you can use a Recordset with your SQL query to fetch what you want, but thats more work and the DLookup is designed to exactly avoid doing that for single column return selects.

Related

MS Access Query to show Inventory Counts per Person (Using comma delimited)

I'm attempting to setup a query that will show how many of each ship is owned and who owns it displaying each "Call Sign" who owns the ship in comma delimited format.
The table being used for the query is called "Members" and I'm using a Count function on the "Current Ships Owned" field in the query to get count totals.
The Base query is the following:
I used VBA to build the following module:
Public Function QueryFieldAsSeparatedString(ByVal fieldName As String, _
ByVal tableOrQueryName As String, _
Optional ByVal criteria As String = "", _
Optional ByVal sortBy As String = "", _
Optional ByVal delimiter As String = ", " _
) As String
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim sql As String
Dim whereCondition As String
Dim sortExpression As String
Dim retVal As String
Set db = CurrentDb
If Len(criteria) > 0 Then
whereCondition = " WHERE " & criteria
End If
If Len(sortBy) > 0 Then
sortExpression = " ORDER BY " & sortBy
End If
sql = "SELECT " & fieldName & " FROM " & "Members" & whereCondition & sortExpression
Set rs = db.OpenRecordset(sql, dbOpenForwardOnly, dbReadOnly)
Do Until rs.EOF
If Not IsNull(rs.Fields(0).Value) Then
retVal = retVal & Nz(rs.Fields(0).Value, "") & delimiter
End If
rs.MoveNext
Loop
retVal = Left(retVal, Len(retVal) - Len(delimiter))
QueryFieldAsSeparatedString = retVal
rs.Close
Set rs = Nothing
Set db = Nothing
End Function
I then added the field with the owners by adding the following expression to my query:
Owners: QueryFieldAsSeparatedString("[Call Sign]","Members",Count([Members]![Current Ships Owned])>=1)
But it comes back with the error "Your query does not include the specified expression 'Owners' as part of an aggregate function". Changing it from expression to group by gives an error "reserved error (-3087);"
If I remove the Count from the expression it runs but gives me all members rather than the members that own the ships.
Any help or push in the right direction would be greatly appreciated. I'm not sure what I'm missing but I think some fresh eyes on the issue may help.
Thank you!!
-Deke
Note that you have basically replicated http://allenbrowne.com/func-concat.html
The criteria parameter is the problem. It expects a string, but you pass an expression.
And even if Access silently converts it, WHERE Count([field]) >= 1 is not valid in the WHERE clause, that would only work in a HAVING clause.
But what you actually need there is a criterium that collects all Members records that belong to the current query record.
See the usage example on Allen Browne's page, and the documentation of the strWhere parameter.

MS Access SQL to Update a RecordSet in Table/Query

I need help regarding the WHERE clause of an SQL statement to UPDATE field values [olnAg] in a query (qryCLFull same as tblCLFull). The field [olnAg] should be updated to the second text of [cellLine] field. So for example if [cellLine] has "
This is the cellLine field
[olnAg] should have
is
Getting the recordset and values has been successful with the code below (with the click of a button on frmSecWord but the issue with UPDATE of the [olnAg] field.
Private Sub btnBySpace_Click()
Dim rsON As DAO.Recordset
Dim rsNN As DAO.Recordset
Dim db2 As Database
Dim sqlON As String
Dim sqlNN As String
Dim newVal As String
Dim arr As Variant
sqlON = " SELECT cellLine FROM qryCLFull"
sqlNN = " SELECT olnAg FROM qryCLFull"
Set db2 = CurrentDb
Set rsON = db2.OpenRecordset(sqlON)
Set rsNN = db2.OpenRecordset(sqlNN)
arr = Split(rsON!cellline, " ")
If IsNull(arr(1)) Then
newVal = arr(0)
Else: newVal = arr(1)
End If
Do Until rsON.EOF
If Not IsNull(rsON.Fields(0).Value) Then
sqlstr = "UPDATE qryCLFull SET qryCLFull.olnAg = '" & newVal & "'
db2.Execute sqlstr
End If
rsON.MoveNext
rsNN.MoveNext
Loop
rsON.Close
rsNN.Close
Set rsNN = Nothing
Set rsNN = Nothing
Set db2 = Nothing
End Sub
Now with this UPDATE and SQL code, all the records of [olNAg] are changed to "is" instead of records WHERE [CellLine] has the text "This is the cellLine field" I have tried severally to adjust the WHERE clause but I haven't been able to write a correct clause. This sql updates [olnAg] for all records in the table instead of just for instances where we find that particular rsON!CellLine. Help will be greatly appreciated.

Pass through query with userinput in access form

I have Access front end which is powered by SQL Server in backend.
I made a form which requires user input, based on the input it should run a pass through query and should display result in the subform. I have read on internet this cannot be done through sql command and it requires sql coding to be wrapped in VBA coding.
I have made a code this like this:
Private Sub id_AfterUpdate()
Dim MyDb As Database, MyQry As QueryDef
Set MyDb = CurrentDb()
Set MyQry = MyDb.CreateQueryDef("")
MyQry.Connect = "ODBC;DSN=mikecollections;UID=***;PWD=****;DATABASE=mikecollections;"
MyQry.SQL = "select currency.tb_coins.id,documenttype,documentsubtype,documentname" & _
"from currency.tb_coins" & _
"inner join collectibles.tb_documents on tb_coins.id=collectibles.tb_documents.prodid" & _
"where currency.tb_coins.id=[forms]![test_form]![id]"
End Sub
This code should fire after I enter value in the id field in the form, but nothing happens. I do not know how to make this code work. Im new to SQL and VBA, Pls help!
I created a stored procedure in sql server and created a parameter in access to pass into sql server and got it working. Thank you Hansup and iDevlop for all the help.
Private Sub userinput_AfterUpdate()
Dim qrypass As DAO.QueryDef
Dim rst As DAO.Recordset
Set qrypass = CurrentDb.QueryDefs("qu_test")
qrypass.SQL = _
"exec collectibles.sp_coinsvsdocuments " _
& "#userinput=" _
& Forms!test_form!userinput
End Sub
You logically can't refer to an Access object in a passthru query.
So your sql should pass the value of the control, instead of referencing the control itself.
If id is a long:
MyQry.SQL = "select currency.tb_coins.id,documenttype,documentsubtype,documentname" & _
"from currency.tb_coins" & _
"inner join collectibles.tb_documents on tb_coins.id=collectibles.tb_documents.prodid" & _
"where currency.tb_coins.id= " & [forms]![test_form]![id]
Then you need to add the code to assign that querydef to a recordset, in order to read it. Something like:
set rs = myQry.OpenRecordset
If you prefer, you can also name your queryDef. it will then be available like any other query:
Set MyQry = MyDb.CreateQueryDef("someName")
'''specify all properties here...
doCmd.OpenQuery "someName"
Here is a solution for all Microsoft Access
just copy the below code into a Microsoft Access Module and change the parameter
Sub test()
' The "Kim_ZZ_Orderlines" has a string 'arg1' in the sql so we just replace this
' with the new value
RunPassThrough "KIM_ZZ_Orderlines", "Indput value", "10"
End Sub
Sub RunPassThrough(QueryToRun, ArgPrompt, ArgDefault)
' John Henriksen
' 2021-09-23
' Sub procedure to run a Pass-through query with argument
' in the query there must be the string 'Arg1" you want to replace
' e.g. AND APPS.OE_ORDER_LINES_ALL.ATTRIBUTE1 = 'arg1'
arg1 = VBA.InputBox(ArgPrompt, ArgPrompt, ArgDefault)
Dim db As DAO.Database
Dim qry, qryNy As String
Dim qrydefOrginal As DAO.QueryDef
Set db = CurrentDb
Set qdef = db.QueryDefs(QueryToRun)
' Save the original sql
qry = qdef.sql
' Make a new sql, here we search for the string "arg1" and replace with our arg1 value
qryNy = VBA.Replace(qry, "arg1", arg1)
' Set the new sql
qdef.sql = qryNy
DoCmd.OpenQuery QueryToRun
' Set the original sql
qdef.sql = qry
Set qdef = Nothing
Set db = Nothing
End Sub

SetFocus is getting ignored - Why?

I have 2 fields - txtTR1_Unit and cmbTR2_Unit. Together, these 2 fields represent the total UNIT.
cmbTR2_Unit has a list of unique values that when selected - txtTR1_Unit automatically gets the related value.
I've created a function called Tier1from2 - that accepts a 'string' and returns the related Tier1 value.
So when I update cmbTR2_Unit in my After_Update event, I'd like to automatically tab to the next field. - Another combo box. I figured that I shouldn't need to set any focus, because it would automatically go to the next field after updating.
txtTR1 gets updated just as expected from my Function, but then it just sits there and won't go to the next field. So I have attempted to 'SetFocus' to the next field after the update.
Still no go. What did I miss??
Private Sub cmbTR2_UNIT_AfterUpdate()
If Len(Me.cmbTR2_UNIT.Value) <> 0 Then
Me.txtTR1_UNIT.Value = Tier1From2(Me.cmbTR2_UNIT.Text)
'cmb_CostCenter.setfocus - 'this doesn't seem necessary - but it doesn't work anyway.
End If
End Sub
As a test I tried removing the function "Tier1From2(Me.cmbTR2_UNIT.text)" simply hard coding the word 'RESULT' in txtTR1_UNIT and it works without a hitch. I know I used to write a more simple function but I haven't touched VBA in awhile - How can I simplify this function:
Private Function Tier1From2(strTier2 As String) As String
Dim qdf As DAO.QueryDef
Dim db As DAO.Database
Dim strQry As String
Dim rs As Recordset
Set db = CurrentDb
Set qdf = db.QueryDefs("qUNIT_HUB")
strQry = "SELECT Tier1_Unit, Tier2_Unit " & _
" FROM LTBL_Cost_Collector " & _
" GROUP BY Tier1_Unit, Tier2_Unit " & _
" HAVING (((Tier2_Unit) = '" & strTier2 & "'));"
qdf.SQL = strQry
db.QueryDefs.Refresh
Set rs = db.OpenRecordset(strQry)
Tier1From2 = rs![Tier1_Unit]
Set db = Nothing
Set qdf = Nothing
Set Recordset = Nothing
End Function
It turns out that something in this function was causing the field and form to loose focus. db.QueryDefs.refresh perhaps? The solution was to update my Function as follows
Private Function Tier1From2(strTier2 As String) As String
Dim rs As DAO.Recordset
Dim db As DAO.Database
Dim strSQL As String
Dim strTier1 As String
Set db = CurrentDb
strSQL = "SELECT Tier1_Unit, Tier2_Unit " & _
" FROM LTBL_Cost_Collector " & _
" GROUP BY Tier1_Unit, Tier2_Unit " & _
" HAVING (((Tier2_Unit) = '" & strTier2 & "'));"
Set rs = db.OpenRecordset(strSQL, dbOpenDynaset)
strTier1 = rs!Tier1_Unit
Set rs = Nothing
Set db = Nothing
Tier1From2 = strTier1
End Function
This worked without a hitch.

RecordSet = Nothing after SQL query returns value

I'm trying to assign the result of an SQL query to a variable using VBA in Access. The query returns a value but the variable which it is assigned to has a value of Nothing. Here is the code snippet:
Dim queryReturnID As String
queryReturnID = "select dbo_tbl_SupplierReturn.ReturnID from dbo_tbl_SupplierReturn" & _
" where SupplierID = " & lstPOHdr.Column(1)
Debug.Print queryReturnID
Dim RecordSet1 As DAO.RecordSet
Set RecordSet1 = CurrentDb.OpenRecordset(queryReturnID)
Not exactly sure what's going on with your Nothing recordset; even a query that returns no records would not have the object set to nothing. As an alternative, however, you could do the same thing with this one line of code:
DLookup("ReturnID", "dbo_tbl_SupplierReturn", "SupplierID = " & lstPOHdr.Column(1))