Reputation: 860
I've written some VBA:
For x = LBound(resProdID) To UBound(resProdID)
CurrentDb.QueryDefs("qry_findID_vba").SQL = "" & _
"SELECT tbl_products.ProdID " & _
"FROM tbl_products " & _
"WHERE (tbl_products.Size = " & resSize(x) & " " & _
"AND tbl_products.SupplID = '" & Forms.frm_suppliers.SupplID & "')"
Dim dbs As DAO.Database
Dim rst As DAO.Recordset
Set dbs = CurrentDb()
Set rst = dbs.OpenRecordset("qry_findID_vba")
MsgBox rst.RecordCount
If rst.RecordCount <> 0 Then
rst.MoveLast
rst.MoveFirst
newProdID(x) = rst.Fields(0).Value
MsgBox "This never fires"
End If
rst.Close
Set rst = Nothing
dbs.Close
Set dbs = Nothing
Next x
What happens when I run it, is that a box pops up saying 0. I click Ok, and it repeats one more time. This is because I have two items in my resProdID-array.
However, if I open the query "qry_findID_vba" normally, it shows one row, like I expected.
Why doesn't VBA return this row? Have I done anything wrong?
Upvotes: 0
Views: 6591
Reputation: 338128
First off, you really should use QueryDef parameters. They provide a number of benefits:
Your situation is exactly what parameterized QueryDefs are for.
Change the query text of qry_findID_vba
in Access to:
PARAMETERS [ProductSize] Text (255), [SupplID] Number;
SELECT ProdID
FROM tbl_products
WHERE [tbl_products].[Size] = [ProductSize] AND [tbl_products].[SupplID] = [SupplID];
Replace the parameter data types according to your actual data types in the table.
Next, when you're in a loop, don't re-define fixed variables again and again. dbs
and rst
don't need to be defined inside the loop at all.
Last point, the RecordCount
property does not work the way you think. Quote from the docs, emphasis mine:
Use the
RecordCount
property to find out how many records in a Recordset or TableDef object have been accessed. The RecordCount property doesn't indicate how many records are contained in a dynaset–, snapshot–, or forward–only–type Recordset object until all records have been accessed. [...] To force the last record to be accessed, use theMoveLast
method on the Recordset object.
Instead of calling MoveLast
, you can also check the .EOF
property. If it is false, at least one record is available.
For one-off query results like this one, I would recommend using the snapshot type Recordset. You can define which type you want to use when you call OpenRecordset
on the QueryDef.
Now:
Dim qry_findID_vba As DAO.QueryDef
Set qry_findID_vba = CurrentDb().QueryDefs("qry_findID_vba")
qry_findID_vba.Parameters("SupplID") = Forms.frm_suppliers.SupplID
For x = LBound(resProdID) To UBound(resProdID)
qry_findID_vba.Parameters("ProductSize") = resSize(x)
With qry_findID_vba.OpenRecordset(dbOpenSnapshot)
If Not .EOF Then
newProdID(x) = .Fields("ProdID").Value
End If
End With
Next x
Note that I use With
to save maintaining a helper rst
variable.
Upvotes: 1
Reputation: 13357
Does this code messagebox the correct count? Can you use it instead? (Note, I haven't actually run it, so watch out for slight syntax errors.)
For x = LBound(resProdID) To UBound(resProdID)
Dim sql as String
Dim rst As DAO.Recordset
sql = "Select tbl_products.ProdID FROM tbl_products " & _
"WHERE (tbl_products.Size = " & resSize(x) & " " & _
"AND tbl_products.SupplID = '" & Forms.frm_suppliers.SupplID & "')"
Set rst = dbs.OpenRecordset(sql)
if not rst.eof then
MsgBox rst.fields("ProdID")
else
Msgbox "None found!"
end if
rst.Close
Set rst = Nothing
Next x
Also, try copying everything to a new form, and compacting and repairing the database ...
Upvotes: 1