We all know about the evils of Lookup fields and why they are to be avoided at all costs! If you aren’t already familiar with why they are to never be used, then take a few moments to review The Evils of Lookup Fields in Tables (pay special attention regarding Upsizing should you ever think you will need to eventually port your db to SQL Server, or another RDMS one day!) and Did I Mention I Have a Thing Against Lookup Fields in Tables?.
The problem is that many novice developers are not aware of the above and use them, some abundantly. So when I take over their projects I need to easily find these fields so I can remove them and set things up properly. As such, here is a simple little procedure I put together that will list all the table lookup field in a database.
'---------------------------------------------------------------------------------------
' Procedure : Tables_FindLookupFields
' Author : Daniel Pineault, CARDA Consultants Inc.
' Website : http://www.cardaconsultants.com
' Purpose : Identify all the table fields that are set as a Lookup (to be avoided!!!)
' Results are displayed in the immediate window
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
' (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Uses Late Binding, so none required
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' None
'
' Usage:
' ~~~~~~
' ? Tables_FindLookupFields
' Call Tables_FindLookupFields
'
' Revision History:
' Rev Date(yyyy/mm/dd) Description
' **************************************************************************************
' 1 2015-02-29 Initial Release
' 2 2017-05-23 Added DisplayControlType Conversion Function
' 3 2018-09-20 Updated Copyright
'---------------------------------------------------------------------------------------
Public Function Tables_FindLookupFields() As String
' https://msdn.microsoft.com/en-us/library/cc185703(v=office.12).aspx
On Error GoTo Error_Handler
Dim tdf As DAO.TableDef
Dim fld As DAO.Field
Dim prp As DAO.Property
Application.Echo False
Debug.Print "Searching for Lookup Fields"
Debug.Print "Table Name", "Fld Name", "DisplayControl Type"
Debug.Print String(80, "-")
For Each tdf In CurrentDb.TableDefs 'Loop through each table
If Left(tdf.Name, 4) <> "MSys" Then 'Don't mess with system tables!
For Each fld In tdf.Fields 'Loop through each field
Set prp = fld.Properties("DisplayControl")
If Not prp Is Nothing Then
If prp <> acTextBox Then Debug.Print tdf.Name, fld.Name, DisplayControlType(prp)
End If
Set prp = Nothing
Next fld
End If
Next tdf
Debug.Print String(80, "-")
Debug.Print "Search Complete"
Error_Handler_Exit:
On Error Resume Next
Application.Echo True
If Not prp Is Nothing Then Set prp = Nothing
If Not fld Is Nothing Then Set fld = Nothing
If Not tdf Is Nothing Then Set tdf = Nothing
Exit Function
Error_Handler:
If Err.Number = 3270 Then
'Property doesn't exits
Resume Next
Else
MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Source: Tables_FindLookupFields" & vbCrLf & _
"Error Description: " & Err.Description & _
Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
, vbOKOnly + vbCritical, "An Error has Occurred!"
Resume Error_Handler_Exit
End If
End Function
Function DisplayControlType(ByVal DisplayControl As Integer) As String
'Purpose: Converts the numeric results of DAO DisplayControl to plain English text
Select Case CLng(DisplayControl)
Case 106
DisplayControlType = "Check Box"
Case 109
DisplayControlType = "Text Box"
Case 110
DisplayControlType = "List Box"
Case 111
DisplayControlType = "Combo Box"
Case Else
DisplayControlType = "Unknown/" & DisplayControl
End Select
End Function
Daniel –
While the function will display controls in a database, how does it know that every control is a lookup field?
Peter,
It is done with the
If the DisplayControl property does not exist or is set to Textbox, then it is not a Lookup Field, otherwise, it is.
Me queda una gran duda. Muchos maestros del ACCESS en otros foros de hecho recomiendan el uso de los campos de búsqueda para evitar las relaciones entre tablas. LA duda que me queda es… ¿Qué es mejor entonces?
Por ejemplo, corrí el código VBA y encontré en una herramienta que yo hice un total de 450 campos de búsqueda… ¿Es un error?
I’ve never heard of this, so I can’t comment on the subject. Access is a RDMS, so driven by relationships, or should be normally.
Daniel Thanks for answering. I enclose two pages where they suggest creating relationships through the search fields. I would like you to read them and give me your opinion.
https://jordisan.net/blog/2008/consejos-access/#more-163
http://www.mvp-access.com/foro/relaciones-entre-las-tablas_topic84232.html
Tanks
From my understanding, the original question was somewhat about the placement of relationships in a split database. In a general sense, relationships should be created in the back-end file. This way they are always enforced.
As for comments regarding not using Relationships, I didn’t see any real reasons why. It seemed to be a personal approach. They also mention using code to enforce things… This can be complex to setup, properly, and certainly not for a novice developer. Furthermore, if ever someone connects through another point other than the front-end the database will not have any referential integrity enforced.
From my perspective, I don’t see any compelling reason to not create and use relationships, but everyone’s entitled to the opinion.
It could be argued, having seen databases loose all their relationships for no reason (some bug or something), that enforcing everything by code is a safer approach that guarantees things work.
Why not do both? Set up relationships and use code to validate everything.
Hi Daniel,
Thanks a lot for the piece of code. I was really looking something like that. Since this code is also looking for checkbox for Yes/No fields. To get rid of lookup field evils, is it recommended to change lookup property of Yes/No fields to textbox or letting checkbox remain there is okay?
Thanks