Duplicate form button with multivalued field and subform - vba

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

Related

Vba ms-access Loop Recordset Print info to textbox

I made a sub that deletes records in a table via a recordset.
I would like to print the key of the record that is deleted to a textbox on a form.
So after each delete the key has to be added to the textbox on the form.
Below you can find the code, that doesn't print anything to the form.
I'm missing something.
Public Sub Erase()
Dim db As DAO.Database
Dim rs1 As DAO.Recordset
Dim strOutput As String
Dim i As Integer
Set db = CurrentDb()
Set rs1 = db.OpenRecordset("Table1", dbOpenDynaset) 'dynaset voor linked tables
If rs1.EOF Then Exit Sub
Do Until rs1.EOF
If rs1!Icoon = "del" Then
Debug.Print "Debug Print :" & rs1(0).Value
strOutput = "Ent: " & rs1(0).Value & vbCrLf
On Error Resume Next
rs1.Delete
txtOutput.value = strOutput
i = DoEvents
End If
rs1.MoveNext
Loop
rs1.Close
Set rs1 = Nothing
Set db = Nothing
End Sub
Forgot the form ... txtOutput.value = strOutput should be: [Forms]![Frm_Main]![txtOutput] = strOutput

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 look up for a particular value in an Access Form record, and if not found, add a new record with that value?

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

multi-combo box search with VBA

I am currently having this issue of my search not working correctly. The idea is to have the user click on different fields and have them assigned to textboxes and then be searched against. Above is what the UI currently looks like in the form and the code is attached below. For example, when I pick firstName as the field 1 and Title as field 2, enter the text "joe" into field 1 into
and "student" into the respective text boxes and then hit search, it shows all of the student results instead of that single row of data in the table. I am thinking this is could be an issue of the combo boxes not being synchronized, where let's say if cbo1 and cbo2 declare fields, then those repsective text fields become filtered. cboField, cboField2 and cboField3 are all combo boxes and command_21 is a search button and command_28 is a show all records. I am very new to this still and am not entirely sure. Any help is appreciated. Thanks in advance
Option Compare Database
Private Sub cboField_Enter()
Dim oRS As DAO.Recordset, i As Integer
If Me.Form.FilterOn = True Then DoCmd.ShowAllRecords
Set oRS = Me.RecordsetClone
cboField.RowSourceType = "Value List"
cboField.RowSource = ""
For i = 0 To oRS.Fields.Count - 1
If oRS.Fields(i).Type = dbText Then cboField.AddItem oRS.Fields(i).Name
Next i
End Sub
Private Sub cboField2_Enter()
Dim rs As DAO.Recordset, i As Integer
If Me.Form.FilterOn = True Then DoCmd.ShowAllRecords
Set rs = Me.RecordsetClone
cboField2.RowSourceType = "Value List"
cboField2.RowSource = ""
For i = 0 To rs.Fields.Count - 1
If rs.Fields(i).Type = dbText Then cboField2.AddItem rs.Fields(i).Name
Next i
End Sub
Private Sub cboField3_Enter()
Dim rs As DAO.Recordset, i As Integer
If Me.Form.FilterOn = True Then DoCmd.ShowAllRecords
Set rs = Me.RecordsetClone
cboField2.RowSourceType = "Value List"
cboField2.RowSource = ""
For i = 0 To rs.Fields.Count - 1
If rs.Fields(i).Type = dbText Then cboField2.AddItem rs.Fields(i).Name
Next i
End Sub
Private Sub Command21_Click()
Dim sfilter As String, oRS As DAO.Recordset
Dim sfilter2 As String, rs As DAO.Recordset
If IsNull(cboField) And IsNull(cboField2) And IsNull(cboField3) Then
DoCmd.ShowAllRecords
MsgBox "select a field"
Exit Sub
End If
If Not IsNull(cboField) Then
sfilter = cboField & " LIKE '" & txtBox & "*'"
DoCmd.ApplyFilter , sfilter
End If
If Not IsNull(cboField2) Then
sfilter2 = cboField2 & " LIKE '" & txtBox2 & "*'"
DoCmd.ApplyFilter , sfilter2
End If
If Not IsNull(cboField3) Then
sfilter3 = cboField3 & " LIKE '" & txtBox3 & "*'"
DoCmd.ApplyFilter , sfilter3
End If
Set oRS = Me.RecordsetClone
Set rs = Me.RecordsetClone
If oRS.RecordCount And rs.RecordCount = 0 Then
MsgBox " no record matches"
DoCmd.ShowAllRecords
End If
End Sub
Private Sub Command28_Click()
DoCmd.ShowAllRecords
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.