Image Map of Navigational Panel to Home / Contents / Search The Right Tools for the Right Job

The central routine is VSReport...

Image of line

Previous to calling this routine, an array of fields (to include in the report) has been created through a series of calls to the library - one call for each field. Also the default font attributes, for different sections, can be altered through other calls before calling this routine. You will note that there are two parameters to this function to specify fields, to group and sort by. In a more enhanced version, arrays of such fields could also be built up through separate calls. For this simpler version, however, this is the easiest way to handle it.

  Sub VSReport (ByVal sTitle_IN As String, sDB_IN As Database, 
                ByVal sTable_IN As String, ByVal sOrderBy_IN As String, 
                ByVal sGroupBy_IN As String)
    Dim frmPrev As New frmVSPreview
    Dim ssReport As SnapShot
    Dim sSQL As String
    Dim iDoGroup As Integer
    Dim sPrevGroup As String
    Dim iCount As Integer
    Dim sOrderClause As String
    Dim sTableForm As String
    Dim sTablehead As String
    Dim sTabletemp As String
    Dim iDetail As Integer

  On Error GoTo VSReportError
    Busy
   
    ' Initialise the section formatting attributes
    If Not miSectionAttrInit Then
      InitSectionAttrs
    End If

    ' Ensure that we have some fields to report
    If miNumFields = 0 Then GoTo NoFields
   
    frmPrev.Caption = sTitle_IN
    frmPrev.vsPrinter.FileName = sTitle_IN
    ' Build order by clause for ordering AND grouping
    sOrderClause = sOrderBy_IN
    If sGroupBy_IN <> "" Then
      iDoGroup = True
      If sOrderBy_IN = "" Then
        sOrderClause = sGroupBy_IN
      Else
        sOrderClause = sGroupBy_IN & ", " & sOrderBy_IN
      End If
    End If
    ' Build field list and other bits of SQL
    sSQL = "SELECT "
    For iCount = 1 To miNumFields
      sSQL = sSQL & mFields(iCount).Name & ","
      ' Build a table header string to spec the table layout to
      ' the VSPrinter.
      If mFields(iCount).Name <>: sGroupBy_IN Then
        sTableForm = sTableForm & "<" & mFields(iCount).Width & "|"
        sTablehead = sTablehead & mFields(iCount).Title & "|"
      Else
        mFields(iCount).GroupField = True
      End If
    Next iCount
    sTableForm = Left$(sTableForm, Len(sTableForm) - 1) & ";"
    sTablehead = Left$(sTablehead, Len(sTablehead) - 1) & ";"
   
    ' Put the sections of the SQL statement together
    sSQL = Left$(sSQL, Len(sSQL) - 1)
    sSQL = sSQL & " FROM " & sTable_IN
    If sOrderClause <> "" Then
      sSQL = sSQL & " ORDER BY " & sOrderClause
    End If
    Set ssReport = sDB_IN.CreateSnapshot(sSQL)

    ' Start the document - report
    frmPrev.vsPrinter.Action = 3 ' StartDoc
    ' Set the header and footer text
    frmPrev.vsPrinter.Header = sTitle_IN
    frmPrev.vsPrinter.Footer = "|Page %d|"
    sTabletemp = sTableForm & sTablehead
    iDetail = False
    Do
      If iDoGroup Then
        If StrComp(ssReport(sGroupBy_IN) & "", sPrevGroup, 1) <> 0 Then
          ' New Group Detected
          sPrevGroup = ssReport(sGroupBy_IN)
          ' Print details of last group if there was one
          If iDetail Then
            ' Include group totals if we are doing that.
            If miDoGroups <> False Then
              sTabletemp = sTabletemp & GetGroupTotals()
              ClearGroupTotals
            End If
            PrintDetailTable sTabletemp, frmPrev.vsPrinter
          End If
            
          ' Print group heading
          SetFontCurrent "GroupHeader", frmPrev.vsPrinter
          frmPrev.vsPrinter.Paragraph = ssReport(sGroupBy_IN) & ""
          SetFontCurrent "Detail", frmPrev.vsPrinter
            
          ' Start new detail section
          sTabletemp = sTableForm & sTablehead
        End If
      End If
      ' We have got to a detail section. Set the flag.
      iDetail = True
      For iCount = 0 To ssReport.Fields.Count - 1
        ' Build a table row of all the fields, with their formats.
        If Not mFields(iCount + 1).GroupField Then
          sTabletemp = sTabletemp & Format$(ssReport.Fields(iCount).Value, 
                                            mFields(iCount + 1).Format) & "|"
          If mFields(iCount + 1).DoGroup Then
            AddGroupTotal (iCount + 1), ssReport.Fields(iCount).Value
          End If
          If mFields(iCount + 1).DoGrand Then
            AddGrandTotal iCount + 1, ssReport.Fields(iCount).Value
          End If
        End If
      Next iCount
      sTabletemp = Left$(sTabletemp, Len(sTabletemp) - 1) & ";"
      ssReport.MoveNext
    Loop Until ssReport.EOF
    ' Check if we need to do group totals.
    If miDoGroups <> False Then
      sTabletemp = sTabletemp & GetGroupTotals()
      ClearGroupTotals
    End If
    PrintDetailTable sTabletemp, frmPrev.vsPrinter

    ' Print a grand total section if there is to be one
    If miDoGrands <> False Then
      SetFontCurrent "GroupHeader", frmPrev.vsPrinter
      frmPrev.vsPrinter.Paragraph = "Grand Totals"
      SetFontCurrent "Detail", frmPrev.vsPrinter
      PrintDetailTable sTableForm & GetGrandTotals(), frmPrev.vsPrinter
    End If
   
    ' Finalise the report
    frmPrev.vsPrinter.Action = 6 ' EndDoc
    frmPrev.vsPrinter.Visible = True
    KillFieldList
    InitSectionAttrs

    ssReport.Close
    Set ssReport = Nothing
  VSReportEnd:
    UnBusy
    Exit Sub
  NoFields:
    MsgBox "There have been no fields defined.", 64, "Report Error"
    Resume VSReportEnd
  VSReportError:
    MsgBox "Error Encountered producing report." & ErrMsg(), 48, "Report Error"
    If Not frmPrev Is Nothing Then
      Unload frmPrev
      Set frmPrev = Nothing
    End If
    Resume VSReportEnd
  End Sub

Notice that the second parameter is a database object from which to get the data. This allows you to simply pass in normal JET databases, ODBC databases, or ISAM databases seamlessly. There is also a wrapper for the VSReport routine which accepts all the same parameters except that it accepts an mdb path and file name instead of a database object. That procedure simply opens up a database object and then passes on all the parameters (including that database object) to the VSReport procedure. It's simple but it saves you from having to have a database object to pass in, and it makes the library more flexible - which I like to do.


Image of arrow to previous article

Image of line

[HOME] [TABLE OF CONTENTS] [SEARCH]