OpenRecordset is not applying query parameters - vba

I'm trying to iterate through the result set generated with the query that has 2 parameters. Values for these parameters are read from the form fields (start and end date). Since Access throws Run-time error '3061'. Too few parameters. Expected 2. even if the value is set in the form fields, I tried to set the parameters through VBA with QueryDef object (given code below).
It worked OK when start and end date are the same, but if I select different start and end date it won't apply the date filter assigned to the query parameters.
I've tried both to change format of the date values and to cast them to another type, but I've had no success.
Has anyone experienced a similar problem?
Any help would be appreciated!
Query:
SELECT DISTINCT
tblComp_Payout.Agent_ID_int As [Agent ID],
tblExchOffices.Agent_Name AS Name
FROM
tblExchOffices
INNER JOIN
tblComp_Payout ON tblExchOffices.Agent_ID_int = tblComp_Payout.Agent_ID_int
WHERE
((DateValue([Paid_Date])) >= ([forms]![frmReporting]![txtDateFrom])
AND (DateValue([Paid_Date]))<=[forms]![frmReporting]![txtDateTo])
UNION
SELECT DISTINCT
tblComp_Sending.Agent_ID_int AS [Agent ID],
tblExchOffices.Agent_Name AS Name
FROM
tblExchOffices
INNER JOIN
tblComp_Sending ON tblExchOffices.Agent_ID_int = tblComp_Sending.Agent_ID_int
WHERE
((DateValue([Sending_Date])) >= ([forms]![frmReporting]![txtDateFrom])
AND (DateValue([Sending_Date]))<=[forms]![frmReporting]![txtDateTo]);
Method:
Private Sub iterate_Click()
On Error GoTo iterate_Err
Dim rs As DAO.Recordset
Dim qdf As DAO.QueryDef
Set qdf = CurrentDb.QueryDefs("queAgentByDate")
qdf.Parameters.Refresh
If CurrentProject.AllForms("frmReporting").IsLoaded Then
qdf.Parameters("[forms]![frmReporting]![txtDateFrom]") = CStr([Forms]![frmReporting]![txtDateFrom])
qdf.Parameters("[forms]![frmReporting]![txtDateTo]") = CStr([Forms]![frmReporting]![txtDateTo])
Else
Beep
Resume iterate_Exit
End If
Set rs = qdf.OpenRecordset(dbOpenDynaset, dbSeeChanges)
MsgBox rs.RecordCount
If rs.EOF Then Exit Sub
With rs
Do Until .EOF
'Loop logic
Loop
End With
rs.Close
Set rs = Nothing
iterate_Exit:
Exit Sub
iterate_Err:
MsgBox Error$
Resume iterate_Exit
End Sub

First, specify your parameters:
PARAMETERS
[forms]![frmReporting]![txtDateFrom] DateTime,
[forms]![frmReporting]![txtDateTo] DateTime;
SELECT DISTINCT tblComp_Payout.Agent_ID_int As [Agent ID],
tblExchOffices.Agent_Name AS Name
FROM tblExchOffices INNER JOIN tblComp_Payout
ON tblExchOffices.Agent_ID_int = tblComp_Payout.Agent_ID_int
WHERE ((DateValue([Paid_Date]))>=([forms]![frmReporting]![txtDateFrom])
And (DateValue([Paid_Date]))<=[forms]![frmReporting]![txtDateTo])
UNION
SELECT DISTINCT tblComp_Sending.Agent_ID_int As [Agent ID],
tblExchOffices.Agent_Name AS Name
FROM tblExchOffices INNER JOIN tblComp_Sending
ON tblExchOffices.Agent_ID_int = tblComp_Sending.Agent_ID_int
WHERE ((DateValue([Sending_Date]))>=([forms]![frmReporting]![txtDateFrom])
And (DateValue([Sending_Date]))<=[forms]![frmReporting]![txtDateTo]);
Then set their values as true date values:
qdf.Parameters("[forms]![frmReporting]![txtDateFrom]") = [Forms]![frmReporting]![txtDateFrom]
qdf.Parameters("[forms]![frmReporting]![txtDateTo]") = [Forms]![frmReporting]![txtDateTo]
To simplify, rename your parameters to, say, DateFrom and DateTo.

Related

Adding records based on value from other records

