How do I look up for a particular value in an Access Form record, and if not found, add a new record with that value? - vba

I have been looking for a solution in many different places, but have not been able to find a clean answer.
I need my Access program to look up for a particular value, based on entry in a text box, if found, go to that record (easy part), and if not, add a new record for that particular value being assigned to the respective field.
Private Sub myTextBox_Exit(Cancel As Integer)
Dim db As Database
Dim rs As Recordset
dim actNo as String
Set db = CurrentDb
actNo = Me.AccountNumber
Set rs = CurrentDb.OpenRecordset(Name:="myClients", Type:=RecordsetTypeEnum.dbOpenDynaset)
With rs
.FindFirst "AccountNumber = '" & actNo & "'"
If Not .NoMatch Then
Me.Bookmark = .Bookmark
Else
' This is where it gets tricky. Tried many of the variations below, none
' works.
.AddNew
!AccountNumber= actNo
.Update
Me.Refresh
' Neither something like:
DoCmd.RunCommand acCmdRecordsGoToNew
End If
End With
Cleanup:
rs.Close
db.Close
Set rs = Nothing
Set db = Nothing
End Sub
Help much appreciated.

Here is how you add a new record to your recordset:
.AddNew
rs!AccountNumber = actNo
.Update
Alternatively:
.AddNew
.Fields("AccountNumber") = actNo
.Update

Use the RecordsetClone:
Private Sub myTextBox_Exit(Cancel As Integer)
Dim rs As DAO.Recordset
Dim actNo As String
actNo = Me!AccountNumber.Value
Set rs = Me.RecordsetClone
With rs
.FindFirst "AccountNumber = '" & actNo & "'"
If .NoMatch Then
.AddNew
!AccountNumber.Value = actNo
.Update
End If
Me.Bookmark = .Bookmark
End With
rs.Close
Set rs = Nothing
End Sub

Related

Duplicate form button with multivalued field and subform

