Страницы: 1 2 След.
RSS
Сортировка цифр с буквами
 
Как можно с помощью макроса отсортировывать список из серийных номеров, если в нем периодически появляются те же номера, но с буквой в конце?  
Т.е. есть возникает список:  
511  
4512  
4513  
511A  
4512B,    
который должен быть отсотирован так (номера должны идти по порядку, а затем те же номера с буквами):  
 
511  
511A  
4512  
4512B  
4513     Обычная сортировка загоняет все номера с буквами в конец списка...
 
а надо куда?
 
А надо, чтобы за каждым номером шел такой же номер с дополнительной буквой в конце
 
нужно, чтобы артикул воспринимался эксом как текст в любом случае  
например, вставьте " " перед цифрами и сортируйте
 
Увы, не помогло... С апострофом впереди тоже...
 
странно
 
С апострофом нормально сортирует, только не нужно добавлять лишних пробелов :)
 
Нет, извиняюсь, не правильно.  
А вот если вместо пробела добавить 0 (т.е.0511, 0511A) - то ОК.
 
{quote}{login=andre532}{date=30.08.2012 11:10}{thema=}{post}Увы, не помогло... С апострофом впереди тоже...{/post}{/quote}  
try this  
=MID(TRIM(I2),1,COUNT(IF(--ISNUMBER(--MID(TRIM(I2),ROW(INDIRECT("1:"&LEN(I2))),1))*ROW(INDIRECT("1:"&LEN(I2)))<>0,--ISNUMBER(--MID(TRIM(I2),ROW(INDIRECT("1:"&LEN(I2))),1))*ROW(INDIRECT("1:"&LEN(I2))))))
MyExcelWorld One World One Dream!
Microsoft MVP Excel from 2012
Aydin Aliyev
 
Да, там действительно много странного... Я скопировал номера из реальной базы, м.б. это как-то связано с форматом ячеек? (Там формат "# ###")  
 
(Кстати пробелы впереди легко исчезают, если выделить ячейку)  
 
А можно ли все-таки как-то макросом решить эту проблему? Чтобы Excel при сортировке понимала, что впереди - это цифры и нужно сначала отсортировать по ним?
 
Пардон, не приложил файл -вот он.  
С нулем не помогло....Буду сейчас пробовать длинную формулу...
 
Вариант
 
Интересное решение MCH.  
Почему-то при пошаговом прогоне ничего не происходит...?  
Я тут пока форум висел (у всех висел?) такое написал:  
 
Можно вероятно написать для доп.столбца UDF, которая будет возвращать нормальные числа - целые для "голых" чисел и дробные для чисел с буквами (значение дроби получить анализируя буквы).  
Вероятно, лучше код на RegExp - это не ко мне :(  
А может даже и стандартными функциями спецы выкрутятся? :)  
Затем по этому столбцу сортировать.
 
MCH буквы по алфавиту не сортирует! :(  
Мой алгоритм должен помочь :)
 
{quote}{login=Hugo}{date=30.08.2012 02:19}{thema=}{post}MCH буквы по алфавиту не сортирует! :({/post}{/quote}  
Я макрорекордером записал сортировку по одному столбцу, а нужно было по двум, вначале по B затем по A  
в примере не было различных букв для одного и того же числа, поэтому как то упустил
 
.
 
МСН, всё заработало! Громадное спасибо!  
У меня на самом деле довольно большая база данных - 15000 строк и 75 столбцов.  
Работа макроса занимает около 40 сек, но это мелочи.  
Насколько я понимаю, мне для его работы  необходимо превратить макрос в функцию и программно создавать доп. столбец рядом, а потом его удалять.  
Еще парочку маленьких вопросов:  
1) Как изменить макрос, чтобы он сортировал всю базу, а не только номера?  
2) Как изменить макрос, чтобы он сортировал затем и по буквам?  
3) Не знаете ли вы случайно, какой задать формат столбцу, чтобы номера с буквами выглядели так же, как и с цифрами (сейчас у меня "# ###" - номера без букв выглядят так: 14 534, а с буквами 14534A (но это, конечно, не существенно...)
 
andre, а у Вас в конце может быть только одна буква или возможно несколько? С одной можно будет просто сделать и точно быстрее 40 сек, а с несколькими сложнее...)
 
В конце только одна буква: A,B,C,D,E... Причем буквы появляются по порядку для каждого номера
 
По порядку или нет - это неважно. Предлагаю вот такой вариант (красивости от ув. MCH, надеюсь он не возражает:).  
ЗЫ. Если используются только прописные англ. буквы, в коде 1000 можно заменить на 100.  
<EM><STRONG>Файл удален</STRONG> - велик размер - [<STRONG>МОДЕРАТОРЫ</STRONG>]</EM>
 
