简体   繁体   English

如何在MS Excel中跨列按字母顺序对行进行排序?

[英]How to sort rows in alphabetical order across columns in MS Excel?

Let's say I have Column A with some names followed by some data in Column B and Column C 假设我在Column A有一些名称,然后在Column B Column CColumn C Column B有一些数据

Similarly, I have Column D with some names followed by some data in Column E and Column F . 同样,我在Column D有一些名称,在Column E Column FColumn F Column E有一些数据。

I would like to sort the rows in alphabetical order keeping certain columns (in this case A and D) as their alphabetical guides. 我想按字母顺序对行进行排序,并保留某些列(在本例中为A和D)作为其字母指南。

Later on, if I add more columns with more names and data, I would want the function/formula to account for that addition to the list as well. 稍后,如果我添加了更多具有更多名称和数据的列,我希望函数/公式也考虑到该列表中的添加。

For Example: 例如:

    A    |    B    |    C    |    D    |    E    |    F
---------+---------+---------+---------+---------+---------
 Albert  | ....... | ....... | Albert  | ....... | .......
 Charlie | ....... | ....... | Brian   | ....... | .......
         |         |         | David   | ....... | .......

Expected Result: 预期结果:

Albert would show in the same row as he is repeated in columns A and D. Brian, Charlie and David would show in different rows as their name is not repeated across columns. 阿尔伯特将在A和D列中重复显示同一行。布莱恩,查理和戴维将在不同的行中显示,因为他们的名字没有在各列中重复。

Is there a way to do it? 有办法吗?

    A    |    B    |    C    |    D    |    E    |    F
---------+---------+---------+---------+---------+---------
 Albert  | ....... | ....... | Albert  | ....... | .......
         |         |         | Brian   | ....... | .......
 Charlie | ......  |......   |         |         |  
         |         |         | David   | ......  | ........

^^ As you notice there are blank rows in the columns in which a name isn't shown in the list. ^^您会注意到,列中有空白行,但列表中未显示名称。

The code below should do what you want. 下面的代码应做您想要的。 Please try it. 请尝试一下。 Note that you can set the main parameters in the enumeration at the top of the code. 请注意,您可以在代码顶部的枚举中设置主要参数。

Option Explicit

Enum Nws                            ' Worksheet navigation: modify as appropriate
    ' 03 Mar 2019
    NwsFirstDataRow = 2             ' assuming 1 caption row: change as appropriate
    NwsSortClm1 = 1                 ' First name column to sort (1 = A)
    NwsSortClm2 = 4                 ' 4 = D
    NwsDataClms = 2                 ' number of data columns next to sort columns
End Enum

Sub SortNames()
    ' 03 Mar 2019

    Dim Wb As Workbook
    Dim Ws As Worksheet
    Dim Rng As Range
    Dim Arr(1) As Variant
    Dim R As Long, C As Long
    Dim i As Long
    Dim p As Long                           ' priority

    Application.ScreenUpdating = False
    Set Wb = ThisWorkbook                   ' change as appropriate: better to define Wb by name
    Set Ws = Worksheets("Sheet1")           ' change tab name as appropriate
    Ws.Copy After:=Ws
    Set Ws = ActiveSheet

    C = NwsSortClm1
    For i = 0 To 1                          ' corresponds to LBound(Arr) To UBound(Arr)
        With Ws
            Set Rng = .Range(.Cells(NwsFirstDataRow, C), _
                             .Cells(.Rows.Count, C + NwsDataClms).End(xlUp))
            With .Sort.SortFields
                .Clear
                .Add Key:=Rng.Columns(1), _
                     SortOn:=xlSortOnValues, _
                     Order:=xlAscending, _
                     DataOption:=xlSortNormal
            End With
            With .Sort
                .SetRange Rng
                .Header = False
                .MatchCase = False
                .Orientation = xlTopToBottom
                .SortMethod = xlPinYin
                .Apply
            End With

            Arr(i) = .Range(.Cells(NwsFirstDataRow, C), _
                             .Cells(.Rows.Count, C + NwsDataClms).End(xlUp)).Value
        End With
        C = NwsSortClm2
    Next i

    R = NwsFirstDataRow
    With Ws
        Do While Len(.Cells(R, NwsSortClm1).Value) And _
                 Len(.Cells(R, NwsSortClm2).Value) > 0
            p = StrComp(.Cells(R, NwsSortClm1).Value, _
                        .Cells(R, NwsSortClm2).Value, _
                        vbTextCompare)          ' not case sensitive !
            If p Then
                C = IIf(p < 0, NwsSortClm2, NwsSortClm1)
                Set Rng = .Range(.Cells(R, C), .Cells(R, C + NwsDataClms))
                Rng.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
            End If
            R = R + 1
        Loop
    End With
    Application.ScreenUpdating = True
