How to transfer data from one table to another in Access VBA? - vba

I thought this would be easy....that will be my famous last words!
I have an access database that is used to keep track of company vehicles. I would like the form used by associates to retain more information that they do not have to see the information populated. I have created a form (fTripInformation) that will allow them to select the company vehicle used for a work trip from a combo box (CarID). Vehicles are numbered for convenience (1-10). What I would like to happen is the associate selects the vehicle number from the combo box drop down menu. When that happens the corresponding information associated with the vehicle (Make,Model, Year, Color, etc...) is added to the temp table (tTemp) for this form from the vehicles table (tVehicles). This way the associate only see the vehicle #, yet all the other information will be recorded when the temp table information is transferred to the actual record table.
Any suggestions on how to do this?

This what I did:First, I redefined the Row Source Query the Combobox uses to include all the related information and updated the total Column Count in the Properties Sheet. Then, added the following code:
Private Sub CarID_Change()
Dim Rs As Recordset
Set Rs = CurrentDb.OpenRecordset("tTemp")
Rs.Edit
Rs!CarID = Me.CarID.Column(0)
Rs!Make = Me.CarID.Column(1)
Rs!Model = Me.CarID.Column(2)
Rs!Year = Me.CarID.Column(3)
Rs!Color = Me.CarID.Column(4)
Rs.Update
End Sub
Private Sub CarID_DblClick()
Dim Rs As Recordset
Set Rs = CurrentDb.OpenRecordset("tTemp")
Rs.Edit
Rs!CarID = ""
Rs!Make = ""
Rs!Model = ""
Rs!Year = ""
Rs!Color = ""
Rs.Update
End Sub

This is, in fact, pretty easy! Download the demo file from the link below and you will have the concept that you described above. Just modify the code to achieve your specific goals.
http://www.mediafire.com/file/x9cuorenr7r9mi5/AccessAndSQL4_2000.mdb/file

Related

Runtime error 3164 for Access when copying [duplicate]

I am having a difficult time how to properly copy specific field data from previous records on my user form. I don't have a code sample to show but my request is very simplistic.
Currently, out of 12 fields, I have 6 that I often repeat data. I can click on and press Ctrl+' ("Insert the value from the same field in the previous record") and it performs the task I want. However, it adds a lot of time to the task. I simply want to write VBA code to perform that command to those specific fields.
I haven't been able to get SendKeys to work. DLast appears to provide random data at times. I feel like this should be a very simple request but for some reason I am not finding a functional solution for it.
Don't fiddle with arrays or queries - use the power of DAO:
Private Sub CopyButton_Click()
CopyRecord
End Sub
If a record is selected, copy this.
If a new record is selected, copy the last (previous) record.
Private Sub CopyRecord()
Dim Source As DAO.Recordset
Dim Insert As DAO.Recordset
Dim Field As DAO.Field
' Live recordset.
Set Insert = Me.RecordsetClone
' Source recordset.
Set Source = Insert.Clone
If Me.NewRecord Then
' Copy the last record.
Source.MoveLast
Else
' Copy the current record.
Source.Bookmark = Me.Bookmark
End If
Insert.AddNew
For Each Field In Source.Fields
With Field
If .Attributes And dbAutoIncrField Then
' Skip Autonumber or GUID field.
Else
Select Case .Name
' List names of fields to copy.
Case "FirstField", "AnotherField", "YetAField" ' etc.
' Copy field content.
Insert.Fields(.Name).Value = Source.Fields(.Name).Value
End Select
End If
End With
Next
Insert.Update
Insert.Close
Source.Close
End Sub
This also, by the way, is an excellent example of the difference between the RecordsetClone and the Clone of a recordset - the first being "the records of the form", while the second is an independant copy.
This also means, that the form will update automatically and immediately.
Provided that it's a simple form to edit a simple table, and that the bound data field names match the control names, you may get away with
If Me.Recordset.AbsolutePosition > 0 Then
With Me.Recordset.Clone()
.AbsolutePosition = Me.Recordset.AbsolutePosition - 1
Dim control_name As Variant
For Each control_name In Array("field1", "field2", "field3", "field4", "field5", "field6")
Me.Controls(control_name).Value = .Fields(control_name).Value
Next
End With
End If
which you assign to a separate button on the same form.
You have a good idea post here already.
You could also say place a function in the before insert event. This event ONLY fires when you start typing into a NEW reocrd, and it becomes dirty.
So, maybe this:
Private Sub Form_BeforeInsert(Cancel As Integer)
Dim rstPrevious As DAO.Recordset
Dim strSQL As String
strSQL = "SELECT TOP 1 * FROM tblPeople ORDER BY ID DESC"
Set rstPrevious = CurrentDb.OpenRecordset(strSQL)
' auto file out some previous values
If rstPrevious.RecordCount > 0 Then
Me.Firstname = rstPrevious!Firstname
Me.LastName = rstPrevious!LastName
End If
End Sub
And some good ideas in say having a "list" or "array" of controls/fields to setup, so you don't have to write a lot of code. (as suggested in the other post/answer here)

