Combobox with LimitToList set to false with non-bound field - ms-access

I have a products table and a tags table with a many-to-many relationship. I also have a pivot table that store the product id and the tag id.
I'd like to be able to show the tag text in the combo box but store the id. This on its own is simple as I can just adjust the column width of the id, however, I'm trying to set LimitToList to No so I can implement some VBA to filter the list when I type in the combo box, but this only appears to be possible if the first column is the bound column, which means the tag id appears in the combo box instead of the text.
How do I show the tag text in the combobox and allow 'LimitToList' to be false?

Leave LimitToList on Yes, and use the NotInList event of the combobox instead.
E.g.
Private Sub cboTag_NotInList(NewData As String, Response As Integer)
Dim RS As Recordset
If MsgBox("Do you want to add '" & NewData & "' as new Tag?", vbYesNo + vbQuestion) _
= vbYes Then
' Add the new tag
Set RS = CurrentDb.OpenRecordset("tbTags")
With RS
.AddNew
!Tag_Text = NewData
.Update
.Close
End With
Response = acDataErrAdded
Else
Response = acDataErrDisplay
' Or a user defined MsgBox and acDataErrContinue
End If
End Sub

(sigh) again I have misunderstood your question. :(
To filter the combobox as the user types a part of a Tag, you use the Change event. This works just fine with LimitToList = Yes.
Private Sub cboTag_Change()
Me.cboTag.RowSource = _
"SELECT Tag_ID, Tag_Text FROM tbTags WHERE Tag_Text LIKE '*" & Me.cboTag.Text & "*'"
' With the instant filtering, it is more convenient for the user
' to always see the filtered dropdown
Me.cboTag.Dropdown
End Sub
Of course at some point the user has to select a Tag from the list. Otherwise there would be no ID to store in the field.
Or if you want him to be able to add new tags, use the code from the other answer. Both events work together as written.

Search-as-you type technique described very good here, including automatic selection of items from opened dropdown combobox after typing few characters.

Related

Editing listbox item

So i have a listbox that displays all the orders entered in the Order table using a select sql query. Now i also want to add the ability to edit the items from the listbox, i see the right click edit list item option but when i click it, it just opens the form but doesnt populate the fields. The form has textboxes that are unbound but i cant figure out how to get them to populate based on the right clicked entry. I have also tried to open the target form from vba and fill the fields through vba with the following code
Private Sub editrecordbttn_Click()
Dim valSelect As Variant
Dim v As Variant
Dim selector As Variant
Dim strValue As String ' just used for the demonstration
Dim splitvalue() As String
Dim selectedsampid As String
Dim selectedcusid As String
Dim Records As DAO.Recordset
Dim SQLcus As String
Dim SQLsamp As String
For Each valSelect In Me.searchlistbox.ItemsSelected
strValue = strValue & "" & Me.searchlistbox.ItemData(valSelect) & "," & "" & Me.searchlistbox.Column(1, valSelect) & ","
Next valSelect
' to remove trailing comma
strValue = Left(strValue, Len(strValue) - 1)
splitvalue() = Split(strValue, ",")
selectedsampid = splitvalue(0)
selectedcusid = splitvalue(1)
DoCmd.OpenForm ("Add Sample")
Forms![Add Sample].fnametxt.SetFocus
'query and fill cus info
SQLcus = "SELECT * FROM CustomerInfo WHERE CusID = '" & selectedcusid & "';"
Set Records = CurrentDb.OpenRecordset(SQLcus)
Me!clienttypetxt = Records![Client type].Value
End Sub
Ok, so say we have a listbox, and we do this:
The first column of the listbox is assumed to be the PK or "ID" of the rows.
so, we have this:
And thus you select a row, and then click on the button.
The button code would look like this:
Private Sub cmdEdit_Click()
Debug.Print "Hotel list id selected = " & Me.HotelList
DoCmd.OpenForm "frmEditHotels", , , "ID = " & Me.HotelList
End Sub
So, in most cases, for a better user experience, it probably better to approach things as per above.
There is of course the case in which you fill the listbox (or combo) with a "list" of values NOT from the database. In that case, you can use the "edit" list option. And this allows you to specify a form (or use the built in editor).
so, if this is NOT a list that you type in, and is from the database, then don't try to use the built in "list editing"
(add a button like above, and launch the form with the "where" clause to load the form to the ONE data record as I did above.
Since oh so very often, a listbox data will come from a table, then the edit list options are not really much particular use. And using a table (as opposed to a list) to fill + drive the combo/listbox is a much better design, and idea anyway.
This is especially the case if you ever want multiple-users, since the "list" edit feature would mean and suggest that each user editing the list would now have their own lists as opposed to using a table which everyone can edit.
Also, there is NO reason to use a loop to fill that list box. We can do this:
' setup critera for listbox.
Dim strSQL As String
' prompt user for Hotel city - we just hard code for this exmaple.
Dim strCity As String
strCity = "Banff"
strSQL = "SELECT ID,FirstName, LastName, City,HotelName FROM tblHotels " & _
"WHERE City = '" & strCity & "' " & "ORDER BY HotelName"
Me.HotelList.RowSource = strSQL
Note how we do not have some MESSAY value list, but can shove the data (sql) right to the listbox. Not only do we don't have loops, but we also don't have to worry about the size limits.
With "value list" (those messy delimited ";" list), then you have a rather small limit of 4,000 characters. Don't take many larger rows to "blow up" the listbox, since it can't handel very many rows.
In fact, I often still suggest you use the wizard to build the listbox, and you can choose a datasource (sql), or the MUCH lessor choice of "value list".
Value list is only a good choice if you have say a few choices like Mr., Mrs. or what not, and it not some large table, but only say 5-10 choices.
Anything larger? Use a data table driven listbox, and avoid use of value list.

expression to check if barcode input exists in which case load data for that barcode else continue to create new record

Hi I'm using Access 2007 and i am doing a program to enter stock items.
I am using a form and i need to make sure that when the user inputs the barcode of the product the system checks in the table if this exists. If it does exists, i need to load data for this existing item into the 3 additional fields in the same form, otherwise to continue creating the new record.
Now i am trying to use set tempvar in the beforeupdate however i cannot get it right.
any suggestions please.
field name : [barcode]
table to look into is "cartridge static data"
additional fields to fill if barcode exists are : [cartridge] , [end user] , [phone no]
Appreciate any help
regards
Tony
I would insert a combo box using the Access wizzard.
Select the data from "cartridge static data" i.e. [barcode] [cartridge] [end user] [phone no]
Do not hide the first row, and make sure you can see the data width in the wizard as you build it.
When completed go to the combo [data] [row source] and click the three {…}
Check what is displayed ~ for example sort by Barcode, remove nulls etc.
If you have the column widths wrong you can change those in the [format tab].
Column headers default to No which may need changing or you may be happy with that.
Under [other] name check you have a sane name e.g. cbo_barcode_search
Now attach this code to the AfterUpdate property of the Combo Box:
Sub cbo_barcode_search_AfterUpdate ()
Dim rs As DAO.Recordset
If Not IsNull(Me.cbo_barcode_search) Then
'Save before move.
If Me.Dirty Then
Me.Dirty = False
End If
'Search in the clone set.
Set rs = Me.RecordsetClone
rs.FindFirst "[BarCode] = " & Me.cbo_barcode_search
'rs.FindFirst "[BarCode] = """ & Me.cbo_barcode_search & """" 'for text
If rs.NoMatch Then
'Trigger new form or add the just typed data into your form as required
‘e.g. me.field1 = cbo_barcode_search.column(0) ' Barcode
Else
'Display the found record in the form.
' Usually use Me.Bookmark = rs.Bookmark but your question suggests this is not what you want so
'NOTE: First column data is column(0) NOT column(1)
me.field1 = cbo_barcode_search.column(0) ' Barcode
me.field2 = cbo_barcode_search.column(1) ' Cartridge
me.field3 = cbo_barcode_search.column(2) ' end user
me.field4 = cbo_barcode_search.column(3) ' phone no
End If
Set rs = Nothing
End If
End Sub
You will need to modify this to match your field names (eg me.field1 is probably me.barcode but it may be me.str_barcode ~ I don't know what you used.
Hope this gets you on the right track. Paul

MS Access combo box setting a record with two primary keys

I have a database with 2 primary keys, one for a LINE NUMBER and one for PHASE of construction. The reason for this is that we have projects that may use the same Line Number but must track several Phases of the project entirely seperatly. What I have is a combo box that will drive the record information on a form. This works fine, but now when I have more than one phase it will only bring up the line's first phase and not the other 4 phases. When something other than phas one is picked it results the first phase information.
Is there a way to tie a combo box with 2 fields to select the proper record based on both fields picked?
Or maybe I need to rething the way the form is brought up... Is there a better way to do this?
Code used to select the record:
Sub SetFilter()
Dim LSQL As String
LSQL = "select * from tblLineData_Horizon"
LSQL = LSQL & " where lineno = '" & cboSelected & "'"
Form_frmHorizon_sub.RecordSource = LSQL
End Sub
Private Sub cboSelected_AfterUpdate()
'Call subroutine to set filter based on selected Line Number
SetFilter
End Sub
Private Sub Form_Open(Cancel As Integer)
'Call subroutine to set filter based on selected Line Number
SetFilter
End Sub
A basic idea, but you'll most likely want to tweak the behaviour a bit and have some more checks. When the form loads, you only have the ability to select LineNo. When cbxLineNo has a value in it, it enables cbxPhaseNo for selection and upon selection, it changes the RecordSource of your subform.
Private Sub cbxLineNo_AfterUpdate()
If IsNull(cbxLineNo) Then
cbxPhaseNo.Enabled = False
Else
cbxPhaseNo.Enabled = True
cbxPhaseNo.RowSource = "SELECT PhaseNo FROM tblLineData_Horizon WHERE LineNo = " & cbxLineNo & ";"
End If
End Sub
Private Sub cbxPhaseNo_AfterUpdate()
If IsNull(cbxPhaseNo) = False And IsNull(cbxLineNo) = False Then
tblLineData_Horizon_sub.Form.RecordSource = "SELECT * FROM tblLineData_Horizon WHERE LineNo = " & cbxLineNo & " AND PhaseNo = " & cbxPhaseNo & ";"
End If
End Sub
Private Sub Form_Load()
cbxLineNo.Enabled = True
cbxPhaseNo.Enabled = False
cbxLineNo.RowSource = "SELECT LineNo FROM tblLineData_Horizon GROUP BY LineNo;"
End Sub
You question is a little unclear, but you can create a combobox with more than one column, then your select statement would be:
where lineno = '" & cboSelected.Column(0) & "' And otherfield='"& cboSelected.Column(1)&"'"
Go to the query behind your combobox by clicking into its RowSource property and clicking the Build button (...). Once you've added the columns you need, bring up the Properties for the query and set Unique Values to Yes, so that it doesn't repeat the combinations of the fields.
You will also need to change other properties of the combobox: 'Column Count' and 'Column Widths'.

Databound CheckBoxList for Microsoft Access

In ASP.NET I have the option for building a CheckBoxList control from a data source where the values of the items can be the "Id" column (for example) while the text displayed next to the checkbox is from a "Name" column.
Is it possible to do something similar to this for Access 2003 with VBA? I am trying to avoid hardcoding the list of items if at all possible, but can't figure out how to do anything similar to this.
Just use a listbox. A list box in Access is great because it allows multiple columns, but will hide the first column as you ask. And you can just set the listbox to allow multiple selections (in the other tab of the property sheet for the listbox, set Multiselect to "simple"
And even better is you don't need any code to fill out the listbox, but can type in the sql or simply base the listbox on a SQL query.
So a listbox can look like this:
The code behind the button to turn the selected items into a useful list of PK id looks like this:
Private Sub cmdFax_Click()
Dim strIDList As String
Dim vID As Variant
Dim strSQLWhere As String
For Each vID In Me.lstFaxList.ItemsSelected
If strIDList <> "" Then strIDList = strIDList & ","
strIDList = strIDList & lstFaxList.ItemData(vID)
Next
If strIDList <> "" Then
strSQLWhere = " ID in (" & strIDList & ")"
End If
DoCmd.OpenReport "rptFax", acViewPreview, , strSQLWhere
End Sub
And if you want, you can in code for supply or set the SQL of the listbox like this:
Sub mytest()
Dim strSql As String
strSql = "Select ID, firstName, LastName, City " & _
"where city = 'Edmonton'"
Me.lstFaxList.RowSource = strSql
End Sub
So you don't need to type in any kind of list here. It not clear if you "must" have a actual check box here - you can use a continues form if you wanted, but I think the above is oh so much more simple and you don't need much code to set this up at all.

Fire update event on keyup

I have textbox ("D_find" in its id) on my form witch i use to filter form's data using LIKE query.
I have following code:
Private Sub D_find_AfterUpdate()
Dim fil
fil = Me.D_find
If fil = Null Then
fil = ""
End If
Me.Filter = "DeloN Like '" + fil + "*'"
End Sub
It's working correctly if i press tab or focus some other control on form, but i need to apply filter immediatly after keyup event of the textbox, but i cant to it, because if i use this code in D_find_keyup i always have D_find is NULL, but in current scenario it's always is not null except if it's empty.
The second trouble present in current scenario: after AfterUpdate fired and filter is applied, text color in D_find textbox is going to be white and it rollbacks to black after i type somethin in this textbox (D_find) or cut some text.
--
I'm sorry for my bad English.
If the textbox still has focus, you can use:
NameOfControl.Text
This will contain the text just entered. However, why must you apply the filter immediately, it would be safer in Afterupdate, because you would be sure that all data was entered, and you can set focus back to the search control.
EDIT re Comments
Using a textbox, txtSearch, and a listbox, lstCompanies the following code illustrates the above:
Private Sub txtSearch_Change()
s = "SELECT Key, Company " _
& "FROM tblCompanies " _
& "WHERE Company LIKE '*" _
& Replace(Me.txtSearch.Text, "'", "''") & "*'"
Me.lstCompanies.RowSource = s
End Sub
The listbox returns a gradually diminishing list as letters are added to txtSearch.