I am trying to duplicate a form from a button using vba. This has worked for years using Allen Browne's "Duplicate the record in form and subform." http://allenbrowne.com/ser-57.html
Now I want to change one of the fields to multivalue. I understand the difficulties with multivalued fields, but this is a 10 year old database and all I need to do is make this field be able to store multiple values, so think this will be easier than creating a new join table and updating everything related.
I am currently getting Invalid use of Property at the rstmv = rstmv.Value line.
I have tried numerous versions and get different errors. I think I should be opening the values of the multi-value field as a separate recordset, updating it then looping through the values but I am getting confused as I am not really sure what I am doing.
Here is the code I I have been using:
'On Error GoTo Err_Handler
'Purpose: Duplicate the main form record and related records in the subform.
Dim strSql As String 'SQL statement.
Dim lngID As Long 'Primary key value of the new record.
Dim rst As Recordset
Dim rstmv As Recordset2
'Save and edits first
If Me.Dirty Then
Me.Dirty = False
End If
'Make sure there is a record to duplicate.
If Me.NewRecord Then
MsgBox "Select the record to duplicate."
Else
'Duplicate the main record: add to form's clone.
With Me.RecordsetClone
.AddNew
!Site_Name = Me.Site_Name
!Date_of_Dive = Me.Date_of_Dive
!Time_of_Dive = Me.Time
Set rst = Me.RecordsetClone
Set rstmv = rst!Staff.Value
Do While Not rstmv.EOF
rsp.Edit
rstmv.Edit
rstmv.AddNew ' Add a new record to the asp Recordset
rstmv = rstmv.Value
rstmv.Update ' Commit the changes to the asp Recordset
imt.MoveNext
Loop
.Update
!O2 = Me.O2
!First_Aid = Me.First_Aid
!Spares = Me.Spares
'etc for other fields.
.Update
'Save the primary key value, to use as the foreign key for the related records.
.Bookmark = .LastModified
lngID = !Dive_Number
'Duplicate the related records: append query.
If Me.[DiveDetailssubform].Form.RecordsetClone.RecordCount > 0 Then
strSql = "INSERT INTO [DiveDetails] (Dive_Number, CustDateID, Type, Price) " & _
"SELECT " & lngID & " As NewID, CustDateID, Type, Price " & _
"FROM [DiveDetails] WHERE Dive_Number = " & Me.Dive_Number & ";"
DBEngine(0)(0).Execute strSql, dbFailOnError
Else
MsgBox "Main record duplicated, but there were no related records."
End If
'Display the new duplicate.
Me.Bookmark = .LastModified
MsgBox "Dive Sucessfully Duplicated. DONT FORGET TO CHANGE THE SITE NAME."
End With
End If
Exit_Handler:
Exit Sub
Err_Handler:
MsgBox "Error " & Err.Number & " - " & Err.Description, , "Duplicate_Click"
Resume Exit_Handler
End Sub
Private Sub Form_Load()
Dim varID As Variant
Dim strDelim As String
'Note: If CustomerID field is a Text field (not a Number field), remove single quote at start of next line.
'strDelim = """"
varID = DLookup("Value", "tblSys", "[Variable] = 'DiveIDLast'")
If IsNumeric(varID) Then
With Me.RecordsetClone
.FindFirst "[dive_number] = " & strDelim & varID & strDelim
If Not .NoMatch Then
Me.Bookmark = .Bookmark
End If
End With
End If
End Sub
Private Sub Form_Unload(Cancel As Integer)
Dim rs As DAO.Recordset
If Not IsNull(Me.Dive_Number) Then
Set rs = CurrentDb().OpenRecordset("tblSys", dbOpenDynaset)
With rs
.FindFirst "[Variable] = 'DiveIDLast'"
If .NoMatch Then
.AddNew 'Create the entry if not found.
![Variable] = "DiveIDLast"
![Value] = Me.Dive_Number
![Description] = "Last DiveID, for form Dive Planner" & Me.Name
.Update
Else
.Edit 'Save the current record's primary key.
![Value] = Me.Dive_Number
.Update
End If
End With
rs.Close
End If
Set rs = Nothing
End Sub
Need recordsets of source data and recordsets for destination. Also should explicitly declare the recordset type as DAO. Consider:
Dim strSql As String 'SQL statement.
Dim lngID As Long 'Primary key value of the new record.
Dim rstF As DAO.Recordset
Dim rstT As DAO.Recordset
Dim rstmvF As DAO.Recordset2
Dim rstmvT As DAO.Recordset2
'Save any edits first
If Me.Dirty Then
Me.Dirty = False
End If
'Make sure there is a record to duplicate.
If Me.NewRecord Then
MsgBox "Select the record to duplicate."
Else
Set rstF = CurrentDb.OpenRecordset("SELECT * FROM Dives WHERE Dive_Number = " & Me.Dive_number)
Set rstmvF = rstF!Staff.Value
'Duplicate the main record: add to form's clone.
With Me.RecordsetClone
.AddNew
!Site_Name = Me.Site_Name
!Date_of_Dive = Me.Date_of_Dive
!Time_of_Dive = Me.Time
!O2 = Me.O2
!First_Aid = Me.First_Aid
!Spares = Me.Spares
.Update
'Save the primary key value of new record.
.Bookmark = .LastModified
lngID = !Dive_number
Set rstT = CurrentDb.OpenRecordset("SELECT * FROM Dives WHERE Dive_Number = " & lngID)
Set rstmvT = rstT!Staff.Value
rstT.Edit
Do While Not rstmvF.EOF
rstmvT.AddNew ' Add a new record to the asp Recordset
rstmvT!Value = rstmvF!Value
rstmvT.Update ' Commit the changes to the asp Recordset
rstmvF.MoveNext
Loop
rstT.Update

Allow data to delete from one table to add to another table

I have posted about this table and form multiple times and I know I shouldn't do it this way. I am having trouble with my code. I need for when the ToGo hits 0 then the row on the WorkOrders table moves to the Done WorkOrders table and then deletes out of the WorkOrders table. The code I had before was
Private Sub ItemCode_Dirty(Cancel As Integer)
Dim DB As DAO.Database
Dim rs As DAO.Recordset
Set DB = CurrentDb
Set rs = DB.OpenRecordset("Select ToGo from WorkOrders where ItemCode =" & Me.ItemCode)
With rs
.Edit
!ToGo = !ToGo - 1
.Update
.Edit
End With
End Sub
This was just making my code decrease by 1 every scan. So, I added the rest of the code to do the switch to a different table and then delete, but now my ToGo won't decrease at all. This is the updated code I have now with the if statement.
Private Sub ItemCode_Dirty(Cancel As Integer)
Dim DB As DAO.Database
Dim rs As DAO.Recordset
Dim i As Integer
Dim rsOld As DAO.Recordset
Dim rsNew As DAO.Recordset
Set DB = CurrentDb
Set rs = DB.OpenRecordset("Select ToGo from WorkOrders where ItemCode =" & Me.ItemCode)
Set rsNew = CurrentDb.OpenRecordset("SELECT * FROM WorkOrders")
Set rsOld = CurrentDb.OpenRecordset("Select * from WorkOrders where ItemCode =" & Me.ItemCode)
If ToGo > 0 Then
With rs
.Edit
!ToGo = !ToGo - 1
.Update
.Edit
End With
Else
rsNew.AddNew
For i = 0 To rsOld.Fields.Count - 1
rsNew.Fields(i).Value = rsOld.Fields(i).Value
Next
rsNew.Update
DoCmd.SetWarnings False
DoCmd.RunSQL "DELETE * FROM WorkOrders WHERE ItemCode= & Me.ItemCode
DoCmd.SetWarnings True
rsNew.Close
rsOld.Close
Set rsNew = Nothing
Set rsOld = Nothing
End If
End Sub
Can someone let me know if this is even possible.
Instead of 'moving' records between tables, change record status with edit in a field. You seem to already have a field that indicates a work order is 'done' - the ToGo field. Consider:
With rs
If Not .EOF Then
If !ToGo = 0 Then
.MoveNext
End If
.Edit
!ToGo = !ToGo - 1
.Update
End If
End With

