I am getting this error in Microsoft Access:
runtime error 424 object required
And below is the VBA code that I have used on the backend of a button:
VBA Code
Private Sub Command87_Click()
If Me.phase <> "" Then
Me.lst_caseItems.RowSource = " " & _
"SELECT tbl_master.fld_masterID, " & _
"tbl_master.fld_masterActionNo AS ActionNumber, " & _
"tbl_master.fld_masterStudyActionNo AS StudyActionNo, tbl_master.fld_masterIssuedTo," & _
"tbl_master.fld_masterRev AS Rev, tbl_phases.fld_phase AS Phase, tbl_studies.fld_study AS Study, " & _
"FROM ((tbl_master LEFT JOIN tbl_studies ON tbl_master.fld_studyID = ' " & tbl_studies.fld_studyID & " ') LEFT JOIN tbl_phases ON tbl_master.fld_phaseID = ' " & tbl_phases.fld_phaseID & " ') LEFT JOIN tbl_locations ON tbl_master.fld_locationID = ' " & tbl_locations.fld_locationID & " ';"
End If
End Sub
In your current code, VBA thinks tbl_studies.fld_studyID is a variable hence asking for an object.
With your current code;
' " & tbl_studies.fld_studyID & " '
The " CLOSES the SQL statement, then your ampersand tbl_studies or etc tells VBA to add in the value of the variable tbl_studies.fld_studyID then the ampersand followed by " reopens the SQL statement within VBA (so on compile all flows as necessary). As you have no variable named studyID it looks like this is the cause of your object required.
To get around this, you either need to assign a variable to the ID you want (such as dim X as long then x = studyIDyouwanthere) or write your query correctly so it links to the studies table with field studyID. Looking at it more closely it looks like you just need to write the query properly in the VBA window so it's syntactically correct (in VBA's interpretation) try the following;
Private Sub Command87_Click()
If Me.phase <> "" Then
Me.lst_caseItems.RowSource = " " & _
"SELECT tbl_master.fld_masterID, " & _
"tbl_master.fld_masterActionNo AS ActionNumber, " & _
"tbl_master.fld_masterStudyActionNo AS StudyActionNo, tbl_master.fld_masterIssuedTo," & _
"tbl_master.fld_masterRev AS Rev, tbl_phases.fld_phase AS Phase, tbl_studies.fld_study AS Study, " & _
"FROM ((tbl_master LEFT JOIN tbl_studies ON tbl_master.fld_studyID = tbl_studies.fld_studyID) LEFT JOIN tbl_phases ON tbl_master.fld_phaseID = tbl_phases.fld_phaseID ) LEFT JOIN tbl_locations ON tbl_master.fld_locationID = tbl_locations.fld_locationID;"
End If
End Sub
When you are joining on queries in VBA you don't join based on the values of variables, you'll only be using them for your select part or having/where/group BY not on the joins.
Related
I'm trying to loop through a column inside a table from a form in Access to find out whether a "Case Name" already exists or not, and if it does not, then add the new record to the table. I want the criteria to be based on the input value of a text box. The good news is I have figured out how to add a new record to the table with the code below. I'm just stuck on how to loop through a table to find out if a record already exists. Thanks in advance!
Private Sub SaveNewCase_Click()
If Me.txtNewCaseName.Value <> "Null" And Me.txtCaseDepth.Value <> "Null" And Me.txtCaseHeight2.Value <> "Null" And Me.txtCaseWeight.Value <> "Null" And Me.txtCaseWidth <> "Null" And Me.cboCaseCategory.Value <> "Null" Then
'I think the loop should go here, but not sure'
CurrentDb.Execute "INSERT INTO tblCases(CaseName, CaseWidth, CaseHeight, CaseCasters, CaseWeight, CaseDepth, CaseCategory) " & _
" VALUES ('" & Me.txtNewCaseName & "'," & Me.txtCaseWidth & "," & Me.txtCaseHeight2 & ",'" & Me.chkboxCasters & "'," & Me.txtCaseWeight & "," & Me.txtCaseDepth & ",'" & Me.cboCaseCategory & "')"
Else
MsgBox "Please enter all new case criteria."
End If
End Sub
Firstly, use parameters!
Concatenating values supplied by a user directly into your SQL statement exposes your to SQL injection, either intentional (i.e. users entering their own SQL statements to sabotage your database) or unintentional (e.g. users entering values containing apostrophes or other SQL delimiters).
Instead, represent each of the field values with a parameter, for example:
With CurrentDb.CreateQueryDef _
( _
"", _
"insert into " & _
"tblcases (casename, casewidth, caseheight, casecasters, caseweight, casedepth, casecategory) " & _
"values (#casename, #casewidth, #caseheight, #casecasters, #caseweight, #casedepth, #casecategory) " _
)
.Parameters("#casename") = txtNewCaseName
.Parameters("#casewidth") = txtCaseWidth
.Parameters("#caseheight") = txtCaseHeight2
.Parameters("#casecasters") = chkboxCasters
.Parameters("#caseweight") = txtCaseWeight
.Parameters("#casedepth") = txtCaseDepth
.Parameters("#casecategory") = cboCaseCategory
.Execute
End With
Since the value of each form control is fed directly to the parameter within the SQL statement, the value will always be interpreted as a literal and cannot form part of the SQL statement itself.
Furthermore, you don't have to worry about surrounding your string values with single or double quotes, and you don't have to worry about formatting date values - the data is used in its native form.
Where testing for an existing value is concerned, you can either use a domain aggregate function, such as DLookup, or you could use a SQL select statement and test that no records are returned, e.g.:
Dim flg As Boolean
With CurrentDb.CreateQueryDef _
( _
"", _
"select * from tblcases where " & _
"casename = #casename and " & _
"casewidth = #casewidth and " & _
"caseheight = #caseheight and " & _
"casecasters = #casecasters and " & _
"caseweight = #caseweight and " & _
"casedepth = #casedepth and " & _
"casecategory = #casecategory " _
)
.Parameters("#casename") = txtNewCaseName
.Parameters("#casewidth") = txtCaseWidth
.Parameters("#caseheight") = txtCaseHeight2
.Parameters("#casecasters") = chkboxCasters
.Parameters("#caseweight") = txtCaseWeight
.Parameters("#casedepth") = txtCaseDepth
.Parameters("#casecategory") = cboCaseCategory
With .OpenRecordset
flg = .EOF
.Close
End With
End With
If flg Then
' Add new record
Else
' Record already exists
End If
Finally, you're currently testing the values of your form controls against the literal string "Null", which will only be validated if the user has entered the value Null into the control, not if the control is blank.
Instead, you should use the VBA IsNull function to check whether a variable holds a Null value.
I'm getting error in ms access while trying change subform recordsource based on combo box
The SELECT statement includes a reserved word or an argument name that is misspelled or missing, or the punctuation is incorrect.
here my code
Private Sub Text4_AfterUpdate()
If (Me.Text4.Value = "(ALL)") Then
filterORIGIN_COD = "SELECT SUMMARY.DEST_CITY, SUMMARY.DESTINATION, Count(SUMMARY.CNOTE_NO) AS CountOfCNOTE_NO1" & _
"FROM SUMMARY" & _
"WHERE (((SUMMARY.ORIGIN_CODE) Like " & "'" * "'" & ")))" & _
"GROUP BY SUMMARY.DEST_CITY, SUMMARY.DESTINATION, SUMMARY.TGL_DATA, SUMMARY.ORIGIN_CODE, SUMMARY.ORIGIN, SUMMARY.DEST_CODE;"
Else
filterORIGIN_COD = "SELECT SUMMARY.DEST_CITY, SUMMARY.DESTINATION, Count(SUMMARY.CNOTE_NO) AS CountOfCNOTE_NO1" & _
"FROM SUMMARY" & _
"WHERE (((SUMMARY.ORIGIN_CODE)=" & """Me![Text4]""" & ")))" & _
"GROUP BY SUMMARY.DEST_CITY, SUMMARY.DESTINATION, SUMMARY.TGL_DATA, SUMMARY.ORIGIN_CODE, SUMMARY.ORIGIN, SUMMARY.DEST_CODE;"
End If
Me![OUTBOUND_DETAIL].Form.RecordSource = filterORIGIN_COD
Me![OUTBOUND_DETAIL].Requery
End Sub
ADDITIONAL
actually I'm trying to filter subform (query record source), can someone show me better ways to do that? :)
If trying to filter subform in a trigger event, simply use DoCmd.ApplyFilter or DoCmd.SetFilter (for Access 2010+) methods which are also available in macros:
Private Sub Text4_AfterUpdate()
DoCmd.ApplyFilter , "[SUMMARY.ORIGIN_CODE]='" & Me![Text4] & "'"
End Sub
I have an MS Access 2007 front end to a MS SQL Server 2008R2 back end.
I've got a query that's part of a loop, and it's suddenly started generating Run-time error '3146': ODBC--call failed. errors on one query as the loop itterates. Oddly, it's not the first iteration. EDIT: When I say suddenly, it's been running like this just fine for several months (probably since March).
Set db = CurrentDb
db.QueryTimeout = 480 'thought there was a timeout issue, so set this very high
Set SupvRS = db.OpenRecordset("SELECT DISTINCT tblProcessors.Supervisor, tblProcessors.SupervisorEmail " & _
" FROM tblProcessors INNER JOIN (tblAuditPr INNER JOIN tblAuditPr_A ON tblAuditPr.PrAudit_ID = tblAuditPr_A.PrAudit_ID)" & _
" ON tblProcessors.Processor = tblAuditPr_A.Processor" & _
" WHERE tblProcessors.Supervisor IS NOT NULL " & _
" AND tblAuditPr.EndDate BETWEEN " & GetSQLDate(Me.txtFrom) & " AND " & GetSQLDate(Me.txtTo) & _
" AND tblProcessors.Processor<>'Default Processor' " & _
" AND tblAuditPr_A.Answer Not In ('NA','NF')" & _
" AND tblAuditPr.Status = 'Submitted'")
Do While Not SupvRS.EOF
'Send Supervisor Email
Attachment = PARG.GenerateAuditReport(SupvRS.Fields("Supervisor"), parSupervisor, Me.txtFrom, Me.txtTo)
Set EmailRS = db.OpenRecordset("SELECT * FROM tblProcessors WHERE Supervisor = " & GetSQLString(SupvRS.Fields("Supervisor")))
If EmailRS.EOF Then
Err.Raise -234923, Description:="Cannot find tblProcessors record for " & SupvRS.Fields("Supervisor") & "."
End If
If IsNull(EmailRS.Fields("SupervisorEmail")) Then
MailTo = <redacted>
Else
MailTo = EmailRS.Fields("SupervisorEmail")
End If
Set EmailRS = Nothing
Mailer.AddMailDocument MailTo:=MailTo, _
Subject:=Subject, _
Body:=Body, _
Attachments:=Attachment, _
From:=<redacted>
'Iterate processor emails if requested.
If Me.chkProcessor Then
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'----------------------------------------------------------------------------------------
'ERROR occurs here, but only after several supervisors have successfully passed through
Set ProcRS = db.OpenRecordset("SELECT DISTINCT tblProcessors.Processor, tblProcessors.ProcessorEmail FROM tblAuditPr" & _
" INNER JOIN (tblProcessors INNER JOIN tblAuditPr_A ON tblProcessors.Processor = tblAuditPr_A.Processor) " & _
" ON tblAuditPr.PrAudit_ID = tblAuditPr_A.PrAudit_ID" & _
" WHERE tblProcessors.Supervisor = " & GetSQLString(SupvRS.Fields("Supervisor")) & _
" AND tblAuditPr.EndDate BETWEEN " & GetSQLDate(Me.txtFrom) & " AND " & GetSQLDate(Me.txtTo))
'----------------------------------------------------------------------------------------
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Do While Not ProcRS.EOF
If Not IsNull(ProcRS.Fields("ProcessorEmail")) Then
On Error Resume Next
Attachment = PARG.GenerateAuditReport(ProcRS.Fields("Processor"), parProcessor, Me.txtFrom, Me.txtTo)
If Attachment <> "" Then
MailTo = ProcRS.Fields("ProcessorEmail")
Mailer.AddMailDocument MailTo:=MailTo, _
Subject:=Subject, _
Body:=Body, _
Attachments:=Attachment, _
From:=<redacted>
Else
Err.Clear
End If
On Error GoTo 0
End If
ProcRS.MoveNext
Loop
Set ProcRS = Nothing
End If
SupvRS.MoveNext
Loop
As noted in the code, the error occurs on an inner loop that successfully executes for other supervisors. It does consistantly break on one particular individual. Using the GetSQLString and GetSQLDate functions (returns ' delimited, double '' when necessary, pretty strings, and # delimited dates, respectivly, for passing Access queries through to SQL Server) in break mode, I duplicated the exact query that was giving me problems in an Access query. It returned a timeout error, but changing the database default timeout (and closing/opening the db) didn't resolve the issue. I pasted the exact same query into SSMS (replacing the # date delimiters with ') and it executed just fine there (taking about 1:30-2:00 to execute each try).
Taking a pause in typing up this post, I put some error trapping in to see if I could get the actual error message SQL Server was returning, when it ran without error. To me, that indicates that it is likely a time out issue. Anyone have a more educated guess as to what it actually is, or a suggestion on how to make the query more efficient so it doesn't time out?
I am creating form in access in which i have to implement cascading combo boxes , data in lower combo box is dependent on its parent value selected by user. Here is form
on left side is structure of the table and on right side is form. Problem is I am getting error of data type mismatch , unable to understand why this is happening. In the afterupdate event of Diametre of Drill I am populating cutting speed . Whenever I press drop down of Cutting Speed "Datatype mismatch in criteria expression" occurs. Here is code of afterupdate event of Diametre of Drill
Private Sub cboDiameterDrilling_AfterUpdate()
cboCuttingSpeedDrilling.RowSource = "Select DISTINCT tblDrilling.cuttingSpeed " & _
"FROM tblDrilling " & _
`"WHERE tblDrilling.materials = '" & cboMaterialDrilling.Value & "' AND tblDrilling.diaOfDrill = '` `cboDiameterDrilling.Value ' " & _`
"ORDER BY tblDrilling.cuttingSpeed;"
End Sub
I think problem is in WHERE Clause . Any help would be greatly appreciated. Thank you
You've surrounded the reference to the object's value (cboDiameterDrilling.Value ) in single quotes.
AND tblDrilling.diaOfDrill = ' & cboDiameterDrilling.Value & "'"
Solution : AND tblDrilling.diaOfDrill = " & cboDiameterDrilling.Value & " " & _
I think you missed a ". Try:
Private Sub cboDiameterDrilling_AfterUpdate()
cboCuttingSpeedDrilling.RowSource = "Select DISTINCT tblDrilling.cuttingSpeed " & _
"FROM tblDrilling " & _
`"WHERE tblDrilling.materials = '" & cboMaterialDrilling.Value & "' AND tblDrilling.diaOfDrill = '" & cboDiameterDrilling.Value & "' " & _
"ORDER BY tblDrilling.cuttingSpeed;"
End Sub
I have an Access application where everytime a user enters the application, it makes a temp table for that user called 'their windows login name'_Temp. In one of my reports I need to query using that table, and I can't just make a query and set it as the recourdsource of the report, since the name of the table is always different.
What I tried then was to programatically set the recordset of the report by running the query and setting the form's recordset as the query's recordset. When I tried this, it kept giving me an error about the query.
I tried to debug, and I found that the string variable isn't able to contain the whole query at once. When I ran it with break points and added a watch for the string variable, it shows me that it cuts off the query somewhere in the middle.
I've experienced this problem before, but that was with an UPDATE query. Then, I just split it into two queries and ran both of them separately. This one is a SELECT query, and there's no way I can split it. Please help!
Thank you
Heres what I've tried doing:
ReturnUserName is a function in a module that returns just the login id of the user
Private Sub Report_Open(Cancel As Integer)
Dim strQuery As String
Dim user As String
user = ReturnUserName
strQuery = "SELECT " & user & "_Temp.EmpNumber, [FName] & ' ' & [LName] AS [Employee Name], " & _
"CourseName, DateCompleted, tblEmp_SuperAdmin.[Cost Centre] " & _
"FROM (tblCourse INNER JOIN (" & user & "_Temp INNER JOIN tblEmpCourses ON " & _
user & "_Temp.EmpNumber = EmpNo) ON tblCourse.CourseID = tblEmpCourses.CourseID) " & _
"INNER JOIN tblEmp_SuperAdmin ON " & user & "_Temp.EmpNumber = tblEmp_SuperAdmin.EmpNumber" & _
"WHERE (((" & user & "_Temp.EmpNumber) = [Forms]![Reports]![txtEmpID].[Text])) " & _
"ORDER BY CourseName;"
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Dim rsCmd As ADODB.Command
Set rsCmd = New ADODB.Command
rsCmd.ActiveConnection = CurrentProject.Connection
rsCmd.CommandText = strQuery
rs.Open rsCmd
Me.Recordset = rs
rs.Close
End Sub
This what strQuery contains when I add a breakpoint on rsCmd.CommandText = strQuery:
SELECT myusername_Temp.EmpNumber, [FName]
& ' ' & [LName] AS [Employee Name],
CourseName, DateCompleted,
tblEmp_SuperAdmin.[Cost Centre] FROM
(tblCourse INNER JOIN (myusername_Temp
INNER JOIN tblEmpCourses ON
myusername_Temp.EmpNumber = EmpNo) ON
tblCourse.CourseID=
(It's all one line, but I've written it like this because the underscores italicize the text)
And the error I get says Run Time Error: Join not Supported.
Not quite what I was hoping for, but guessing, for:
strQuery = "long query goes here"
Try:
strQuery = "some long query goes here "
strQuery = strQuery & "more query goes here "
BASED ON NEW INFORMATION:
strQuery = "SELECT " & user & "_Temp.EmpNumber, [FName] & ' ' & [LName] AS [Employee Name], " & _
"CourseName, DateCompleted, tblEmp_SuperAdmin.[Cost Centre] " & _
"FROM (tblCourse " & _
"INNER JOIN tblEmpCourses ON tblCourse.CourseID = tblEmpCourses.CourseID) " & _
"INNER JOIN (Temp INNER JOIN tblEmp_SuperAdmin " & _
"ON Temp.EmpNumber = tblEmp_SuperAdmin.EmpNumber) " & _
"ON Temp.EmpNumber = tblEmpCourses.EmpNo " & _
"WHERE " & user & "_Temp.EmpNumber = " & [Forms]![Reports]![txtEmpID] & _
" ORDER BY CourseName;"
Note that in VBA:
& [Forms]![Reports]![txtEmpID].[Text] &
That is, the reference to the form must go outside the quotes so you get the value.
NEW INFORMATION #2
Your best bet would be to add these tables to the Access query design window and create the joins that you want, then switch to SQL view and use the string generated for you. I do not believe that the string is too long, only that the SQL is incorrect. The SQL I posted above should work, but it may not be what you want.
You can programmatically create a querydef that fits the user. So, when your report is called, you
Delete LoginName_Query_Temp (CurrentDb.QueryDefs.Delete), if it already exists.
Create the querydef (CurrentDB.CreateQueryDef), using LoginName_Temp as the table name.
Set the RecordSource of your Report to LoginName_Query_Temp.
Open the report.
I don't see what purpose the table myusername_Temp serves here. Is that where the name fields are? If so, avoid the join entirely:
Dim lngEmpNumber As Long
Dim strName As String
Dim strSQL As String
lngEmpNumber = Forms!Reports!txtEmpID
strName = DLookup("[FName] & ' ' & [LName]", "myusername_Temp", "EmpNumber=" & lngEmpNumber
strSQL = "SELECT " & Chr(34) & strName & Chr(34) & " AS [Employee Name], " & _
"CourseName, DateCompleted, tblEmp_SuperAdmin.[Cost Centre] " & _
"FROM tblCourse " & _
"INNER JOIN tblEmpCourses " & _
"ON tblCourse.CourseID = tblEmpCourses.CourseID) " & _
"INNER JOIN tblEmp_SuperAdmin " & _
"ON tblEmp_SuperAdmin.EmpNumber = tblEmpCourses.EmpNo " & _
"WHERE tblEmp_SuperAdmin.EmpNumber = " & lngEmpNumber & _
" ORDER BY CourseName;"
Now, the parentheses may need to be changed in the join (I always do my equi-joins in the Access QBE and let it take care of the getting the order and parens correct!), and my assumptions about the purpose of the temp table may be wrong, but I don't see it being used for anything other than as an intermediate link between tables, so I guessed it must be there to provide the name fields.
If that's wrong, then I'm at a loss as to why the temp table needs to be there.
Also, in your second post you referred to the control on the form as:
Forms!Reports!txtEmpID.Text
...the .Text property of Access controls is accessible only when the control has the focus. You could use the .Value property, but since that's the default property of Access controls, you should just stop after the name of the control:
Forms!Reports!txtEmpID
...you'll see this is how I did it in my suggested code.
I find the idea of your name-based temp table to be highly problematic to begin with. Temp tables don't belong in a front end, and it's not clear to me that it is actually a temp table. If it's temp data, put it in a shared table and key the record(s) to the username. Then you don't have to worry about constructing the table name on the fly.