I'm going to try this again because I'm so lost..: I have an Access database and the backend contains the tables:
tblStat
groupID
Userid
complex
open
new account
Shipped
not-shipped
code
A
123
Yes
No
Yes
869
B
147
No
Yes
no
936
And tblCode
uniqueid
codetype
code
A,yes,No,Yes
shipped
869
B,No,Yes,No
not-Shipped
936
When I upload a report, it populates the tblStats and using the groupid, complex, open and new account records to make a uniqueid and later adds the code to tblStats. Based on the uniqueID, it can be shipped or not-shipped. The old reports we used contained shipped or not-shipped number values, but with the new reports, I will need to use codetype and code record to reference the tblStat for each order and determine whether the order is shipped or not, and add 1 to tblStats.
I want to do something like
if tblCode.codetype = shipped and the code are the same then tblStat.shipped = 1 else if tblCode.Codetype = not-shipped and the codes are the same tblStat.not-shipped = 1
and then:
with recordset .shipped = shipped .not-shipped = notshipped end with
I just can't seem to figure it out..
I really hope I've provided enough info and cleraity this time around. If you need any code, let me know. thanks.
I cant get my head around for a solution purely in SQL, but in VBA, the method below does the following:
Gather records due to be updated from tblStat.
Loop and try to find a match in tblCode.
Update record accordingly.
There's a helper function to try to find the match in tblCode and an enum the function returns to make the code a bit cleaner and easier to read.
I'm pretty sure something better exists.
Private Enum ShipEnum
None = 0
Shipped
NotShipped
End Enum
Sub T()
On Error GoTo catch
'get records due to be updated
Dim r As DAO.Recordset
Set r = CurrentDb().OpenRecordset("SELECT groupID, complex, [open], [new account], Shipped, [not-shipped], code FROM tblStat WHERE Shipped Is Null AND [not-shipped] Is Null;", dbOpenDynaset)
If r.EOF Then
MsgBox "No records."
GoTo Leave
End If
r.MoveLast
r.MoveFirst
'loop and try to match each record with a record in tblCode
Dim idx As Long, uniqueId As String, shippedStatus As ShipEnum
For idx = 1 To r.RecordCount
'build the unique id for the record
uniqueId = r![groupID] & "," & r![Complex] & "," & r![Open] & "," & r![new account]
'get codetype
shippedStatus = CodeTypeByCriteria(uniqueId, r![Code])
'update if shipped or not-shipped
If shippedStatus <> ShipEnum.None Then
r.Edit
r![Shipped] = IIf(shippedStatus = ShipEnum.Shipped, 1, 0)
r![not-shipped] = IIf(shippedStatus = ShipEnum.NotShipped, 1, 0)
r.Update
End If
r.MoveNext
Next idx
'all good
MsgBox "Complete"
Leave:
If Not r Is Nothing Then r.Close
Exit Sub
catch:
MsgBox Err.Description, vbCritical
Resume Leave
End Sub
Private Function CodeTypeByCriteria(ByVal stringUniqueId As String, ByVal stringCode As String) As ShipEnum
With CurrentDb().OpenRecordset("SELECT codetype FROM tblCode WHERE StrConv(uniqueId, 2)='" & StrConv(stringUniqueId, vbLowerCase) & "' And code='" & stringCode & "'", dbOpenSnapshot)
If Not .EOF Then
Select Case ![codetype]
Case "shipped":
CodeTypeByCriteria = ShipEnum.Shipped
Case "not-shipped":
CodeTypeByCriteria = ShipEnum.NotShipped
Case Else:
Exit Function
End Select
End If
End With
End Function
If code column in both the tables have unique values and you haven't made mistake while writing code field's values for both tables in your question then these queries should work:
UPDATE tblStat JOIN tblCode ON tblStat.code = tblCode.code
SET shipped = 1
WHERE CONCAT(groupID, ',', complex, ',', open, ',', new_account) = uniqueid
AND codetype = 'shipped';
UPDATE tblStat JOIN tblCode ON tblStat.code = tblCode.code
SET not_shipped = 1
WHERE CONCAT(groupID, ',', complex, ',', open, ',', new_account) = uniqueid
AND codetype = 'not-shipped';
Edit:
These queries are according to MySQL. In VBA, there should be some other function or way - like joining string with + operator?

Why is access vba throwing sub or function not defined when attempting to read a recordset field?

