Sub Macros() Dim i As Long, j As Long, jj As Long WS_count = ActiveWorkbook.Worksheets.Count jj = 0 For i = 3 To WS_count For j = 3 + jj To WS_count nj = CInt(Mid(Worksheets(j).Name, 6, Len(Worksheets(j).Name) - 6)) ni = CInt(Mid(Worksheets(i).Name, 6, Len(Worksheets(i).Name) - 6)) If nj < ni Then Worksheets(j).Move Before:=Worksheets(i) End If Next j jj = jj + 1 Next i End Sub
[/vba]
А если так [vba]
Code
Sub Macros() Dim i As Long, j As Long, jj As Long WS_count = ActiveWorkbook.Worksheets.Count jj = 0 For i = 3 To WS_count For j = 3 + jj To WS_count nj = CInt(Mid(Worksheets(j).Name, 6, Len(Worksheets(j).Name) - 6)) ni = CInt(Mid(Worksheets(i).Name, 6, Len(Worksheets(i).Name) - 6)) If nj < ni Then Worksheets(j).Move Before:=Worksheets(i) End If Next j jj = jj + 1 Next i End Sub
AlexM, посмотрел, спасибо за помощь. Подходит для мойх целей, жаль что нет возможности в окне Project-VBA выстроить листы. Мне бы еще закомментировать все это. Если, не трудно, конечно.
AlexM, посмотрел, спасибо за помощь. Подходит для мойх целей, жаль что нет возможности в окне Project-VBA выстроить листы. Мне бы еще закомментировать все это. Если, не трудно, конечно.Мур
Sub Macros() Dim i As Long, j As Long, jj As Long ' описание переменных WS_count = ActiveWorkbook.Worksheets.Count ' определение количества листов в книге jj = 0 ' эта строка необязательна, так как при объявлении переменной она равна нулю For i = 3 To WS_count ' цикл по листам начиная с 3-го For j = 3 + jj To WS_count ' цикл по листам начиная с 3-го nj = CInt(Mid(Worksheets(j).Name, 6, Len(Worksheets(j).Name) - 6)) ' выделение номера из названия листа ni = CInt(Mid(Worksheets(i).Name, 6, Len(Worksheets(i).Name) - 6)) ' выделение номера из названия листа If nj < ni Then ' если условие выполняется ... Worksheets(j).Move Before:=Worksheets(i) ' перемещаем лист с меньшим номером вперед. End If Next j jj = jj + 1 ' переменная нужна для того, чтобы не обрабатывать уже перемещенные листы Next i End Sub
[/vba]
Код можно немного сократить [vba]
Code
jj = 0 'убрать строку ' три строки условия If nj < ni Then Worksheets(j).Move Before:=Worksheets(i) End If ' заменить одной If nj < ni Then Worksheets(j).Move Before:=Worksheets(i)
[/vba]
[vba]
Code
Sub Macros() Dim i As Long, j As Long, jj As Long ' описание переменных WS_count = ActiveWorkbook.Worksheets.Count ' определение количества листов в книге jj = 0 ' эта строка необязательна, так как при объявлении переменной она равна нулю For i = 3 To WS_count ' цикл по листам начиная с 3-го For j = 3 + jj To WS_count ' цикл по листам начиная с 3-го nj = CInt(Mid(Worksheets(j).Name, 6, Len(Worksheets(j).Name) - 6)) ' выделение номера из названия листа ni = CInt(Mid(Worksheets(i).Name, 6, Len(Worksheets(i).Name) - 6)) ' выделение номера из названия листа If nj < ni Then ' если условие выполняется ... Worksheets(j).Move Before:=Worksheets(i) ' перемещаем лист с меньшим номером вперед. End If Next j jj = jj + 1 ' переменная нужна для того, чтобы не обрабатывать уже перемещенные листы Next i End Sub
[/vba]
Код можно немного сократить [vba]
Code
jj = 0 'убрать строку ' три строки условия If nj < ni Then Worksheets(j).Move Before:=Worksheets(i) End If ' заменить одной If nj < ni Then Worksheets(j).Move Before:=Worksheets(i)
Мурат, в окне браузера VBE листы и вообще все объекты автоматически сортируются по их ИМЕНИ (CodeName), задаваемому в первой строке листа свойств объекта (F4), обозванной там как (Name) Программно изменить CodeName достаточно сложно (хотя и возможно - я где-то видел как, кажется EducatedFool, это делал в примерах). А вот ручками изменить в свойствах - элементарно (только, конечно, не для 150 листов ). К стати, в своих проектах я иногда использую ручное изменение CodeName именно для того, чтобы код, "заточенный" под страницу, продолжал работать даже если какой-нибудь шибко дюже грамотный пользователь переименует ярлык (изменит Name) нужного для расчётов листа. Обращение к такому нестандартно переименованному листу по его CodeName даже проще, чем обращение по его Name (имени, написанному на ярлыке листа). Например, Вы листу, отображавшемуся в VBE как Лист100(Исходные данные), изменили CodeName на MySheet. После этого в броузере этот лист "всплывёт" над всеми листами, т.к. получит название MySheet(Исходные данные). Если ранее обращаться из прочих модулей проекта к диапазону, например, А1 этого листа нужно было по Name как [vba]
Code
WorkSheets("Исходные данные").Range("A1")
[/vba] или по его CodeName как [vba]
Code
Лист100.Range("A1")
[/vba] (приходилось менять рус-лат при вводе), то после переименования Вы сможете обращаться к листу как [vba]
Code
MySheet.Range("A1")
[/vba]
Quote (Мур)
Возможна ли вообще сортировка в окне Project-VBA?
Мурат, в окне браузера VBE листы и вообще все объекты автоматически сортируются по их ИМЕНИ (CodeName), задаваемому в первой строке листа свойств объекта (F4), обозванной там как (Name) Программно изменить CodeName достаточно сложно (хотя и возможно - я где-то видел как, кажется EducatedFool, это делал в примерах). А вот ручками изменить в свойствах - элементарно (только, конечно, не для 150 листов ). К стати, в своих проектах я иногда использую ручное изменение CodeName именно для того, чтобы код, "заточенный" под страницу, продолжал работать даже если какой-нибудь шибко дюже грамотный пользователь переименует ярлык (изменит Name) нужного для расчётов листа. Обращение к такому нестандартно переименованному листу по его CodeName даже проще, чем обращение по его Name (имени, написанному на ярлыке листа). Например, Вы листу, отображавшемуся в VBE как Лист100(Исходные данные), изменили CodeName на MySheet. После этого в броузере этот лист "всплывёт" над всеми листами, т.к. получит название MySheet(Исходные данные). Если ранее обращаться из прочих модулей проекта к диапазону, например, А1 этого листа нужно было по Name как [vba]
Code
WorkSheets("Исходные данные").Range("A1")
[/vba] или по его CodeName как [vba]
Code
Лист100.Range("A1")
[/vba] (приходилось менять рус-лат при вводе), то после переименования Вы сможете обращаться к листу как [vba]
Если же нужно просто отсортировать ярлыки листов, то я пользуюсь таким кодом: [vba]
Code
Sub СОРТИРОВАТЬ_ЛИСТЫ() ' сортировка листов в активной книге (не сортирует скрытые листы) If ActiveWorkbook.ProtectStructure Then _ MsgBox "Структура книги " & ActiveWorkbook.Name & " защищена. Сортировка листов невозможна.", vbCritical: Exit Sub On Error Resume Next ' ошибка может возникнуть при наличии скрытых листов Dim i%, j% Application.ScreenUpdating = False: Application.EnableEvents = False With ActiveWorkbook For i = 1 To .Sheets.Count - 1 For j = i + 1 To .Sheets.Count If UCase(.Sheets(i).Name) > UCase(.Sheets(j).Name) Then .Sheets(j).Move Before:=.Sheets(i) Next j Next i End With Application.EnableEvents = True: Application.ScreenUpdating = True End Sub
[/vba] но он сортирует именно ярлыки листов. При этом в браузере проектов VBE они останутся в прежнем порядке - с сортировкой по .CodeName
Если же нужно просто отсортировать ярлыки листов, то я пользуюсь таким кодом: [vba]
Code
Sub СОРТИРОВАТЬ_ЛИСТЫ() ' сортировка листов в активной книге (не сортирует скрытые листы) If ActiveWorkbook.ProtectStructure Then _ MsgBox "Структура книги " & ActiveWorkbook.Name & " защищена. Сортировка листов невозможна.", vbCritical: Exit Sub On Error Resume Next ' ошибка может возникнуть при наличии скрытых листов Dim i%, j% Application.ScreenUpdating = False: Application.EnableEvents = False With ActiveWorkbook For i = 1 To .Sheets.Count - 1 For j = i + 1 To .Sheets.Count If UCase(.Sheets(i).Name) > UCase(.Sheets(j).Name) Then .Sheets(j).Move Before:=.Sheets(i) Next j Next i End With Application.EnableEvents = True: Application.ScreenUpdating = True End Sub
[/vba] но он сортирует именно ярлыки листов. При этом в браузере проектов VBE они останутся в прежнем порядке - с сортировкой по .CodeNameAlex_ST
С уважением, Алексей MS Excel 2003 - the best!!!
Сообщение отредактировал Alex_ST - Четверг, 13.12.2012, 14:38
Если нужно сортировать ещё и скрытые листы, то[vba]
Code
Sub СОРТИРОВАТЬ_ВСЕ_ЛИСТЫ() ' сортировка листов в активной книге (сортирует даже скрытые листы) If ActiveWorkbook.ProtectStructure Then _ MsgBox "Структура книги " & ActiveWorkbook.Name & " защищена. Сортировка листов невозможна.", vbCritical: Exit Sub Application.ScreenUpdating = False: Application.EnableEvents = False Dim iSht As Worksheet, oDict As Object, i%, j% Set oDict = CreateObject("Scripting.Dictionary") For Each iSht In ActiveWorkbook.Sheets ' запомнить состояние видимости каждого из листов и сделать все видимыми oDict.Item(iSht.Name) = iSht.Visible: iSht.Visible = True Next With ActiveWorkbook ' сортировка видимых листов For i = 1 To .Sheets.Count - 1 For j = i + 1 To .Sheets.Count If UCase(.Sheets(i).Name) > UCase(.Sheets(j).Name) Then .Sheets(j).Move Before:=.Sheets(i) Next j Next i End With For Each iSht In ActiveWorkbook.Sheets ' восстановить исходное состояние видимости каждого из листов iSht.Visible = oDict.Item(iSht.Name) Next Application.EnableEvents = True: Application.ScreenUpdating = True End Sub
[/vba]
Если нужно сортировать ещё и скрытые листы, то[vba]
Code
Sub СОРТИРОВАТЬ_ВСЕ_ЛИСТЫ() ' сортировка листов в активной книге (сортирует даже скрытые листы) If ActiveWorkbook.ProtectStructure Then _ MsgBox "Структура книги " & ActiveWorkbook.Name & " защищена. Сортировка листов невозможна.", vbCritical: Exit Sub Application.ScreenUpdating = False: Application.EnableEvents = False Dim iSht As Worksheet, oDict As Object, i%, j% Set oDict = CreateObject("Scripting.Dictionary") For Each iSht In ActiveWorkbook.Sheets ' запомнить состояние видимости каждого из листов и сделать все видимыми oDict.Item(iSht.Name) = iSht.Visible: iSht.Visible = True Next With ActiveWorkbook ' сортировка видимых листов For i = 1 To .Sheets.Count - 1 For j = i + 1 To .Sheets.Count If UCase(.Sheets(i).Name) > UCase(.Sheets(j).Name) Then .Sheets(j).Move Before:=.Sheets(i) Next j Next i End With For Each iSht In ActiveWorkbook.Sheets ' восстановить исходное состояние видимости каждого из листов iSht.Visible = oDict.Item(iSht.Name) Next Application.EnableEvents = True: Application.ScreenUpdating = True End Sub
With ActiveWorkbook For Each sh In .Sheets i = i + 1 .VBProject.VBComponents(sh.CodeName).Name = "sh" & i '& "_" & sh.Name Next End With
[/vba]
! необходимо: прицепить ссылку Microsoft Visual Basic for Applications Extensibility 5.3 (Tools/References...) доверить доступ к объектной модели проектов:
сортируешь листы и [vba]
Code
With ActiveWorkbook For Each sh In .Sheets i = i + 1 .VBProject.VBComponents(sh.CodeName).Name = "sh" & i '& "_" & sh.Name Next End With
[/vba]
! необходимо: прицепить ссылку Microsoft Visual Basic for Applications Extensibility 5.3 (Tools/References...) доверить доступ к объектной модели проектов: Саня
Саня, спасибо! Не пришлось мне искать, где я у Игоря (EducatedFool) на сайте видел работу с CodeName. Давно хотел себе примерчик состряпать. Вот теперь можно сначала отсортировать листы по Name, а потом пройтись по индексу и переименовать CodeName по возрастанию (а может быть и за один проход сделать удастся, хотя, наверное, всё-таки сортировку листов "пузырьком"лучше один раз провести). Сегодня уже не успею слепить пример, а завтра меня засылают на весь день на обучение по PowerPoint'у (нафиг он мне не нужен, а деваться некуда - меня записали не спрашивая). Но, надеюсь, в начале следующей недели я его таки-слеплю чтобы к себе в копилку положить.
Саня, спасибо! Не пришлось мне искать, где я у Игоря (EducatedFool) на сайте видел работу с CodeName. Давно хотел себе примерчик состряпать. Вот теперь можно сначала отсортировать листы по Name, а потом пройтись по индексу и переименовать CodeName по возрастанию (а может быть и за один проход сделать удастся, хотя, наверное, всё-таки сортировку листов "пузырьком"лучше один раз провести). Сегодня уже не успею слепить пример, а завтра меня засылают на весь день на обучение по PowerPoint'у (нафиг он мне не нужен, а деваться некуда - меня записали не спрашивая). Но, надеюсь, в начале следующей недели я его таки-слеплю чтобы к себе в копилку положить.Alex_ST
С уважением, Алексей MS Excel 2003 - the best!!!
Сообщение отредактировал Alex_ST - Четверг, 13.12.2012, 21:59