not able to edit record by passing text value through form access 2007

I have a first table called "BreedingTable" with primary key "ID" and "TransactionStatus" = "Active".
I have "Kidding form" data populated from the combo box to Text fields
Text2.value = "ID" from BreedingTable.
When I am done with all the process, I want to change TransactionStatus of Breeding table = Closed.
I am using the below code but it never works.
Note" if I give exact transaction id number it works fine,
but if I ask to find based on text2 it doesn't work.
My code is as follows:
Private Sub exitprograme3()
Me.Text2.SetFocus
Dim i As Integer
Dim db As Database
Dim rs As Recordset
Dim Trn As Integer
Set db = CurrentDb
Set rs = db.OpenRecordset("BreedingTable")
For i = 0 To rs.RecordCount - 1
Me.Text2.SetFocus
If rs.Fields("ID") = Me.Text2.Value Then
rs.Edit
rs.Fields("BreedingStatus") = "Closed"
rs.Update
End If
rs.MoveNext
Next i
rs.Close
Set rs = Nothing
db.Close
DoCmd.Close
End Sub
Please assist ...
If I type exact transaction id number in below if statement it works
If rs.Fields("ID") = "323" Then
this works fine.
But if I type like below it doesn't work
If rs.Fields("ID") = Me.Text2.Value Then
No loop is needed:
Private Sub exitprograme3()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("Select * From BreedingTable")
rs.FindFirst "[ID] = " & Me!Text2.Value & ""
' If ID is text, then quotes:
' rs.FindFirst "[ID] = '" & Me!Text2.Value & "'"
If Not rs.NoMatch Then
rs.Edit
rs.Fields("BreedingStatus").Value = "Closed"
rs.Update
End If
rs.Close
Set rs = Nothing
Set db = Nothing
DoCmd.Close
End Sub

How do I loop using multiple conditions for a submit button?

