Figure 5   Prototype Request Requirements

 Private Sub btnRequestRequirements_Click()

'Get the request requirements object by telling the Broker  
'what report we want
oRequestBroker.RequestRequirements cbolReports.Text,_oRequirements
    
'The gathering of the requirements is way simple here.  A 
'future version will have a structured meta information 
'methodology that will allow a local engine to generate a 
'wizard-like interface for requirements input.
lblDataRequired.Caption = oRequirements.Caption

End Sub

Figure 6   Request Requirements Module

 Public Sub RequestRequirements(sReportName As String, 
                               oRequirementsOUT As Object)
'Build the requirements structure for the report requested by the 
'client. This will become a much more comprehensive structure 
'for use by a client-side wizard.

    'Set the Requirements write-once properties
    oRequirements.ReportName = sReportName
    oRequirements.ReportObjectName = RemoveSpaces(sReportName)
    
    'Simple data structure population. These will be stored in an 
    'odbc database when the wizard is on the scene
    Select Case sReportName
        Case asReports(0)
            oRequirements.Caption = "No Data Required"
        Case asReports(1)
            oRequirements.Caption = "Person's Name"
    End Select
    Set oRequirementsOUT = oRequirements
 End Sub

Figure 7   Stub Notification Object

clsNotify.cls

 Option Explicit

'Our internal variables are private. They are set by properties 
'and methods
Private bFinished As Boolean
Private sReport As String

Public Function SetFinished(sReportIN As String) As Boolean
    'This is the function that the Broker calls to let us know
    'it is finished, and what the report is
    sReport = sReportIN
    bFinished = True
End Function

Private Sub Class_Initialize()
    'When the class is instantiated, we set default values
    bFinished = False
End Sub

Public Property Get Finished()
    'This is the property that we keep checking to see if
    'the Broker is done.
    Finished = bFinished
End Property

Public Property Get Report()
    'This is the property that the Request generation form
    'will call after finish is set to get the report name
    Report = sReport
End Property

Figure 8   Stub Notification Object

clsNotify.cls


 Option Explicit

'Our internal variables are private. They are set by properties 
'and methods
Private bFinished As Boolean
Private sReport As String

Public Function SetFinished(sReportIN As String) As Boolean
    'This is the function that the Broker calls to let us know
    'it is finished, and what the report is
    sReport = sReportIN
    bFinished = True
End Function

Private Sub Class_Initialize()
    'When the class is instantiated, we set default values
    bFinished = False
End Sub

Public Property Get Finished()
    'This is the property that we keep checking to see if
    'the Broker is done.
    Finished = bFinished
End Property

Public Property Get Report()
    'This is the property that the Request generation form
    'will call after finish is set to get the report name
    Report = sReport
End Property

Figure 9   Stub Report Request Method

 Public Sub ReportRequest(oRequirementsIN As Object, 
                         oNotify As Object)
'Process the request for a report

    'Create a report object and class (lest we think there is too 
    'much stuff going on for what we are doing, let us not forget 
    'that this is the beginning structure of the app seeing its 
    'way through the prototype stage)
    Dim oReportObject As Object
    Dim oReport As New clsReport
    
    'Create the Report requested
    Set oReportObject = CreateObject(
                     oRequirementsIN.ReportObjectName & ".Report")
    
    'Request that the report be generated
    oReportObject.Request oRequirementsIN, oReport
    
    'Notify the client we are done, and pass the results
    oNotify.SetFinished oReport.FileName

End Sub

Figure 10   Stub Report Object

Report.Cls

 Option Explicit

Public Sub Request(oRequirementsIN As Object, oReportIN As Object)

    'Processing will take place here (I've the strong urge to say
    '"This part is obvious and is left for the student to explore 
    'at home." hee hee). This will be the heart of the DataMart  
    'services in the coming articles.

    'Result File name ready for viewing
    oReportIN.SetFileName "REPORT1.XLS"

End Sub

Figure 13   Messaging Classes

Field.cls

 Option Explicit

'External handles
Public Filters As Filters

'Internal variables
Private sName As String
Private bAString As Boolean
Private sDescription As String
Private bRequired As Boolean
Private iSize As Integer
Private vValue As Variant
Private sSelectedFilter As String

Private Sub Class_Initialize()
    Set Filters = New Filters
End Sub

Public Property Get AString() As Boolean
'AString because String is a reserved word.
    AString = bAString
End Property

Public Property Let AString(bNewValue As Boolean)
    bAString = bNewValue
End Property

Public Property Get Description() As String
    Description = sDescription
End Property

Public Property Let Description(sNewValue As String)
    sDescription = sNewValue
End Property

Public Property Get Required() As Boolean
    Required = bRequired
End Property

Public Property Let Required(bNewValue As Boolean)
    bRequired = bNewValue
End Property

Public Property Get Size() As Integer
    Size = iSize
End Property

Public Property Let Size(iNewValue As Integer)
    iSize = iNewValue
End Property

Public Property Get Value() As Variant
    Value = vValue
End Property

