Customised Reporting using Word

In this example, Microsoft Word is used to construct a printed report describing the frame currently opened within Multiframe.  The example is contained in the file MFReport.doc which is distributed with Multiframe and can be found in the /Automation Samples/Word directory under the file path to which Multiframe was installed.

 

The report is generated as a series of tables describing the elements of the structure, the loading and, if available, the results.  Each table in the report is generated by a separate subroutine.  These have been grouped into 4 modules within the VBA project.  The FrameTables module contains the subroutines for generating the tables describing the structure, the LoadTables module contains those for reporting loads and the ResultTable module encapsulates all the subroutines for outputting the results. The 4th module, named Utilities, contains some utility subroutines used to create tables and format the report.

 

The MFReport.doc document contains two buttons.  The Generate Report button is used to run the Generate Report

 

The GenerateReport subroutine is the main routine for compiling the report.  It calls all the subroutines for generating the individual tables within the report and is responsible for creating the titles to the various sections of the report.  This subroutine is also used to set the values of some global variables that store the names of some commonly used units, and for setting the contents of the headers and footers in the report.

 


All of the subroutines for generating a table within the report have the same structure and use the same techniques for extracting the data from Multiframe and creating a table containing that information.  The InsertMbrGeomTable() subroutine, which is listed below, is a typical example of these subroutines.  This subroutine inserts a table containing the properties of elements within the frame.  It is written to minimise the number of calls between Word and Multiframe by using the ElementList object.  By adding all the elements in the frame to an ElementList, the value of a single element property can be obtained for each element in the frame in a single call to Multiframe.  These values are stored in a variant variable that contains an array of values, each value corresponding to an element within the frame.  The subroutine begins by obtaining all of the data to be presented in the table and storing this data as in arrays declared as variants. 

Sub InsertMbrGeomTable()

  Dim nEls As Long
  Dim element, node1, node2 As Variant
  Dim length, slope, orient As Variant
  Dim SectionName, GroupName As Variant
  Dim list As New Multiframe.ElementList
  Dim myTable As Table
  Dim i As Long
 
  nEls = mfApp.Frame.Elements.Count
  If (nEls > 0) Then
 
    'Import data from Multfframe
    list.Add mfApp.Frame.Elements
    element = list.Number
    node1 = list.NodeIndex(1)
    node2 = list.NodeIndex(2)
    SectionName = list.Section.Name
    GroupName = list.Section.SectionGroup.Name
    length = list.length
    slope = list.slope
    orient = list.Orientation
   
    'Create new paragraph and insert headings for table
    Call StartTable("Member", "Joint 1", "Joint 2", "Group", _
                    "Section", "Orientation", "Length", "Slope")
   
    'Insert tab delimited text that will form table
    For i = 1 To nEls
       Selection.InsertAfter element(i) & vbTab & _
                            Str(node1(i)) & vbTab & _
                            Str(node2(i)) & vbTab & _
                            GroupName(i) & vbTab & _
                            SectionName(i) & vbTab & _
                            Format(orient(i), gFormat) & vbTab & _
                            Format(length(i), gFormat) & vbTab & _
                            Format(slope(i), gFormat) & vbCr
    Next
   
    'Create table from tabbed text and set default style
    Call CreateTable(myTable, 1)
   
    'Add units to header row
    With myTable.Rows(1)
      .Cells(6).Range.InsertAfter vbVerticalTab + sAngle
      .Cells(7).Range.InsertAfter vbVerticalTab + sLength
      .Cells(8).Range.InsertAfter vbVerticalTab + sAngle
    End With
    
  Else
    Call EmptyTableMessage("Members")
  End If

End Sub

Rather than insert a table and set the contents of each cell in the table, the data is inserted into the document as tab delimited text. This delimited text is then converted into a table.

 

Public Sub StartTable(ParamArray Titles() As Variant)
  Dim s As String
  Dim i As Long
 
  With ActiveDocument.Content
    'Create single paragraph to seperate table from title
    .InsertParagraphAfter
   
    'Create new paragraph for table
    .InsertParagraphAfter
       
    'Create string containing tab delimted headings for each column
    For i = 0 To (UBound(Titles()) - 1)
      s = s & Titles(i) & vbTab
    Next i
    s = s & Titles(i) & vbVerticalTab
       
    ' Insert tab delimited text into document
    .Paragraphs.Last.Range.InsertAfter s
   
  End With

 

Public Sub CreateTable(otable As Table, nHeaderRows As Long)

  With ActiveDocument.Content.Paragraphs.Last.Range
    'Delete vertical tab on last line of text
    .Characters.Last.Previous.Delete
   
    ' convert tabbed text into table
    Set otable = .ConvertToTable(Separator:=vbTab)
  End With
 
  'Set style of table
  Call SetStdTableStyle(otable, nHeaderRows)
   
End Sub