Results 1 to 4 of 4
  1. #1
    DepricatedZero's Avatar
    DepricatedZero is offline Cthulhu Fhtagn!
    Windows 8 Access 2007
    Join Date
    Apr 2013
    Location
    Cincinnati
    Posts
    65

    QuickSort a ListView preserving ListSubItems data

    So I'm trying to write a QuickSort for a ListView control. Built in ListView sorting is only alphabetical, not numeric, thus the need for this.

    But I'm getting errors left and right. Mainly the problem is in moving the values around. It seems to be handling the rest of the quicksort logic without issue.

    Typically I would just

    storeItem = leftItem
    leftItem = rightItem
    rightItem = storeItem

    however, the reassignment of the values of the listsubitems is being a reeeaaal pita. Any advice, or anyone know the 'correct' methods I should be calling on these? I've been at this for hours and can't find aaanything.



    Code:
    Public Sub SortByDate(ByRef lvwBox As Object, dateColumn As Integer, left As Integer, right As Integer)
        
        Dim rightIndex As Integer
        Dim leftIndex As Integer
        Dim comparisonItem As Variant
        Dim storedItem As ListItem
        
        leftIndex = left
        rightIndex = right
        comparisonItem = lvwBox.ListItems(CInt((leftIndex + rightIndex) / 2)).SubItems(dateColumn)
        
        Do
            Do While (lvwBox.ListItems(leftIndex).SubItems(dateColumn) < comparisonItem And leftIndex < rightIndex)
            leftIndex = leftIndex + 1
            Loop
            
            Do While (comparisonItem < lvwBox.ListItems(rightIndex).SubItems(dateColumn) And rightIndex > leftIndex)
            rightIndex = rightIndex - 1
            Loop
    
    
            If leftIndex <= rightIndex Then
                'This is the part giving errors. 
                Dim i As Integer
                Set storedItem = lvwBox.ListItems(leftIndex)
                
                For i = 1 To lvwBox.ListItems(leftIndex).ListSubItems.Count
                    storedItem.ListSubItems.Add i, , lvwBox.ListItems(leftIndex).SubItems(i)
                Next
                
                lvwBox.ListItems.Remove leftIndex
                lvwBox.ListItems.Add (leftIndex)
                lvwBox.ListItems(leftIndex) = lvwBox.ListItems(rightIndex)
                
                For i = 1 To lvwBox.ListItems(rightIndex).ListSubItems.Count
                    lvwBox.ListItems(leftIndex).ListSubItems.Add i, , lvwBox.ListItems(rightIndex).SubItems(i)
                Next
                
                lvwBox.ListItems(rightIndex) = storedItem
                
                For i = 1 To lvwBox.ListItems(leftIndex).ListSubItems.Count
                    lvwBox.ListItems(rightIndex).ListSubItems.Add i, , storedItem.ListSubItems.Item(i).text
                Next
                
                leftIndex = leftIndex + 1
                rightIndex = rightIndex - 1
            End If
        Loop While leftIndex <= rightIndex
        
        If left < rightIndex Then
            SortByDate lvwBox, dateColumn, left, rightIndex
        End If
        
        If leftIndex < right Then
            SortByDate lvwBox, dateColumn, leftIndex, right
        End If
        
    End Sub

  2. #2
    DepricatedZero's Avatar
    DepricatedZero is offline Cthulhu Fhtagn!
    Windows 8 Access 2007
    Join Date
    Apr 2013
    Location
    Cincinnati
    Posts
    65
    GOT IT!

    Code:
    Public Sub SortByDate(ByRef lvwBox As Object, dateColumn As Integer, left As Integer, right As Integer)
        
        Dim rightIndex As Integer
        Dim leftIndex As Integer
        Dim comparisonItem As Variant
        Dim storedItem As ListItem
        
        leftIndex = left
        rightIndex = right
        comparisonItem = lvwBox.ListItems(CInt((leftIndex + rightIndex) / 2)).SubItems(dateColumn)
        
        Do
            Do While (CDate(lvwBox.ListItems(leftIndex).SubItems(dateColumn)) < CDate(comparisonItem) And leftIndex < rightIndex)
            leftIndex = leftIndex + 1
            Loop
            
            Do While (CDate(comparisonItem) < CDate(lvwBox.ListItems(rightIndex).SubItems(dateColumn)) And rightIndex > leftIndex)
            rightIndex = rightIndex - 1
            Loop
            If leftIndex <= rightIndex Then
            Debug.Print "moving"
                Dim i As Integer
                Dim movedItem As ListItem
                Set storedItem = lvwBox.ListItems(leftIndex)
                
                lvwBox.ListItems.Remove leftIndex
                Set movedItem = lvwBox.ListItems.Add(leftIndex)
                
                movedItem.text = lvwBox.ListItems(rightIndex)
                For i = 1 To lvwBox.ListItems(rightIndex).ListSubItems.Count
                    movedItem.SubItems(i) = SafeInsert(lvwBox.ListItems(rightIndex).ListSubItems(i))
                Next
                
                lvwBox.ListItems(rightIndex) = SafeInsert(storedItem)
                For i = 1 To storedItem.ListSubItems.Count
                    lvwBox.ListItems(rightIndex).SubItems(i) = storedItem.ListSubItems(i)
                Next
                
                leftIndex = leftIndex + 1
                rightIndex = rightIndex - 1
            End If
        Loop While leftIndex <= rightIndex
        
        If left < rightIndex Then
            SortByDate lvwBox, dateColumn, left, rightIndex
        End If
        
        If leftIndex < right Then
            SortByDate lvwBox, dateColumn, leftIndex, right
        End If
        
    End Sub
    Thought I'd share


    oh also, for not choking on null values when you expect they might be passed
    Code:
    Public Function SafeInsert(lstItem As Variant) As Variant
        If IsNull(lstItem) Then
            SafeInsert = ""
        Else
            SafeInsert = lstItem
        End If
    End Function

  3. #3
    June7's Avatar
    June7 is online now VIP
    Windows XP Access 2010 32bit
    Join Date
    May 2011
    Location
    The Great Land
    Posts
    52,930
    Or deal with possible null up front, no function needed.

    lvwBox.ListItems(rightIndex) = storedItem & ""
    How to attach file: http://www.accessforums.net/showthread.php?t=70301 To provide db: copy, remove confidential data, run compact & repair, zip w/Windows Compression.

  4. #4
    DepricatedZero's Avatar
    DepricatedZero is offline Cthulhu Fhtagn!
    Windows 8 Access 2007
    Join Date
    Apr 2013
    Location
    Cincinnati
    Posts
    65
    Putting it in a separate function is just a clean code practice I picked up from the book...Clean Code...hehe both work well. More I just wanted to give context to the function SafeInsert() that was being used all over the place.

Please reply to this thread with any new information or opinions.

Similar Threads

  1. Replies: 1
    Last Post: 03-20-2013, 02:43 AM
  2. Replies: 2
    Last Post: 11-09-2012, 10:49 AM
  3. Listview pulling data from a second table
    By Yesideez in forum Access
    Replies: 8
    Last Post: 06-29-2011, 05:08 AM
  4. Replies: 1
    Last Post: 06-16-2010, 09:25 AM
  5. Transfer data from ListView to Table
    By Zyckie in forum Access
    Replies: 1
    Last Post: 12-15-2009, 11:23 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Other Forums: Microsoft Office Forums