Можно ли сортировать строки в таблице Microsoft WORD без сортировки данных в алфавитном, буквенно-цифровом или в порядке дат?

#vba #sorting #ms-word

#vba #сортировка #ms-word

Вопрос:

Это сложный вопрос, и я не смог даже попытаться использовать код VBA, чтобы попытаться разобраться в этом. Использование таблицы.Сортировка не помогает. Вот пример ниже, если вас смущает то, что мне требуется:

 BEFORE            AFTER
rice              rice
pea               rice
apple             pea
vegetable         pea
vegetable         apple
pea               apple
apple             vegetable
rice              vegetable
orange            orange
 

Как вы можете видеть выше, хотя данные во втором столбце отсортированы упорядоченным образом, они не в алфавитном порядке. Возможно ли это сделать без необходимости размещать цифры перед текстом в столбце таблицы, а затем сортировать? Или мне не нужно делать все это вручную? Мой приведенный выше пример является простым, и для больших объемов информации было бы непрактично делать это вручную. Я могу делать то, что мне нужно в EXCEL, используя формулы, но мне действительно нужны возможности обработки текста WORD, а не EXCEL.

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

1. можете ли вы временно поместить свою таблицу в таблицу Excel, выполнить нужную сортировку, а затем вернуть ее обратно в Word?

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

Ответ №1:

Для работы этого кода вам нужна эта ссылка.
Это выполняется из Word VBA, а не из Excel.

 Sub SortingSortOf()
Dim XL As Excel.Application, WB As Excel.Workbook
Dim WS As Excel.Worksheet, MatchCol As Excel.Range, Tbl As Table

    Set XL = Excel.Application
    Set WB = XL.Workbooks.Open("C:PathToWorkbookWithYourTable.xlsm") ' or.xlsx
    Set WS = WB.Sheets("NameOfTableSheet")
    
    ' places a sort value one column to the right of the current data
    Set MatchCol = WS.UsedRange.Columns(WS.Cells.SpecialCells(xlCellTypeLastCell).Column   1)
    
    ' change this to whatever column holds your sort value
    MatchCol.Formula = "=Match(A1, A:A, 0)"
    
    ' i'm assuming you have some sort of header
    WS.UsedRange.Sort Key1:=MatchCol, Header:=xlYes
    
    'optional, unless you want the sort number displayed in the table
    MatchCol.Delete
    
    ' or wherever you want. doesn't have to be paragraph 1
    If ActiveDocument.Paragraphs(1).Range.Tables.Count > 0 Then
        ' for some reason it doesn't overwrite an existing table
        ' so this will delete it first (even if there is more than one)
        For Each Tbl In ActiveDocument.Paragraphs(1).Range.Tables
            Tbl.Delete
        Next Tbl
    End If
    WS.UsedRange.Copy
    ActiveDocument.Paragraphs(1).Range.Paste
    
    ' putting false on close should prevent the save changes dialog,
    ' but there seems to be an excel bug, so shutting off alerts
    XL.DisplayAlerts = False
    WB.Close , False
    XL.DisplayAlerts = True
End Sub
 

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

1. Привет, стеки. Спасибо, что перезвонили мне и нашли время для компиляции этого кода для меня. Для меня большая честь получить от вас этот код. Мне потребовалось некоторое время, чтобы разобраться в этом (мне пришлось поиграть с этим), но я лучше понимаю VBA. Еще раз большое вам спасибо за вашу помощь.

Ответ №2:

У меня было немного свободного времени, поэтому я создал программу для сортировки таблицы в Word на основе моего понимания ваших правил сортировки.

 Sub Example()
    Call CustomSort(ThisDocument.Tables(1))
End Sub

