Как отсортировать строки в алфавитном порядке по столбцам в MS Excel?

#excel #vba #sorting #excel-formula #alphabetical

#excel #vba #сортировка #excel-формула #алфавитный

Вопрос:

Допустим, у меня есть Column A с некоторыми именами, за которыми следуют некоторые данные в Column B и Column C

Аналогично, у меня есть Column D с некоторыми именами, за которыми следуют некоторые данные в Column E и Column F .

Я хотел бы отсортировать строки в алфавитном порядке, сохраняя определенные столбцы (в данном случае A и D) в качестве их алфавитных ориентиров.

Позже, если я добавлю больше столбцов с большим количеством имен и данных, я бы хотел, чтобы функция / формула учитывала и это добавление в список.

Например:

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

Ожидаемый результат:

Альберт будет отображаться в той же строке, что и он повторяется в столбцах A и D. Брайан, Чарли и Дэвид будут отображаться в разных строках, поскольку их имя не повторяется в столбцах.

Есть ли способ сделать это?

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

^^ Как вы заметили, в столбцах есть пустые строки, имя которых не отображается в списке.

Комментарии:

1. Почему бы вам в этом случае не объединить столбцы A и D, а затем отсортировать таблицу по столбцу A?

2. Какая у вас версия Excel? вы открыты для power query или решения vba?

Ответ №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
  

Код должен быть установлен в стандартном модуле code. Выполняемая процедура называется SortNames.

В целях тестирования создайте краткую версию ваших фактических данных, скажем, только от 5 до 8 строк. Создайте как минимум 3 версии этого тестового листа. Один с обоими столбцами сортировки одинаковой длины и по одному, где любой из столбцов сортировки длиннее. Обратите внимание, что должно иметь значение, содержит ли один столбец сортировки несколько записей в конце после завершения другого столбца сортировки. Не забудьте изменить название вкладки в Set Ws = Worksheets("Sheet1") перед запуском теста.

Добавьте этот код под двойной строкой Do While Len(.Cells(R, NwsSortClm1).Value) И _ 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)
  

и добавить к нему точку останова. Чтобы добавить точку останова, щелкните на серой вертикальной полоске слева от окна кода. Там появятся две коричневые точки, а две строки будут выделены коричневым цветом. (Чтобы удалить точку разрыва, щелкните коричневые точки.) Теперь, когда вы размещаете курсор в любом месте процедуры сортировки и нажимаете F5, код будет выполняться до точки останова. После остановки все значения находятся в памяти, и вы можете запросить их, чтобы убедиться, что они соответствуют ожиданиям.

Первая часть теста заключается в запуске кода выше точки останова. Создается копия листа и сортируются оба столбца. Вы сможете увидеть прогресс. Если есть какие-либо нарушения, необходимо выполнить дополнительные тесты для первой половины кода. Если нет, нажмите F5 еще раз. Каждый раз, когда вы нажимаете клавишу F5, выполняется один цикл кода, пока снова не будет достигнута точка останова. Вместо нажатия клавиши F5 вы можете нажать клавишу F8, чтобы запустить только одну строку кода и остановиться.

В цикле сначала будет выполнена Debug.Print инструкция. Вы можете навести курсор на R , и рядом с курсором будет показан номер текущей строки. Debug.Print Инструкции выведут текущие значения двух сортировочных столбцов и длину (количество символов) этих строк в ближайшее окно (под панелью code window). Код продолжает выполнение цикла, пока длина обеих ячеек больше нуля. Если по причине логической ошибки этого никогда не произойдет, цикл будет продолжаться до бесконечности, что не является намерением.

Чтобы остановить тест, удалить точку останова и нажать клавишу F5 или нажмите на малой площади над запуска команд в верхней командной строке, которая «сбрасывается» в качестве управления всплывающей подсказки текст.

Комментарии:

1. Я в Office 2016. Извините за мое невежество, но где мне установить этот код?

2. Основной целью этой диаграммы было бы легко найти недостающие элементы из предыдущих столбцов в новые столбцы. В приведенном выше примере вы можете видеть, что Альберт попал в столбцы A и D, но Чарли не удалось попасть в новый список. Таким образом, я могу видеть, что Чарли отсутствует в столбце D, и я могу отследить его до последнего действия в столбце. Это была бы динамичная, постоянно растущая диаграмма, в которой я мог бы очень быстро отслеживать записи активности.

3. Я попытался запустить макросы, но это не сработало. Возможно, мне нужно настроить в нем какой-то диапазон. Фактическая диаграмма, которая у меня есть, имеет некоторый заголовок, и реальные значения для сортировки начинаются с A4, за которыми следуют данные до I4, затем следующий набор значений начинается с J4, за которым следуют данные до R4 … затем я буду продолжать добавлять все больше и больше данных, используя тот же интервал.

4. Кажется, вы его установили, но «не работает» — слишком широкое слово, чтобы быть полезным. Если ваши данные начинаются с формата A4, то NwsFirstDataRow = 4 и NwsSortClm1 = 1 (без изменений). Поскольку у вас есть 8 столбцов данных B: I, NwsDataClms = 8 и NwsSortClm2 = 10 . Обратите внимание, что код создает отсортированную копию исходных данных, не затрагивая последние.

5. Поэтому я меняю диапазон, чтобы он соответствовал диаграмме. файл Excel застрял, и при запуске excel мой процессор разгонялся до 97% только в Excel. После принудительного закрытия Excel загрузка моего процессора снизилась до 8%.