End Sub

The code should be installed om a standard code module. 该代码应安装在标准代码模块中。 The procedure to run is called SortNames . 运行的过程称为SortNames

For testing purposes create a short version of your actual data, say 5 to 8 rows only. 为了进行测试,请为您的实际数据创建一个简短的版本,例如仅5至8行。 Create at least 3 versions of this test sheet. 创建此测试表的至少3个版本。 One with both SortColumns of equal length and one each where either of the SortColumns is longer. 一个具有两个相等长度的SortColumns,每个具有一个SortColumns较长的地方。 Observe that it should make a difference whether one SortColumn has several entries at the end after the other SortColumn is complete. 观察到一个SortColumn在另一SortColumn完成之后是否在末尾有多个条目应该有所不同。 Remember to change the tab name in Set Ws = Worksheets("Sheet1") before test runs. 记住在测试运行之前在Set Ws = Worksheets("Sheet1")更改选项卡名称。

Add this code below the double line Do While Len(.Cells(R, NwsSortClm1).Value) And _ Len(.Cells(R, NwsSortClm2).Value) > 0 将此代码添加到双行Do While Len(.Cells(R,NwsSortRTI1).Value)和_ Len(.Cells(R,NwsSortRTI2).Value)> 0下

Debug.Print .Cells(R, NwsSortClm1).Value, Len(.Cells(R, NwsSortClm1).Value), _
                    .Cells(R, NwsSortClm2).Value, Len(.Cells(R, NwsSortClm2).Value)

and add a break point to it. 并添加一个断点。 To add a break point click on the grey, vertical bar to the left of the code window. 要添加断点,请单击代码窗口左侧的灰色垂直栏。 Two brown points will appear there and the two lines will be highlighted brown. 此处将出现两个棕色点,两行将突出显示为棕色。 (To remove the break point click the brown points.) Now, when you place the cursor anywhere in the procedure SortNames and press F5 the code will run up to the break point and stop. (要删除断点,请单击棕色点。)现在,将光标放在过程SortNames中的任意位置并按F5键,代码将运行到断点并停止。 When stopped all values are in memory and you can query them to make sure they are as expected. 停止时,所有值都在内存中,您可以查询它们以确保它们符合预期。

The first part of the test is to run the code above the break point. 测试的第一部分是在断点以上运行代码。 It creates a copy of the sheet and sorts both columns. 它创建工作表的副本并对两列进行排序。 You will be able to see the progress. 您将能够看到进度。 If there is any irregularity so far more tests have to be done on the first half of the code. 到目前为止,如果有任何不正常之处,则必须对代码的前半部分进行更多测试。 If not, press F5 again. 如果不是,请再次按F5。 Each time you press F5 one loop of the code will run until the break point is hit again. 每次按F5键,都会运行一个代码循环,直到再次击中断点为止。 Instead of pressing F5 you can press F8 to run only one line of code and stop. 代替按F5,您可以按F8只运行一行代码并停止。

In the loop the Debug.Print instruction will be carried out first. 在循环中,将首先执行Debug.Print指令。 You can point the cursor at R and the current row number will be shown next to the cursor. 您可以将光标指向R ,当前行号将显示在光标旁边。 The Debug.Print instructions will print the current values of the two SortColumns and the length (number of characters) of these strings to the Immediate Window (below the code window panel). Debug.Print指令会将两个SortColumns的当前值以及这些字符串的长度(字符数)打印到立即窗口(在代码窗口面板下方)。 The code continues looping while both cells have a value the length of which is greater than zero. 当两个像元的长度均大于零时,代码将继续循环。 If, by reason of a logical error, this never happens the loop would continue ad infinitum which isn't the intention. 如果由于逻辑错误而永远不会发生,则循环将无限期地继续下去,这不是故意的。

To stop the test, remove the break point and press F5 or press the little square above the Run command in the top command bar which has "Reset" as a control tip text. 要停止测试,请移除断点并按F5或按顶部命令栏中“ 运行”命令上方的小方块,该命令栏中将“重置”作为控制提示文本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM