3
votes

I have a Subform/Subreport control displayed on a Form in an Access 2010 database, and I use it to display both Forms and Reports. I have a few event handlers in which I need to know whether a Report is currently loaded into the Subform/Subreport control, or if it's a Form that's loaded. I have tried all of the following to no avail.

Any of the following conditions

If IsEmpty(NavigationSubform.Form) Then '...
If IsNull(NavigationSubform.Form) Then '...
If IsOject(NavigationSubform.Form) Then '...
If NavigationSubform.Form Is Nothing Then '...
If NavigationSubform.Form Is Null Then '...
If Nz(NavigationSubform.Form) Then '...
If (Not NavigationSubform.Form) = -1 Then '... This is a trick I use to check for uninitialized arrays

Results in

Run-time error '2467':

The expression you entered refers to an object that is closed or doesn't exist.

Is there some way that I can check whether a Subform/Subreport control currently has a Form or Report loaded without intentionally causing an error?

2

2 Answers

2
votes

I don't believe that there is a way to reliably perform the check without error trapping, so you may want to wrap the code in a Public Function and put it into a regular VBA Module:

Public Function CheckSubformControlContents(ctl As SubForm) As String
Dim obj As Object, rtn As String
rtn = "None"
On Error Resume Next
Set obj = ctl.Form
If Err.Number = 0 Then
    rtn = "Form"
Else
    On Error Resume Next
    Set obj = ctl.Report
    If Err.Number = 0 Then
        rtn = "Report"
    End If
End If
Set obj = Nothing
On Error GoTo 0
CheckSubformControlContents = rtn
End Function

Then your form code can simply call CheckSubformControlContents(Me.NavigationSubform).

-1
votes

Here are two functions that work in Access 2013 for determining if a name is a Report or a Form. Once that is determined the IsLoaded function of AllForms or AllReports can be used. Note that dbs is an object and rpt or frm are AccessObjects not forms or reports

Public Function IsForm(FormName As String) As Boolean
    Dim dbs As Object
    Dim frm As AccessObject
    Set dbs = Application.CurrentProject
    IsForm = False
    For Each frm In Application.CurrentProject.AllForms
        If frm.Name = FormName Then
            IsForm = True
            Exit For
        End If
    Next frm
    Set frm = Nothing
    Set dbs = Nothing
End Function
Public Function IsReport(ReportName As String) As Boolean
    Dim dbs As Object
    Dim rpt As AccessObject
    Set dbs = Application.CurrentProject
    IsReport = False
    For Each rpt In Application.CurrentProject.AllReports
        If rpt.Name = ReportName Then
            IsReport = True
            Exit For
        End If
    Next rpt
    Set rpt = Nothing
    Set dbs = Nothing
End Function

Here is a program that uses the above functions:

Public Sub EnumerateTaggedControls(ReportName As String, MyTag As String) Dim dbs As Object Dim rpt As Report Dim frm As Form Dim col As Controls Dim ctl As Control Dim left As Integer Dim top As Integer Dim width As Integer Dim height As Integer Dim tag As String Dim i As Integer Const format1 As String = "0000 "

Set dbs = Application.CurrentProject
If IsForm(ReportName) Then
    If dbs.AllForms(ReportName).IsLoaded Then
        DoCmd.OpenForm ReportName, acViewDesign
        Set frm = Forms(ReportName)
        Set col = frm.Controls
    End If
Else
    If dbs.AllReports(ReportName).IsLoaded Then
        DoCmd.OpenReport ReportName, acViewDesign
        Set rpt = Reports(ReportName)
        Set col = rpt.Controls
    Else
        Debug.Print ReportName & " is not a loaded form or report."
        Exit Sub
    End If
End If
Set dbs = Nothing
Debug.Print Tab(53); "Left   Top    Width  Height"
For Each ctl In col
    With ctl
    left = .Properties("Left")
    top = .Properties("Top")
    width = .Properties("Width")
    height = .Properties("Height")
    tag = Nz(.Properties("Tag"), vbNullString)
    If MyTag = "" Then
        i = 1
    Else
        i = InStr(1, tag, MyTag)
    End If
    If i > 0 Then
        Debug.Print .Name & ">"; Tab(33); tag; Tab(53); Format(left, format1) &         Format(top, format1) & Format(width, format1) & Format(height, format1)
    End If
    End With
Next ctl
Debug.Print "====================================================="
Set ctl = Nothing
Set rpt = Nothing
Set col = Nothing
Set frm = Nothing

End Sub

I hope this meets your requirements.