Code to accompany the Relationship Report with Field Information article. Last updated April 2010.
Option Compare Database
Option Explicit
Public Function RelReport(Optional bSetMarginsAndOrientation As Boolean = True) As Long
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim ctl As Control
Dim lngKt As Long
Dim strReportName As String
Dim strMsg As String
Set db = CurrentDb()
strReportName = OpenRelReport(strMsg)
If strReportName <> vbNullString Then
For Each ctl In Reports(strReportName).Controls
If ctl.ControlType = acListBox Then
If TdfSetOk(db, tdf, ctl, strMsg) Then
ctl.RowSource = DescribeFields(tdf)
lngKt = lngKt + 1&
End If
End If
Next
If lngKt = 0& Then
strMsg = strMsg & "Diagram of tables not found on report " & strReportName & vbCrLf
Else
Reports(strReportName).Section(acFooter).Height = 0&
DoCmd.OpenReport strReportName, acViewPreview
If bSetMarginsAndOrientation Then
Call SetMarginsAndOrientation(Reports(strReportName))
End If
End If
End If
Exit_Handler:
If strMsg <> vbNullString Then
MsgBox strMsg, vbInformation, "Relationships Report (adjusted)"
End If
Set ctl = Nothing
Set db = Nothing
RelReport = lngKt
Exit Function
Err_Handler:
strMsg = strMsg & "RelReport: Error " & Err.Number & ": " & Err.Description & vbCrLf
Resume Exit_Handler
End Function
Private Function OpenRelReport(strErrMsg As String) As String
On Error GoTo Err_Handler
Dim iAccessVersion As Integer
iAccessVersion = Int(Val(SysCmd(acSysCmdAccessVer)))
Select Case iAccessVersion
Case Is < 9
strErrMsg = strErrMsg & "Requires Access 2000 or later." & vbCrLf
Case 9
RunCommand acCmdRelationships
SendKeys "%FR", True
RunCommand acCmdDesignView
Case Is > 9
RunCommand acCmdRelationships
RunCommand 483
RunCommand acCmdDesignView
End Select
OpenRelReport = Reports(Reports.Count - 1&).Name
Exit_Handler:
Exit Function
Err_Handler:
Select Case Err.Number
Case 2046&
If iAccessVersion > 9 Then
Resume Next
Else
strErrMsg = strErrMsg & "Close the relationships window, and try again." & vbCrLf
Resume Exit_Handler
End If
Case 2451&, 2191&
strErrMsg = strErrMsg & "The Relationships report must be open in design view." & vbCrLf
Resume Exit_Handler
Case Else
strErrMsg = strErrMsg & "Error " & Err.Number & ": " & Err.Description & vbCrLf
Resume Exit_Handler
End Select
End Function
Private Function TdfSetOk(db As DAO.Database, tdf As DAO.TableDef, ctl As Control, strErrMsg As String) As Boolean
On Error GoTo Err_Handler
Dim strTable As String
strTable = ctl.Controls(0).Caption
Set tdf = db.TableDefs(strTable)
TdfSetOk = True
Exit_Handler:
Exit Function
Err_Handler:
Select Case Err.Number
Case 3265&
strErrMsg = strErrMsg & "Skipped table " & strTable & vbCrLf
Case Else
strErrMsg = strErrMsg & "Error " & Err.Number & ": " & Err.Description & vbCrLf
End Select
Resume Exit_Handler
End Function
Private Function DescribeFields(tdf As DAO.TableDef) As String
to use as the RowSource of the list box (Value List type).
Dim fld As DAO.Field
Dim strType As String
Dim strReturn As String
For Each fld In tdf.Fields
If (fld.Attributes And dbSystemField) = 0& Then
Select Case CLng(fld.Type)
Case dbText
strType = IIf((fld.Attributes And dbFixedField) = 0&, "T", "Tf") & fld.Size & _
IIf(fld.AllowZeroLength, "Z", vbNullString)
strReturn = strReturn & DescribeFieldSub(tdf, fld, strType)
Case 109&
strType = IIf((fld.Attributes And dbFixedField) = 0&, "T", "Tf") & fld.Size & _
IIf(fld.AllowZeroLength, "Z", vbNullString)
strReturn = strReturn & DescribeFieldSub(tdf, fld, strType, True)
Case dbMemo
strType = IIf((fld.Attributes And dbHyperlinkField) = 0&, "M", "Hyp") & _
IIf(fld.AllowZeroLength, "Z", vbNullString)
strReturn = strReturn & DescribeFieldSub(tdf, fld, strType)
Case dbLong
strType = IIf((fld.Attributes And dbAutoIncrField) = 0&, "L", "A")
strReturn = strReturn & DescribeFieldSub(tdf, fld, strType)
Case 104&
strReturn = strReturn & DescribeFieldSub(tdf, fld, "L", True)
Case dbInteger
strReturn = strReturn & DescribeFieldSub(tdf, fld, "Int")
Case 103&
strReturn = strReturn & DescribeFieldSub(tdf, fld, "Int", True)
Case dbCurrency
strReturn = strReturn & DescribeFieldSub(tdf, fld, "C")
Case dbDate
strReturn = strReturn & DescribeFieldSub(tdf, fld, "Dt")
Case dbDouble
strReturn = strReturn & DescribeFieldSub(tdf, fld, "Dbl")
Case 106&
strReturn = strReturn & DescribeFieldSub(tdf, fld, "Dbl", True)
Case dbSingle
strReturn = strReturn & DescribeFieldSub(tdf, fld, "Sng")
Case 105&
strReturn = strReturn & DescribeFieldSub(tdf, fld, "Sng", True)
Case dbByte
strReturn = strReturn & DescribeFieldSub(tdf, fld, "B")
Case 102&
strReturn = strReturn & DescribeFieldSub(tdf, fld, "B", True)
Case dbDecimal
strReturn = strReturn & DescribeFieldSub(tdf, fld, "Dec")
Case 108&
strReturn = strReturn & DescribeFieldSub(tdf, fld, "Dec", True)
Case dbBoolean
strReturn = strReturn & DescribeFieldSub(tdf, fld, "Yn")
Case dbLongBinary
strReturn = strReturn & DescribeFieldSub(tdf, fld, "Ole")
Case dbGUID
strReturn = strReturn & DescribeFieldSub(tdf, fld, "Guid")
Case 107&
strReturn = strReturn & DescribeFieldSub(tdf, fld, "Guid", True)
Case 101&
strReturn = strReturn & DescribeFieldSub(tdf, fld, "Att", True)
Case dbBinary
strReturn = strReturn & DescribeFieldSub(tdf, fld, "Bin")
Case Else
strReturn = strReturn & DescribeFieldSub(tdf, fld, "?")
End Select
End If
Next
DescribeFields = strReturn & """ (" & DCount("*", tdf.Name) & ")"""
End Function
Private Function IsCalcTableField(fld As DAO.Field) As Boolean
On Error GoTo ExitHandler
Dim strExpr As String
strExpr = fld.Properties("Expression")
If strExpr <> vbNullString Then
IsCalcTableField = True
End If
ExitHandler:
End Function
Private Function DescribeFieldSub(tdf As TableDef, fld As Field, strTypeDescrip As String, Optional bIsComplex As Boolean) As String
Dim strOut As String
Const strcSep = ";"
strOut = """" & fld.Name & " "
If bIsComplex Then
strOut = strOut & "X"
End If
If IsCalcTableField(fld) Then
strOut = strOut & "*"
End If
strOut = strOut & strTypeDescrip
If fld.Required Then
strOut = strOut & "R"
End If
If fld.ValidationRule <> vbNullString Then
strOut = strOut & "V"
End If
If fld.DefaultValue <> vbNullString Then
strOut = strOut & "D"
End If
strOut = strOut & DescribeIndexField(tdf, fld.Name) & """" & strcSep
If bIsComplex Then
If fld.Type = 101 Then
strOut = strOut & """ (" & fld.Name & ".FileData)""" & strcSep & _
""" (" & fld.Name & ".FileName)""" & strcSep & _
""" (" & fld.Name & ".FileType)""" & strcSep
Else
strOut = strOut & """ (" & fld.Name & ".Value)" & """" & strcSep
End If
End If
DescribeFieldSub = strOut
End Function
Private Function DescribeIndexField(tdf As DAO.TableDef, strField As String) As String
Dim ind As DAO.Index
Dim fld As DAO.Field
Dim iCount As Integer
Dim strReturn As String
For Each ind In tdf.Indexes
iCount = 0
For Each fld In ind.Fields
If fld.Name = strField Then
If ind.Primary Then
strReturn = strReturn & IIf(iCount = 0, "P", "p")
ElseIf ind.Unique Then
strReturn = strReturn & IIf(iCount = 0, "U", "u")
Else
strReturn = strReturn & IIf(iCount = 0, "I", "i")
End If
End If
iCount = iCount + 1
Next
Next
DescribeIndexField = strReturn
End Function
Private Function SetMarginsAndOrientation(obj As Object) As Boolean
Const lngcMargin = 720&
If Int(Val(SysCmd(acSysCmdAccessVer))) >= 10 Then
With obj.Printer
.TopMargin = lngcMargin
.BottomMargin = lngcMargin
.LeftMargin = lngcMargin
.RightMargin = lngcMargin
.Orientation = 2
End With
SetMarginsAndOrientation = True
End If
End Function