Public Property Let Value(vNewValue As Variant)
    vValue = vNewValue
End Property

Public Property Get SelectedFilter() As String
    SelectedFilter = sSelectedFilter
End Property

Public Property Let SelectedFilter(sNewValue As String)
    sSelectedFilter = sNewValue
End Property

Public Property Get Name() As String
    Name = sName
End Property

Public Property Let Name(sNewValue As String)
    sName = sNewValue
End Property

Fields.cls

 Option Explicit

'Internal variables
Private coFields As Collection

Public Sub Create(sKey As String)
    'Make the name the same as the key
    Dim cField As New Field
    cField.Name = sKey
    coFields.Add Item:=cField, Key:=sKey
End Sub

Public Function Item(vKey As Variant)
    Set Item = coFields.Item(vKey)
End Function

Public Function Count() As Integer
    Count = coFields.Count
End Function

Private Sub Class_Initialize()
    Set coFields = New Collection
End Sub

Filter.cls

 'This class contains information on the filter type in question
'Later a rule property can be added that will be used to more 
'precisely validate data entry
Option Explicit

'Internal variables
Private sName As String
Private sDescription As String

Public Property Get Name() As String
    Name = sName
End Property

Public Property Let Name(sNewValue As String)
    sName = sNewValue
End Property

Public Property Get Description() As String
    Description = sDescription
End Property

Public Property Let Description(sNewValue As String)
    sDescription = sNewValue
End Property

Filters.cls

 Option Explicit

'Internal variables
Private coFilters As Collection

Public Sub Create(sKey As String)
    'Make the Name the same as the key
    Dim cFilter As New Filter
    cFilter.Name = sKey
    coFilters.Add Item:=cFilter, Key:=sKey
End Sub

Public Function Item(vKey As Variant)
    Set Item = coFilters.Item(vKey)
End Function

Public Function Count() As Integer
    Count = coFilters.Count
End Function

Private Sub Class_Initialize()
    Set coFilters = New Collection
End Sub

Header.cls

 Option Explicit

'External Handles
Private sReportID As String
Private sReportName As String

Public Property Get ReportID() As String
    ReportID = sReportID
End Property

Public Property Let ReportID(sNewValue As String)
    sReportID = sNewValue
End Property

Public Property Get ReportName() As String
    ReportName = sReportName
End Property

Public Property Let ReportName(sNewValue As String)
    sReportName = sNewValue
End Property

ReportBuildMessage.cls

 Option Explicit

'External handles
Public Header As Object
Public Fields As Object

Private Sub Class_Initialize()
    Set Header = New Header
    Set Fields = New Fields
End Sub

modMain.bas

 Option Explicit
Sub Main()
    'These classes are in their own project so all programs can use 
    'them. They are compiled into an OLE.DLL and can be referenced 
    'in the Tools.References to facilitate early binding.
End Sub

Figure 14   Display Field Data

 Private Sub DisplayFieldData(iFieldNumber As Integer)
'Move message classes information into the visual controls

    Dim oField As Object
    Dim iFilters As Integer
    Dim iFoundFilter As Integer
    
    Set oField = oMessage.Fields.Item(iFieldNumber)
    iFoundFilter = 0

    lblFieldName.Caption = oField.Name
    lblFieldDescription.Caption = oField.Description
    
    iFilters = oField.Filters.Count
    
    Dim iLoop As Integer
    For iLoop = 1 To iFilters
        If iLoop > 1 Then
            Load optFilterType(iLoop - 1)
            optFilterType(iLoop - 1).Top = _
                   optFilterType(iLoop - 2).Top + _
                   optFilterType(iLoop - 2).Height + 100
            optFilterType(iLoop - 1).Visible = True
        End If
        optFilterType(iLoop - 1).Caption = _ oFi
              eld.Filters.Item(iLoop).Name
        If oField.Filters.Item(iLoop).Name = oField.SelectedFilter 
            Then iFoundFilter = iLoop - 1
        End If
    Next iLoop
    
    optFilterType(iFoundFilter).Value = True
    
    txtValue.Top = optFilterType(iLoop - 2).Top + _  _
         FilterType(iLoop - 2).Height + 300
    txtValue.Visible = True
    txtValue.Left = optFilterType(iLoop - 2).Left
    txtValue.Text = oField.Value
End Sub

Figure 15   Beveling the Panels

 Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

            Panel.Bevel = 1
            DoEvents
            Sleep 250
            Panel.Bevel = 2

Figure 16   Panel Click Event

 Private Sub sbMain_PanelClick(ByVal Panel As Panel)