MS Access VBA equivalent to Ctrl+'?

I am having a difficult time how to properly copy specific field data from previous records on my user form. I don't have a code sample to show but my request is very simplistic.
Currently, out of 12 fields, I have 6 that I often repeat data. I can click on and press Ctrl+' ("Insert the value from the same field in the previous record") and it performs the task I want. However, it adds a lot of time to the task. I simply want to write VBA code to perform that command to those specific fields.
I haven't been able to get SendKeys to work. DLast appears to provide random data at times. I feel like this should be a very simple request but for some reason I am not finding a functional solution for it.
Don't fiddle with arrays or queries - use the power of DAO:
Private Sub CopyButton_Click()
CopyRecord
End Sub
If a record is selected, copy this.
If a new record is selected, copy the last (previous) record.
Private Sub CopyRecord()
Dim Source As DAO.Recordset
Dim Insert As DAO.Recordset
Dim Field As DAO.Field
' Live recordset.
Set Insert = Me.RecordsetClone
' Source recordset.
Set Source = Insert.Clone
If Me.NewRecord Then
' Copy the last record.
Source.MoveLast
Else
' Copy the current record.
Source.Bookmark = Me.Bookmark
End If
Insert.AddNew
For Each Field In Source.Fields
With Field
If .Attributes And dbAutoIncrField Then
' Skip Autonumber or GUID field.
Else
Select Case .Name
' List names of fields to copy.
Case "FirstField", "AnotherField", "YetAField" ' etc.
' Copy field content.
Insert.Fields(.Name).Value = Source.Fields(.Name).Value
End Select
End If
End With
Next
Insert.Update
Insert.Close
Source.Close
End Sub
This also, by the way, is an excellent example of the difference between the RecordsetClone and the Clone of a recordset - the first being "the records of the form", while the second is an independant copy.
This also means, that the form will update automatically and immediately.
Provided that it's a simple form to edit a simple table, and that the bound data field names match the control names, you may get away with
If Me.Recordset.AbsolutePosition > 0 Then
With Me.Recordset.Clone()
.AbsolutePosition = Me.Recordset.AbsolutePosition - 1
Dim control_name As Variant
For Each control_name In Array("field1", "field2", "field3", "field4", "field5", "field6")
Me.Controls(control_name).Value = .Fields(control_name).Value
Next
End With
End If
which you assign to a separate button on the same form.
You have a good idea post here already.
You could also say place a function in the before insert event. This event ONLY fires when you start typing into a NEW reocrd, and it becomes dirty.
So, maybe this:
Private Sub Form_BeforeInsert(Cancel As Integer)
Dim rstPrevious As DAO.Recordset
Dim strSQL As String
strSQL = "SELECT TOP 1 * FROM tblPeople ORDER BY ID DESC"
Set rstPrevious = CurrentDb.OpenRecordset(strSQL)
' auto file out some previous values
If rstPrevious.RecordCount > 0 Then
Me.Firstname = rstPrevious!Firstname
Me.LastName = rstPrevious!LastName
End If
End Sub
And some good ideas in say having a "list" or "array" of controls/fields to setup, so you don't have to write a lot of code. (as suggested in the other post/answer here)

Generate Records to Add to Table - Loop or Recordset? [duplicate]

