使用Microsoft Excel的宏进行排序
在使用Excel进行数据处理的时候经常使用排序功能,但是有些时候我们会遇到一些需要排序,但是又不能直接使用标准类型进行排序,如数字,ASCII文本,日期等形式的标准类型。那么这时候可以使用宏编程进行数据处理。
宏编程
宏编程其实是一门Visual Basic语言的编程,通过VB进行Excel表格数据的处理,提供最强大的数据处理方式,在宏观上看,宏编程相当于数据的自动化处理的一种工具。在进行大量表格的数据分析过程中,宏编程可以提供一种通用且相对灵活的处理方式。
以下通过简要的教程展示如何在Microsoft Office上使用宏编程:
注意:本文使用Microsoft Office 2016以上版本,WPS不支持。
开启开发者模式
设置路径:
File->Options->Customize Ribbon
选择标签:
点击Developer的标签卡Visual Basic模块,界面如下:
解决方案
需求:
假设大头有一份表格,数据长这样:
分析: 以上表格的数据需要按照B列进行排布,但是B列数据源数据为一个日期字符串,这个日期字符串不是一个标准的日期字符串,如2022-02-12这类表示方式,为用户自定义分隔符表示。这种情况可以使用数据分列的功能进行数据转换,转换成统一的日期格式即可进行排序。
宏排序原理:
流程:
- 用Range读取原表格数据;
- 将数据保存到数组中;
- 将数组中的结果提取修改并排序;
- 根据目标流程进行反解析;
- 回写数据到文件。
以上操作主要将数据处理后再回放,其中排序算法使用的是较易理解的冒泡算法。
宏编码:
源码使用的是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