Sub CustomSort(sortTable As Table)
    'Create an array that contains the table values
    Dim Items() As String
    ReDim Items(1 To sortTable.Rows.Count, 1 To sortTable.Columns.Count)
    
    Dim i As Long, j As Long
    For i = 1 To sortTable.Rows.Count
        For j = 1 To sortTable.Columns.Count
            Items(i, j) = Left(sortTable.Cell(i, j).Range.Text, Len(sortTable.Cell(i, j).Range.Text) - 2) 
            'removes the extra characters at the end of a cell - credit to Timothy Rylatt
        Next j
    Next i

    'Sort the table
    Dim r As Long
    For i = 1 To UBound(Items, 1) - 2
        For r = i   2 To UBound(Items, 1)
            If Items(i, 1) = Items(r, 1) Then Call ArrayRowShift(Items, r, i   1)
        Next r
    Next i
    
    'Output the table
    For i = 1 To sortTable.Rows.Count
        For j = 1 To sortTable.Columns.Count
            sortTable.Cell(i, j).Range.Text = Items(i, j)
        Next j
    Next i
End Sub
Sub ArrayRowShift(ByRef Arr As Variant, RowIndex As Long, MoveTo As Long)
    'For 2D arrays, takes an array row, moves it to the specified index, returns the shifted array
    If RowIndex = MoveTo Then Exit Sub
    Dim tmpRow() As Variant
    ReDim tmpRow(LBound(Arr, 2) To UBound(Arr, 2))
    For j = LBound(Arr, 2) To UBound(Arr, 2)
        tmpRow(j) = Arr(RowIndex, j)
    Next j
    If RowIndex < MoveTo Then
        For i = RowIndex   1 To MoveTo
            For j = LBound(Arr, 2) To UBound(Arr, 2)
                Arr(i - 1, j) = Arr(i, j)
            Next j
        Next i
    Else
        For i = RowIndex To MoveTo   1 Step -1
            For j = LBound(Arr, 2) To UBound(Arr, 2)
                Arr(i, j) = Arr(i - 1, j)
            Next j
        Next i
    End If
    For j = LBound(Arr, 2) To UBound(Arr, 2)
        Arr(MoveTo, j) = tmpRow(j)
    Next j
End Sub
 

Я беру текст таблицы в массив, переупорядочиваю элементы в массиве с помощью VBA, затем вставляю его обратно в таблицу. Это работает для любого размера таблицы в Word (1D или 2D).

Если вы хотите настроить правила сортировки, вам нужно отредактировать строку If Items(i, 1) = Items(r, 1) Then . Возможно, вы захотите добавить LCase оба, чтобы убрать чувствительность к регистру. Или Trim , чтобы убедиться, что лишний пробел не мешает совпадениям.

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

1. Тоддлсон, я просто хотел бы сказать………… ты — абсолютный Бог!!!!! Этот код, который вы скомпилировали так скоро после того, как я опубликовал свой вопрос, работает как мечта!!! Я размышлял о том, как это сделать, около года, и никто не мог помочь. me. Я не могу отблагодарить вас за то, что вы сделали!

2. Еще пара вещей: каждый раз, когда вы используете макрос, он добавляет дополнительную строку пробела в каждую ячейку. как я могу предотвратить это и как сохранить исходное форматирование ячеек после использования макроса?

3. @KevinO — проблема связана с хранением sortTableCell(i,j).Range.Text в массиве. Для ячейки таблицы Range.Text содержит два непечатаемых символа, знак абзаца и знак конца ячейки. Вы можете проверить это, создав документ с пустой таблицей и введя ?Len(ActiveDocument.Tables(1).Cell(1,1).Range.Text) в немедленном окне. Чтобы устранить проблему, просто удалите лишние символы — Left(sortTable.Cell(i, j).Range.Text, Len(sortTable.Cell(i, j).Range.Text) - 2)

4. Большое вам спасибо, Тим. Я новичок в этой области и нахожу все это увлекательным. Мне нужно многому научиться, и я действительно ценю время, которое вы все потратили, чтобы объяснить и помочь мне в моем затруднительном положении. Мне потребовалось некоторое время, чтобы разобраться в вашем объяснении, но наконец-то наступил момент лампочки!

5. @KevinO мой код был обновлен для решения этой проблемы. Если этот код отвечает на ваш вопрос, я был бы признателен за зеленую галочку в моем сообщении. Спасибо!