Access technique
One lookup table, many drop-downs
A typical Access file grows a pile of tiny lookup tables. This pattern keeps those lists in one table, tlkpInfo. The combo still stores the ID and shows the name.
Download the Access file (Access 2007+, sample data only).
What you get
Beside each combo, Edit opens that list only. Hide Me takes a value out of the drop-down without deleting the row -- so old records still have an ID to show. Do not delete lookup rows in the product. There is no referential integrity here; a delete leaves orphan IDs and broken queries. Physical delete is an admin job later.
If you hide a value that a record still uses, a naive combo goes blank. The Row Source below keeps the current ID in the list and labels it (hidden).
Combo Row Source
Status combo on frmDemoItem. Tag on the combo is 2 (the group id). Category uses [CategoryID] and Tag 3; Assigned uses [AssignedToID] and Tag 4.
The listings are coloured like Visual Studio on a white sheet. Switch the site to Light (top right) if names look faint — keywords stay blue either way.
SELECT tlkpInfo.tlkpInfoID, IIf([tlkpInfoDel],[tlkpInfoDesc] & " (hidden)",[tlkpInfoDesc]) FROM tlkpInfo WHERE (([tlkpInfoGrp]=2 AND [tlkpInfoDel]=False) OR [tlkpInfoID]=[StatusID]) ORDER BY IIf([tlkpInfoDel],1,0), [tlkpInfoOrder];
Form events
Requery on Current so the extra hidden row follows the record. Not In List on Assigned only -- one displayed field, current Access acDataErrAdded (Access requeries; do not Requery yourself).
Private Sub Form_Current() On Error Resume Next Me.cboStatus.Requery Me.cboCategory.Requery Me.cboAssigned.Requery End Sub Private Sub btnEditStatus_Click() Call fEditComboData(Me.cboStatus) End Sub Private Sub cboAssigned_NotInList(NewData As String, Response As Integer) Response = fNotInListLookup(Me.cboAssigned, NewData) End Sub
basConstants
Option Compare Database Option Explicit Public Const conQuote As String = """""" Public Const conOPEN As String = "Open" Public Const conAppName As String = "Nifty Lookup Demo"
basLookupInfo
Edit opens frmTlkpInfo for that combo's group. Not In List uses DAO AddNew (or unhides a Hide Me row). Group id comes from the combo Tag first; parsing RowSource is only a fallback.
Option Compare Database Option Explicit ' Combo+Edit for tlkpInfo. Prefer Combo.Tag = group id (e.g. "2"). ' fGroupNumber still parses RowSource if Tag is blank (Access scar; web passes groupId). ' ' NotInList (current Access): LimitToList Yes; DAO AddNew (or unhide); ' Response = acDataErrAdded so Access requeries -- do not Requery yourself. ' On No: Undo + acDataErrContinue. ' Access 2007+ ListItemsEditForm is for a normal lookup table, not a grouped ' tlkpInfo list (it cannot pass Grp). Use the Edit button + fEditComboData. Public Function fEditComboData(oComboToUpdate As ComboBox) As String On Error GoTo Error_Handler Dim strFrmName As String strFrmName = "frmTlkpInfo" DoCmd.OpenForm strFrmName, acNormal With Forms(strFrmName) .prpGrpNumber = fGroupNumber(oComboToUpdate) .fSetUp Set .prpComboBox = oComboToUpdate End With Exit Function Error_Handler: MsgBox "fEditComboData: " & Err.Number & " " & Err.Description, vbExclamation, conAppName End Function Public Function fAppendToLookUpTableGroup(ByVal lngInfoOrder As Long, ByVal strInfoDesc As String, ByVal blnInfoDel As Boolean, ByVal lngInfoGrp As Long) Dim rst As DAO.Recordset On Error GoTo Error_Handler Set rst = CurrentDb.OpenRecordset("tlkpInfo") rst.AddNew rst!tlkpInfoOrder = lngInfoOrder rst!tlkpInfoDesc = strInfoDesc rst!tlkpInfoDel = blnInfoDel rst!tlkpInfoGrp = lngInfoGrp rst.Update rst.Close Set rst = Nothing Exit Function Error_Handler: On Error Resume Next If Not rst Is Nothing Then rst.Close Set rst = Nothing End If MsgBox "fAppendToLookUpTableGroup: " & Err.Number & " " & Err.Description, vbExclamation, conAppName End Function Public Function fNotInListLookup(oCombo As ComboBox, ByVal strNewData As String) As Integer ' Usage in the combo NotInList event: ' Response = fNotInListLookup(Me.cboAssigned, NewData) Dim lngGrp As Long Dim lngOrder As Long Dim rst As DAO.Recordset Dim strCrit As String On Error GoTo Error_Handler fNotInListLookup = acDataErrContinue strNewData = Trim$(strNewData) If Len(strNewData) = 0 Then oCombo.Undo Exit Function End If If MsgBox("'" & strNewData & "' is not in the list. Add it?", vbYesNo + vbQuestion, conAppName) <> vbYes Then oCombo.Undo Exit Function End If lngGrp = fGroupNumber(oCombo) If lngGrp = 0 Then MsgBox "This combo has no tlkpInfo group (set Tag to the group id).", vbExclamation, conAppName oCombo.Undo Exit Function End If strCrit = "tlkpInfoGrp=" & lngGrp & " AND tlkpInfoDesc='" & Replace(strNewData, "'", "''") & "'" Set rst = CurrentDb.OpenRecordset("tlkpInfo", dbOpenDynaset) rst.FindFirst strCrit If Not rst.NoMatch Then If rst!tlkpInfoDel Then rst.Edit rst!tlkpInfoDel = False rst.Update End If Else lngOrder = Nz(DMax("tlkpInfoOrder", "tlkpInfo", "tlkpInfoGrp=" & lngGrp), 0) + 1 rst.AddNew rst!tlkpInfoOrder = lngOrder rst!tlkpInfoDesc = strNewData rst!tlkpInfoDel = False rst!tlkpInfoGrp = lngGrp rst.Update End If rst.Close Set rst = Nothing fNotInListLookup = acDataErrAdded Exit Function Error_Handler: On Error Resume Next If Not rst Is Nothing Then rst.Close Set rst = Nothing End If fNotInListLookup = acDataErrContinue MsgBox "fNotInListLookup: " & Err.Number & " " & Err.Description, vbExclamation, conAppName End Function Public Function fGroupNumber(oCombo As ComboBox) As Long Dim strRow As String Dim strPrefix As String Dim x As Integer Dim intPlaces As Integer Dim strCh As String On Error GoTo Error_Handler If Len(Trim$(Nz(oCombo.Tag, ""))) > 0 And IsNumeric(oCombo.Tag) Then fGroupNumber = CLng(oCombo.Tag) Exit Function End If strRow = oCombo.RowSource & "" strPrefix = "SELECT tlkpInfo.tlkpInfoID, tlkpInfo.tlkpInfoDesc FROM tlkpInfo WHERE (((tlkpInfo.tlkpInfoDel)=False) AND ((tlkpInfo.tlkpInfoGrp)=" For x = 1 To 50 strCh = Mid$(strRow, Len(strPrefix) + x, 1) If strCh = ")" Then intPlaces = x - 1 Exit For End If Next x If intPlaces < 1 Then fGroupNumber = 0 Exit Function End If fGroupNumber = CLng(Mid$(strRow, Len(strPrefix) + 1, intPlaces)) Exit Function Error_Handler: fGroupNumber = 0 MsgBox "fGroupNumber: " & Err.Number & " " & Err.Description, vbExclamation, conAppName End Function
What this is not
It is not a value list typed into the combo. It is not a replacement for a lookup that needs extra columns (billable, tax). Those stay their own table. The web demo is sample data in this browser only.