Provided by Allen Browne, August 2006.
Code for Find As You Type utility
The code below is from the Find As You Type application.
Option Compare Database
Option Explicit
Private Const mbcStartOfField = False
Private Const mstrcWildcardChar = "*"
Private Const mstrcSep = ";"
Private Const micControlName = 0
Private Const micControlLabel = 1
Private Const micControlType = 2
Private Const micFilterField = 3
Private Const micFieldType = 4
Private Const mlngcOnTheForm = -1&
Private Const conMod = "ajbFindAsUType"
Public Function FindAsUTypeLoad(frm As Form, ParamArray avarExceptionList()) As Boolean
On Error GoTo Err_Handler
Dim rs As DAO.Recordset
Dim ctl As Control
Dim strForm As String
Dim strControl As String
Dim strField As String
Dim strControlSource As String
Dim strOut As String
Dim lngI As Long
Dim lngJ As Long
Dim bSkip As Boolean
Dim bResult As Boolean
Dim lngParentNumber As Long
Dim lngMaxParentNumber As Long
Dim astrControls() As String
Const lngcControl = 0&
Const lngcField = 1&
strForm = frm.Name
If HasUnboundControls(frm, "cboFindAsUTypeField", "txtFindAsUTypeValue") And (frm.RecordSource <> vbNullString) Then
frm!cboFindAsUTypeField.AfterUpdate = "=FindAsUTypeChange([Form])"
frm.txtFindAsUTypeValue.OnChange = "=FindAsUTypeChange([Form])"
lngMaxParentNumber = MaxParentNumber(frm)
ReDim astrControls(0& To frm.Controls.Count - 1&, mlngcOnTheForm To lngMaxParentNumber, lngcControl To lngcField) As String
Set rs = frm.RecordsetClone
For Each ctl In frm.Controls
If ctl.Visible Then
If (ctl.ControlType = acTextBox) Or (ctl.ControlType = acComboBox) Then
bSkip = False
strField = vbNullString
strControl = ctl.Name
For lngI = LBound(avarExceptionList) To UBound(avarExceptionList)
If avarExceptionList(lngI) = strControl Then
bSkip = True
Exit For
End If
Next
If Not bSkip Then
strControlSource = ctl.ControlSource
If (strControlSource = vbNullString) Or (strControlSource Like "=*") Then
bSkip = True
Else
Select Case rs(strControlSource).Type
Case dbBoolean, dbLongBinary, dbBinary, dbGUID, Is > 100
bSkip = True
End Select
End If
End If
If Not bSkip Then
strField = GetFilterField(ctl)
If strField = vbNullString Then
bSkip = True
End If
End If
If Not bSkip Then
lngParentNumber = ParentNumber(ctl)
astrControls(ctl.TabIndex, lngParentNumber, lngcControl) = strControl
astrControls(ctl.TabIndex, lngParentNumber, lngcField) = strField
End If
End If
End If
Next
For lngJ = LBound(astrControls, 2) To UBound(astrControls, 2)
For lngI = LBound(astrControls) To UBound(astrControls)
If astrControls(lngI, lngJ, lngcControl) <> vbNullString Then
Set ctl = frm.Controls(astrControls(lngI, lngJ, lngcControl))
strOut = strOut & """" & ctl.Name & """" & mstrcSep & _
"""" & Caption4Control(frm, ctl) & """" & mstrcSep & _
ctl.ControlType & mstrcSep & _
"""" & astrControls(lngI, lngJ, lngcField) & """" & mstrcSep & _
"""" & rs(ctl.ControlSource).Type & """" & mstrcSep
End If
Next
Next
rs.Close
lngI = Len(strOut) - Len(mstrcSep)
If lngI > 0 Then
With frm.cboFindAsUTypeField
.RowSource = Left(strOut, lngI)
.Value = .ItemData(0)
End With
bResult = True
End If
End If
Call ShowHideControl(frm, "cboFindAsUTypeField", bResult)
Call ShowHideControl(frm, "txtFindAsUTypeValue", bResult)
FindAsUTypeLoad = bResult
Exit_Handler:
Set ctl = Nothing
Set rs = Nothing
Exit Function
Err_Handler:
Call LogError(Err.Number, Err.Description, conMod & ".FindAsUTypeLoad", "Form " & strForm)
Resume Exit_Handler
End Function
Public Function FindAsUTypeChange(frm As Form) As Boolean
On Error GoTo Err_Handler
Dim strText As String
Dim lngSelStart As Long
Dim strField As String
Dim bHasFocus As Boolean
Const strcTextBox = "txtFindAsUTypeValue"
bHasFocus = (frm.ActiveControl.Name = strcTextBox)
If bHasFocus Then
strText = frm!txtFindAsUTypeValue.Text
lngSelStart = frm!txtFindAsUTypeValue.SelStart
Else
strText = Nz(frm!txtFindAsUTypeValue.Value, vbNullString)
End If
If frm.Dirty Then
frm.Dirty = False
End If
strField = Nz(frm.cboFindAsUTypeField.Column(micFilterField), vbNullString)
If (strText = vbNullString) Or (strField = vbNullString) Then
frm.FilterOn = False
Else
frm.Filter = strField & " Like """ & IIf(mbcStartOfField, vbNullString, mstrcWildcardChar) & _
strText & mstrcWildcardChar & """"
frm.FilterOn = True
End If
If bHasFocus Then
If frm.ActiveControl.Name <> strcTextBox Then
frm(strcTextBox).SetFocus
End If
If strText <> vbNullString Then
frm!txtFindAsUTypeValue = strText
frm!txtFindAsUTypeValue.SelStart = lngSelStart
End If
End If
FindAsUTypeChange = True
Exit_Handler:
Exit Function
Err_Handler:
Select Case Err.Number
Case 2474
Resume Next
Case 2185
Resume Exit_Handler
Case Else
MsgBox "Error " & Err.Number & ": " & Err.Description, vbExclamation, "txtFindAsUTypeValue_Change"
Resume Exit_Handler
End Select
End Function
Private Function Caption4Control(frm As Form, ctl As Control) As String
On Error GoTo Err_Handler
Dim strCaption As String
strCaption = ctl.Controls(0).Caption
If strCaption = vbNullString Then
strCaption = CaptionFromHeader(frm, ctl)
End If
If Right$(strCaption, 1&) = ":" Then
strCaption = Left$(strCaption, Len(strCaption) - 1&)
End If
If InStr(strCaption, "&") > 0& Then
strCaption = Replace(strCaption, "&&", Chr$(31))
strCaption = Replace(strCaption, "&", vbNullString)
strCaption = Replace(strCaption, Chr$(31), "&")
End If
If strCaption = vbNullString Then
strCaption = ctl.Name
End If
Caption4Control = strCaption
Exit_Handler:
Exit Function
Err_Handler:
Select Case Err.Number
Case 2467&
Resume Next
Case Else
MsgBox "Error " & Err.Number & ": " & Err.Description, vbExclamation, "Caption4Control()"
Resume Exit_Handler
End Select
End Function
Private Function CaptionFromHeader(frm As Form, ctl As Control) As String
On Error GoTo Err_Handler
Dim ctlHeader As Control
Const icRadius = 120
If (frm.CurrentView = 1) And (frm.DefaultView = 1) Then
For Each ctlHeader In frm.Section(acHeader).Controls
If ctlHeader.ControlType = acLabel Then
If (ctlHeader.Left > ctl.Left - icRadius) And (ctlHeader.Left < ctl.Left + icRadius) Then
CaptionFromHeader = ctlHeader.Caption
End If
End If
Next
End If
Exit_Handler:
Set ctlHeader = Nothing
Exit Function
Err_Handler:
If Err.Number <> 2462& Then
Call LogError(Err.Number, Err.Description, conMod & ".CaptionFromHeader")
End If
Resume Exit_Handler
End Function
Private Function HasUnboundControls(frm As Form, ParamArray avarControlNames()) As Boolean
On Error GoTo Err_Handler
Dim lngI As Long
Dim bCancel As Boolean
If UBound(avarControlNames) > 0& Then
For lngI = LBound(avarControlNames) To UBound(avarControlNames)
If frm.Controls(avarControlNames(lngI)).ControlSource <> vbNullString Then
bCancel = True
Exit For
End If
Next
HasUnboundControls = Not bCancel
End If
Exit_Handler:
Exit Function
Err_Handler:
Resume Exit_Handler
End Function
Private Function MaxParentNumber(frm As Form) As Long
On Error GoTo Err_Handler
Dim ctl As Control
Dim lngReturn As Long
lngReturn = mlngcOnTheForm
For Each ctl In frm.Controls
If ctl.ControlType = acTabCtl Then
lngReturn = ctl.Pages.Count - 1
Exit For
End If
Next
MaxParentNumber = lngReturn
Exit_Handler:
Exit Function
Err_Handler:
Call LogError(Err.Number, Err.Description, conMod & ".MaxParentNumber")
Resume Exit_Handler
End Function
Private Function ParentNumber(ctl As Control) As Integer
On Error Resume Next
Dim iReturn As Integer
iReturn = ctl.Parent.PageIndex
If Err.Number <> 0& Then
iReturn = mlngcOnTheForm
End If
ParentNumber = iReturn
End Function
Private Function ShowHideControl(frm As Form, strControlName As String, bShow As Boolean) As Boolean
On Error Resume Next
frm.Controls(strControlName).Visible = bShow
ShowHideControl = (Err.Number = 0&)
End Function
Private Function GetFilterField(ctl As Control) As String
On Error GoTo Err_Handler
Dim rs As DAO.Recordset
Dim iColumn As Integer
Dim strField As String
Dim bCancel As Boolean
If ctl.ControlType = acComboBox Then
iColumn = FirstVisibleColumn(ctl)
If iColumn = ctl.BoundColumn - 1 Then
strField = "[" & ctl.ControlSource & "]"
Else
If Int(Val(SysCmd(acSysCmdAccessVer))) >= 10 Then
If ctl.RowSourceType = "Table/Query" Then
Set rs = DBEngine(0)(0).OpenRecordset(ctl.RowSource, dbOpenDynaset, dbAppendOnly)
With rs.Fields(iColumn)
strField = "[Lookup_" & ctl.Name & "].[" & .SourceField & "]"
End With
rs.Close
Else
bCancel = True
End If
Else
bCancel = True
End If
End If
Else
strField = "[" & ctl.ControlSource & "]"
End If
If strField <> vbNullString Then
GetFilterField = strField
ElseIf Not bCancel Then
GetFilterField = "[" & ctl.ControlSource & "]"
End If
Exit_Handler:
Set rs = Nothing
Exit Function
Err_Handler:
Call LogError(Err.Number, Err.Description, conMod & ".GetFilterField")
Resume Exit_Handler
End Function
Private Function FirstVisibleColumn(cbo As ComboBox) As Integer
On Error GoTo Err_Handler
Dim i As Integer
Dim varArray As Variant
Dim iResult As Integer
Dim bFound As Boolean
If cbo.ColumnWidths = vbNullString Then
iResult = 0
bFound = True
Else
varArray = Split(cbo.ColumnWidths, mstrcSep)
For i = LBound(varArray) To UBound(varArray)
If varArray(i) <> 0 Then
iResult = i
bFound = True
Exit For
End If
Next
If Not bFound Then
If i < cbo.ColumnCount Then
iResult = i
bFound = True
End If
End If
End If
FirstVisibleColumn = iResult
Exit_Handler:
Exit Function
Err_Handler:
Call LogError(Err.Number, Err.Description, conMod & ".FirstVisibleColumn")
Resume Exit_Handler
End Function
Private Function LogError(ByVal lngErrNumber As Long, ByVal strErrDescription As String, _
strCallingProc As String, Optional vParameters, Optional bShowUser As Boolean = True) As Boolean
On Error GoTo Err_LogError
Dim strMsg As String
Select Case lngErrNumber
Case 0
Debug.Print strCallingProc & " called error 0."
Case 2501
Case 3314, 2101, 2115
If bShowUser Then
strMsg = "Record cannot be saved at this time." & vbCrLf & _
"Complete the entry, or press <Esc> to undo."
MsgBox strMsg, vbExclamation, strCallingProc
End If
Case Else
If bShowUser Then
strMsg = "Error " & lngErrNumber & ": " & strErrDescription
MsgBox strMsg, vbExclamation, strCallingProc
End If
LogError = True
End Select
Exit_LogError:
Exit Function
Err_LogError:
strMsg = "An unexpected situation arose in your program." & vbCrLf & _
"Please write down the following details:" & vbCrLf & vbCrLf & _
"Calling Proc: " & strCallingProc & vbCrLf & _
"Error Number " & lngErrNumber & vbCrLf & strErrDescription & vbCrLf & vbCrLf & _
"Unable to record because Error " & Err.Number & vbCrLf & Err.Description
MsgBox strMsg, vbCritical, "LogError()"
Resume Exit_LogError
End Function