I'm trying to make a database for paperwork for a summer camp. Right now I have a form setup that has a combo box with the the children's name in the header. And I have three tabs separating the different papers they need to turn in (medical, permissions, etc). I have the combo box working, sort of. When I click on it I have it showing the list of names, but I don't seem to have it connected to the underlying table, so it could show the records. The records are all a mix of checkboxes (yes/no) and text boxes (for additional comments). Does the combo box need to have an After Update event, or would it be in another event? I've tried copying some code that I've found, but it hasn't seemed to work. Right now there should be some information that shows up that I've already entered directly into the table, but other fields I know are blank.
My goal is to be able to select a child from the combo box and pull up their records and edit information as needed. I'm a real beginner with coding, but I think it's something that would lead me to a solution here. I've been across a variety of forms today and nothing seems to have worked for me yet. I'm also just beginning to learn access so I'm only starting to know the kinds of questions to ask. Any help or suggestions would really be appreciated.
In an Access form, there are either bound or unbound controls. Bound means table fields are connected and unbound means there are no table field connection. The same can be said about bound and unbound forms where bound has a whole table connected to form and unbound does not. If you enter Design View, you will either see a field name in textbox or "Unbound" written in textbox. For checkboxes you cannot tell unless you enter its Property Sheet \ Data tab \ Control Source.
From your explanation, you seem to refer to a search box. This would be an unbound form as no data should be tied to it. Your header of Student's Name seems to be a bound textbox of student name. Search boxes have an AfterUpdate event built in either as a macro or VBA that searches a record that matches the selection of the drop down:
Macro:
Search Record
Object Type: Form
Object Name: YourFormName
Record: First
Where Condition: ="[ID] = " & Str(Nz([Screen].[ActiveControl],0))
VBA:
DoCmd.SearchForRecord acDataForm, "yourFormName", acFirst, "[ID] = " & Forms!YourFormNam!DropDownField
Please note you can create a search box simply by placing a new combo box on the form and following the Wizard all the way through. The outcome of this will be an AfterUpdate event macro as listed above. You must have canceled the wizard before finishing to have an unbound combo box with no functionality.
The problem I am having is displaying the correct information in a combobox on an unbound form when a users views/edits data.
The table that populates the combobox:
tblLocation
idLocation
Location
Location Description
In the tblPerson table, there is a FK field called idLocation. I have a form that allows a user to pick a person from a listbox and displays the information in textboxes and comboboxes.
The combobox is setup with these items:
idLocation <--- column width set to 0
Location
The problem I am having is having the data show up correctly in the comobox when I view/edit a new person.
When a person is selected from a ListBox, the information from tblPerson should display in textboxes and comboboxes. The textboxes work just fine. However, I'm struggling with the comboboxes. Keep in mind all of the fields
My research finds only two methods on solving this problem:
DLOOKUP
Manual check and set
If I use the DLOOKUP method:
cmbLocation = (DLookup("Location", "tblLocation", "idLocation=" & .Fields("idLocation")))
The problem is that msgBox cmbLocation will display the text and not the FK. If the user tries to edit the data, but makes no changes, it will try to save the text and not the FK.
I found a manual way that does work, but I'm not sure it is the best approach:
For i = 0 To (cmbLocation.ListCount - 1)
If Val(cmbLocation.Column(0, i)) = Val(.Fields("idLocation").Value) Then
cmbLocation = cmbLocation.ItemData(i)
Exit For
End If
Next
Again, this works - but I have to think that I'm doing something wrong - probably something obvious.
Is there a better way to do this?
you can dynamically change which data is displayed in a combobox. in your scenario, i suggest you use the OnClick event of the listbox (once the person is selected). Add the following code:
YourComboBoxName.RowSource = "SELECT * FROM tblLocation WHERE idLocation=" & FK
If after clicking on a person, the data doesn't change in the combobox, you may need a Me.Refresh
Base the form on a query that left joins in the location column.
Then that field when bound to a text box will will display automatic and without any code. And better is if the actual location value changes, then no update code etc. is required. In fact this is the whole beauty of a relational database!
I created a data entry from and split my database to front-end and back-end. When I enter in data I want certain fields to autocomplete. To be specific, I want to do something like (assuming the term Request had been previously entered) when you type in Requ... it would show Request and you could just press enter or tab to move to the next field. I don't want the rest of the fields autofilled, just individual fields autocompleted. Not sure if the fact that the database is split prohibits this?
Using a form, set the controls for the fields you want to autocomplete to comboboxes and the row source of the combo to a select from the table:
Control Source : MyFieldToComplete
Row Source : SELECT DISTINCT MyFieldToComplete FROM MyTableWithMyField
Limit To List : No
There are wizards for building combos, or you can change controls manually with right-click.
The problem is that i have two forms. First is parent form, second is daughter grid-like form.
On parent form there are some maniplations which must fill in some fields in daughter form.
Its like "Update Set Where" query in SQL, but in this grid. After all manipulation i press button "Save" and only then changes save into DB
thanks
You can access the child form using the following syntax in VBA
Me.Controls("YourSubFormName").Form.Controls("ControlOnYourTargetForm").Text = ..
However, if you have a datasheet view of your form then you need to modify the underlying data, since the form is tightly data bound and reflects the chnanges in your data. You can't just add a new line here as you would do in a "normal" GridView in .Net etc.
I have searched around, and it seems that this is a limitation in MS Access, so I'm wondering what creative solutions other have found to this puzzle.
If you have a continuous form and you want a field to be a combo box of options that are specific to that row, Access fails to deliver; the combo box row source is only queried once at the beginning of the form, and thus show the wrong options for the rest of the form.
The next step we all try, of course, is to use the onCurrent event to requery the combo box, which does in fact limit the options to the given row. However, at this point, Access goes nuts, and requeries all of the combo boxes, for every row, and the result is often that of disappearing and reappearing options in other rows, depending on whether they have chosen an option that is valid for the current record's row source.
The only solution I have found is to just list all options available, all the time. Any creative answers out there?
Edit Also, I should note that the reason for the combo box is to have a query as a lookup table, the real value needs to be hidden and stored, while the human readable version is displayed... multiple columns in the combo box row source. Thus, changing limit to list doesn't help, because id's that are not in the current row source query won't have a matching human readable part.
In this particular case, continuous forms make a lot of sense, so please don't tell me it's the wrong solution. I'm asking for any creative answers.
I also hate Access, but you must play with the cards you are dealt.
Continuous forms are a wonderful thing in Access, until you run into any sort of complexity as is commonly the case, like in this instance.
Here is what I would do when faced with this situation (and I have implemented similar workarounds before):
Place an UNBOUND combobox on the form. Then place a BOUND textBox for the field you want to edit.
Make sure the combobox is hidden behind (NOT invisible, just hidden) behind the textBox.
In the OnCurrent event fill the listBox with the necessary data. Go ahead and "Limit to list" it too.
In the OnEnter or OnClick event of the textBox give the combobox focus. This will bring the combobox to the forefront. When focus leaves the combobox it will hide itself once more.
In the AfterUpdate event of the combobox set the value of the textbox equal to the value of the combobox.
Depending on your situation there may be some other details to work out, but that should more or less accomplish your goal without adding too much complexity.
use continuous forms .. definitely. In fact you can build entire applications with great and intuitive user interface built on continuous forms. Don't listen to Toast!
Your solution of listing all options available is the correct one. In fact there is no other clean solution. But you are wrong when you say that Acccess goes nuts. On a continuous form, you could see each line as an instance of the detail section, where the combobox is a property common to all instances of the detail section. You can update this property for all instances, but cannot set it for one specific instance. This is why Access MUST display the same data in the combobox for all records!
If you need to accept only record-specific values in this combobox, please use the beforeUpdate event to add a control procedure. In case a new value cannot be accepted, you can cancel data update, bringing back the previous value in the field.
You cannot set the limitToList property to 'No' where the linked data (the one that is stored in the control) is hidden. This is logical: how can the machine accept the input of a new line of data when the linked field (not visible) stays empty?
You could also make the value of the combo box into an uneditable text field and then launch a pop-up/modal window to edit that value. However, if I was doing that, I might be inclined to edit the whole record in one of those windows.
I don't think that Access continuous forms should be condemned at all, but I definitely believe that they should be avoided for EDITING DATA. They work great for lists, and give you substantially more formatting capabilities than a mere listbox (and are much easier to work with, too, though they don't allow multi-select, of course).
If you want to use a continuous form for navigation to records for editing, use a subform displaying the detailed data for editing, and use the PK value from the subform for the link field. This can be done with a continuous form where you place a detail subform in the header or footer, linked on the PK of the table behind the continuous form.
Or, if you are using a continuous form to display child data in a parent form, you can link the detail subform with a reference to the PK in the continuous subform, something like:
[MySubForm].[Form]!MyID
That would be the link master property, and MyID would be the link child property.
We also encounter this a lot in our applicatins. What we have found to be a good solution:
Just show all rows in the comboboxes.
Then, as soon as the user enters the compobox in a specific row, adjust the rowsource (with the filter for that row). When the combobox loses the focus, you can re-set the rowsource to display everything.
I have a simpler way to go than Gilligan. It seems like a lot of work but it really isn't. My solution requires having my continuous form as a subform datasheet. On my subform I have two lookup comboboxes, among other fields, called Equipment and Manufacturer. Both simply hold a Long Integer key in the data source. Manufacturer needs to be filtered by what is selected in Equipment. The only time I filter Manufacturer.RowSource is in the Manufacturer_GotFocus event.
Private Sub Manufacturer_GotFocus()
If Nz(Me.Equipment, 0) > 0 Then
Me.Manufacturer.RowSource = GetMfrSQL() '- gets filtered query based on Equipment
Else
Me.Manufacturer.RowSource = "SELECT MfgrID, MfgrName FROM tblManufacturers ORDER BY MfgrName"
End If
End Sub
In Manufacturer_LostFocus I reset Manufacturer.RowSource to all Manufacturers as well. You need to do this because when you first click in the subform, GotFocus events fire for all controls, including Manufacturer, even though you are not actually updating any fields.
Private Sub Manufacturer_LostFocus()
Me.Manufacturer.RowSource = "SELECT MfgrID, MfgrName FROM tblManufacturers ORDER BY MfgrName"
End Sub
In the Enter event of Manufacturer you have to check if Equipment has been selected, if not set focus to Equipment.
Private Sub Manufacturer_Enter()
If Nz(Me.EquipmentID, 0) = 0 Then
'-- Must select Equipment first, before selecting Manufacturer
Me.Equipment.SetFocus
End If
End Sub
You also need to requery the Manufacturer combobox in Form_Current event (i.e. Me.Manufacturer.Requery), and you should set the Cycle property of this subform to "Current Record".
Seems simple enough, but you're not done yet. You also have to reset Manufacturer.RowSource to all Manufacturers in the SubForm_Exit event in the parent form in case the user goes to the Manufacturer combobox but does not make a selection and clicks somewhere on the parent form. Code sample (in parent form):
Private Sub sFrmEquip_Exit(Cancel As Integer)
Me.sFrmEquip.Controls("Manufacturer").RowSource = "SELECT MfgrID, MfgrName FROM tblManufacturers ORDER BY MfgrName"
End Sub
There is still one piece of this that is not clean. When you click on Manufacturer and have multiple rows in the datasheet grid, Manufacturer field will go blank in other rows (the data underneath the comboboxes is still intact) while you're changing the Manufacturer in the current row. Once you move off this field the text in the other Manufacturer fields will reappear.
This seems to work well.
CBOsfrmTouchpoint8 is a combobox shortened to just the dropdown square.
CBOsfrmTouchpoint14 is a textbox that makes up the rest of the space.
Never say never:
Private Sub CBOsfrmTouchpoint8_Enter()
If Me.CBOsfrmTouchpoint8.Tag = "Yes" Then
CBOsfrmTouchpoint14.SetFocus
Me.CBOsfrmTouchpoint8.Tag = "No"
Exit Sub
End If
Me.CBOsfrmTouchpoint8.Tag = "No"
Me.CBOsfrmTouchpoint8.RowSource = "XXX"
Me.CBOsfrmTouchpoint8.Requery
Me.CBOsfrmTouchpoint8.SetFocus
End Sub
Private Sub CBOsfrmTouchpoint8_GotFocus()
Me.CBOsfrmTouchpoint14.Width = 0
Me.CBOsfrmTouchpoint8.Width = 3420
Me.CBOsfrmTouchpoint8.Left = 8580
Me.CBOsfrmTouchpoint8.Dropdown
End Sub
Private Sub CBOsfrmTouchpoint8_LostFocus()
Me.CBOsfrmTouchpoint8.RowSource = "XXX"
Me.CBOsfrmTouchpoint8.Requery
End Sub
Private Sub CBOsfrmTouchpoint8_Exit(Cancel As Integer)
Me.CBOsfrmTouchpoint14.Width = 3180
Me.CBOsfrmTouchpoint8.Width = 240
Me.CBOsfrmTouchpoint8.Left = 11760
Me.CBOsfrmTouchpoint8.Tag = "Yes"
End Sub
What if you turn off the "Limit To List" option, and do some validation before update to confirm that what the user might have typed in matches something in the list that you presented them?
Better...
Set you combo box Control Source to a column on the query where the values from your combo box will be stored.
For Me I think the best way and easiest way is to create a temporary table that has all your bound fields plus an extra field that is a yeas/no field.
then you will use this table as the data source for the continuous for. You can use onLoad to fill the temporary table with the data you want.
I think it is easy after that to loop for the choices, just a small loop to read the yeas/no field form the temporary table.
I hope this will help
Use OnEnter event to populate the combo box, don't use a fixed rowsource.
I've just done similar. My solution was to use a fixed row source bound to a query. The query's WHERE clauses reference the form's control i.e. Client=Forms!frmMain!ClientTextBox. This alone will fill the combo boxes with the first row's data. The trick then is to set an 'On Enter' event which simply does a re-query on the combo box e.g. ComboBox1.Requery, this will re-query that combo box alone and will only drag in the data related to that record row.
Hope that works for you too!
Disclaimer: I hate Access with a passion.
Don't use continuous forms. They're a red herring for what you want to accomplish. Continuous forms is the same form repeated over and over with different data. It is already a kludge of Access's normal mode of operation as you can't have the same form opened multiple times. The behavior you are seeing is "as designed" in Access. Each of those ComboBox controls is actually the same control. You cannot affect one without affecting the others.
Basically, what you have done here is run into the area where Access is no longer suitable for your project (but cannot ditch because it represents a large amount of work already).
What seems to be the most likely course of action here is to fake it really well. Run a query against the data and then create the form elements programmatically based on the results. This is a fair amount of work as you will be duplicating a good bit of Access's data handling functionality yourself.
Reply to Edit:
But as they are, continuous forms cannot accomplish what you want. That's why I suggested faking out your own continuous forms, because continuous forms have real limitations in what they can do. Don't get so stuck on a particular implementation that you can't let go of it when it ceases to work.