VBA array sort function?

后端 未结 13 1954
北荒
北荒 2020-11-22 05:28

I\'m looking for a decent sort implementation for arrays in VBA. A Quicksort would be preferred. Or any other sort algorithm other than bubble or merge would suffice.

<
13条回答
  •  粉色の甜心
    2020-11-22 06:17

    You didn't want an Excel-based solution but since I had the same problem today and wanted to test using other Office Applications functions I wrote the function below.

    Limitations:

    • 2-dimensional arrays;
    • maximum of 3 columns as sort keys;
    • depends on Excel;

    Tested calling Excel 2010 from Visio 2010


    Option Base 1
    
    
    Private Function sort_array_2D_excel(array_2D, array_sortkeys, Optional array_sortorders, Optional tag_header As String = "Guess", Optional tag_matchcase As String = "False")
    
    '   Dependencies: Excel; Tools > References > Microsoft Excel [Version] Object Library
    
        Dim excel_application As Excel.Application
        Dim excel_workbook As Excel.Workbook
        Dim excel_worksheet As Excel.Worksheet
    
        Set excel_application = CreateObject("Excel.Application")
    
        excel_application.Visible = True
        excel_application.ScreenUpdating = False
        excel_application.WindowState = xlNormal
    
        Set excel_workbook = excel_application.Workbooks.Add
        excel_workbook.Activate
    
        Set excel_worksheet = excel_workbook.Worksheets.Add
        excel_worksheet.Activate
        excel_worksheet.Visible = xlSheetVisible
    
        Dim excel_range As Excel.Range
        Set excel_range = excel_worksheet.Range("A1").Resize(UBound(array_2D, 1) - LBound(array_2D, 1) + 1, UBound(array_2D, 2) - LBound(array_2D, 2) + 1)
        excel_range = array_2D
    
    
        For i_sortkey = LBound(array_sortkeys) To UBound(array_sortkeys)
    
            If IsNumeric(array_sortkeys(i_sortkey)) Then
                sortkey_range = Chr(array_sortkeys(i_sortkey) + 65 - 1) & "1"
                Set array_sortkeys(i_sortkey) = excel_worksheet.Range(sortkey_range)
    
            Else
                MsgBox "Error in sortkey parameter:" & vbLf & "array_sortkeys(" & i_sortkey & ") = " & array_sortkeys(i_sortkey) & vbLf & "Terminating..."
                End
    
            End If
    
        Next i_sortkey
    
    
        For i_sortorder = LBound(array_sortorders) To UBound(array_sortorders)
            Select Case LCase(array_sortorders(i_sortorder))
                Case "asc"
                    array_sortorders(i_sortorder) = XlSortOrder.xlAscending
                Case "desc"
                    array_sortorders(i_sortorder) = XlSortOrder.xlDescending
                Case Else
                    array_sortorders(i_sortorder) = XlSortOrder.xlAscending
            End Select
        Next i_sortorder
    
        Select Case LCase(tag_header)
            Case "yes"
                tag_header = Excel.xlYes
            Case "no"
                tag_header = Excel.xlNo
            Case "guess"
                tag_header = Excel.xlGuess
            Case Else
                tag_header = Excel.xlGuess
        End Select
    
        Select Case LCase(tag_matchcase)
            Case "true"
                tag_matchcase = True
            Case "false"
                tag_matchcase = False
            Case Else
                tag_matchcase = False
        End Select
    
    
        Select Case (UBound(array_sortkeys) - LBound(array_sortkeys) + 1)
            Case 1
                Call excel_range.Sort(Key1:=array_sortkeys(1), Order1:=array_sortorders(1), Header:=tag_header, MatchCase:=tag_matchcase)
            Case 2
                Call excel_range.Sort(Key1:=array_sortkeys(1), Order1:=array_sortorders(1), Key2:=array_sortkeys(2), Order2:=array_sortorders(2), Header:=tag_header, MatchCase:=tag_matchcase)
            Case 3
                Call excel_range.Sort(Key1:=array_sortkeys(1), Order1:=array_sortorders(1), Key2:=array_sortkeys(2), Order2:=array_sortorders(2), Key3:=array_sortkeys(3), Order3:=array_sortorders(3), Header:=tag_header, MatchCase:=tag_matchcase)
            Case Else
                MsgBox "Error in sortkey parameter:" & vbLf & "Maximum number of sort columns is 3!" & vbLf & "Currently passed: " & (UBound(array_sortkeys) - LBound(array_sortkeys) + 1)
                End
        End Select
    
    
        For i_row = 1 To excel_range.Rows.Count
    
            For i_column = 1 To excel_range.Columns.Count
    
                array_2D(i_row, i_column) = excel_range(i_row, i_column)
    
            Next i_column
    
        Next i_row
    
    
        excel_workbook.Close False
        excel_application.Quit
    
        Set excel_worksheet = Nothing
        Set excel_workbook = Nothing
        Set excel_application = Nothing
    
    
        sort_array_2D_excel = array_2D
    
    
    End Function
    

    This is an example on how to test the function:

    Private Sub test_sort()
    
        array_unsorted = dim_sort_array()
    
        Call msgbox_array(array_unsorted)
    
        array_sorted = sort_array_2D_excel(array_unsorted, Array(2, 1, 3), Array("desc", "", "asdas"), "yes", "False")
    
        Call msgbox_array(array_sorted)
    
    End Sub
    
    
    Private Function dim_sort_array()
    
        Dim array_unsorted(1 To 5, 1 To 3) As String
    
        i_row = 0
    
        i_row = i_row + 1
        array_unsorted(i_row, 1) = "Column1": array_unsorted(i_row, 2) = "Column2": array_unsorted(i_row, 3) = "Column3"
    
        i_row = i_row + 1
        array_unsorted(i_row, 1) = "OR": array_unsorted(i_row, 2) = "A": array_unsorted(i_row, 3) = array_unsorted(i_row, 1) & "_" & array_unsorted(i_row, 2)
    
        i_row = i_row + 1
        array_unsorted(i_row, 1) = "XOR": array_unsorted(i_row, 2) = "A": array_unsorted(i_row, 3) = array_unsorted(i_row, 1) & "_" & array_unsorted(i_row, 2)
    
        i_row = i_row + 1
        array_unsorted(i_row, 1) = "NOT": array_unsorted(i_row, 2) = "B": array_unsorted(i_row, 3) = array_unsorted(i_row, 1) & "_" & array_unsorted(i_row, 2)
    
        i_row = i_row + 1
        array_unsorted(i_row, 1) = "AND": array_unsorted(i_row, 2) = "A": array_unsorted(i_row, 3) = array_unsorted(i_row, 1) & "_" & array_unsorted(i_row, 2)
    
        dim_sort_array = array_unsorted
    
    End Function
    
    
    Sub msgbox_array(array_2D, Optional string_info As String = "2D array content:")
    
        msgbox_string = string_info & vbLf
    
        For i_row = LBound(array_2D, 1) To UBound(array_2D, 1)
    
            msgbox_string = msgbox_string & vbLf & i_row & vbTab
    
            For i_column = LBound(array_2D, 2) To UBound(array_2D, 2)
    
                msgbox_string = msgbox_string & array_2D(i_row, i_column) & vbTab
    
            Next i_column
    
        Next i_row
    
        MsgBox msgbox_string
    
    End Sub
    

    If anybody tests this using other versions of office please post here if there are any problems.

提交回复
热议问题