I'm having an issue with the following lines of code, I feel its something simple but I can't put my finger on it. I get a Run-time error '91' object variable or with block variable not set error. The error happens on the rsc.OpenRecordSet... line. BadgeV is a number, I have the DAO reference installed, It is pulling from a linked sql server table where I have a primary key and identity. What am I missing?
Function FNC_Scan()
Dim db As DAO.Database
Dim rsc As DAO.Recordset
Set db = CurrentDb()
rsc.OpenRecordset ("SELECT dbo_ScanData.CardID, dbo_ScanData.Complete FROM dbo_ScanData WHERE (((dbo_ScanData.CardID)= Forms![Scan]!BadgeV))) AND ((dbo_ScanData.Complete)=0));")
If rsc.EOF Then
MsgBox "new item"
Else
MsgBox "Append Item"
End If
Set rsc = Nothing
Set db = Nothing
End Function
Should be
set rsc = db.OpenRecordset(...)
instead of
rsc.OpenRecordset(...)
Related
Recently I needed to add the parameter dbSeeChanges to the OpenRecordset method of the Database object in order to prepare the system for SQL Server progressive migration.
The thing is that change seemingly altered the functioning of the Recordset object in the following way.
Previously, if I had a Recordset that returned no records and I used the FindFirst method it went smoothly without errors, it simply found nothing and moved on. But now, in this same scenario, that action raises the following runtime error: 3021 "No current record".
Given a recordset with that returns no records the following code runs without errors:
Dim dbCurrDB As Dao.Database
Dim rstA As Recordset
Set dbCurrDB = CurrentDB
Set rstA = dbCurrDB.OpenRecordset("SomeTable", dbOpenDynaset)
With rst
.FindFirst "Id=1"
If .NoMatch=False Then
.Edit
!SomeField=SomeValue
.Uptade
End If
End With
Given the same conditions, the following code raises that 3021 error on the '.FindFirst "Id=1"' instruction:
Dim dbCurrDB As Dao.Database
Dim rstA As Recordset
Set dbCurrDB = CurrentDB
Set rstA = dbCurrDB.OpenRecordset("SomeTable", dbOpenDynaset, dbSeeChanges)
With rst
.FindFirst "Id=1"
If .NoMatch=False Then
.Edit
!SomeField=SomeValue
.Uptade
End If
End With
I know how to solve the issue (although it will finally force me to correct all legacy...). What I want is to understand why this happens. What exactly did change? Something with the pointer of the Recordset object? And also, if there can be other unintended side effects.
I wonder if there are some detailed technical specifications for DAO that can show me what the heck really happens with the mehods of the Recordset object behind the scenes.
Thanks in advance!
Check for records, or there is nothing to find:
With rst
If .RecordCount > 0 Then
.FindFirst "Id=1"
If .NoMatch = False Then
.Edit
!SomeField.Value = SomeValue
.Update
End If
End If
.Close
End With
In my code I run a SQL statement in VBA like this:
Dim rs As DAO.Recordset
Dim db As DAO.Database
Set db = CurrentDb
Set rs = CurrentDb.OpenRecordset( SQL-Statement)
This SQL-Statement either returns one value or none.
I then want to check wether a value is returned or not.
If IsError(rs.Fields("Name").Value) = True Then
MsgBox(Error)
Else
Variable = rs.Fields("Name").Value
End If
However: If there is an error the method IsError doesn't return true but the script says runtime-error 3021 and breaks.
Why does the method fail on this?
Unfortunately I have to write this on my mobile since I'm not allowed to log in on platforms from my work PC.
Ty all in Advance
You need to check the EOF property of the recordset.
Try this:
If Not rs.EOF Then Variable = rs.Fields("Name").Value
which is the same as
If Not rs.EOF Then Variable = rs![Name]
I have a form that creates two queries, exports them to Excel and then deletes them. However, when I hit an error on my exporting, it doesn't make it the deletions. How would I go about checking to see if they already exist? And if they do, delete them so I can re-create them with the new/updated data?
Code so far:
Dim qdfNewQry As Object
Dim qdfNewWS As Object
'//----- qdfNewQry
If Not IsNull(DLookup("myExportQry", "MSysObjects", "Name='myExportQry'")) Then
CurrentDb.QueryDefs.Delete qdfNewQry.Name
Set qdfNewQry = CurrentDb.CreateQueryDef("myExportQry", exportQry)
Else
Set qdfNewQry = CurrentDb.CreateQueryDef("myExportQry", exportQry)
End If
'//----- qdfNewWS
If Not IsNull(DLookup("myExportWS", "MSysObjects", "Name='myExportWS'")) Then
CurrentDb.QueryDefs.Delete qdfNewWS.Name
Set qdfNewWS = CurrentDb.CreateQueryDef("myExportWS", exportWS)
Else
Set qdfNewWS = CurrentDb.CreateQueryDef("myExportWS", exportWS)
End If
I'm getting the error "The expression you entered as a query parameter produced this error: 'myExportQry'" on the line If Not IsNull(DLookup("myExportQry", "MSysObjects", "Name='myExportQry'")) Then
I'm pretty lost it seems. Any help/advice/corrections would be greatly appreciated!
EDIT1:
Just for clarification, I'm wanting to delete the entire query. Other alternative solutions would also be welcome!
I wouldn't use the Dlookup function for this!
Private Sub Command1_Click()
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Set db = CurrentDb()
For Each qdf In db.QueryDefs
Debug.Print qdf.Name
If qdf.Name = "strQry" Then
CurrentDb.QueryDefs.Delete "strQry"
CurrentDb.QueryDefs.Refresh
Exit For
End If
Next qdf
Set qdf = Nothing
Set db = Nothing
End Sub
DLookup uses the following format:
DLookup([Field], [Table], [Criteria])
There's no field in MSysObjects named "MyExportQuery". So, the first argument in DLookup() is wrong.
Also, remember that when you use a reserved word (like "Name"), you need to enclose it in brackets.
I think you want to say,
DLookup("[ID]", "MSysObjects", "[Name]='myExportQry'")
That should either return a number or a NULL, so that will give you what you need to determine if the query already exists.
The above is untested, but logically it makes sense to me.
I use this. If the query is not there the DeleteObject will be "skipped"
On Error Resume Next
DoCmd.DeleteObject acQuery, "myExportQry"
Set qdfTemp = CurrentDb.CreateQueryDef("myExportQry", "SELECT From ....")
In an access application's VBA code there is a function to convert some database fields over to another format. This happens for 2 tables, in code you can tell them appart by the 2 loops, for BOM and ROUTING. This code had poor performance because sometimes 200000+ records passed through it. In order to speed it up I added transactions to it- its 3x as fast now. However, when trying to close the ROUTING recordset, I get an error saying "object invalid or no longer set". Therefor I added 2 checks to it, a not nothing and not null before I attempt to close it. when stepping through with the debugger it passes both checks and then attempts to close the recordset, then goes to ErrorHandler which gives the message. What makes this error extra weird is that it has no problems closing the BOM recordset for the first loop.
Code:
Public Sub SomeSub()
' set up variables
Dim BOM As DAO.Recordset
Dim ROUTING As DAO.Recordset
Dim Workspace As DAO.Workspace
Set Workspace = DBEngine.Workspaces(0)
' set up errorhandler
On Error GoTo ErrorHandler
' run some process on BOM
Set BOM = CurrentDb.OpenRecordset("some query;", dbOpenDynaset, dbSeeChanges, dbOptimistic)
Workspace.BeginTrans
If Not (BOM.BOF And BOM.EOF) Then
BOM.MoveFirst
Do While (Not BOM.EOF) And (Not BOM.BOF)
' Do some stuff with BOM here
BOM.MoveNext
Loop
End If
Workspace.CommitTrans
BOM.Close
Set BOM = Nothing
Set ROUTING = CurrentDb.OpenRecordset("some query;", dbOpenDynaset, dbSeeChanges, dbOptimistic)
Workspace.BeginTrans
If Not (ROUTING.BOF And ROUTING.EOF) Then
ROUTING.MoveFirst
Do While (Not ROUTING.EOF)
' Do some stuff with ROUTING here
ROUTING.MoveNext
Loop
End If
Workspace.CommitTrans
Workspace.Close
If Not ROUTING Is Nothing Then
If Not ROUTING Is Null Then
ROUTING.Close
End If
End If
GoTo SuccesHandler
ErrorHandler:
MsgBox "Ran into error. Info: " & Err.number & ": " & Err.DESCRIPTION & vbNewLine
Resume SuccesHandler
SuccesHandler:
End Sub
Questions:
- Why does this error happen?
- What is the proper way of null/nothing checking? (obviously the way Im doing it doesn't work?)
You need to close the Recordset before closing the Workspace.
Workspace.CommitTrans
If Not ROUTING Is Nothing Then
ROUTING.Close
Set ROUTING= Nothing
End If
Workspace.Close
Set Workspace = Nothing
I would adjust that block to match the one that works - and move the Workspace handling out of the block:
Set ROUTING = CurrentDb.OpenRecordset("some query;", dbOpenDynaset, dbSeeChanges, dbOptimistic)
Workspace.BeginTrans
If Not (ROUTING.BOF And ROUTING.EOF) Then
ROUTING.MoveFirst
Do While (Not ROUTING.EOF)
' Do some stuff with ROUTING here
ROUTING.MoveNext
Loop
End If
Workspace.CommitTrans
ROUTING.Close
Set ROUTING = Nothing
Set Workspace = Nothing
I am fetching a set of names from a database query and then reformatting it to a comma separated list. As I am using this functionallity a few Places in my app, I try to write it as a function getting the sql-query and returning the string.
Public Function String_from_query(StrSQL As String) As String
Dim dbs As Database
Dim rs As Recordset
Set dbs = CurrentDb
Dim results As String
results = ""
Set rs = dbs.OpenRecordset(StrSQL)
If Not (rs.EOF And rs.BOF) Then
rs.MoveFirst
Do While Not rs.EOF
If results > "" Then
results = results & ", "
End If
results = results & rs("Navn")
rs.MoveNext
Loop
End If
Set String_from_query = results
End Function
This is then called from an event handler:
Private Sub Detalj_Format(Cancel As Integer, FormatCount As Integer)
Dim StrSQL As String
StrSQL = "SELECT Personer.Navn FROM Personer INNER JOIN Personoppgaver ON Personer.Initialer = Personoppgaver.Initialer WHERE Personoppgaver.Oppgaveid =" & Me.Oppgaveid.Value
Me.Tekst52.Value = String_from_query(StrSQL)
End Sub
If I have the code from the String_from_query function within the event handler and then directly assigns Me.Tekst52 to results, everything works fine. When I refactor the code as shown, I get a "Compile Error, Object required" when I try to run it and a marker on the last line in the sub. (Set String_from_query = results). I am not able to see what is wrong. Any help?
The keyword Set is only required when assigning variables to an Object. For Access, this would be Forms, Reports, Recordsets, etc. Or other Objects outside of Access (FileSystemObject, for example).
When setting strings, dates, numbers, etc, you do not need Set.
You can surmise this from the error message as well, Object required.