MSAccess Form Search-Button conflicts with Edit-Button - vba

I'm new to this forum and quite new to Access. I have the following problem. I've created an Form/Subform to edit the Data of a Query. Two Controls seem to be in conflict in my code.
"Search_Order" is an unbound text field. If text is entered and enter is pressed the corresponding fields of a query are shown. The code looks like the following:
Set rs_Search = Me.RecordsetClone
rs_Search.FindFirst "[OrderNumber]=""" & Search_Order & """"
If rs_Search.NoMatch Then
MsgBox "Sorry, no such record '" & Search_Order & "' was found.", _
vbOKOnly + vbInformation
Else
Me.Recordset.Bookmark = rs_Search.Bookmark
End If
rs_Search.Close
Search_Order = Null
Set rs_Search = Nothing
End Sub
The second command "ButtonSetOrderDetails10" should create a RecordsetClone of the Subform "sfrmChangeOrderDetails" and change the Value of the Field "OrderStatus" to the Vlaue of "10".
It has this code:
Private Sub ButtonSetOrderDetails10_Click()
Dim rs_Status_Change As DAO.Recordset
Set rs_Status_Change = Me.sfrmChangeOrderDetails.Form.RecordsetClone
With rs_Status_Change
Do While Not .EOF
.Edit
.Fields("OrderStatus") = 10
.Update
.MoveNext
Loop
End With
rs_Status_Change.Close
Set rs_Status_Change = Nothing
End Sub
I've looked both codes here up and modified them to the needs of my database. Both codes work fine so far, but unfortunately only once.
My problem is that as soon as I hit the Button "ButtonSetOrderDetails10" I can't do the same trick with a different order. I can search for the other order, it is displayed but the Button "ButtonSetOrderDetails10" does not work anymore. If I close the Form and reopen it, it works again.
It would be great if someone can give me a hint what I'm doing wrong here.
Best regards, Ferdi

I am surprised even works one time. With DAO recordset need to read dataset into memory before it will be able see records for edit otherwise just sees EOF and the loop doesn't run. Try:
rs_Status_Change.MoveLast
rs_Status_Change.MoveFirst
With rs_Status_Change
Don't even need to declare/set/close a recordset object.
Private Sub Search_Order_AfterUpdate()
With Me.RecordsetClone
.FindFirst "[OrderNumber]='" & Me.Search_Order & "'"
If .NoMatch Then
MsgBox "Sorry, no such record '" & Me.Search_Order & "' was found.", _
vbOKOnly + vbInformation
Else
Me.Bookmark = .Bookmark
End If
End With
Me.Search_Order = Null
End Sub
Private Sub ButtonSetOrderDetails10_Click()
With Me.sfrmChangeOrderDetails.Form.RecordsetClone
.MoveLast
.MoveFirst
Do While Not .EOF
.Edit
.Fields("OrderStatus") = 10
.Update
.MoveNext
Loop
End With
End Sub
Could really simplify code by running an UPDATE action SQL.
Private Sub ButtonSetOrderDetails10_Click()
CurrentDb.Execute "UPDATE ChangeOrderDetails SET OrderStatus=10 WHERE OrderNumber='" & Me.OrderNumber & "'"
End Sub

Related

changing sql string based on active userform

I have a SQL query that I'm calling from a couple of different forms using the ctrl as object method. It works fine, but when I run it from a click event it will also open whichever form isn't currently loaded. The query returns the results I want, it just does it to both forms at the same time regardless of which is loaded.
Only one form is loaded at a time. A drop down list called Team exists on both forms. The query passes the currently selected item from that drop down list to return a list of agents assigned to that team.
I know that part of the issue is my query using an or statement that refers to values on both forms, but I'm not sure how to change it to reference the active form.
Attendance and reporting are the names of the two UserForms currently calling this query. Both of them have combobox controls named Team. I've tried activeform, etc. But I can't seem to find a way to make it work.
Sub agents(ctrl As Object)
database_connect
Dim SQLStr As String
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Dim Counter As Long
SQLStr="select distinct[Agentname] from dbo.[Attendance] Where [Team]='" & _
attendance.Team.Value & "' or [Team] ='" & Reporting.Team.Value & "'"
If appconn.State = 0 Then
Call database_connect
End If
rs.Open SQLStr, appconn, adOpenStatic
With ctrl
Do
.AddItem rs![Agentname]
rs.MoveNext
Loop Until rs.EOF
End With
rs.Close
database_Disconnect
Set rs = Nothing
Exit Sub
End Sub
1) Well first off to refer to controls you have to have the form loaded.
2) Youre referring to controls in the oddest way. Review AND save this URL http://access.mvps.org/access/forms/frm0031.htm
3) If one form is closed your query might always return nothing. Is this a desired output?
For anyone who may find this looking for something similar, this is the solution I used.
I used a Function to test if a userform is loaded or not.
Public Function IsLoaded(formName As String) As Boolean
Dim frm As Object
For Each frm In VBA.UserForms
If frm.Name = formName Then
IsLoaded = True
Exit Function
End If
Next frm
IsLoaded = False
End Function
Then adjusted my above code like so
database_connect
Dim SQLStr As String
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Dim Counter As Long
If IsLoaded("Attendance") Then
SQLStr = "select distinct[Agentname] from dbo.[Attendance] Where [Team] ='" & attendance.Team.value & "'"
ElseIf IsLoaded("Reporting") Then
SQLStr = "select distinct[Agentname] from dbo.[Attendance] Where [Team] ='" & Reporting.Team.value & "'"
End If
If appconn.State = 0 Then
Call database_connect
End If
rs.Open SQLStr, appconn, adOpenStatic
With ctrl
Do
.AddItem rs![Agentname]
rs.MoveNext
Loop Until rs.EOF
End With
rs.Close
database_Disconnect
Set rs = Nothing
Exit Sub
now it works like a charm!

Access report not updating after query change

I have a form, below, that allows the user to filter the database multiple ways. When they push the filter button on the form a report populates based on the filter query. The issue is if I filter the database again, even with .requery in the report code, the report doesn't update to the new Query results. I know if I manually close out of the report it works, however when I code it to DoCmd.Close it doesn't actually close the report. If I show it in
acViewPreview it updates each time I use the refilter button on the form but then I cant use buttons on the report. I am trying to make it like a kiosk so I don't want the nav tabs to show.
Filter form
Report
Form Code:
Private Sub btnFilter_Click()
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim SQL2 As String
Dim ToDate As Date
Dim FromDate As Date
SQL2 = ""
Set db = CurrentDb()
Set qdf = db.QueryDefs("Filter")
If cmbFilter.Value = "Vended Date" Then
ToDate = Format(DTPickerTo.Value, "YYYY-MM-DD")
FromDate = Format(DTPickerFrom.Value, "YYYY-MM-DD")
SQL2 = "SELECT CribMaster_Quality.Line,CribMaster_Quality.[Vended Date],CribMaster_Quality.PartNumber,CribMaster_Quality.Group,CribMaster_Quality.ItemNumber,CribMaster_Quality.Amount,CribMaster_Quality.Description,CribMaster_Quality.Cost,CribMaster_Quality.[Extended Cost],CribMaster_Quality.User " & _
" FROM CribMaster_Quality" & _
" WHERE CribMaster_Quality.[Vended Date]" & _
" BETWEEN #" & FromDate & "# AND #" & ToDate & "#" & _
" ORDER BY CribMaster_Quality.[Vended Date] DESC;"
ElseIf ckbDateConst = True Then
ToDate = Format(DTPickerTo.Value, "YYYY-MM-DD")
FromDate = Format(DTPickerFrom.Value, "YYYY-MM-DD")
SQL2 = "SELECT CribMaster_Quality.Line,CribMaster_Quality.[Vended Date],CribMaster_Quality.PartNumber,CribMaster_Quality.Group,CribMaster_Quality.ItemNumber,CribMaster_Quality.Amount,CribMaster_Quality.Description,CribMaster_Quality.Cost,CribMaster_Quality.[Extended Cost],CribMaster_Quality.User " & _
" FROM CribMaster_Quality" & _
" WHERE CribMaster_Quality." & Me!cmbFilter.Value & " = '" & Me!cmbFilterBy.Value & "' And CribMaster_Quality.[Vended Date] " & _
" BETWEEN #" & FromDate & "# AND #" & ToDate & "#" & _
" ORDER BY " & Me.cmbFilter.Value & " DESC;"
Else
SQL2 = "SELECT CribMaster_Quality.Line,CribMaster_Quality.[Vended Date],CribMaster_Quality.PartNumber,CribMaster_Quality.Group,CribMaster_Quality.ItemNumber,CribMaster_Quality.Amount,CribMaster_Quality.Description,CribMaster_Quality.Cost,CribMaster_Quality.[Extended Cost],CribMaster_Quality.User " & _
" FROM CribMaster_Quality" & _
" WHERE CribMaster_Quality." & Me!cmbFilter.Value & " = '" & Me!cmbFilterBy.Value & "'" & _
" ORDER BY " & Me.cmbFilter.Value & " DESC;"
End If
qdf.SQL = SQL2
Set db = Nothing
Set qdf = Nothing
DoCmd.OpenReport "CribMasterReport", acViewReport
End Sub
Report Code:
Private Sub btnReFilter_Click()
DoCmd.Close , acSaveNo
DoCmd.OpenForm "Filter Database Form"
End Sub
Private Sub Report_Load()
Me.Requery
With VendedDatetxt
.Requery
End With
With ItemNumbertxt
.Requery
End With
With Linetxt
.Requery
End With
With PartNumbertxt
.Requery
End With
With Usertxt
.Requery
End With
With Amounttxt
.Requery
End With
With Costtxt
.Requery
End With
With ExtendedCosttxt
.Requery
End With
End Sub
Issue 1: Requerying the Report
When a report is opened using standard techniques, such as clicking on a report in the Navigation pane or when opening a report using DoCmd.OpenReport, Access creates a default instance of the Report that is accessible via the Application.Reports collection. Before the report is first opened or if the default report instance is completely closed (i.e. removed from memory), the Application.Reports collection will not contain an instance of the report. Before accessing the default instance, ensure that the report is already open.
Like other MS Office object-model collections, Application.Reports does not have a "Contains" method or other direct way to test whether a report is already open, only by looping through numeric indexes and testing each report object. Although it seems sloppy to me, the easiest method is to use error handling to try getting the report directly, then catching the error if it's not found:
On Error Resume Next
Set frm = Application.Reports("CribMasterReport")
If err.Number <> 0 Then
'Default instance not open
End If
CAUTION: Do not refer to the report using the class name like an object, as in Report_CribMasterReport.Requery. If you do that, VBA will automatically create a new, hidden instance of the report, but it is NOT the same default instance as described above and this new instance will not be accessible via the Application.Reports collection. Likewise, using the properties and calling methods on such an object will be largely ineffective. (It is possible to create and use such independent instances, but that is an advance technique riddled with its own pitfalls and challenges.)
As the question describes, which is also confirmed by other online sources, the Report.Requery is not effective in refreshing the report after the underlying query or data have changed. However, resetting the Report.RecordSource forces a full refresh of the report when in normal Report View.
Issue 2: Report not closing
The DoCmd.Close command was missing a comma. It should be DoCmd.Close , , acSaveNo. Even better is to always use explicit names for optional parameters. Typing an extra parameter is definitely worth the saved frustration and time with typos in an ambiguous list of commas:
DoCmd.Close Save:=acSaveNo
Issue 3: Unnecessary calls
It is completely unnecessary to call Requery on the report and every single control in the Report_Load event. I get that you were trying to debug the situation, but this behavior should happen automatically. Also, the Form_Load event occurs only once when the form is first loaded, so that code would not be called again unless the report is completely closed and reopened.
Finally some alternative code
Private Sub btnFilter_Click()
'... Include previous code to reset report query
'* Call DoCmd.OpenReport every time to
'* 1) Ensure default report is open
'* 2) Automatically activate the report (even if it was already open)
DoCmd.OpenReport "CribMasterReport", acViewReport
On Error Resume Next
Dim frm As Report_CribMasterReport
Set frm = Application.Reports("CribMasterReport")
If Err.Number = 0 Then
'* Force the Report object to re-run query and recreate report
frm.RecordSource = frm.RecordSource
End If
End Sub
It is no longer be necessary to completely close the report.
Private Sub btnReFilter_Click()
''DoCmd.Close Save:=acSaveNo
DoCmd.OpenForm "Filter Database Form"
End Sub
Private Sub Report_Load()
'* Eliminated unnecessary Requery calls
End Sub

Access, VBA: Find First not working correctly

I hope this is a simple question for someone. I have this method that uses two form fields to check if a record exists in my table and either adds a record or does nothing. So if patient_id is 100, and visit_number is 1, then I will only add a new record if it doesn't already exist.
So, if rst.NoMatch is true - add a new record. However, I can't get it to recognize a duplicate. Here is the code:
Private Sub add_record_button_Click()
Dim rst As DAO.Recordset
Set rst = Me.RecordsetClone
Dim dbs As DAO.Database
Set dbs = CurrentDb
If IsNull(Form.patient_id) Or IsNull(Form.visit_number) = True Then
MsgBox "Please fill in both fields."
Else
rst.FindFirst "[patient_id] = " & Form.patient_id & " And [visit_number] = " & Form.visit_number
If rst.NoMatch Then
Set rst = dbs.OpenRecordset("Visits")
rst.AddNew
rst!patient_id = Form.patient_id
rst!visit_number = Form.visit_number
rst.Update
MsgBox "New patient visit has been added to the database."
Else
MsgBox "That visit already exists."
End If
rst.Close
End If
End Sub
I believe that my FindFirst line isn't correct. In the database, the variables are named patient_id and visit_number. On the form they are named the same.
Any help would be appreciated, thanks.
EDIT.
From the comments below, I was able to get my logic working but using a different compare feature, Dlookup.
IsNull(DLookup("[patient_id]", "MyTable", "[patient_id] = " & Forms("MyForm").patient_id & " AND [visit_number] = " & Forms("MyForm").visit_number)
FINAL EDIT.
The above line made everything work if I used the form directly, however if I put the form into a navigation form - it stopped working. The string that ultimately got it working from within a navigation form looks like this:
If IsNull(DLookup("[patient_id]", "Visits", "[patient_id] = " & Me!patient_id.Value & " AND [visit_number] = " & Me!visit_number.Value)) = True Then
Thank you all for your help.
I've never seen Form used this way, and you should be able to add the record directly in the form, so try:
Private Sub add_record_button_Click()
Dim rst As DAO.Recordset
Set rst = Me.RecordsetClone
Dim PatientId As Variant
Dim VisitNumber As Variant
PatientId = Me!patient_id.Value
VisitNumber = Me!visit_number.Value
If IsNull(PatientId) Or IsNull(VisitNumber) Then
MsgBox "Please fill in both fields."
Else
rst.FindFirst "[patient_id] = " & PatientId & " And [visit_number] = " & VisitNumber & ""
If rst.NoMatch Then
rst.AddNew
rst!patient_id.Value = PatientId
rst!visit_number.Value = VisitNumber
rst.Update
MsgBox "New patient visit has been added to the database."
Else
MsgBox "That visit already exists."
Me.Bookmark = rst.Bookmark
End If
End If
End Sub

Checking off checkbox when record gets focus

I'm guessing this has been answered before but I cant seem to word it right to find help.
Anyways, I'm using a barcode scanner in access to find records (it just enters the number in a textbox then hits enter). What I need is to make it so that when a record is found (using rs.FindFirst), the check box field (Named "Audit Check") gets checked off.
Here is my code for the search, I have a feeling that it can be incorporated into this event.
Private Sub BarcodeBox_AfterUpdate()
Dim rs As DAO.Recordset
If Not IsNull(Me![Barcodebox]) Then
Set rs = Me.RecordsetClone
rs.FindFirst "[Barcode] = '" & Me![Barcodebox] & "'"
If Not rs.EOF Then Me.Bookmark = rs.Bookmark
Else
Exit Sub
End If
End Sub
Thanks so much guys!
Try changing
If Not rs.EOF Then Me.Bookmark = rs.Bookmark
to
If Not rs.EOF Then
Me.Bookmark = rs.Bookmark
Me.MyCheckbox = True
End If

If Then Else on 2 separate recordsets

I need to test 2 different conditions on 2 separate recordsets. I am not good with VBA, I have a very basic code, I just need help with If Then syntax. Here is my Code:
Private Sub SaveRecord_Click()
'**** add a new record ****
Dim db As Database, rs1 As Recordset, rs2 As Recordset
Set db = CurrentDb
Set rs1 = db.OpenRecordset("ExpAsset", DB_OPEN_DYNASET)
Set rs2 = db.OpenRecordset("LogTest", DB_OPEN_DYNASET)
'**** Following code is updating the tables in the ExpAsset table with new information from the form****
If rs1.NoMatch Then
rs1.AddNew
rs1("User") = Me!Location
rs1("Type") = Me!Type
rs1("Model") = Me!MODEL
rs1("Asset_ID") = Me!Asset_ID
rs1("Serial_Number") = Me!Serial
rs1.Update
Else
MsgBox "Serial Number: " & Me!Serial & " already exists.", 48, "ERROR!"
Me!Serial.SetFocus
End If
'**** Following code is creating a log in Logtest table with information provided in the form****
If rs2.NoMatch Then
rs2.AddNew
rs2("Asset_Type") = Me!Type
rs2("Transfer_Type") = "New purchase"
rs2("Description") = Me!DESCRIPTION
rs2("DELIVERED_TO") = Me!Location
rs2("DELIVERED_BY") = Me!DeliveredBy
rs2("RECEIVED_BY") = Me!Receiver
rs2("RECEIVED_DATE") = Me!Date
rs2.Update
MsgBox "Part information has been updated in the database!"
'clear the controls to add more customers
Call ClearControls
Else
MsgBox "Asset ID: " & Me!Asset_ID & " already exists.", 48, "ERROR!"
Me!Asset_ID.SetFocus
End If
rs1.Close
rs2.Close
db.Close
End Sub
I know The If Then Else syntax is incorrect, I need to check both conditions, serial no. and asset ID.
Check the Access online help topic for Recordset.NoMatch Property:
Indicates whether a particular record was found by using the Seek method or one of the Find methods (Microsoft Access workspaces only).
However in your code, you're opening a recordset but not using either seek or find. In that situation, you haven't asked to match anything, so .NoMatch will be False every time. The logic is similar to this ...
If rs1.NoMatch Then
' this code will never run
Else
' this code runs every time
End If
You can use DCount to determine whether ExpAsset contains a given Asset_ID value.
DCount("*", "ExpAsset", "Asset_ID = " & Me!Asset_ID) ' if Asset_ID is numeric
DCount("*", "ExpAsset", "Asset_ID = '" & Me!Asset_ID & "'") ' if Asset_ID is text
Once you have a working DCount expression, you can use logic like this ...
If DCount("*", "ExpAsset", "Asset_ID = " & Me!Asset_ID) = 0 Then
' Asset_ID not present in table -> add it
Else
' inform user Asset_ID already present in table
End If
You are right HansUp, my code was silly, I realised later after I had posted that there was no criteria to test against. Following is the right code, I tested it and it works :)
Private Sub SaveRecord_Click()
'**** add a new record ****
Dim db As Database, rs1 As Recordset, rs2 As Recordset, Criteria As String, Criteria2 As String
Set db = CurrentDb
Set rs1 = db.OpenRecordset("ExpAsset", DB_OPEN_DYNASET)
Set rs2 = db.OpenRecordset("LogTest", DB_OPEN_DYNASET)
Criteria = "[serial_number]='" & Me!Serial & "'"
Criteria2 = "[Asset_ID]='" & Me!Asset_ID & "'"
'**** Following code is updating the tables in the ExpAsset table with new information from the form****
rs1.FindFirst Criteria
If rs1.NoMatch Then
rs1.FindFirst Criteria2
If rs1.NoMatch Then
rs1.AddNew
rs1("User") = Me!Location
rs1("Type") = Me!Type
rs1("Model") = Me!MODEL
rs1("Asset_ID") = Me!Asset_ID
rs1("Serial_Number") = Me!Serial
rs1.Update
'**** Following code is creating a log in Logtest table with information provided in the form****
rs2.AddNew
rs2("Asset_Type") = Me!Type
rs2("Transfer_Type") = "New purchase"
rs2("Description") = Me!DESCRIPTION
rs2("DELIVERED_TO") = Me!Location
rs2("DELIVERED_BY") = Me!DeliveredBy
rs2("RECEIVED_BY") = Me!Receiver
rs2("RECEIVED_DATE") = Me!Date
rs2.Update
MsgBox "Part information has been updated in the database!"
'clear the controls to add more customers
Call ClearControls
Else
MsgBox "Asset_ID: " & Me!Asset_ID & " already exists.", 48, "ERROR!"
Me!Asset_ID.SetFocus
End If
Else
MsgBox "Serial Number: " & Me!Serial & " already exists.", 48, "ERROR!"
Me!Serial.SetFocus
End If
rs1.Close
rs2.Close
db.Close
End Sub