'Handle interaction with the status bar
    Select Case Panel.Index
        'Back button
        Case 2
            'Display button action
            Panel.Bevel = 1
            DoEvents
            Sleep 250
            Panel.Bevel = 2
            
            'Collect Field Data
            CollectFieldData pbMain.Value - 1
            
            'Move, use pb as locator
            pbMain.Value = pbMain.Value - 1
            
            'Turn Back off if we just entered the first screen
            If pbMain.Value = 1 Then
                Panel.Visible = False
                pnlFieldData.Visible = False
                pnlPickReport.Visible = True
            End If
            
            'If pbMain.Value > 1 then
            If pbMain.Value > 1 Then
                DisplayFieldData pbMain.Value - 1
            End If

            'Change Finish to Next on backing off last screen
            If pbMain.Value = pbMain.Max - 1 Then
                sbMain.Panels.Item(3).Text = "Next >>"
            End If
            
            'We are in the fields
            If pbMain.Value > 1 Then
            End If

        'Forward button
        Case 3
            'Display button action
            Panel.Bevel = 1
            DoEvents
            Sleep 250
            Panel.Bevel = 2
    
            'Finished
            If pbMain.Value = pbMain.Max Then
                Exit Sub
            End If
                    
            'Collect Field Data
            If pbMain.Value > 1 Then
                CollectFieldData pbMain.Value - 1
            End If
            
            'Turn Back on if we just left the first screen
            If pbMain.Value = 1 Then
                If cbReportList.Text = "" Then
                    Exit Sub
                Else
                    Set oMessage = Nothing
                    oRequestBroker.GetReportDescription _
                         cbReportList.Text, oMessage
                    pbMain.Max = oMessage.Fields.Count + 1
                End If
                sbMain.Panels.Item(2).Visible = True
                pnlPickReport.Visible = False
                pnlFieldData.Visible = True
            End If
             
            'Move, use pb as locator
            pbMain.Value = pbMain.Value + 1
           
            'If pbMain.Value > 1 then
            DisplayFieldData pbMain.Value - 1
            
            'Change Next to Finish on entering last screen
            If pbMain.Value = pbMain.Max Then
                sbMain.Panels.Item(3).Text = "Finished"

Figure 17   Request Broker

Broker.cls

 Option Explicit

Public Sub GetReportsList(asReportList() As String)
'Test Harness/Stub for Reporter to develop against.
    ReDim asReportList(0) As String
    asReportList(0) = "How much are we paying for an Employee..."
End Sub

Public Sub GetReportDescription(sName As String, oMessage As
     ReportBuildMessage)
'Test Harness/Stub for Reporter to develop against.
    PopulateDummyData oMessage
End Sub

Private Sub PopulateDummyData(oMessage As ReportBuildMessage)
'Test Harness/Stub for Reporter to develop against.
    With oMessage
        .Header.ReportName = "The Test Report"
        .Header.ReportID = 819
        .Fields.Create "Employee"
            With .Fields.Item("Employee")
                .Name = "Employee"
                .AString = True
                .Description = "Employee's Name"
                .Required = True
                .Size = 35
                .Value = ""
                .SelectedFilter = "= (Equal)"
                .Filters.Create "= (Equal)"
                    With .Filters.Item("= (Equal)")
                        .Name = "= (Equal)"
                        .Description = "A Value that is Equal " & _
                            "the entered value."
                    End With
                .Filters.Create "Like"
                    With .Filters.Item("Like")
                        .Name = "Like"
                        .Description = "A Value that is similar" & _ 
                             " to the entered value.  Wild " & _
                             "cards can be used."
                    End With
            End With
        
        .Fields.Create "Total Yearly Compensation"
            With .Fields.Item("Total Yearly Compensation")
                .Name = "Total Yearly Compensation"
                .AString = True
                .Description = "The amount that the Employee " & _
                     "receives in a year as total compensation"
                .Required = False
                .Size = 6
                .Value = "25000"
                .SelectedFilter = ""
                .Filters.Create "= (Equal)"
                    With .Filters.Item("= (Equal)")
                        .Name = "= (Equal)"
                        .Description = "A Value that is Equal " & _
                             "to the entered value."
                    End With
                .Filters.Create "< (Less Than)"
                    With .Filters.Item("< (Less Than)")
                        .Name = "< (Less Than)"
                        .Description = "A Value that is Less " & _
                            "Than the entered value."
                    End With
                .Filters.Create "> (Greater Than)"
                    With .Filters.Item("> (Greater Than)")
                        .Name = "> (Greater Than)"
                        .Description = "A Value that is Greater" & _ 
                             " Than the entered value."
                    End With
            End With
            
        .Fields.Create "Job Description"
            With .Fields.Item("Job Description")
                .Name = "Job Description"
                .AString = True
                .Description = "Employee's Name"
                .Required = True
                .Size = 255
                .Value = "Building machines that go PIIING!"
                .SelectedFilter = "Like"
                .Filters.Create "= (Equal)"
                    With .Filters.Item("= (Equal)")
                        .Name = "= (Equal)"
                        .Description = "A Value that is Equal " & _
                             "to the entered value."
                    End With
                .Filters.Create "Like"
                    With .Filters.Item("Like")
                        .Name = "Like"
                        .Description = "A Value that is similar" & _
                             " to the entered value. Wild cards" & _
                             " can be used."
                    End With
            End With
    End With
End Sub

modMain.bas

 Option Explicit

Sub Main()
End Sub