As the title says, I get an error "Sub or Function Not Defined" when the code tries to compile. It breaks on the RS_Logistics![Received]. That field does exist in the recordset which is verified by looking at the table IM_Logistics, and by checking the watch that I set on the object and confirming the Field Item "Received" exists. It's a boolean field.
Option Compare Database
Option Explicit
Private ROID As Long
Private RS As Recordset
Private RS_PartDetail As Recordset
Private RS_Logistics As Recordset
Public Sub Load_ID(RepOrderID As Long)
Dim strSQL As String
strSQL = "SELECT TOP 1 * FROM IM_ReplenishmentOrders WHERE ReplenishmentOrderID = " & RepOrderID
Set RS = CurrentDb.OpenRecordset(strSQL)
If RS.RecordCount > 0 Then
ROID = RepOrderID
strSQL = "SELECT TOP 1 * FROM MT_PartDetail Where MT_PartDetail_ID = " & RS!MT_PartDetail_ID
Set RS_PartDetail = CurrentDb.OpenRecordset(strSQL)
strSQL = "SELECT * FROM IM_Logistics Where ReplenishmentOrderID = " & ROID
Set RS_Logistics = CurrentDb.OpenRecordset(strSQL)
Else
ROID = 0
End If
End Sub
Public Property Get ETA() As Date 'Derived from Logistics Records
On Error GoTo fail
RS_Logistics.MoveFirst
While Not RS_Logistics.EOF
If ((RS_Logistics![Received] = False) And Nz(ETA, DateAdd("Y", 10, today())) > RS_Logistics![Expected Date]) Then
ETA = RS_Logistics![Expected Date]
End If
RS_Logistics.MoveNext
Wend
fail:
End Property
I've been working with recordsets in this database for over a year. No idea why this is popping up now.
Error message has nothing to do with recordset or its fields. "Sub or Function Not Defined" is because Today() is not an Access VBA function. Use Date().
Also, Access VBA DateAdd requires "yyyy" as year interval.
2 suggestions to catch things like these easier:
Set the "option explicit" on all your modules (and/ir in the preferences to save you doing it manually). This would have told you that today() is an undefined variable instead of looking for a sub/function by that name
Learn to look out for today() remaining as today() and not being corrected to Today() which the editor would have done if Today() had been valid Sub/Function.

Assign Value from Query with sum to Textbox

I am trying to assign the value from a SQL Query to a text box.
I have the function tied to a ComboBox After update.
I tested the SQL by running it.
How do I assign the result to the Txtbox named prepoffEIC?
Dim MyVar2 As Integer
MyVar2 = Me.SelectedExam.Column(0)
ExamViewQry = "SELECT Sum(tblentrys.entryhours) AS TotalHoursPerFunction FROM tBleExams INNER JOIN (tBlBankList INNER JOIN (tBlExaminers INNER JOIN (tBlEntrys INNER JOIN tBlActivity ON tBlEntrys.EntryActivityID = tBlActivity.FunctionKey) ON tBlExaminers.ExaminersKey = tBlEntrys.EntryExaminerID) ON tBlBankList.BankID = tBlEntrys.EntryInstitutionID) ON (tBlBankList.BankID = tBleExams.ExamBankID) AND (tBleExams.ExamID = tBlEntrys.EntryExamID) WHERE tBlEntrys.EntryActivityID=1 AND tblEntrys.EntryExamStageID=1 AND tBleExams.ExamID=" & MyVar2
Me.prepoffEIC.ControlSource = "ExamViewQry"
Me.prepoffEIC.Requery
Create a query using the sql you have, but slightly modded paste it here:
PARAMETERS eid long;
SELECT Sum(tblentrys.entryhours) AS TotalHoursPerFunction
FROM tBleExams
INNER JOIN (
tBlBankList INNER JOIN (
tBlExaminers INNER JOIN (
tBlEntrys INNER JOIN tBlActivity ON tBlEntrys.EntryActivityID = tBlActivity.FunctionKey
) ON tBlExaminers.ExaminersKey = tBlEntrys.EntryExaminerID
) ON tBlBankList.BankID = tBlEntrys.EntryInstitutionID
) ON (tBlBankList.BankID = tBleExams.ExamBankID)
AND (tBleExams.ExamID = tBlEntrys.EntryExamID)
WHERE tBlEntrys.EntryActivityID = 1
AND tblEntrys.EntryExamStageID = 1
AND tBleExams.ExamID = [eid]
lets call it qryGetHours (since i dont know what you need it for.)
in the after update event (also use better naming, this is quick and dirty)
dim db as DAO.Database
dim qry as QueryDef
dim rs as DAO.Recordset
set db = currentdb
set qry = db.querydefs("qryGetHours")
'this is the name of the query you made above
qry.parameters("eid").value = me.SelectedExam.Column(0)
set rs = qry.openrecordset(dbopendynaset,dbseechanges)
'dbseechanges is more for if you have a sql server backend, but i usually do
if not ( rs.eof and rs.bof) then
rs.movefirst
me.prepoffEIC = rs.fields("TotalHoursPerFunction").value
'This portion assumes that you only get one record back,
'or if you do end up with more than one, it only goes
'after the first one.
else
msgbox "Errors... Errors everywhere."
'You will definitely want to put something meaningful
'here relating to it not being able to find the data you
'were looking for.
end if
if not rs is nothing then
rs.close
set rs = nothing
end if
set qry = nothing
set db = nothing
'you will always want to do this portion where you properly
'check if a recordset exists and then close it when you are
'done, along with closing out the querydef and database variables.

