home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / ownrdclb / cshsort.cls next >
Encoding:
Visual Basic class definition  |  1998-01-28  |  11.0 KB  |  329 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4. END
  5. Attribute VB_Name = "cShellSort"
  6. Attribute VB_GlobalNameSpace = False
  7. Attribute VB_Creatable = False
  8. Attribute VB_PredeclaredId = False
  9. Attribute VB_Exposed = True
  10. Option Explicit
  11.  
  12. ' =================================================================
  13. ' Class:    cShellSort
  14. ' Author:   SPM, PACG
  15. ' Date:     1 Feb 1997
  16. '
  17. ' Shell sorts a variant array according to a given
  18. ' column, using numeric, string or date type, ascending
  19. ' or descending.
  20. '
  21. ' =================================================================
  22. Public Enum ESSTypeConstants
  23.     CCLSortNumeric = 1
  24.     CCLSortString = 2
  25.     CCLSortDate = 4
  26. End Enum
  27. Public Enum ESSOrderCOnstants
  28.     CCLOrderAscending = 1
  29.     CCLOrderDescending = 2
  30. End Enum
  31.  
  32. Private m_iSortColumn() As Integer
  33. Private m_eSortOrder() As ESSOrderCOnstants
  34. Private m_eSortType() As ESSTypeConstants
  35. Private m_iSortIndexCount As Integer
  36. Private m_iLastSortIndex As Integer
  37. Public Sub Clear()
  38.     m_iSortIndexCount = 0
  39.     Erase m_iSortColumn
  40.     Erase m_eSortOrder
  41.     Erase m_eSortType
  42. End Sub
  43. Property Get LastSortIndex() As Integer
  44.     LastSortIndex = m_iLastSortIndex
  45. End Property
  46. Property Let LastSortIndex( _
  47.         ByVal iLastSortIndex As Integer _
  48.     )
  49.     m_iLastSortIndex = iLastSortIndex
  50. End Property
  51. Property Let SortCOlumn( _
  52.         ByVal iSortIndex As Integer, _
  53.         ByVal iSortColumn As Integer _
  54.     )
  55.     If (pbValidSortIndex(iSortIndex)) Then
  56.         m_iSortColumn(iSortIndex) = iSortColumn
  57.     End If
  58. End Property
  59. Property Get SortCOlumn( _
  60.         ByVal iSortIndex As Integer _
  61.     ) As Integer
  62.     SortCOlumn = m_iSortColumn(iSortIndex)
  63. End Property
  64. Property Let SortOrder( _
  65.         ByVal iSortIndex As Integer, _
  66.         ByVal iSortOrder As ESSOrderCOnstants _
  67.     )
  68.     If (pbValidSortIndex(iSortIndex)) Then
  69.         m_eSortOrder(iSortIndex) = iSortOrder
  70.     End If
  71. End Property
  72. Property Get SortOrder( _
  73.         ByVal iSortIndex As Integer _
  74.     ) As ESSOrderCOnstants
  75.     SortOrder = m_eSortOrder(iSortIndex)
  76. End Property
  77. Property Get SortType( _
  78.         ByVal iSortIndex As Integer _
  79.     ) As ESSTypeConstants
  80.     SortType = m_eSortType(iSortIndex)
  81. End Property
  82. Property Let SortType( _
  83.         ByVal iSortIndex As Integer, _
  84.         ByVal eSortType As ESSTypeConstants _
  85.     )
  86.     If (pbValidSortIndex(iSortIndex)) Then
  87.         m_eSortType(iSortIndex) = eSortType
  88.     End If
  89. End Property
  90. Private Function pbValidSortIndex( _
  91.         ByVal iSortIndex As Integer _
  92.     ) As Boolean
  93.     If (iSortIndex > 0) And (iSortIndex < 4) Then
  94.         If (iSortIndex > m_iSortIndexCount) Then
  95.             m_iSortIndexCount = iSortIndex
  96.             ReDim Preserve m_iSortColumn(1 To m_iSortIndexCount) As Integer
  97.             ReDim Preserve m_eSortOrder(1 To m_iSortIndexCount) As ESSOrderCOnstants
  98.             ReDim Preserve m_eSortType(1 To m_iSortIndexCount) As ESSTypeConstants
  99.         End If
  100.         pbValidSortIndex = True
  101.     Else
  102.         Err.Raise vbObjectError + 1048 + 1, App.EXEName & ".cShellSort", "Invalid sort array index."
  103.     End If
  104. End Function
  105.  
  106. Public Sub SortItems( _
  107.         ByRef vItems() As Variant _
  108.     )
  109. Dim iSwapIndex As Integer
  110. Dim iIncrement As Integer
  111. Dim iMainLoop As Integer
  112. Dim iSubLoop As Integer
  113. Dim vSortItem() As Variant
  114. Dim iItemCount As Integer
  115. Dim iCol As Integer
  116. Dim iColumns As Integer
  117.            
  118.     iColumns = UBound(vItems, 1)
  119.     iItemCount = UBound(vItems, 2)
  120.  
  121.     ' Shell sort the list:
  122.     ' ========================================================
  123.     ' Implementation of Shell Sort algorithm using
  124.     ' + 1 * 3 increment.
  125.     ' ========================================================
  126.     ' Prepare swap space storage:
  127.     ReDim vSortItems(1 To iColumns)
  128.     ' Get inital shell sort increment
  129.     If (iItemCount > 1) Then
  130.         iIncrement = piGetSuitableShellSortInitialIncrement(iItemCount)
  131.         Do Until iIncrement < 1
  132.             For iMainLoop = iIncrement + 1 To iItemCount
  133.                 ' Store iMainLoop in vSortItems():
  134.                 For iCol = 1 To iColumns
  135.                     vSortItems(iCol) = vItems(iCol, iMainLoop)
  136.                 Next iCol
  137.                 ' Loop form MainLoop-Increment to 0
  138.                 For iSubLoop = (iMainLoop - iIncrement) To 1 Step -iIncrement
  139.                     If (pbGreater(vItems(), vSortItems, iSubLoop)) Then
  140.                         Exit For
  141.                     End If
  142.                     For iCol = 1 To iColumns
  143.                         vItems(iCol, (iSubLoop + iIncrement)) = vItems(iCol, iSubLoop)
  144.                     Next iCol
  145.                 Next iSubLoop
  146.                 For iCol = 1 To iColumns
  147.                     vItems(iCol, (iSubLoop + iIncrement)) = vSortItems(iCol)
  148.                 Next iCol
  149.             Next iMainLoop
  150.             ' Get next shell sort increment value:
  151.             iIncrement = iIncrement - 1
  152.             iIncrement = iIncrement \ 3
  153.         Loop
  154.     Else
  155.         ' For only two items just check whether the second should
  156.         ' be swapped with the first:
  157.         If (iItemCount > 1) Then
  158.             If (pbGreater(vItems(), vSortItems, iSubLoop)) Then
  159.                 For iCol = 0 To iColumns
  160.                     vSortItems(iCol) = vItems(iCol, 0)
  161.                     vItems(iCol, 0) = vItems(iCol, 1)
  162.                 Next iCol
  163.                 For iCol = 0 To iColumns
  164.                     vItems(iCol, 1) = vSortItems(iCol)
  165.                 Next iCol
  166.             End If
  167.         End If
  168.     End If
  169.     'm_iLastSortIndex = m_iSortColumn
  170.     
  171. End Sub
  172. Public Sub SortGridItems( _
  173.         ByRef vItems() As Variant, _
  174.         ByRef bEnable() As Boolean _
  175.     )
  176. Dim iSwapIndex As Integer
  177. Dim iIncrement As Integer
  178. Dim iMainLoop As Integer
  179. Dim iSubLoop As Integer
  180. Dim vSortItem() As Variant
  181. Dim bEnableItems() As Boolean
  182. Dim iItemCount As Integer
  183. Dim iCol As Integer
  184. Dim iColumns As Integer
  185.            
  186.     iColumns = UBound(vItems, 1)
  187.     iItemCount = UBound(vItems, 2)
  188.  
  189.     ' Shell sort the list:
  190.     ' ========================================================
  191.     ' Implementation of Shell Sort algorithm using
  192.     ' + 1 * 3 increment.
  193.     ' ========================================================
  194.     ' Prepare swap space storage:
  195.     ReDim vSortItems(1 To iColumns) As Variant
  196.     ReDim bEnableItems(1 To iColumns) As Boolean
  197.     ' Get inital shell sort increment
  198.     If (iItemCount > 1) Then
  199.         iIncrement = piGetSuitableShellSortInitialIncrement(iItemCount)
  200.         Do Until iIncrement < 1
  201.             For iMainLoop = iIncrement + 1 To iItemCount
  202.                 ' Store iMainLoop in vSortItems():
  203.                 For iCol = 1 To iColumns
  204.                     vSortItems(iCol) = vItems(iCol, iMainLoop)
  205.                     bEnableItems(iCol) = bEnable(iCol, iMainLoop)
  206.                 Next iCol
  207.                 ' Loop from MainLoop-Increment to 0
  208.                 For iSubLoop = (iMainLoop - iIncrement) To 1 Step -iIncrement
  209.                     If (pbGreater(vItems(), vSortItems, iSubLoop)) Then
  210.                         Exit For
  211.                     End If
  212.                     For iCol = 1 To iColumns
  213.                         vItems(iCol, (iSubLoop + iIncrement)) = vItems(iCol, iSubLoop)
  214.                         bEnable(iCol, (iSubLoop + iIncrement)) = bEnable(iCol, iSubLoop)
  215.                     Next iCol
  216.                 Next iSubLoop
  217.                 For iCol = 1 To iColumns
  218.                     vItems(iCol, (iSubLoop + iIncrement)) = vSortItems(iCol)
  219.                     bEnable(iCol, (iSubLoop + iIncrement)) = bEnableItems(iCol)
  220.                 Next iCol
  221.             Next iMainLoop
  222.             ' Get next shell sort increment value:
  223.             iIncrement = iIncrement - 1
  224.             iIncrement = iIncrement \ 3
  225.         Loop
  226.     Else
  227.         ' For only two items just check whether the second should
  228.         ' be swapped with the first:
  229.         If (iItemCount > 1) Then
  230.             If (pbGreater(vItems(), vSortItems, iSubLoop)) Then
  231.                 For iCol = 1 To iColumns
  232.                     vSortItems(iCol) = vItems(iCol, 0)
  233.                     vItems(iCol, 0) = vItems(iCol, 1)
  234.                     bEnableItems(iCol) = bEnable(iCol, 0)
  235.                     bEnable(iCol, 0) = bEnable(iCol, 1)
  236.                 Next iCol
  237.                 For iCol = 1 To iColumns
  238.                     vItems(iCol, 1) = vSortItems(iCol)
  239.                     bEnable(iCol, 1) = bEnableItems(iCol)
  240.                 Next iCol
  241.             End If
  242.         End If
  243.     End If
  244.     'm_iLastSortIndex = m_iSortColumn
  245.     
  246. End Sub
  247.  
  248. Private Function pbGreater( _
  249.         ByRef vItems() As Variant, _
  250.         ByRef vSortItems As Variant, _
  251.         ByVal iSubLoop As Integer _
  252.     ) As Boolean
  253. Dim iSortIndex As Integer
  254. Dim bIsEqual As Boolean
  255. Dim bR As Boolean
  256.  
  257.     For iSortIndex = 1 To m_iSortIndexCount
  258.         bR = pbIsGreater(vSortItems(m_iSortColumn(iSortIndex)), vItems(m_iSortColumn(iSortIndex), iSubLoop), iSortIndex, bIsEqual)
  259.         If (iSortIndex < m_iSortIndexCount) And bIsEqual Then
  260.             ' Must go to the next one
  261.         Else
  262.             pbGreater = bR
  263.             Exit For
  264.         End If
  265.     Next iSortIndex
  266.  
  267. End Function
  268. Private Function pbIsGreater( _
  269.         ByRef vSortItem As Variant, _
  270.         ByRef vItem As Variant, _
  271.         ByVal iSortIndex As Integer, _
  272.         ByRef bIsEqual As Boolean _
  273.     ) As Boolean
  274. Dim vR As Variant
  275. Dim lR As Long
  276.  
  277.     Select Case m_eSortType(iSortIndex)
  278.     Case CCLSortNumeric
  279.         vR = Val(vSortItem - vItem)
  280.         bIsEqual = (vR = 0)
  281.         If (m_eSortOrder(iSortIndex) = CCLOrderAscending) Then
  282.             pbIsGreater = (vR >= 0)
  283.         Else
  284.             pbIsGreater = (vR <= 0)
  285.         End If
  286.     Case CCLSortString
  287.         lR = StrComp(vSortItem, vItem)
  288.         bIsEqual = (lR = 0)
  289.         If (m_eSortOrder(iSortIndex) = CCLOrderAscending) Then
  290.             pbIsGreater = (lR > -1)
  291.         Else
  292.             pbIsGreater = (lR < 1)
  293.         End If
  294.     Case CCLSortDate
  295.         bIsEqual = (vSortItem = vItem)
  296.         If Not (bIsEqual) Then
  297.             If (m_eSortOrder(iSortIndex) = CCLOrderAscending) Then
  298.                 pbIsGreater = (vSortItem >= vItem)
  299.             Else
  300.                 pbIsGreater = (vItem >= vSortItem)
  301.             End If
  302.         Else
  303.             pbIsGreater = True
  304.         End If
  305.     End Select
  306.     
  307. End Function
  308. Private Function piGetSuitableShellSortInitialIncrement( _
  309.         iSortSize As Integer _
  310.     ) As Integer
  311. ' ==============================================================
  312. ' Part of the implementation of Shell Sort algorithm using
  313. ' + 1 * 3 increment strategy.  This function returns the
  314. ' largest increment based on +1*3 which is less than the
  315. ' sort size.
  316. ' ==============================================================
  317. Dim iRet As Integer
  318. Dim iLastRet As Integer
  319.     iLastRet = 1
  320.     iRet = 1
  321.     Do While iRet < iSortSize
  322.         iLastRet = iRet
  323.         iRet = iRet * 3 + 1
  324.     Loop
  325.     piGetSuitableShellSortInitialIncrement = iLastRet
  326. End Function
  327.  
  328.  
  329.