home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 32 / IOPROG_32.ISO / SOFT / SqlEval7 / MSOLAP / samples / Samples.exe / VbMdHTMLdll / Table.cls < prev   
Encoding:
Visual Basic class definition  |  1998-10-30  |  10.6 KB  |  305 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4.   Persistable = 0  'NotPersistable
  5.   DataBindingBehavior = 0  'vbNone
  6.   DataSourceBehavior  = 0  'vbNone
  7.   MTSTransactionMode  = 0  'NotAnMTSObject
  8. END
  9. Attribute VB_Name = "Table"
  10. Attribute VB_GlobalNameSpace = False
  11. Attribute VB_Creatable = True
  12. Attribute VB_PredeclaredId = False
  13. Attribute VB_Exposed = True
  14. '
  15. ' MDTHML Table
  16. '
  17. ' This class implements a middle-tier object that an HTML table from a
  18. ' passed-in ADO/MD Cellset.  The object requires IIS 4.0 or better as it
  19. ' uses IIS's ScriptingContext object to acquire access to an output
  20. ' stream for the HTML.
  21. '
  22. ' Typical usage:
  23. '
  24. ' Set tbl = Server.CreateObject ("MDHTML.Table")
  25. ' tbl.Display (cs)
  26. '
  27. ' 10.12.98  BillBak     Initial coding
  28. ' 10.14.98  BillBak     Clean-up, documentation
  29. '
  30.  
  31. Option Explicit
  32.  
  33. Public m_sc As ScriptingContext         ' passed to us by IIS on the start page event
  34.  
  35. ' Variables to hold the property values
  36. Public m_szTableHTMLStart As String     ' HTML for <TABLE> tag
  37. Public m_szTableHTMLEnd As String       ' HTML for </TABLE> tag
  38. Public m_szRowHeaderHTMLStart As String ' HTML for <TD> tag for row headers
  39. Public m_szRowHeaderHTMLEnd As String   ' HTML for </TD> tag for row headers
  40. Public m_szColHeaderHTMLStart As String ' HTML for <TD> tag for col headers
  41. Public m_szColHeaderHTMLEnd As String   ' HTML for </TD> tag for col headers
  42. Public m_szDataCellHTMLStart As String  ' HTML for <TD> tag for data cells
  43. Public m_szDataCellHTMLEnd As String    ' HTML for </TD> tag for data cells
  44.  
  45. Public Sub OnStartPage(sContext As ScriptingContext)
  46.  
  47.     ' IIS calls us here when it loads a page containing the control.  The IIS
  48.     ' ScriptingContext object has methods to return references to the IIS
  49.     ' Application, Session, Response and Request objects.  We use the Write
  50.     ' method on the Response object to emit HTML streams.
  51.     
  52.     Set m_sc = sContext                 ' saved for use during the Display method
  53.     
  54.     ' Default HTML tags for the various elements of the table
  55.     m_szTableHTMLStart = "<TABLE>"
  56.     m_szTableHTMLEnd = "</TABLE>"
  57.     m_szRowHeaderHTMLStart = "<TD>"
  58.     m_szRowHeaderHTMLEnd = "</TD>"
  59.     m_szColHeaderHTMLStart = "<TD>"
  60.     m_szColHeaderHTMLEnd = "</TD>"
  61.     m_szDataCellHTMLStart = "<TD>"
  62.     m_szDataCellHTMLEnd = "</TD>"
  63.  
  64. End Sub
  65.  
  66.  
  67. Sub Display(cs As ADOMD.Cellset)
  68.  
  69.     ' This is where we do the work.  We handle Cellsets with one or two
  70.     ' axes.  We punt if the Cellset has zero axes.
  71.     
  72.     ' Get the IIS response object for our HTML output
  73.     Dim response As response
  74.     Set response = m_sc.response
  75.  
  76.     ' Do we have any interesting axes?
  77.     If cs.Axes.Count < 1 Then
  78.         response.Write "The cellset has no displayable axes.<BR>"
  79.     End If
  80.     
  81.     Dim x As Integer, y As Integer      ' general purpose loop variables
  82.     
  83.     'These variables store the number of "layers" on each axis
  84.     Dim nColHeaderDepth As Integer, nRowHeaderWidth As Integer
  85.     
  86.     ' How many "layers" do the headers have?
  87.     nColHeaderDepth = cs.Axes(0).DimensionCount
  88.     If cs.Axes.Count > 1 Then
  89.         nRowHeaderWidth = cs.Axes(1).DimensionCount
  90.     Else
  91.         nRowHeaderWidth = 0
  92.     End If
  93.     
  94.     ' Create the HTML for the upper-left cell.  This requires modifying the
  95.     ' m_szRowHeaderHTMLStart variable to have a COLSPAN modifier.  So for
  96.     ' example, if Axis(1) (the row labels) contains two dimensions, the
  97.     ' width of the row labels is two columns.  The upper left cells are
  98.     ' empty (because they are left of the leftmost column and above the
  99.     ' first row.)  So we need to convert the HTML from "<TD></TD>" into
  100.     ' "<TD COLSPAN=2></TD>".
  101.     
  102.     Dim szULHTML As String
  103.     szULHTML = InsertColspan(m_szColHeaderHTMLStart, nRowHeaderWidth) & _
  104.                         m_szColHeaderHTMLEnd
  105.     
  106.     ' Write the <TABLE> tag
  107.     response.Write m_szTableHTMLStart
  108.         
  109.     ' Write out the layers of the column header.  We have one layer for
  110.     ' each dimension in the axis.  So if the MDX query contains a CrossJoin,
  111.     ' we have to emit more than one HTML Table row.  For example the function
  112.     ' CrossJoin ({A, B, C}, {[1], [2], [3]}) produces an axis with nine
  113.     ' positions.  Each position contains two members.  It looks like:
  114.     '
  115.     '   A  A  A  B  B  B  C  C  C
  116.     '   1  2  3  1  2  3  1  2  3
  117.     '
  118.     ' The first pass through the loop will display A  A  A  B  etc.
  119.     ' The second pass gets the inner members.
  120.     
  121.     Dim p As ADOMD.Position
  122.     Dim nLayer As Integer
  123.     For nLayer = 0 To nColHeaderDepth - 1
  124.     
  125.         response.Write "<TR>"               ' start this row
  126.         response.Write szULHTML             'upper-left cell
  127.         ' Run across the positions collection in axis 0 using only one
  128.         ' of the members for each position.  We only output a cell when we notice
  129.         ' that the caption for the current column (position) in this layer is
  130.         ' different than the previous caption.  When we do output a cell, we use
  131.         ' the COLSPAN tag to make that cell of the table span multiple columns.
  132.         ' The goal is to display:
  133.         '
  134.         '   A  A  A  B  B  B  C  C  C
  135.         '   1  2  3  1  2  3  1  2  3
  136.         '
  137.         ' as:
  138.         '
  139.         '   A        B        C
  140.         '   1  2  3  1  2  3  1  2  3
  141.         '
  142.         
  143.         ' Seed the previous-caption variable with the first caption.  We need to
  144.         ' trigger output when we finally see something different, or hit the
  145.         ' end of the position list.
  146.         Dim szPreviousCaption As String, nColCount As Integer
  147.         szPreviousCaption = cs.Axes(0).Positions(0).Members(nLayer).Caption
  148.         nColCount = 0
  149.         
  150.         For Each p In cs.Axes(0).Positions
  151.             If (p.Members(nLayer).Caption = szPreviousCaption) Then
  152.                 nColCount = nColCount + 1   ' one more just like the previous
  153.             Else
  154.                 ' A new caption, write what we've saved up (szPreviousCaption and
  155.                 ' nColCount) and then reset these variables.
  156.                 response.Write InsertColspan(m_szColHeaderHTMLStart, nColCount)
  157.                 response.Write szPreviousCaption
  158.                 response.Write m_szColHeaderHTMLEnd
  159.                 nColCount = 1
  160.                 szPreviousCaption = p.Members(nLayer).Caption
  161.             End If
  162.         Next
  163.         ' Write the last column
  164.         response.Write InsertColspan(m_szColHeaderHTMLStart, nColCount)
  165.         response.Write szPreviousCaption
  166.         response.Write m_szColHeaderHTMLEnd
  167.         response.Write "</TR>"          ' finish off this row
  168.         
  169.     Next nLayer
  170.     
  171.     ' Write out the rows of data including the row headers.  We have the same goal
  172.     ' as before, to only write repeating captions once.  In this case we are able
  173.     ' to write the caption at the front of the span since we are not using ROWSPAN.
  174.     ' So we use an array of previous captions and check each caption against the
  175.     ' previous caption at that level.
  176.     '
  177.     Dim m As ADOMD.Member
  178.     ReDim szPrevCaption(nRowHeaderWidth) As String  ' an array of previous captions
  179.     For x = 1 To nRowHeaderWidth
  180.         szPrevCaption(x) = ""                       ' init to null strings
  181.     Next x
  182.     
  183.     y = 0
  184.     ' Loop over the Rows access or Axis(1)
  185.     For Each p In cs.Axes(1).Positions
  186.     
  187.         response.Write ("<TR>")         ' start this row
  188.         
  189.         ' First write a cell for each member in the axis at this position
  190.         x = 1
  191.         For Each m In p.Members
  192.             response.Write m_szRowHeaderHTMLStart
  193.             If m.Caption <> szPrevCaption(x) Then
  194.                 ' This caption is different that the last one we wrote for this
  195.                 ' level.  Write it and update the previous caption for this level.
  196.                 response.Write m.Caption
  197.                 szPrevCaption(x) = m.Caption
  198.             End If
  199.             response.Write m_szRowHeaderHTMLEnd
  200.             x = x + 1
  201.         Next
  202.                 
  203.         ' Now write the data cells for this row
  204.         For x = 0 To cs.Axes(0).Positions.Count - 1
  205.             response.Write m_szDataCellHTMLStart
  206.             response.Write cs(x, y).FormattedValue
  207.             response.Write m_szDataCellHTMLEnd
  208.         Next x
  209.     
  210.         response.Write "</TR>"          ' finish this row
  211.         y = y + 1
  212.     Next
  213.     
  214.     ' Finish the table
  215.     response.Write m_szTableHTMLEnd
  216.     
  217. End Sub
  218.  
  219. Public Property Let RowHeaderHTMLStart(ByVal myVal As String)
  220.  
  221.     m_szRowHeaderHTMLStart = myVal
  222.  
  223. End Property
  224.  
  225. Public Property Let RowHeaderHTMLEnd(ByVal myVal As String)
  226.  
  227.     m_szRowHeaderHTMLEnd = myVal
  228.  
  229. End Property
  230.  
  231.  
  232. Public Property Let ColHeaderHTMLStart(ByVal myVal As String)
  233.  
  234.     m_szColHeaderHTMLStart = myVal
  235.  
  236. End Property
  237.  
  238. Public Property Let ColHeaderHTMLEnd(ByVal myVal As String)
  239.  
  240.     m_szColHeaderHTMLEnd = myVal
  241.  
  242. End Property
  243.  
  244.  
  245. Public Property Let DataCellHTMLStart(ByVal myVal As String)
  246.  
  247.     m_szDataCellHTMLStart = myVal
  248.  
  249. End Property
  250.  
  251. Public Property Let DataCellHTMLEnd(ByVal myVal As String)
  252.  
  253.     m_szDataCellHTMLEnd = myVal
  254.  
  255. End Property
  256.  
  257.  
  258. Public Property Let TableHTMLStart(ByVal myVal As String)
  259.  
  260.     m_szTableHTMLStart = myVal
  261.  
  262. End Property
  263.  
  264. Public Property Let TableHTMLEnd(ByVal myVal As String)
  265.  
  266.     m_szTableHTMLEnd = myVal
  267.  
  268. End Property
  269.  
  270. Function InsertColspan(szTag, nCols)
  271.     
  272.     ' Takes the passed tag string (similar to <TD Property=VALUE><B>) and adds
  273.     ' COLSPAN=n (where n is nCols) right after the tag name
  274.  
  275.     Dim iInsertPoint As Integer         ' index to where we open the string
  276.     Dim iFirstCaret As Integer          ' index to the caret
  277.     
  278.     iFirstCaret = InStr(1, szTag, "<")
  279.     If iFirstCaret = 0 Then
  280.         ' No HTML tag in the passed string, make our own
  281.         InsertColspan = "<TD COLSPAN=" & Str(nCols) & ">"
  282.         Exit Function
  283.     End If
  284.     
  285.     ' Get first space after the tag
  286.     iInsertPoint = InStr(iFirstCaret, szTag, " ")
  287.     If iInsertPoint = 0 Then
  288.         ' No spaces, insert before the first close caret
  289.         iInsertPoint = InStr(iFirstCaret, szTag, ">")
  290.         If iInsertPoint = 0 Then
  291.             ' Sheesh, no closing caret!  Append the COLSPAN modifier and be done
  292.             InsertColspan = szTag & " COLSPAN=" & Str(nCols) & " >"
  293.             Exit Function
  294.         End If
  295.     End If
  296.     
  297.     ' Split the string into left and right parts around the insertion point
  298.     Dim szLeft As String, szRight As String
  299.     szLeft = Left(szTag, iInsertPoint - 1)
  300.     szRight = Right(szTag, Len(szTag) - iInsertPoint + 1)
  301.     
  302.     InsertColspan = szLeft & " COLSPAN=" & Str(nCols) & szRight
  303.     
  304. End Function
  305.