【问题标题】:How to sort rows in alphabetical order across columns in MS Excel?如何在 MS Excel 中跨列按字母顺序对行进行排序?
【发布时间】:2019-03-02 16:41:21
【问题描述】:

假设我有 Column A,其中一些名称后跟 Column BColumn C 中的一些数据

同样,我有Column D 的一些名称,后跟Column EColumn F 中的一些数据。

我想按字母顺序对行进行排序,保留某些列(在本例中为 A 和 D)作为它们的字母指南。

稍后,如果我添加更多具有更多名称和数据的列,我希望函数/公式也能将添加到列表中的内容考虑在内。

例如:

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

预期结果:

Albert 将显示在同一行,因为他在 A 和 D 列中重复出现。 Brian、Charlie 和 David 将显示在不同的行中,因为他们的名字不会跨列重复。

有办法吗?

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

^^ 如您所见,列中有空白行,其中名称未显示在列表中。

【问题讨论】:

  • 在这种情况下,为什么不将 A 列和 D 列合并,然后在 A 列上对表格进行排序?
  • 你有什么 Excel 版本?您愿意接受电源查询或 vba 解决方案吗?

标签: excel vba sorting excel-formula alphabetical


【解决方案1】:

下面的代码应该做你想做的事。请尝试一下。请注意,您可以在代码顶部的枚举中设置主要参数。

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

代码应安装在标准代码模块中。要运行的过程称为SortNames

出于测试目的,请创建一个简短版本的实际数据,例如 5 到 8 行。创建此测试表的至少 3 个版本。一个具有两个 SortColumns 的长度相等,一个每个 SortColumns 都更长。请注意,在另一个 SortColumn 完成后,一个 SortColumn 最后是否有多个条目应该会有所不同。记得在测试运行前更改Set Ws = Worksheets("Sheet1") 中的选项卡名称。

在双线下面添加这段代码 Do While Len(.Cells(R, NwsSortClm1).Value) And _ Len(.Cells(R, NwsSortClm2).Value) > 0

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

并为其添加一个断点。要添加断点,请单击代码窗口左侧的灰色垂直条。那里将出现两个棕色点,两条线将突出显示为棕色。 (要删除断点,请单击棕色点。)现在,当您将光标放在过程 SortNames 中的任意位置并按 F5 时,代码将运行到断点并停止。停止时,所有值都在内存中,您可以查询它们以确保它们符合预期。

测试的第一部分是在断点之上运行代码。它创建工作表的副本并对两列进行排序。您将能够看到进度。如果到目前为止有任何不规则之处,则必须对代码的前半部分进行更多测试。如果没有,请再次按 F5。每次按 F5 时,将运行一个代码循环,直到再次命中断点。您可以按 F8 而不是按 F5 只运行一行代码并停止。

在循环中,Debug.Print 指令将首先执行。您可以将光标指向R,当前行号将显示在光标旁边。 Debug.Print 指令会将两个 SortColumns 的当前值和这些字符串的长度(字符数)打印到即时窗口(代码窗口面板下方)。当两个单元格的值都大于零时,代码继续循环。如果由于逻辑错误,这种情况永远不会发生,那么循环将无限期地继续下去,这不是本意。

要停止测试,请删除断点并按 F5 或按顶部命令栏中的 Run 命令上方的小方块,其中有“重置”作为控制提示文本。

【讨论】:

  • 我在 Office 2016 上。请原谅我的无知,但我在哪里安装此代码?
  • 此图表的主要目标是轻松找到从先前列到新列的缺失项。在上面的示例中,您可以看到 Albert 进入 A 和 D 列,但 Charlie 未能进入新列表。这样我就可以看到查理在 D 列中丢失了,我可以追踪他回到他的最后一个列活动。这将是一个不断增长的动态图表,我可以在其中非常快速地跟踪活动记录。
  • 我尝试运行宏,但没有成功。也许我需要调整一些范围。我的实际图表有一些标题,要排序的实际值从 A4 开始,然后是数据,直到 I4,然后下一组值从 J4 开始,然后是数据,直到 R4 ......然后我将继续使用添加越来越多的数据间距相同。
  • 您似乎已经安装了它,但“不起作用”太宽泛而无济于事。如果您的数据以 A4 开头,则 NwsFirstDataRow = 4NwsSortClm1 = 1(不变)。由于您有 8 个数据列 B:I、NwsDataClms = 8NwsSortClm2 = 10。请注意,代码会创建原始数据的排序副本,而不是触及后者。
  • 所以我更改了范围以匹配图表。 excel 文件卡住并运行 excel 仅在 excel 上运行我的 CPU 高达 97%。强制关闭 excel 后,我的其余 CPU 总共达到 8%。
猜你喜欢
  • 1970-01-01
  • 2011-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-29
  • 1970-01-01
  • 2010-11-23
相关资源
最近更新 更多