Такой вариант:  
 
Sub MySort()  
     
   ' --> Константы для настройки (вписать реальные)  
   Const DataTopRow = "A2:BW2" ' первая строка с данными  
   Const SortColumn = "A"      ' сортируемый столбец  
   ' <-- Конец констант для настроки  
     
   Dim c&, cs&, r&, rs&, vt&  
   Dim a(), x  
   Dim LastCell As Range, Rng As Range  
     
   ' Определить диапазон данных  
   With ActiveSheet.Range(DataTopRow)  
     c = .EntireRow.Columns(SortColumn).Column - .Column + 1  
     Set LastCell = .Parent.Cells.SpecialCells(xlCellTypeLastCell)  
     rs = LastCell.Row - .Row + 1  
     If rs < 2 Then MsgBox "Нет данных": Exit Sub  
     Set Rng = .Resize(rs)  
   End With  
     
   ' Создать в массиве a() числовыне значения сортируемого столбца  
   a() = Rng.Columns©.Value  
   For r = 1 To rs  
     If VarType(a(r, 1)) = vbString Then  
       a(r, 1) = Val(a(r, 1))  
     End If  
   Next  
     
   ' Скопировать a() во вспом. столбец правее рабочего диапазона, отсортировать и очистить  
   Application.ScreenUpdating = False  
   With Range(Rng, LastCell)  
     cs = .Columns.Count + 1  
     With .Resize(, cs)  
       .Columns(cs).Value = a  
       .Sort .Cells(1, cs), xlAscending, .Cells(1, c), , xlAscending, Header:=xlNo  
       .Columns(cs).ClearContents  
     End With  
   End With  
   Application.ScreenUpdating = True  
     
   ' Восстановить UsedRange  
   With Rng.Parent.UsedRange: End With  
     
End Sub
 
Влад, не сортируются столбцы после пустых колонок...  
По-видимому сортируется только непрерывная область, а в реальной базе есть пробелы в данных...Выделение базы перед сортировкой не помогает...
 
ZVI, всё отлично работает! Большое спасибо!  
 
Может быть вы знаете ответ на вопрос, который я уже задавал:  
 
Не знаете ли вы случайно, какой задать формат столбцу, чтобы номера с буквами выглядели так же, как и с цифрами (сейчас у меня "# ###" - номера без букв выглядят так: 14 534, а с буквами 14534A (но это, конечно, не существенно...)
 
Немного исправил код с учетом Ваших пожеланий (работает без доп. столбца). Прошу прощения за предыдущий пост, не обратил внимания, что файл "распух" после экспериментов)  
ЗЫ. Формат ячеек "# ###" замените на Общий.
 
Вот мне счастье привалило-то!  
Уважаемые ZVI и Влад, еще раз спасибо!  
Оба кода очень быстро работают, почти мгновенно (кажется код Влада на пару миллисекунд дольше (а может, показалось:)).  
 
Тему считаю закрытой. Всем приятной ночи!
 