Access crosstab query data parameter not filtering query

I have finally got my crosstab report to dynamically update but for some reason the date parameters are not passing to either the report or the query.
I have a recordset updating the crosstab report and on hover/step through the date parameter in vba is showing the correct date but the report is still showing all data.
The query is also showing data for all dates. Is it something I have done wrong in the query? I have tried every option I could find in what seems like every forum and just can't get a solution.
This is the SQL for the query
PARAMETERS [Forms]![frm_menu]![txtFromDate] DateTime,
[Forms]![frm_menu]![txtToDate] DateTime,
[Forms]![frm_menu]![cmbMplTag1] Text ( 255 ),
[Forms]![frm_menu]![cmbMplTag2] Text ( 255 ),
[Forms]![frm_menu]![cmbMplTag3] Text ( 255 ),
[Forms]![frm_menu]![cmbMplTag4] Text ( 255 ),
[Forms]![frm_menu]![cmbMplTag5] Text ( 255 );
TRANSFORM First(tbl_logdata.Input_Value) AS FirstOfInput_Value
SELECT tbl_logdata.Log_Date, tbl_logdata.Log_Time
FROM tbl_logdata
WHERE (((tbl_logdata.Log_Date) Between [Forms]![frm_menu]![txtFromDate]
And [Forms]![frm_menu]![txtToDate])
AND ((tbl_logdata.tag)=[Forms]![frm_menu]![cmbMplTag1]))
OR (((tbl_logdata.tag)=[Forms]![frm_menu]![cmbMplTag2]))
OR (((tbl_logdata.tag)=[Forms]![frm_menu]![cmbMplTag3]))
OR (((tbl_logdata.tag)=[Forms]![frm_menu]![cmbMplTag4]))
OR (((tbl_logdata.tag)=[Forms]![frm_menu]![cmbMplTag5]))
GROUP BY tbl_logdata.Log_Date, tbl_logdata.Log_Time
PIVOT tbl_logdata.tag;
And this is the VBA for the crosstab report. The parameters for the cmbMplTag# are working fine:
Private Sub Report_Open(Cancel As Integer)
Dim rst As dao.Recordset
Dim db As dao.Database
Dim qdf As dao.QueryDef
Dim i As Integer
Dim j As Integer
Set db = CurrentDb
Set qdf = db.QueryDefs("qry_MplTagsSummary")
'on hover shows date from textbox'
qdf.Parameters("Forms!frm_menu!txtFromDate") = [Forms]![frm_menu]![txtFromDate]
'on hover shows date from textbox'
qdf.Parameters("Forms!frm_menu!txtToDate") = [Forms]![frm_menu]![txtToDate]
qdf.Parameters("[Forms]![frm_menu]![cmbMplTag1]") = [Forms]![frm_menu]![cmbMplTag1]
qdf.Parameters("[Forms]![frm_menu]![cmbMplTag2]") = [Forms]![frm_menu]![cmbMplTag2]
qdf.Parameters("[Forms]![frm_menu]![cmbMplTag3]") = [Forms]![frm_menu]![cmbMplTag3]
qdf.Parameters("[Forms]![frm_menu]![cmbMplTag4]") = [Forms]![frm_menu]![cmbMplTag4]
qdf.Parameters("[Forms]![frm_menu]![cmbMplTag5]") = [Forms]![frm_menu]![cmbMplTag5]
Set rst = qdf.OpenRecordset()
rst.MoveFirst
j = -1
i = 0
For i = 0 To rst.Fields.Count - 1
j = j + 1
Select Case j
Case 0
Me.Log_Date.ControlSource = rst.Fields(i).Name
Case 1
Me.Log_Time.ControlSource = rst.Fields(i).Name
Case 2
Me.field1.ControlSource = rst.Fields(i).Name
Case 3
Me.field2.ControlSource = rst.Fields(i).Name
Case 4
Me.Field3.ControlSource = rst.Fields(i).Name
Case 5
Me.Field4.ControlSource = rst.Fields(i).Name
Case 6
Me.Field5.ControlSource = rst.Fields(i).Name
End Select
skip_it:
Next i
rst.Close
Set rst = Nothing
End Sub
Please let me know if I have not provided enough details/information
Check your SQL WHERE clause conditional logic. As is, the logic filters records in either (not both) camps:
Falling in the date range and query's tag equals only form's tag1
Query's tag equals any of form's tag2 - tag5.
Possibly you meant to separate the date range and tags. So wrap parentheses around each condition with an AND operator, even use the IN clause. See below with indentation to illustrate:
...
WHERE (
(
(tbl_logdata.Log_Date) Between [Forms]![frm_menu]![txtFromDate]
And [Forms]![frm_menu]![txtToDate]
)
AND (
(tbl_logdata.tag) IN (
[Forms]![frm_menu]![cmbMplTag1],
[Forms]![frm_menu]![cmbMplTag2],
[Forms]![frm_menu]![cmbMplTag3],
[Forms]![frm_menu]![cmbMplTag4],
[Forms]![frm_menu]![cmbMplTag5]
)
)
)
GROUP BY tbl_logdata.Log_Date, tbl_logdata.Log_Time
You may have to convert to a true date value. And use the Value property:
qdf.Parameters("Forms!frm_menu!txtFromDate").Value = DateValue([Forms]![frm_menu]![txtFromDate])
qdf.Parameters("Forms!frm_menu!txtToDate").Value = DateValue([Forms]![frm_menu]![txtToDate])

