使用Microsoft Excel的宏进行排序

在使用Excel进行数据处理的时候经常使用排序功能,但是有些时候我们会遇到一些需要排序,但是又不能直接使用标准类型进行排序,如数字,ASCII文本,日期等形式的标准类型。那么这时候可以使用宏编程进行数据处理。

宏编程

宏编程其实是一门Visual Basic语言的编程,通过VB进行Excel表格数据的处理,提供最强大的数据处理方式,在宏观上看,宏编程相当于数据的自动化处理的一种工具。在进行大量表格的数据分析过程中,宏编程可以提供一种通用且相对灵活的处理方式。

以下通过简要的教程展示如何在Microsoft Office上使用宏编程:

注意:本文使用Microsoft Office 2016以上版本,WPS不支持。
开启开发者模式

设置路径:

File->Options->Customize Ribbon

开启开发者模式

选择标签:

Developer标签

点击Developer的标签卡Visual Basic模块,界面如下:

Visual Basic界面

解决方案

需求:

假设大头有一份表格,数据长这样:

源数据

分析: 以上表格的数据需要按照B列进行排布,但是B列数据源数据为一个日期字符串,这个日期字符串不是一个标准的日期字符串,如2022-02-12这类表示方式,为用户自定义分隔符表示。这种情况可以使用数据分列的功能进行数据转换,转换成统一的日期格式即可进行排序。

宏排序原理:

流程:

  1. 用Range读取原表格数据;
  2. 将数据保存到数组中;
  3. 将数组中的结果提取修改并排序;
  4. 根据目标流程进行反解析;
  5. 回写数据到文件。

以上操作主要将数据处理后再回放,其中排序算法使用的是较易理解的冒泡算法。

宏编码:

源码使用的是Visual Basic语言进行编程,语法相对较易理解,其中Range("A1:D" & num)取决于使用者的实际数据,不同的表格数据所需要的列都不会完全一致,以下源码中的sortedColNum 仅作为此实例数据作为引用。

'Convert date string to a standard Date Object.
'@param str, date string such as 2022.1.03
Function convertDate(str As String, delimiter As String) As Date
    arr = Split(str, delimiter) 'Split the string of date
    res = arr(0) & "/" & arr(1) & "/" & arr(2)
    convertDate = CDate(res)
End Function

'Convert date string to custom format
'@param aDate
Function convertStandardDate(aDate As Date) As String
    Dim str As String
    str = Format(aDate, "YYYY/MM/DD")
    arr = Split(str, "/") 'Split the string of date
    'custom to 2022.1.03
    res = arr(0) & "." & CInt(arr(1)) & "." & arr(2)
    convertStandardDate = res
End Function

'Sort the DataArray by bubble sort.
'@param arr, Array of Worksheet data.
'@param columnNum,Key of Column which will be as a sorting key.
'@param isAscending, sorting order, no default.
Function sortDataArray(arr As Variant, columnNum As Integer, isAscending As Boolean) As Variant
    Dim DataArr() As Variant
    DataArr = arr
    For i = 1 To UBound(DataArr, 1)
        For j = i + 1 To UBound(DataArr, 1)
            If UCase(DataArr(i, columnNum) > DataArr(j, columnNum)) And isAscending = True Then
                For C = 1 To UBound(DataArr, 2)
                    Temp = DataArr(i, C)
                    DataArr(i, C) = DataArr(j, C)
                    DataArr(j, C) = Temp
                Next
            ElseIf UCase(DataArr(i, columnNum) < DataArr(j, columnNum)) And isAscending = False Then
                For C = 1 To UBound(DataArr, 2)
                    Temp = DataArr(i, C)
                    DataArr(i, C) = DataArr(j, C)
                    DataArr(j, C) = Temp
                Next
            End If
        Next
    Next
    sortDataArray = DataArr
End Function

Sub MySort()

    Dim rowLines As Long
    Dim DataArr() As Variant
    Dim sortedColNum As Integer 'Which Column will be as key
    
    rowLines = Cells(Rows.Count, "B").End(xlUp).Row 'How many lines
    
    'Read all data to Array
    DataArr = Range("A1:D" & rowLines)
    
    ' aka B Column
    sortedColNum = 2
    
    'In VBA, the Array is begin with 1(different from other languages.)
    
    'Convert date string to target format.
    For R = 1 To UBound(DataArr, 1)
        '2 is second column(aka Column B)
        DataArr(R, sortedColNum) = convertDate(CStr(DataArr(R, sortedColNum)), ".")
    Next
    
    '********************* Important!!! SORTING...
    sortedDataArr = sortDataArray(DataArr, sortedColNum, False)
    '********************* Important!!! SORTING...
    
    ' convert standard date format to custom format
    For R = 1 To UBound(sortedDataArr, 1)
        '2 is second column(aka Column B)
        sortedDataArr(R, sortedColNum) = convertStandardDate(CDate(sortedDataArr(R, sortedColNum)))
    Next
    
    ' Test to present how many lines have been processed.
    For i = 1 To UBound(sortedDataArr, 1)
        For j = 1 To UBound(sortedDataArr, 2)
            Debug.Print sortedDataArr(i, j)
        Next
    Next
    
    ' Finally, we write the sorted result to Worksheet!
    Range("A1:D" & rowLines) = sortedDataArr

End Sub
最后修改:2023 年 08 月 02 日
如果觉得我的文章对你有用,请随意赞赏