Cannot Update. Database or Object is Read-only after Requery - ms-access

Okay, cannot find anything online about this error, so here goes.
Using Access 2003. I have a form that has a combobox dropdown. Users choose from the dropdown, and the VBA code looks at a particular table to see if data already exists. If it finds it, it displays the data associated with the record. If it does not find it, it adds a new record to the table, then tries to display the new data. The problem is that when using the following code, it does not display the new data, unless I add in Me.Requery. However, if I do that, it then gives me the above error if I try to do the same process again.
So, how can I get the data to display after adding without the above error?
Here is the relevant code...
' Find the record that matches the control.
Dim rs As DAO.Recordset
Set rs = Me.Recordset.Clone
'if no record found, then add a default record
If IsNull(Combo119) Then
Set rs = CurrentDb.OpenRecordset("SELECT * FROM [Master Reject Data]")
rs.AddNew
rs.Fields("production Date") = Date
rs.Fields("Work Order #") = Combo119.Column(0)
rs.Fields("Product Type") = ""
rs.Fields("Shift") = ""
rs.Fields("Line") = ""
rs.Fields("# Produced") = 0
rs.Fields("Reject Type") = ""
rs.Fields("Reject Quantity") = 0
rs.Fields("Reject Category") = "Rejection"
Dim tRec As Long
tRec = Combo142.ItemData(0)
rs.Fields("Report Number") = tRec
rs.Update
Me.Requery 'this is the line I added to try to get the data to appear
Set rs = Me.Recordset.Clone
rs.FindFirst "[Report Number] = " & tRec 'navigate to the newly added record
Else
rs.FindFirst "[Report Number] = " & Nz(Me![Combo119], 0) 'navigate to the record with the requested report number
End If
If Not rs.EOF Then Me.Bookmark = rs.Bookmark

Sorry, found the issue after looking at it again. The problem is that the Me.Requery statement needs to be Me.Recordset.Requery. After doing that and adding Me.Refresh, it works as intended.

To avoid requerying I think you should open the recordset specifying that it should be a dynaset
CurrentDb.OpenRecordset("SELECT * FROM [Master Reject Data]", dbOpenDynaset) - in case you want to make it a bit neater. as for the small bug, I see you've already found yourself

Related

Check a filtered table for specific data