I am writing a function that checks if the amount paid is equal or more to a number of items selected if they are checked. For this example there are 10 items with 10 check boxes. I could check one or more boxes in any order.If an item or more meets the condition it is cleared otherwise it remains.
Public Sub processItem1()
Dim db As DAO.Database
Dim pr As DAO.Recordset, so As DAO.Recordset
Dim strSQL1 As String
Dim strSQL2 As String
Set db = CurrentDb
strSQL1 = "SELECT * FROM PharmSales WHERE PharmSalesID= (SELECT MAX(PharmSalesID) FROM PharmSales WHERE HospitalNo='" & Me.txtRegNo & "' And TDate = #" & Format(Me.txtTDate, "M\/dd\/yyyy") & "# AND SalesItem1 = '" & Me.txtSalesItem1 & "')"
strSQL2 = "SELECT * FROM tblItem WHERE ItemName = '" & Me.txtSalesItem1 & "'"
Set pr = db.OpenRecordset(strSQL1)
Set so = db.OpenRecordset(strSQL2)
With pr
If Not .BOF And Not .EOF Then 'Ensure that the recordset contains records
.MoveLast
.MoveFirst
If .Updatable Then 'To ensure record is not locked by another user
.Edit 'Must start an update with the edit statement
![DispQty1] = Nz(![DispQty1] + Me.txtSalesQty1.Value, 0)
.Update
End If
End If
pr.Close 'Make sure you close the recordset..
Set pr = Nothing '...and set it to nothing
Set db = Nothing
End With
With so
If Not .BOF And Not .EOF Then 'Ensure that the recordset contains records
.MoveLast
.MoveFirst
If .Updatable Then 'To ensure record is not locked by another user
.Edit 'Must start an update with the edit statement
![Stock_Out] = Nz(![Stock_Out] + Me.txtSalesQty1.Value, Me.txtSalesQty1.Value)
![SO_Date] = Me.txtTDate
![Stock_In] = Nz(![Stock_In] + 0, 0)
.Update 'And finally we will need to confirm the update
End If
End If
so.Close 'Make sure you close the recordset..
ExitSub:
Set so = Nothing '...and set it to nothing
Set db = Nothing
End With
End Sub
For processItem2:
Public Sub processItem2()
Dim db As DAO.Database
Dim pr As DAO.Recordset, so As DAO.Recordset
Dim strSQL1 As String
Dim strSQL2 As String
Set db = CurrentDb
strSQL1 = "SELECT * FROM PharmSales WHERE PharmSalesID= (SELECT MAX(PharmSalesID) FROM PharmSales WHERE HospitalNo='" & Me.txtRegNo & "' And TDate = #" & Format(Me.txtTDate, "M\/dd\/yyyy") & "# AND SalesItem2 = '" & Me.txtSalesItem2 & "')"
strSQL2 = "SELECT * FROM tblItem WHERE ItemName = '" & Me.txtSalesItem2 & "'"
Set pr = db.OpenRecordset(strSQL1)
Set so = db.OpenRecordset(strSQL2)
With pr
If Not .BOF And Not .EOF Then 'Ensure that the recordset contains records
.MoveLast
.MoveFirst
If .Updatable Then 'To ensure record is not locked by another user
.Edit 'Must start an update with the edit statement
![DispQty2] = Nz(![DispQty2] + Me.txtSalesQty2.Value, 0)
.Update
End If
End If
pr.Close 'Make sure you close the recordset..
Set pr = Nothing '...and set it to nothing
Set db = Nothing
End With
With so
If Not .BOF And Not .EOF Then 'Ensure that the recordset contains records
.MoveLast
.MoveFirst
If .Updatable Then 'To ensure record is not locked by another user
.Edit 'Must start an update with the edit statement
![Stock_Out] = Nz(![Stock_Out] + Me.txtSalesQty2.Value, Me.txtSalesQty2.Value)
![SO_Date] = Me.txtTDate
![Stock_In] = Nz(![Stock_In] + 0, 0)
.Update 'And finally we will need to confirm the update
End If
End If
so.Close 'Make sure you close the recordset..
ExitSub:
Set so = Nothing '...and set it to nothing
Set db = Nothing
End With
End Sub
Don't ever copy&paste code like this. It is a maintenance nightmare.
You can loop over objects by concatenating their name at runtime:
Me("txtSalesItem" & i) ' form control
pr("DispQty" & i).Value ' recordset field
etc.
Side note:
With recordset
.MoveLast
.MoveFirst
These MoveLast/MoveFirst commands are unnecessary. You only need them if you want to get the correct .RecordCount of a recordset.

Access VBA find record in code and then set to form

The following code produces this error runtime error '2455' you entered an expression that has an invalid reference to the property Form/Report.
The RecordSource behind the subforms is an actual table name.
When debugging, it stops on Set rs = ... or the next line.
Private Sub Form_Current()
Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset("SELECT * FROM " & Forms!frmTrafficAndLogistics!sfrTnLPO.Form.RecordSource)
If Not (rs.EOF And rs.BOF) Then rs.MoveFirst
rs.FindFirst "PONum = " & Me.PONum
If Not rs.NoMatch Then
Forms!frmTrafficAndLogistics!sfrTnLPO.Form.Bookmark = rs.Bookmark
End If
rs.Close
Set rs = Nothing
End Sub
You will only need to assign the Form's recordsource to the Recordset object, like
Private Sub Form_Current()
Dim rs As Recordset
Set rs = Forms!frmTrafficAndLogistics!sfrTnLPO.Form.RecordSetClone
If Not (rs.EOF And rs.BOF) Then rs.MoveFirst
rs.FindFirst "PONum = " & Me.PONum
If Not rs.NoMatch Then
Forms!frmTrafficAndLogistics!sfrTnLPO.Form.Bookmark = rs.Bookmark
End If
rs.Close
Set rs = Nothing
End Sub