Существует проблема. Список сотрудников (более 200 человек) в формате "И. О. Фамилия", т.е. сначала идут инициалы, затем фамилия.
Задача - отсортировать список по алфавиту по критерию фамилии средствами VBA. Знаю, что можно разделить данные по столбцам, потом сортировать диапазон, потом собрать все снова в один столбец, но это "костылинг". Есть идеи?
Aiden_ko написал: отсортировать список ... средствами VBA
Есть решение на PQ. Надо? или только vba рассматриваете? Вдруг, кому-то понадобится...
Код
let
Источник = Excel.CurrentWorkbook(){[Name="Таблица1"]}[Content],
#"Вставленный текст после разделителя" = Table.AddColumn(Источник, "Текст после разделителя", each Text.AfterDelimiter([Столбец1], ". ", {0, RelativePosition.FromEnd}), type text),
#"Сортированные строки" = Table.Sort(#"Вставленный текст после разделителя",{{"Текст после разделителя", Order.Ascending}}),
#"Удаленные столбцы" = Table.RemoveColumns(#"Сортированные строки",{"Текст после разделителя"})
in
#"Удаленные столбцы"
Sub sort()
Dim oRecordSet As Object, oConn As Object
sTblQuery = "[" & Sheet1.Name & "$" & Sheet1.Range("D5:d10").Address(False, False) & "]"
Set oRecordSet = CreateObject("ADODB.Recordset")
Set oConn = CreateObject("ADODB.Connection")
oRecordSet.CursorLocation = 3 'adUseClient
sSQL_text = "SELECT * FROM " & sTblQuery & " ORDER BY MID(F1,7,255)"
sConnStr = "Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=NO"";"
oConn.Open sConnStr
oRecordSet.Open sSQL_text, oConn
ReDim Res(1 To oRecordSet.RecordCount, 1 To 1)
For i = 1 To UBound(Res)
Res(i, 1) = oRecordSet.Fields("F1").Value
oRecordSet.movenext
Next
Sheet1.Range("F5:F10") = Res
'Sheet1.Range("D5:d10")=Res
End Sub
Sub SortBySurname()
Dim arrNames(), i As Long, lngSpacePos As Long, strName As String
With ActiveSheet
arrNames = .Range("D5:D" & .Cells(.Rows.Count, "D").End(xlUp).Row).Value2
For i = 1 To UBound(arrNames)
strName = Application.Trim(arrNames(i, 1))
lngSpacePos = InStrRev(strName, " ")
arrNames(i, 1) = Mid(strName, lngSpacePos + 1, Len(strName)) & " " & Left(strName, lngSpacePos - 1)
Next i
Call uSort(arrNames, 1)
For i = 1 To UBound(arrNames)
lngSpacePos = InStr(1, arrNames(i, 1), " ", vbTextCompare)
arrNames(i, 1) = Left(arrNames(i, 1), lngSpacePos) & Mid(arrNames(i, 1), lngSpacePos, Len(arrNames(i, 1)))
Next i
.Range("E5").Resize(UBound(arrNames, 1), 1).Value2 = arrNames
End With
End Sub
Private Sub uSort(ByRef vArray(), Optional ColumnNumberToSortBy As Long = 1)
Dim tempVal As String, iRow As Long, lowBound As Long, iCol As Long, i As Long
If Not IsArray(vArray) Then Exit Sub
lowBound = LBound(vArray)
i = lowBound
For iRow = lowBound + 1 To UBound(vArray)
If vArray(iRow, ColumnNumberToSortBy) < vArray(i, ColumnNumberToSortBy) Then
For iCol = 1 To UBound(vArray, 2)
tempVal = vArray(i, iCol)
vArray(i, iCol) = vArray(iRow, iCol)
vArray(iRow, iCol) = tempVal
Next
iRow = i - 1
i = iRow - 1
If iRow < lowBound Then
i = iRow
iRow = lowBound
End If
End If
i = i + 1
Next iRow
End Sub
Aiden_ko, ))) я так и хотел сделать, но видно отвлёкся, надо поправить 1 строку, вот код
Код
Sub SortBySurname()
Dim arrNames(), i As Long, lngSpacePos As Long, strName As String
With ActiveSheet
arrNames = .Range("D5:D" & .Cells(.Rows.Count, "D").End(xlUp).Row).Value2
For i = 1 To UBound(arrNames)
strName = Application.Trim(arrNames(i, 1))
lngSpacePos = InStrRev(strName, " ")
arrNames(i, 1) = Mid(strName, lngSpacePos + 1, Len(strName)) & " " & Left(strName, lngSpacePos - 1)
Next i
Call uSort(arrNames, 1)
For i = 1 To UBound(arrNames)
lngSpacePos = InStr(1, arrNames(i, 1), " ", vbTextCompare)
arrNames(i, 1) = Mid(arrNames(i, 1), lngSpacePos + 1, Len(arrNames(i, 1))) & " " & Left(arrNames(i, 1), lngSpacePos)
Next i
.Range("E5").Resize(UBound(arrNames, 1), 1).Value2 = arrNames
End With
End Sub
Private Sub uSort(ByRef vArray(), Optional ColumnNumberToSortBy As Long = 1)
Dim tempVal As String, iRow As Long, lowBound As Long, iCol As Long, i As Long
If Not IsArray(vArray) Then Exit Sub
lowBound = LBound(vArray)
i = lowBound
For iRow = lowBound + 1 To UBound(vArray)
If vArray(iRow, ColumnNumberToSortBy) < vArray(i, ColumnNumberToSortBy) Then
For iCol = 1 To UBound(vArray, 2)
tempVal = vArray(i, iCol)
vArray(i, iCol) = vArray(iRow, iCol)
vArray(iRow, iCol) = tempVal
Next
iRow = i - 1
i = iRow - 1
If iRow < lowBound Then
i = iRow
iRow = lowBound
End If
End If
i = i + 1
Next iRow
End Sub
ADO на малых объемах проигрывает, наверное, из-за CreateObject. А если сделать раннее связывание (добавить ссылку на библиотеку), то и на малых объемах будет быстрее P.s. но надо следить, чтобы фамилия всегда начиналась с 7-го символа, и надеется, что никто не поставит где-нибудь 2 пробела вместо одного, а так же не забудет поставить 1 пробел между именем и отчеством