{quote}{login=}{date=30.08.2012 09:16}{thema=}{post}Не знаете ли вы случайно, какой задать формат столбцу, чтобы номера с буквами выглядели так же, как и с цифрами (сейчас у меня "# ###" - номера без букв выглядят так: 14 534, а с буквами 14534A (но это, конечно, не существенно...){/post}{/quote}  
Текст можно так отформатировать только макросом, при этом лучше использовать моноширинный шрифт, например, Courier New. Код такой:  
 
Sub MySort()  
 
 ' --> Константы для настройки (вписать реальные)  
 Const DataTopRow = "A2:BW2" ' первая строка с данными  
 Const SortColumn = "A"      ' сортируемый столбец  
 ' <-- Конец констант для настройки  
 
 Dim c&, cs&, r&, rs&, s$  
 Dim a(), b()  
 Dim LastCell As Range, Rng As Range  
 
 ' Определить диапазон данных  
 With ActiveSheet.Range(DataTopRow)  
   c = .EntireRow.Columns(SortColumn).Column - .Column + 1  
   Set LastCell = .Parent.Cells.SpecialCells(xlCellTypeLastCell)  
   rs = LastCell.Row - .Row + 1  
   If rs < 2 Then MsgBox "Нет данных": Exit Sub  
   Set Rng = .Resize(rs)  
 End With  
 
 ' Создать в a() числовые значения сортируемого столбца, а в b()-отформатированные  
 a() = Rng.Columns©.Value  
 b() = a()  
 For r = 1 To rs  
   If VarType(a(r, 1)) = vbString Then  
     s = Right$(a(r, 1), 1)  
     a(r, 1) = Val(a(r, 1))  
     If s >= "A" Then  
       b(r, 1) = Format(a(r, 1), "# ###") & s  
       a(r, 1) = a(r, 1) + Asc(s) * 0.001  
     End If  
   End If  
 Next  
 
 ' Отключить перерисовку экрана  
 Application.ScreenUpdating = False  
   
 ' Отформатировать сортируемый столбец, скопировав в него b()  
 With Rng.Columns©  
   .Value = b()  
   .Font.Name = "Courier New" ' моноширинный шрифт  
   .HorizontalAlignment = xlRight  
   .NumberFormat = "# ###_."  
 End With  
   
 ' Скопировать a() правее рабочего диапазона, отсортировать и очистить  
 With Range(Rng, LastCell)  
   cs = .Columns.Count + 1  
   With .Resize(, cs)  
     .Columns(cs).Value = a  
     .Sort .Cells(1, cs), xlAscending, Header:=xlNo  
     .Columns(cs).ClearContents  
   End With  
 End With  
   
 ' Включить перерисовку экрана  
 Application.ScreenUpdating = True  
 
 ' Восстановить UsedRange  
 With Rng.Parent.UsedRange: End With  
 
End Sub
 
упс...  
или я ещё не проснулся, или ничего не понял :(  
Владимир, вот это как и зачем?  
{quote}{login=ZVI}{date=31.08.2012 01:47}{thema=Re: }{post}  ' Восстановить UsedRange  
 With Rng.Parent.UsedRange: End With{/post}{/quote}  
UsedRange - свойство read-only ведь.  
изменить его нельзя.  
тогда что такое "восстановить" и чего мы добиваемся таким "пустым" оператором?
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
Александр, в коде используется SpecialCells(xlCellTypeLastCell) – последняя используемая ячейка, на которую устанавливается курсор по нажатию Ctrl-End.    
 
Если где-нибудь за пределами используемых ячеек (UsedRange), например, запишем в ячейку что-нибудь, а затем очистим ее содержимое, то по Ctrl-End мы уже попадем в эту очищенную (новую последнюю) ячейку. Если сохранить книгу, то последняя ячейка возвращается на свое законное место, то же самое обычно происходит при обращении к UsedRange.  
 
Код для проверки:  
 
Sub Test()  
 With Workbooks.Add.Sheets(1)  
     
   ' Добавим данные на чистый лист  
   .Range("D2:E5") = "UsedRange"  
     
   ' Проверим адрес последней ячейки  
   Debug.Print 1, .Cells.SpecialCells(xlCellTypeLastCell).Address  
     
   ' Запишем и удалим что-нибудь в ячейке правее и ниже данных  
   .Range("F10").Value = 1  
   .Range("F10").ClearContents  
     
   ' Адрес последней ячейки изменится  
   Debug.Print 2, .Cells.SpecialCells(xlCellTypeLastCell).Address  
     
   ' Восстановим правильное положение последней ячейки, просто обратившись к UsedRange  
   With .UsedRange: End With  
     
   ' Адрес последней ячейки вернется на свое место  
   Debug.Print 3, .Cells.SpecialCells(xlCellTypeLastCell).Address  
     
 End With  
End Sub
 
умгу...  
восстанавливает.  
спасибо и за пояснения, и за пример.  
 
но... что-то пакостное в таком поведении Excel'я есть.  
почему он не может корректно и оперативно отслеживать реальный диапазон UsedRange?  
и где ещё об этом можно узнать, кроме как от MVP?..  
:)  
 
офф-пс. я сейчас вспоминаю, какие макросы я писал три года назад и был очень доволен, что за 5-10 минут они выполняют то, что другие делают пол-дня... смешно становится. оказывается. макросы могут работать десятые доли секунды и делать при этом гораздо больше и правильнее.  
спасибо форуму - раньше я думал, что я вумный, а теперь оказывается - практически дурак :)
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
Владимир,  
в данном контексте можно написать просто  
 
.UsedRange  
 
, ничего с ним не делая.  
То есть можно использовать конструкцию Sheets(x).UsedRange или ActiveSheet.UsedRange.  
Но в коде листа нельзя написать просто Me.UsedRange - Compile error: Invalid use of property. Приходится писать  
 
With Me.UsedRange: End With  
или  
Sheets(Me.Name).UsedRange  
 
Есть этому феномену какое-нибудь объяснение?
Страницы: 1 2 След.
Наверх