It's been awhile since i've worked in VBA. I have a bound form. It has two drop down lists. One list is bound the other not (the first ddl is a list of values. The second gets refreshed when the first one changes, using the value of the first to create a query for the second. That value is used as a fk in the table the form is bound too).
Anyway, when the form is first run and uses the default value for ddl 1, if the second combobox is empty, and I try to get the value, it's null, which is what you would expect. But, I have code that runs when ddl1's value changes, to requery ddl2. When it requeries, if the list is empty, and I do combobox1.value, instead of being null, the value is 1. This is confusing, because, since the list is empty, I would think it should be null. What's going on here? Here is what I have:
Combo1 is bound to a table
Combo 2 uses this query:
SELECT tbl_office.id, tbl_office.office_name
FROM tbl_office
WHERE (((tbl_office.otherTable_id)=[Forms]![dlg_addDivision].[Combo1]));
On Combo1 afterUpdate event:
me.Combo2.requery
So, after combo1 afterUpdate, the above sql gets called. If this produces an empty dataset, and I try to get the value of combo2, even though the list is empty, the value says it's 1
thanks
The requery requeries the List - not the value. The value stays whatever it is/was before. Its not a bug - its a feature ;-)
If you page through datasets that are already filled you wouldn't want them to be changed without user interaction. The List is just a helper for dataEntry (and validation - if you check "only listitems allowed") - but it has nothing to do with your dataset.
By setting the value to your first Entry like you proposed: Me.Combo2.Value = Me.Combo2.ItemData(0) you change the dataset intentionally. And that is how it is supposed to happen. Not via changing the list.
Related
I am pretty much a newbie to using VBA in Access and I'm having trouble with something that seems like it should be quite simple.
I have two listboxes (called LB1_ID and LB2_ID) on my form (MainForm) that I want to list related IDs from their respective Row Sources. I need LB2 to be populated based on the selection in LB1. They both have Row Sources from the same Table (Table1) and it is a many to many relationship of Requirement IDs ("Req ID1" and "Req ID2"). My current form, which is not working, has the Row Source of LB1 as:
SELECT Table1.ID, Table1.[Req ID1] FROM Table1 ORDER BY Table1.ID;
and the Row Source of LB2 as:
SELECT Table1.ID, Table1.[Req ID2] FROM Table1 WHERE ([Forms]![MainForm]![LB1_ID]=Table1.[Req ID1]);
When I make a selection in LB1, nothing happens in LB2. The column widths are formatted correctly and I can get it to work if I use Me.[Forms]![MainForm]![LB1_ID] but I have to type out the LB1 selection manually in a popup box if I use that.
What am I missing?
If your listbox is multi-select, you cannot use a simple form reference as query criteria. If it is not multi-select, keep in mind that its value may be a hidden column (usually an ID field), so there are two possible issues and solutions:
Possible Issues:
Single-Select listbox has an ID field that is hidden (column width = 0") and you are matching it to the wrong field in your table. To check the output of the listbox, open the VBE and type ?[Forms]![MainForm]![LB1_ID] into the immediate window and press enter when your form is open in form view and a row is selected in LB1_ID. If the returned line is what you expect, then the problem must be elsewhere.
Multi-Select listbox property is enabled. In this case, your query will not work, because the listbox will only return Null. You will need to write some VBA to loop through the rows and figure out which ones are selected, which is a bit of a pain. Ultimately you'll build some code that will alter your query with the specific criteria for each selected row. Instead of explaining here, take a look at this article for a tutorial.
The .Requery method is still important to put in the AfterUpdate event of your first listbox to refresh the second.
Your query seems to work, but you need to refresh your listbox2 whenever you make selection into listbox1, so if both listbox are in the same form add this event handler :
Private sub LB1_ID_Change()
Me.LB2_ID.Requery
End sub
Without this, your listbox2 will only get populated once on load based on the initial value of listbox1.
Also, if you have not already done it, I would recommend to add your listbox1 control as a parameter into your listbox2 query (in query builder, right click -> parameters).
I have an Access database that uses linked tables residing on a SQL Server. For one of these tables I created a simple form showing several fields of the underlying table.
I want to switch records using a combo box, so I added one using the Combo Box Wizard, where I selected the option "Find a record on my form based on the value I selected in my combo box".
The combo box works, but I noticed that whenever a new value is selected, Access will briefly return to the first record before displaying the selected record. I can verify this by both noticing a screen flicker (e.g., bound fields briefly display data from the first record), as well as profiling the calls to SQL Server, where I can see one query for the first record, and another query for the selected record.
This problem does not occur if I use the next/previous Navigation Buttons at the bottom of the form.
How can I avoid this unnecessary query?
What using the Wizard did was create a Macro behind the Event of your combobox click. It probably looks something like .. , , First, ="[SomeField] = " & Str(Nz(Screen.ActiveControl,0)) .. What you can actually do, instead of using the Macro, is follow something like this
If we look at what that Macro does (or what arguments it accepts), it is a little more clear on why you may be experiencing that behavior.
The first argument is Object Type then Object Name, then Record, then Offset.
Object Type - The type of object that contains the record you want
to make current. Click Table, Query, Form, Server View, Stored
Procedure, or Function in the Object Type box in the Action
Arguments section of the Macro Builder pane. Leave this argument
blank to select the active object. <- Yours would be left blank because you're referring to the combobox on the form
Object Name - The name of the object that contains the record you
want to make the current record. The Object Name box shows all
objects in the current database of the type selected by the Object
Type argument. If you leave the Object Type argument blank, leave
this argument blank also. <- Because the first was left blank
Record - The record to make the current
record. Click Previous, Next, First, Last, Go To, or New in the
Record box. The default is Next. <- This defaulted to First for me and possibly for you too, probably why you were seeing this 'odd' behavior
Offset - An integer or expression that evaluates to an integer. An
expression must be preceded by an equal sign (=). This argument
specifies the record to make the current record. You can use the
Offset argument in two ways: When the Record argument is Next or
Previous, Microsoft Office Access 2007 moves the number of records
forward or backward specified in the Offset argument. When the
Record argument is Go To, Access moves to the record with the number
equal to the Offset argument. The record number is shown in the
record number box at the bottom of the window. Note If you use
the First, Last, or New setting for the Record argument, Access
ignores the Offset argument. If you enter an Offset argument that is
too large, Access displays an error message. You can't enter
negative numbers for the Offset argument.
I wish I could give you more details, but I have not used Access in conjunction with SQL Server, so if that plays into account I would not have any insight.
I have a combo-box on a form with:
ControlSource=Target Basis ---------- [A field in the form recordsource]
RowSource=Target Basis -------------- [A separate table of the same name]
RowSourceType = Table/Query
The table "Target Basis" has 20-odd values. The above behaves as expected ... until,
VB code changes the above as follows:
Select Case xyzVar 'xyzVar is taken from another field on form.
Case xyzValue
Me.Target_Basis.RowSourceType = "Value List"
Me.Target_Basis.RowSource = vbNullString
Me.Target_Basis.RowSource = "'Trend Channel'; 'Adjusted Trnd Ch.'"
Me.Target_Basis.Locked = False
Me.Target_Basis = "Choose"
Case Else 'etc.
Upon completion of the above code, the text "Choose" appears in the combo as expected, but when the user drops the choice list, only one option appears, and it's the following text --
SELECT [Target Basis].Basis FROM [Target Basis]
I used documenter on the entire database and determined that the above query is not defined anywhere. I assumed that the system must be generating it from the controlSource name. To check this, I changed the name of the separate table (i.e. the rowSource table) from "Target Basis" to "Target Type". I got the identical behavior, except that now the single item in the list was --
SELECT [Target Type].Basis FROM [Target Type]
At that point I changed the name of the table back to "Target Basis"; however, the item that appears in the droplist remains as above -- despite that now, neither the query nor the table "Target Type" exist in the system. I tried closing, compacting and re-opening the Db; no change.
Further experimentation revealed the following:
When the code completes execution, the rowSourceType and rowSource are as they should be. I checked this by creating a button that outputs these properties. As soon as the user clicks on the combo's drop arrow however, the rowSource property changes to the SELECT statement above. The rowSourceType stays "Value List", which is why it appears in the drop list rather than executing.
If the controlSource is deleted, i.e. the control is unbound, the problem disappears.
Where is this query coming from??
Much obliged for any insight - IG
Firstly, I'm not sure why you have:
Me.Target_Basis.RowSource = vbNullString
I think it is unnecessary and may be causing the problem.
Try adding Me.Target_Basis.Requery to refresh the combobox list.
Access often leaves "ghosts in the machine". I've been working with Access for close to 20 years and I can't tell you how many times I've had to fix a problem and then import all the forms/macros/queries/etc.. into a fresh empty database. it happens. Not sure if that's your current problem, but it does happen.
I have a form with a few bound fields and a few 'custom made' checkboxes, which set values per vba. When I now start a new record with 'DoCmd.GoToRecord , , acNewRec', Access clears my form but won't create a fresh ID until a value is entered into one of the bound fields. Since my checkbox-fields are not bound, any changes before a bound field has been edited won't be saved. I tried adding values via sql statements, but access throws an error after I change another field stating that the current recordset has been changed so I doubt that this is the way to go.
My form is based on a query and witch vba I set the checkboxes like [value_x] = true (which works fine when I first enter data into a bound field and thereby a new record is created).
(Another way to avoid this would be to set any bound field during the onload-event to a value and remove the value afterwards. But that's not very clean I guess ..)
After testing a few approaches I found my earlier stated idea to be the easiest approach. This means I set a value of a bound field in the form_load event and work with me.dirty where neccessary.
Of course I have to delete empty recordsets afterwards (if someone only opens and closes the form), but that can be handled very easy.
Another great idea was the one Robert Harvey gave me. He suggested to add a click event to my unbound custom checkboxes and use this to change a hidden bound checkbox field, which also worked great.
I have a combobox, and a button, that makes runs a query with the values it gets from combobox, but it does not seem to get the right value.
I tried using
[Forms]![Kooli otsing]![Combobox]
or
[Forms]![Kooli otsing]![Combobox].[Text]
the query did not work, it seems like it does not get the value from combobox. because it worked with normal TextBox.
I ADDED EXPLAINING PICTURE!!!!!
ADDED PICTURE OF VBA EDITOR
ADDED PICTURE OF ERROR AND NO COMMENT AUTOCOMPLETE
Based on the latest comments you posted on your question, you want to use:
[Forms]![Kooli otsing]![Combo19].Column(1)
Here's why. You said you have the following settings for your combobox:
column count: 2
bound column : 1
row source type : table/query
row source: SELECT [Haridusasutused].[ID], [Haridusasutused].[Nimetus] FROM Haridusasutused;
Column count of 2 is telling Access to use the first two columns from your rowsource (the only two columns in this case). Bound column is telling access that the default value of the combobox should be the first column of the row source. In this case, that would be [Haridusasutused].[ID]. Often ID columns are autonumber fields.
The reason you were having problems is that [Forms]![Kooli otsing]![Combo19] was returning data from the ID column (most likely a number) not "Elva Gümnaasium". By adding the .Column(1) you are telling Access to choose the data from the second column (.Column is a zero-based array) of the rowsource, ie, "Elva Gümnaasium".
EDIT: Alternatively, you can change the bound column from 1 to 2 and leave the rest alone (ie, you won't need the .Column(1) part at all).
This works in my application:
[Forms]![Hour-registration]![mwkselect]
^form ^combobox
Maybe try this to refresh:
Me.Requery
Me.Refresh
Have you tried to step through debugger and search for the value through the watch window? For instance put a breakpoint into a button click event, then add [Forms] to the watch window and look into it.
You can use:
[Forms]![Form1]![Combo1].[Text]