I have a form (frm_Property) that shows information for a property and within that form another form (frm_Rate) that is a filtered table that displays all rates associated with that property. I want to check the filtered rate table to make sure that there are either no rates entered or there is a current rate (ie the current date falls between the start and end date of a rate). If there is no current rate (only with other rates entered) I want to stop the close of the form and a message box to open telling the user to enter a current rate.
After searching and complying many different things, this is the code that I have currently.
Private Sub Form_Unload(Cancel As Integer)
Dim rs As DAO.Recordset
Dim currdate, check As String
Set rs = CurrentDb.OpenRecordset("SELECT * FROM tbl_Rate WHERE Property = " & Me.Property)
currdate = Date
'Check to see if the recordset actually contains rows
If Not (rs.EOF And rs.BOF) Then
rs.MoveFirst
Do Until rs.EOF = True
'Check if rate is current rate
If currdate >= [tbl_rate.Start_Date] And currdat <= [tbl_rate.End_Date] Then
check = "Good"
Exit Do
Else
'Move to the next record.
check = "Bad"
rs.MoveNext
End If
Loop
MsgBox check 'testing to see if correctly identified if current rate exists
Else
MsgBox "There are no records in the recordset."
End If
If check = "Bad" Then
MsgBox "Please enter current rate."
Cancel = True
End If
rs.Close 'Close the recordset
Set rs = Nothing 'Clean up
End Sub
Currently it can detect if no record is entered, but it always tells me that there is no current rate even if there is and I am not sure why.
I also have this code located within frm_rate. I don't know if that is why I am having difficulty stopping the form from closing. I was reading about on unload stopping the form from closing which is why I chose that one. I suspect I am having trouble because my "On Unload" is in the subform.
Any insight would be much appreciated.
Unload event for subform occurs after Unload of main form, so the code in subform is useless. In main form you need to save the data first Me.Dirty = false After this your code will be able to see new data in table. Also you can use RecordsetClone property of subform for accessing the data in in subform.
Use the RecordsetClone of the subform and FindFirst:
Dim currdate As String
Set rs = Me!NameOfYourSubformCONTROL.Form.RecordsetClone
' Check to see if the recordset actually contains rows.
If rs.RecordCount = 0 Then
check = "Empty"
Else
' Check if rate is current rate.
currdate = Format(Date, "yyyy\/mm\/dd"
rs.FindFirst "#" & currdate "# Between tbl_rate.Start_Date And tbl_rate.End_Date"
If Not rs.NoMatch Then
check = "Good"
Else
check = "Bad"
End If
End If

How to find next record based on combobox "filter"

I have a form with two comboboxes, the first (cboSet) picks a class set, the second (cboName) displays student names within that set (the ID is hidden in the 1st column). I have a button which I would like to use to find the next student in that set. I have tried implementing a next button which will go to the next record but not the correct student. Any help would be much appreciated.
When you say next student, do you mean the student with the next numerical ID or are you using some other criteria for the next student?
here's one possible solution assuming that you want to filter your form with the next student. Without more details this example is somewhat vague. Seeing what you already have would make it more precise.
in the onclick event of your button:
Dim ID as Integer
ID = me.cboName.column(0) + 1
me.filter = "[ID] = " & ID
me.filteron = true
to find the next value in your set you could do something like the following, Of course this is only generic, basic (hopefully someone correct) code, so you'll have to change it to suit your needs, but it should point you in the correct direction.
dim db as dao.database
dim rs as dao.recordset
dim nextID as interger
dim SQLquery as string
nextID = 0
SQLquery = "SELECT TOP 1 ID from COMBO_RECORD_SOURCE WHERE ID > " & me.namecombo.column(0) & " ORDER BY ID"
set db = currentdb
set rs = db.openrecordset(SQLquery,dbOpenSnapshot)
if rs.recordCount > 0 THEN
rs.movefirst //I know it's not strictly necessary, old habit I like to do..
nextID = rs!ID
end if
if nextID > 0 then
me.filter = "[ID] = " & nextID
me.filteron = true
else
msgbox "There are no more names in this set."
end if
set rs = nothing
set db = nothing

Get Record based on form textbox value

I am trying to get a record based on the value contain within the textbox on a form. i.e i type in the information into the textbox and other values associated with that value are returned to other textbox on the form.
I thought this would be easy but can't seem to get it to work.
Currently I was trying
Dim rst As DAO.Recordset
Dim SQL As String
Dim SQL2 As String
SQL = "SELECT tblmytbl.[IDCODE]"
"FROM tblmytbl " & _
"WHERE (((tblmytbl.[IDCODE]) = forms!myform!mybox.value "
Set db = CurrentDb
Set rst = db.OpenRecordset(SQL)
If Not ((rst.BOF = True) And (rst.EOF = True)) Then
Forms!myform!Text102 = rst.Fields("[Name]")
Forms!myform!Text103 = rst.Fields("[Surname]")enter code here
Note: The search information is alphanumeric and i have tried without the .value
Any help would be appreciated.
Thanks
The SQL you send to the server can't access the form. However, you can concatenate the value into the string that you send like:
" WHERE (((mytable.myfield) = '" & FixQuotes(Forms!myform!mybox.value) & "') " & _
Note, you may need to defend yourself against SQL injection, a simple (but not complete) defense would be something like:
Public Function FixQuotes(input as string) As String
FixQuotes = Replace(input,"'","''")
End Function
EDIT:
Based on your updated code, there's quite a number of changes you need to make. Beyond my statement above, the .OpenRecordset only applies to full tables, you can't use it with a SELECT statement. Instead, you have to instantiate a QueryDef. On top of that, you try to reference fields you didn't include in the query. Also, you can simplify the expression Forms!myform! to Me (which could help if you want to reuse the code somewhere else) So your code should look something like this:
Dim db as Database 'always dim everything, you should use Option Explicit'
Dim rst as Recordset 'DAO is the default anyway'
Dim qdf as QueryDef 'this object is required for queries'
Set db = CurrentDb
'prepare single-use query, to return the values you're going to use
'as mentioned before, the query doesn't have access to the form
'we can use Me since it references the form'
' use TOP 1 since you only expect 1 record'
Set qdf = db.CreateQueryDef("","SELECT TOP 1 Name,Surname FROM tblmytbl " & _
"WHERE IDCODE = '" & FixQuotes(Me.mybox.value) & "';")
Set rst = qdf.OpenRecordset(DbOpenForwardOnly)
'forwardonly since you only care about the first record'
If Not rst.EOF Then 'ForwardOnly has to start at the first record'
Me.Text102.Value = rst!Name
Me.Text103.Value = rst!Surname
'I highly suggest giving these boxes better names'
Else
'no record found'
End if
rst.Close
qdf.Close
db.Close 'close these objects, it can sometimes cause memory leaks otherwise'

Setting focus in MS Access

I am creating a recordset from a Qdefs and then displaying the records in a form.
When I filter the values, focus is going to the first record. But, I want the focus to point to the same record that was in focus before filtering.
This is how am creating a recordset from an existing querydefs before and after filtering
db.QueryDefs("Query_vinod").Sql = filter
Set rs_Filter_Rowsource = db.OpenRecordset("Abfr_SSCI_Check_Findings_List")
I think you can do this by using a bookmark. Set up a RecordsetClone and then find your active record by using the FindFirst method. I have some sample code that will need to be modified a little to fit your exact variables:
Dim Rs As Recordset
Dim Test As Integer
Dim varBookmark As Variant
DoCmd.OpenForm "Contracts"
Set Rs = Forms!Contracts.RecordsetClone
Rs.FindFirst ("[ID] = '" & Me![ID] & "'")
varBookmark = Rs.Bookmark
Forms!Contracts.Form.Bookmark = varBookmark
If Rs.NoMatch Then
MsgBox "That does not exist in this database."
Else
End If

Copying a record in VBA 2 (the new question)

I have this code that I am trying to copy a record with in VBA. Unfortunately I cannot get it to work. I do not knw why it won't do anything.
Dim OldRecord As DAO.Recordsets, NewRecord As DAO.Recordset
Dim strSQL As String
strSQL = "SELECT [Tote Log].* FROM [Tote Log] WHERE Number = " & _
Me.tbScannerRead.Value
Set OldRecord = CurrentDb.OpenRecordset(strSQL)
If OldRecord.Count = 1 Then
Set NewRecord = _
CurrentDb.OpenRecordset("SELECT [Tote Log].* FROM [Tote Log]")
With NewRecord
.AddNew
For i = 0 To .Fields.Count - 1
.Fields(i).Value = OldRecord.Fields(i).Value
Next i
.Fields("Number").Value = Me.tbScannerRead & "B2"
.Update
varBookMark = .Bookmark
End With
NewRecord = varBookMark
DoCmd.RunCommand acCmdSelectRecord
Me.tbMessageBox = "Added new record"
Me.tbMessageBox.Visible = True
GoodToteRead = False
Me.tbScannerRead.SetFocus
End If
I get nothing, I am trying to copying a record from the tote log and change the number from, lets say, L20444 to L20444B2 and have the same field information as the original. This is where I am so far but I get nothing. Ahy Help would be greatly, and I mean greatly, appreciated. Thanks
There are a few things that could be causing it. Here is one. Does your table have a primary key? It looks like you are trying to update the primary key to a value that already exists in the table before changing it. Is this happening on a form? If so Access can get upset at you for changing a recordset behind it's back. a me.undo() before making changes can help. Also if you are on a form you can acomplish the same thing this way. It's a bit hacky, but it is the easy way.
DoCmd.RunCommand acCmdSelectRecord
DoCmd.RunCommand acCmdCopy
DoCmd.GoToRecord , , acNewRec
DoCmd.RunCommand acCmdPaste
As an alternative, I would recommend something along these lines.
Dim sSql As String
Dim sUpdateSuffix as string
sUpdateSuffix="B2"
Const sTableName As String = "[Tote Log] "
sSql = "INSERT INTO "[Tote Log]([number],[whateverelse]) " & _
"SELECT [number]" & sUpdateSuffix & ",[whateverelse] FROM [Tote Log] WHERE Number = " & Me.tbScannerRead.Value
CurrentProject.Connection.Execute sSql
If you want to build the sql string dynamically use the same method as you already used to loop through the fields and build the query string.
me.requery will rebuild the form recordset.
Hope that helps you
Well it might actually be saving the database record but not redisplaying it; I'm having a hard time deciphering that part of the code, and I don't know what your form is bound to.
Anyway, you should open your recordsets like this:
Set rs = db.OpenRecordset(strSQL, dbOpenDynaset, dbSeeChanges)
especially if you are using SQL Server as the backend (which you should).
Once you have saved the record, you should probably just reload the record back into your form by doing a recordset.find(), rather than trying to bookmark it. Bookmarks only work on the same recordset they originated from. This provides round-trip verification that the data was actually saved into the database.