Добрый день, есть журнал учеников, каждый класс на отдельном листе, задача состоит в том чтобы вывести данные всех классов на один лист согласно шаблону, и если количество учеников изменится в классах нужно чтобы классы были по порядку без пустых строк. Пример во вложении.
Добрый день, есть журнал учеников, каждый класс на отдельном листе, задача состоит в том чтобы вывести данные всех классов на один лист согласно шаблону, и если количество учеников изменится в классах нужно чтобы классы были по порядку без пустых строк. Пример во вложении.udjin
Добрый день! Вариант (запускать по Alt+F8, результат на листе с именем Шаблон) : [vba]
Код
Sub pupils() Dim sh As Worksheet, lr As Long, LastRow As Long, pupilsCount As Integer, pupilsRange As Range Dim AppScrUpd AppScrUpd = Application.ScreenUpdating Application.ScreenUpdating = False
LastRow = 1 ThisWorkbook.Worksheets("Шаблон").Cells.Clear For Each sh In ThisWorkbook.Worksheets If sh.Name <> "Шаблон" Then With sh lr = .Cells(.Rows.Count, 1).End(xlUp).Row Set pupilsRange = .Range("A2:B" & lr) pupilsCount = lr - 1 With ThisWorkbook.Worksheets("Шаблон") .Cells(LastRow, 1) = sh.Name & " ----> " & pupilsCount & " учеников" .Cells(LastRow, 1).Interior.Color = 4697456 With .Range(.Cells(LastRow, 1), .Cells(LastRow, 9)) .Merge .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter .Font.Bold = True End With pupilsRange.Copy .Cells(LastRow + 1, 1) LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
End With End With End If Next sh Application.ScreenUpdating = AppScrUpd End Sub
[/vba]
Добрый день! Вариант (запускать по Alt+F8, результат на листе с именем Шаблон) : [vba]
Код
Sub pupils() Dim sh As Worksheet, lr As Long, LastRow As Long, pupilsCount As Integer, pupilsRange As Range Dim AppScrUpd AppScrUpd = Application.ScreenUpdating Application.ScreenUpdating = False
LastRow = 1 ThisWorkbook.Worksheets("Шаблон").Cells.Clear For Each sh In ThisWorkbook.Worksheets If sh.Name <> "Шаблон" Then With sh lr = .Cells(.Rows.Count, 1).End(xlUp).Row Set pupilsRange = .Range("A2:B" & lr) pupilsCount = lr - 1 With ThisWorkbook.Worksheets("Шаблон") .Cells(LastRow, 1) = sh.Name & " ----> " & pupilsCount & " учеников" .Cells(LastRow, 1).Interior.Color = 4697456 With .Range(.Cells(LastRow, 1), .Cells(LastRow, 9)) .Merge .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter .Font.Bold = True End With pupilsRange.Copy .Cells(LastRow + 1, 1) LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
End With End With End If Next sh Application.ScreenUpdating = AppScrUpd End Sub
добавил второй вариант с сортировкой учеников и произвольным порядком листов: [vba]
Код
Sub pupils() Dim sh As Worksheet, lr As Long, LastRow As Long, pupilsCount As Integer, pupilsRange As Range Dim AppScrUpd, j As Integer, arr(), shName, pupilsArray j = 1 With ThisWorkbook For Each sh In .Worksheets If RegexExtract(sh.Name) Then If sh.Name <> "Шаблон" Then ReDim Preserve arr(1 To j): arr(j) = sh.Name: j = j + 1 End If Next sh End With
LastRow = 1 ThisWorkbook.Worksheets("Шаблон").Cells.Clear For Each shName In arr With ThisWorkbook.Worksheets(shName) lr = .Cells(.Rows.Count, 1).End(xlUp).Row pupilsArray = .Range("A2:B" & lr) pupilsArray = sort_pupil(pupilsArray) pupilsCount = lr - 1 With ThisWorkbook.Worksheets("Шаблон") .Cells(LastRow, 1) = shName & " ----> " & pupilsCount & " учеников" .Cells(LastRow, 1).Interior.Color = 4697456 With .Range(.Cells(LastRow, 1), .Cells(LastRow, 9)) .Merge .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter .Font.Bold = True End With .Cells(LastRow + 1, 1).Resize(UBound(pupilsArray, 1), UBound(pupilsArray, 2)) = pupilsArray LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1 End With End With Next shName Application.ScreenUpdating = AppScrUpd End Sub Private Function sort_arr(arr) As Variant Dim i, j, tmp For i = LBound(arr) To UBound(arr) For j = i To UBound(arr) If arr(i) > arr(j) Then tmp = arr(j) arr(j) = arr(i) arr(i) = tmp End If Next j Next i sort_arr = arr End Function Private Function sort_pupil(arr) As Variant Dim i, j, tmp For i = LBound(arr, 1) To UBound(arr, 1) For j = i To UBound(arr, 1) If arr(i, 2) > arr(j, 2) Then tmp = arr(j, 2) arr(j, 2) = arr(i, 2) arr(i, 2) = tmp End If Next j Next i sort_pupil = arr End Function Private Function RegexExtract(s As String) As Boolean RegexExtract = False With CreateObject("VBScript.Regexp") .Global = False: .MultiLine = False: .Pattern = "^\d[0-2]?[А-Жа-ж]$" If .test(s) Then RegexExtract = True: Exit Function End With End Function
[/vba]
добавил второй вариант с сортировкой учеников и произвольным порядком листов: [vba]
Код
Sub pupils() Dim sh As Worksheet, lr As Long, LastRow As Long, pupilsCount As Integer, pupilsRange As Range Dim AppScrUpd, j As Integer, arr(), shName, pupilsArray j = 1 With ThisWorkbook For Each sh In .Worksheets If RegexExtract(sh.Name) Then If sh.Name <> "Шаблон" Then ReDim Preserve arr(1 To j): arr(j) = sh.Name: j = j + 1 End If Next sh End With
LastRow = 1 ThisWorkbook.Worksheets("Шаблон").Cells.Clear For Each shName In arr With ThisWorkbook.Worksheets(shName) lr = .Cells(.Rows.Count, 1).End(xlUp).Row pupilsArray = .Range("A2:B" & lr) pupilsArray = sort_pupil(pupilsArray) pupilsCount = lr - 1 With ThisWorkbook.Worksheets("Шаблон") .Cells(LastRow, 1) = shName & " ----> " & pupilsCount & " учеников" .Cells(LastRow, 1).Interior.Color = 4697456 With .Range(.Cells(LastRow, 1), .Cells(LastRow, 9)) .Merge .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter .Font.Bold = True End With .Cells(LastRow + 1, 1).Resize(UBound(pupilsArray, 1), UBound(pupilsArray, 2)) = pupilsArray LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1 End With End With Next shName Application.ScreenUpdating = AppScrUpd End Sub Private Function sort_arr(arr) As Variant Dim i, j, tmp For i = LBound(arr) To UBound(arr) For j = i To UBound(arr) If arr(i) > arr(j) Then tmp = arr(j) arr(j) = arr(i) arr(i) = tmp End If Next j Next i sort_arr = arr End Function Private Function sort_pupil(arr) As Variant Dim i, j, tmp For i = LBound(arr, 1) To UBound(arr, 1) For j = i To UBound(arr, 1) If arr(i, 2) > arr(j, 2) Then tmp = arr(j, 2) arr(j, 2) = arr(i, 2) arr(i, 2) = tmp End If Next j Next i sort_pupil = arr End Function Private Function RegexExtract(s As String) As Boolean RegexExtract = False With CreateObject("VBScript.Regexp") .Global = False: .MultiLine = False: .Pattern = "^\d[0-2]?[А-Жа-ж]$" If .test(s) Then RegexExtract = True: Exit Function End With End Function
Благодарю, второй вариант вообще бомба) но первый больше подходит тем что нет привязки к именам листов, подскажите если в книге будут еще листы которые не должны попасть в шаблон, куда прописать их в коде чтобы они не участвовали в макросе.
Благодарю, второй вариант вообще бомба) но первый больше подходит тем что нет привязки к именам листов, подскажите если в книге будут еще листы которые не должны попасть в шаблон, куда прописать их в коде чтобы они не участвовали в макросе.udjin
Второй вариант подразумевает названия листов по имени класса - 1А, 4Б, 11В, и так далее (используются буквы от А до Ж). Если будете использовать первый вариант, то названия листов, которые нужно исключить нужно дописать в строку: [vba]
Код
If sh.Name <> "Шаблон" Then
[/vba] в цикле, через оператор and. То есть: [vba]
Код
If sh.Name <> "Шаблон" and sh.Name <> "имя1" and sh.Name <> "имя2" Then
[/vba]
Но я бы сделал на каждый класс отдельный лист и пользовался макросом из второго варианта
Второй вариант подразумевает названия листов по имени класса - 1А, 4Б, 11В, и так далее (используются буквы от А до Ж). Если будете использовать первый вариант, то названия листов, которые нужно исключить нужно дописать в строку: [vba]
Код
If sh.Name <> "Шаблон" Then
[/vba] в цикле, через оператор and. То есть: [vba]
Код
If sh.Name <> "Шаблон" and sh.Name <> "имя1" and sh.Name <> "имя2" Then
[/vba]
Но я бы сделал на каждый класс отдельный лист и пользовался макросом из второго вариантаjun
Сообщение отредактировал jun - Вторник, 16.01.2024, 15:50
а я через ";" пробовал в цикле указать имена книг и соответственно получал ошибку) теперь буду знать про "and" и еще задача чтобы получившееся таблица копировалась на лист "Отчет" с определенной строки в данном примере с 8 строки и если не сложно разбивалась по столбцам. Изначально я так понимаю на листе "Шаблон" этого сделать нельзя потому что после выполнения макроса лист обновляется.
а я через ";" пробовал в цикле указать имена книг и соответственно получал ошибку) теперь буду знать про "and" и еще задача чтобы получившееся таблица копировалась на лист "Отчет" с определенной строки в данном примере с 8 строки и если не сложно разбивалась по столбцам. Изначально я так понимаю на листе "Шаблон" этого сделать нельзя потому что после выполнения макроса лист обновляется.udjin
Сегодня проверил, получается если добавить лист или увеличить или уменьшить количество учеников то ломается вся структура, наверное проще тогда как в первом варианте каждый класс идет под следующим, только вот не могу слепить из двух вариантов чтобы оставалась шапка и изменялись данные.
Сегодня проверил, получается если добавить лист или увеличить или уменьшить количество учеников то ломается вся структура, наверное проще тогда как в первом варианте каждый класс идет под следующим, только вот не могу слепить из двух вариантов чтобы оставалась шапка и изменялись данные.udjin
Если правильно понял, то (см. файл) Доработал код из своего первого ответа. Тестируйте. Подразумевается, что в книге будут только листы с именами классов (1А, 4Б, 11В, и т.д.). И листы с именами Шаблон и ОТЧЕТ, или один, с именем ОТЧЕТ Также при каждом запуске макроса, перед копированием данных на лист ОТЧЕТ, строки, начиная с 8 и ниже очищаются и затем данные с листов, с именами классов копируются, начиная с 8 строки обновление файла 19.01: нашел ошибку в коде и исправил. Корректный макрос от 19.01
Если правильно понял, то (см. файл) Доработал код из своего первого ответа. Тестируйте. Подразумевается, что в книге будут только листы с именами классов (1А, 4Б, 11В, и т.д.). И листы с именами Шаблон и ОТЧЕТ, или один, с именем ОТЧЕТ Также при каждом запуске макроса, перед копированием данных на лист ОТЧЕТ, строки, начиная с 8 и ниже очищаются и затем данные с листов, с именами классов копируются, начиная с 8 строки обновление файла 19.01: нашел ошибку в коде и исправил. Корректный макрос от 19.01jun
во время экспериментов возник вопрос как можно указать что бы таблица строились не с первого столбца а со второго, как в примере, чтобы построение в отчете начиналось со столбца "B"
во время экспериментов возник вопрос как можно указать что бы таблица строились не с первого столбца а со второго, как в примере, чтобы построение в отчете начиналось со столбца "B"udjin
Подправил сортировку в файле. Исправил код Но код привязан к именам листов. Не знаю, недостаток это или нет. Подразумевается, что имена классов состоят из 1-2 цифр в начале и заканчиваются 1 буквой
Подправил сортировку в файле. Исправил код Но код привязан к именам листов. Не знаю, недостаток это или нет. Подразумевается, что имена классов состоят из 1-2 цифр в начале и заканчиваются 1 буквойjun