Where I work we receive electronic meters from customers and try to solve the errors they have. We will receive 4-8 meters at a time that all have the same problem, same specs, same everything, the only thing different between each meter is the Serial Number. I want to be able to enter every serial number, and the common specs all in one form to create multiple records.
Here's a pic of what I have for the form. I was able to create records for just one serial number at a time, but I would like to do it all at once to make data entry quicker and easier.
Meter Entry Form
So summary, Multiple Meters, all identical specs, different serial numbers. I want to enter it all into a form and have multiple records created. Thanks for any help or insight you can provide me.
-Chris
You could bind a subform to the table that stores your meter records and then have some unbound fields on your main form that allows you to enter the information that would be repeated in your batch of records. You could also put another unbound text box on the main form to specify the number of records you want that will have this repeated information.
So in the mock-up below, you'd specify how many records you want (red box), e.g. 10 records:
Then you'd supply the data that would be repeated for these 10 records (blue boxes):
You'd then click a button that would create the number of records specified with the repeated information given:
It would then just be a case completing the unique serial number for each of the records in the batch you have generated.
Here's the VBA I used on the Add button:
Private Sub cmdAddRecords_Click()
batchAdd Me.txtRecords
Me.tblMeters_sub.Requery
End Sub
...and the batchAdd sub routine it calls:
Public Sub batchAdd(records As Integer)
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim i As Integer
Set db = CurrentDb
Set rs = db.OpenRecordset("tblMeters")
i = 1
Do While i <= records
rs.AddNew
rs!SerialNumber = ""
rs!MeterFirmware = Me.MeterFirmware
rs!MeterCatalog = Me.MeterCatalog
rs!Customer = Me.Customer
rs!MeterKh = Me.MeterKh
rs!MeterForm = Me.MeterForm
rs!MeterType = Me.MeterType
rs!MeterVoltage = Me.MeterVoltage
rs.Update
i = i + 1
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
Here's a link to the mock-up (if you want a closer look).
Update
In response to your query about whether the subform could be filtered so it doesn't just become a big list of all meters, you could add another field to the tblMeters table that will take the date and time that you added records to the table:
You'd then need to add another line to the batchAdd sub that will put the system time and date in this new field:
...
Do While i <= records
rs.AddNew
rs!SerialNumber = ""
rs!MeterFirmware = Me.MeterFirmware
rs!MeterCatalog = Me.MeterCatalog
rs!Customer = Me.Customer
rs!MeterKh = Me.MeterKh
rs!MeterForm = Me.MeterForm
rs!MeterType = Me.MeterType
rs!MeterVoltage = Me.MeterVoltage
rs!DateAdded = Now ' <-- HERE!
rs.Update
i = i + 1
Loop
...
You'll then need to change the subform's Record Source property (Design View > select subform > Property Sheet > Data tab > Record Source):
Put the following SQL in there:
SELECT TOP 15 tblMeters.SerialNumber, tblMeters.MeterFirmware, tblMeters.MeterCatalog,
tblMeters.Customer, tblMeters.MeterType, tblMeters.MeterForm, tblMeters.MeterKh,
tblMeters.MeterVoltage, tblMeters.DateAdded
FROM tblMeters
ORDER BY tblMeters.DateAdded DESC;
... which will order the records by the date/time field (most recent at the top) and then show only the first 15 of these records. If you want a different number of records change the TOP 15 bit to a different number of your choosing.
When you click "Add", your new batch of records should be added to the top of the list and the list should stay at a maximum of 15 records (or whatever number you specify in TOP ...)
Be aware that when I was testing this, clicking the "Add" button rapidly a few times seemed to cause the sql to not bother with the TOP ... filter, but as long there's like a second or more between each "Add" click it seemed to work fine.
Hope this helps.

How to add check boxes to a form based on columns in table in Access?