Using a 'lookup' table in MS-ACCESS for an update query

I have an Access Database with a table [tblManipulate] with the following four fields populated with data:
[tblManipulate].[Name]
[tblManipulate].[Description]
[tblManipulate].[Price]
[tblManipulate].[Account code]
I also have an 150 entry table of descriptions called [tblDescLookup] that needs to be utilized like a lookup table in order to manipulate account codes. Example entries follow:
[tblDescLookup].[Description Lookup] [tblDescLookup].[Account Code Result]
*demonstration* 10000
*coding* 12000
*e-mail* 13000
What is the best way to take every record in [tblManipulate] and check the [tblManipulate].[Description] field against [tblDescLookup].[Description Lookup], assigning the account code result into the original table if a 'like' match is found?
This seems to me like one of those instances where Access is not the best tool for the job, but it is what I have been instructed to use. I would appreciate any help or insight (or alternatives!). Thank you!
Something like this should do it for you.
Dim Description As String
Dim lookupDescription As String
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset(SELECT * FROM tblManipulate)
If Not (rs.EOF And rs.BOF) Then
rs.MoveFirst 'good habit
Do Until rs.EOF = True
Description = rs("Description")
Dim rsLookUp As DAO.Recordset
Set rsLookUp = CurrentDb.OpenRecordset(SELECT * FROM tblDescLookup)
If Not (rsLookUp .EOF And rsLookUp .BOF) Then
rsLookUp .MoveFirst 'good habit
Do Until rsLookUp.EOF = True
lookupDescription = rsLookUp("Description Lookup")
If() Then 'match criteria
'assign value
End if
rsLookUp.MoveNext
Loop
Else
MsgBox "No records in the recordset."
End If
rs.MoveNext
Loop
Else
MsgBox "No records in the recordset."
End If
Oy. You're going to need a loop here. I would open up tblDescLookup in a recordset:
Set rec = CurrentDB.OpenRecordset ("Select * from tblDescLookup")
Then loop through each record and run the query that way:
Do While rec.EOF = False
Set rec2 = CurrentDB.OpenRecordset ("Select * from rec where Description like '" & rec("Description Lookup") & "'")
rec.MoveNext
Loop
Or maybe you need to make that an Update statement instead? I can't write that off the top of my head, but you get the idea.
Have you tried something like this?
Update tblManipulate as t1
Set [Account Code] = (Select [Account Code Result] from [tblDescLookup] where [Description Lookup] = t1.[Description])