I have a form in Access that allows a user to select a table from a combo box that lists all of the tables using VBA. Based on what table the user selects, I want a set of check boxes to be added to the form. Each check box would represent a column in the chosen table. I have a VBA function that will work with the columns that are chosen through the form after a button is pressed.
How would I make the check boxes appear after the user has chosen a table? I want this form to be applicable to tables that would be added in the future as well so I won't know the number of columns in advance. I can get check boxes to appear dynamically in a Userform but I've heard that they aren't commonly used in Access. I have also heard that there is a limit for the amount of controls that can be added to a form in its lifetime. Is there anyway of renaming controls so that I don't hit this limit?
This is the code that I use to populate the combo box:
Private Sub Form_Load()
Dim tbl As DAO.TableDef
Dim db As Database
Set db = CurrentDb
With Me![TableName]
For Each tbl In db.TableDefs
If Not (tbl.name Like "MSys*" Or tbl.name Like "~*") Then
.AddItem tbl.name
End If
Next
End With
End Sub
This is example code that can generate the check boxes in a Userform:
Private Sub RetrieveColumns_Click()
Dim TableName As String
Dim MethodName As String
Dim tdf As DAO.TableDef
Dim rs As Recordset
Dim fld As Field
Dim chkBox As MSForms.CheckBox
TableName = Me![TableName]
Set tdf = dbs.CreateTableDef(TableName)
Set rs = dbs.OpenRecordset(TableName)
With rs
For i = 0 To .Fields.Count - 1
Set chkBox = Me.Controls("Forms.checkbox.1", "CheckBox_" & i)
chkBox.Caption = .Fields(i).name
chkBox.Left = 5
chkBox.Top = 5 + ((i - 1) * 20)
Next i
End With
End Sub
The best solution would be a continuous form / datasheet that shows all table column names with an adjacent checkbox.
Create a table with ColumnName (Text) and Checked (Yes/No, Default No).
Then when a table is selected:
delete * from this table,
In your .Fields loop, insert all column names into this table,
and show the table as subform (or have the table selection combobox in the form header).
With this, you don't need any dynamic controls.
Alternatively, for a truly simple solution, use a multi-select listbox.
A listbox has the slightly obscure RowSourceType Field List.
The data is a list of field names from a table, query, or SQL statement specified by the RowSource setting.
So all you'd need is to set the RowSource property to the selected table name.

Microsoft Access - Add all items from a listbox into a table without having to be selected?

I'm making a data entry form that allows me to add new businesses and details for that business, before importing them into their respective tables. For the most part, I have completed it all.
However, there are some pieces of information that require more than one input. For example - a business could have multiple telephone numbers/documents/staff members etc.
I have set up a text box and an add/remove button which adds/removes the text in the textbox to a listbox. I want to be able to import all of the items in the listbox, without having to select them into a table. Is this possible? Most of the answers that I've found online require you to have the items selected.
An example piece of code that I have on the import button is show below. This code adds the address details of the business to the 'Business Address' table.
'Set Table to 'Business Address' then add the fields to the table
Set RST = CurrentDb.OpenRecordset("Business Address", dbOpenTable)
RST.AddNew
RST![Business Name] = Me.txtBusinessName
RST![Address] = Me.txtAddress1 & ", " & Me.txtAddress2
RST![Town/City] = Me.txtTownCity
RST![Postal Code] = Me.txtPostalCode
RST.Update
RST.Close
I was thinking some sort of for loop to add all items in the listbox to a table?
Logically speaking (This is not a real example of working code, just something I imagine this might look like if possible?):
Set RST = CurrentDb.OpernRecordset("Business Telephone", dbOpenTable)
For each item in TelephoneListBox
Rst.AddNew
Rst![Business Name] = Me.txtBusinessName
Rst![Telephone] = Me.TelephoneListBox.Column(0)
I'm not sure how to go about it and if it can actually be done without the items being selected? Any ideas?
Dim l As Long
For l = 0 To Me.List0.ListCount - 1
' Debug.Print Me.List0.ItemData(l) or me.list0.column(0,l)
Next l
This will loop through the items in the list.
To improve on Nathan_Sav's answer:
Dim i As Long
Set RST = CurrentDb.OpenRecordset("Business Telephone", dbOpenTable)
For i = 0 To Me.TelephoneListBox.ListCount - 1
RST.AddNew
Rst![Business Name] = Me.txtBusinessName
RST![Telephone] = Me.TelephoneListBox.Column(0, i)
RST.Update
Next i
Adds the value of 'txtBusinessName' to the table 'Business Telephone', under the field specified (Business Name), for each item that is in the listbox.
Also adds all items in the listbox (TelephoneListBox) to the same table under the field specified (Telephone).