Добрый день! Имеется исходная таблица в которой отражен список смет с определенными данными Из этой таблицы необходимо заполнить 100 листов книги, 1 лист - отдельная смета с наименованием "см.N" (в примере работает макрос для 5 листов) Наименования листов - строго: "см.1, см.2 ... см.100"
Количество столбцов исходной таблицы, а следовательно и сметы - может увеличиваться. Все данные с исходной таблице должны копироваться в виде значения (без форматирования и формул).
Я записал макрос для 5 листов через штатную функцию Excel, убрал лишнее, но объем макроса для 5 листов - получился очень внушительный Для вас это покажется кодом "вырви глаз", но я не программист, поэтому и прошу вашей помощи в оптимизации макроса...
Может это как-то сделать блоками, допустим: 1) блок копирования Столбца "Наименование" в каждый лист сметы см.1...см.100 2) блок копирования Столбца "Стоимость" в каждый лист сметы см.1...см.100 . . n) блок копирования любого нового столбца...
Shuav написал: Не знаю для чего это нужно но я бы сделал слияние в "Ворд"
Слияние в Word - не нужно, т.к. в каждой смете потом будет производиться экономический расчет показателей (форма заполнения каждого листа будет соблюдена, подцеплю формулы). Вообще рабочим файлом пользуюсь лет 9, а вот заполняется каждая смета всегда вручную, поэтому хочу как-нибудь оптимизировать процесс заполнения
может лучше воспользоваться формулой типа =ИНДЕКС(Расценки!$E$2:$E$89;ПОИСКПОЗ(Расчет!$C16;Расценки!$B$2:$B$89;0)), а наименование работы выбирать из раскрывающегося списка ?
Shuav написал: Я так понимаю у Вас коммерческие сметы? А не по сборникам
Нет, сметы по сборникам ФЭР, БЦ. Рабочий файл - бюджет проекта, к каждой смете есть вкладка с выгрузкой ресурсов. Выгрузку ресурсов отрабатывают производтственники и МТС (что и сколько купить по факту, а не по смете, сколько стоит) В во вкладках см.1 и тд - формируется экономическая составляющая данной работы
В примере - я создал примитивную рыбу самого бюджета, т.к. это госорганизация и показывать такое нельзя.
Maxim, добрый вечер! Код прокомментировал (см. ниже). Нажимаете кнопку и смотрите результат
Код
Sub CopyData()
Dim arr, i As Long, j, shName As String, lr As Long, lC As Long, sh As Worksheet
arr = Worksheets("Сводка").Cells(4, 2).CurrentRegion ' подразумевается, что левый верхний угол таблицы - это В4
For i = 3 To UBound(arr, 1) ' 3 - это строка Подготовка котлована (первые 2 - это шапка)
shName = "см." & arr(i, 1) ' склеиваем строку см. с №п.п
If Not SheetExists(shName) Then
Set sh = Application.Worksheets.Add(after:=Worksheets(Worksheets.Count)): shName = "см." & Int(Right(shName, 1)) - 1
With sh
.Name = ("см." & Int(Right(shName, 1)) + 1): Worksheets(shName).Cells(4, 2).CurrentRegion.Copy sh.Cells(3, 2): shName = ("см." & Int(Right(shName, 1)) + 1)
.Cells(3, 2).CurrentRegion.Columns.AutoFit
End With
End If
With Worksheets(shName)
.[B3] = "Смета" & arr(i, 1): .[B4] = "Наименование работы"
For j = 2 To UBound(arr, 2)
If j = 2 Then
.Cells(4, 2) = .Cells(4, 2).Value & ": """ & arr(i, j) & """" ' Cells(4,2) == [B4]
With .Cells(4, 2) ' B4
.HorizontalAlignment = xlCenter ' выравнивание по горизонтали ячейки И4
.WrapText = True ' перенос текста == переносить текст
End With
lr = 5: lC = 3
Else
.Cells(lr, lC) = arr(i, j)
lC = lC + 1 ' смещаемся на 1 столбец вправо
End If
Next j
End With
Next i
End Sub
Private Function SheetExists(shName As String) As Boolean
Dim sh As Worksheet
For Each sh In Worksheets
If sh.Name = shName Then SheetExists = True: Exit Function
Next sh
SheetExists = False
End Function
см. вложение макрос написан (ВНИМАНИЕ! вносить в него исправления не нужно) вносите в колонки А, В новые пары правил копирования заполняйте данными сметы на листе Сводка Удачи!
Код
Sub EstimateFill()
Dim a, adr$, b, c&, cc&, m, r&, rc&, re, s$, ws1 As Worksheet
Set re = CreateObject("VBScript.RegExp"): re.Pattern = "[A-Z]+:*[A-Z]*"
With Worksheets(1)
rc = .Cells(Rows.Count, 1).End(xlUp).Row: Set ws1 = .[a1].Parent
cc = .Cells(Rows.Count, 3).End(xlUp).Row: a = .[a1].CurrentRegion
End With
For c = 3 To cc
If c - 1 > Worksheets.Count Then Worksheets(2).Copy after:=Worksheets(Worksheets.Count)
With Worksheets(c - 1)
For r = 2 To rc
Set m = re.Execute(a(r, 1))(0)
If InStr(m, ":") Then adr = Replace(m, ":", c & ":") & c Else adr = m & c
b = ws1.Range(adr)
If InStr(adr, ":") Then
.Range(a(r, 2)).Resize(UBound(b), UBound(b, 2)) = b
Else
.Range(a(r, 2)) = Replace(a(r, 1), m, b)
End If
Next
End With
Next
MsgBox "Заполнено смет: " & cc - 2 & " шт.", , "Готово!"
End Sub
artemkau88 написал: Maxim , добрый вечер! Код прокомментировал (см. ниже). Нажимаете кнопку и смотрите результат
Код
[URL=#]?[/URL] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 Sub CopyData() Dim arr, i As Long , j, shName As String , lr As Long , lC As Long , sh As Worksheet arr = Worksheets( "Сводка" ).Cells(4, 2).CurrentRegion ' подразумевается, что левый верхний угол таблицы - это В4 For i = 3 To UBound(arr, 1) ' 3 - это строка Подготовка котлована (первые 2 - это шапка) shName = "см." & arr(i, 1) ' склеиваем строку см. с №п.п If Not SheetExists(shName) Then Set sh = Application.Worksheets.Add(after:=Worksheets(Worksheets.Count)): shName = "см." & Int(Right(shName, 1)) - 1 With sh .Name = ( "см." & Int(Right(shName, 1)) + 1): Worksheets(shName).Cells(4, 2).CurrentRegion.Copy sh.Cells(3, 2): shName = ( "см." & Int(Right(shName, 1)) + 1) .Cells(3, 2).CurrentRegion.Columns.AutoFit End With End If With Worksheets(shName) .[B3] = "Смета" & arr(i, 1): .[B4] = "Наименование работы" For j = 2 To UBound(arr, 2) If j = 2 Then .Cells(4, 2) = .Cells(4, 2).Value & ": " "" & arr(i, j) & "" "" ' Cells(4,2) == [B4] With .Cells(4, 2) ' B4 .HorizontalAlignment = xlCenter ' выравнивание по горизонтали ячейки И4 .WrapText = True ' перенос текста == переносить текст End With lr = 5: lC = 3 Else .Cells(lr, lC) = arr(i, j) lC = lC + 1 ' смещаемся на 1 столбец вправо End If Next j End With Next i End Sub Private Function SheetExists(shName As String ) As Boolean Dim sh As Worksheet For Each sh In Worksheets If sh.Name = shName Then SheetExists = True : Exit Function Next sh SheetExists = False End Function
Ігор Гончаренко написал: см. вложение макрос написан (ВНИМАНИЕ! вносить в него исправления не нужно) вносите в колонки А, В новые пары правил копирования заполняйте данными сметы на листе Сводка Удачи!
Код
[URL=#]?[/URL] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Sub EstimateFill() Dim a, adr$, b, c&, cc&, m, r&, rc&, re, s$, ws1 As Worksheet Set re = CreateObject( "VBScript.RegExp" ): re.Pattern = "[A-Z]+:*[A-Z]*" With Worksheets(1) rc = .Cells(Rows.Count, 1). End (xlUp).Row: Set ws1 = .[a1].Parent cc = .Cells(Rows.Count, 3). End (xlUp).Row: a = .[a1].CurrentRegion End With For c = 3 To cc If c - 1 > Worksheets.Count Then Worksheets(2).Copy after:=Worksheets(Worksheets.Count) With Worksheets(c - 1) For r = 2 To rc Set m = re.Execute(a(r, 1))(0) If InStr(m, ":" ) Then adr = Replace(m, ":" , c & ":" ) & c Else adr = m & c b = ws1.Range(adr) If InStr(adr, ":" ) Then .Range(a(r, 2)).Resize(UBound(b), UBound(b, 2)) = b Else .Range(a(r, 2)) = Replace(a(r, 1), m, b) End If Next End With Next MsgBox "Заполнено смет: " & cc - 2 & " шт." , , "Готово!" End Sub
Ігор Гончаренко написал: см. вложение макрос написан (ВНИМАНИЕ! вносить в него исправления не нужно) вносите в колонки А, В новые пары правил копирования заполняйте данными сметы на листе Сводка Удачи!
Код
[URL=#]?[/URL] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Sub EstimateFill() Dim a, adr$, b, c&, cc&, m, r&, rc&, re, s$, ws1 As Worksheet Set re = CreateObject( "VBScript.RegExp" ): re.Pattern = "[A-Z]+:*[A-Z]*" With Worksheets(1) rc = .Cells(Rows.Count, 1). End (xlUp).Row: Set ws1 = .[a1].Parent cc = .Cells(Rows.Count, 3). End (xlUp).Row: a = .[a1].CurrentRegion End With For c = 3 To cc If c - 1 > Worksheets.Count Then Worksheets(2).Copy after:=Worksheets(Worksheets.Count) With Worksheets(c - 1) For r = 2 To rc Set m = re.Execute(a(r, 1))(0) If InStr(m, ":" ) Then adr = Replace(m, ":" , c & ":" ) & c Else adr = m & c b = ws1.Range(adr) If InStr(adr, ":" ) Then .Range(a(r, 2)).Resize(UBound(b), UBound(b, 2)) = b Else .Range(a(r, 2)) = Replace(a(r, 1), m, b) End If Next End With Next MsgBox "Заполнено смет: " & cc - 2 & " шт." , , "Готово!" End Sub
Посмотрел как работает макрос - это шедевр! Огромное спасибо еще раз! Полностью раскрывает тему вопроса и гибко настраивается!
Правила копирования настраиваются так: в колонке А пишете откуда взять данные, с какой колонки или с диапазона колонок, если данные из строки сметы ложатся в бланк сметы в таком же порядке имя колонки (диапазона пишется БОЛЬШИМИ ЛАТИНСКИМИ БУКВАМИ) для копирования одиночной ячейки допускается в А внести дополнительный текст, например: Смета № C (здесь последняя С это латинская С) в результатте в бланк попадет надпись Смета № №№, где №№ - № сметы указанный в колонке С в колонке В указываете адрес конкретной ячейки, куда скопировать данные. если копируете диапазон, можно указать адрес первой ячейки (остальное будет размещено правее), например а А написано E:G, то в В можно написать С5:Е5, а можно просто С5, результат будет один и тот же. в колонке В нужно указывать конкретный и корректный адрес ячейки в бланке сметы.
Ігор Гончаренко написал: Правила копирования настраиваются так: в колонке А пишете откуда взять данные, с какой колонки или с диапазона колонок, если данные из строки сметы ложатся в бланк сметы в таком же порядке имя колонки (диапазона пишется БОЛЬШИМИ ЛАТИНСКИМИ БУКВАМИ) для копирования одиночной ячейки допускается в А внести дополнительный текст, например: Смета № C (здесь последняя С это латинская С) в результате в бланк попадет надпись Смета № №№, где №№ - № сметы указанный в колонке С в колонке В указываете адрес конкретной ячейки, куда скопировать данные. если копируете диапазон, можно указать адрес первой ячейки (остальное будет размещено правее), например а А написано E:G, то в В можно написать С5:Е5, а можно просто С5, результат будет один и тот же. в колонке В нужно указывать конкретный и корректный адрес ячейки в бланке сметы.
Скажите, а как быть если: 1) Между сметами находятся суперскрытые листы? Например между сметой 1 и 2 есть лист. Тогда значения с исходной таблицы будут заполняться во все листы, которые идут после листа с Исходными данными, в т.ч. и в суперскрытые листы 2) Лист с исходными данными по счету не первый, а любой другой (перед листом с исходными данными есть еще листы)
1. нужно придумать какими будут имена листов и чуть поправить макрос и обращаться к листам не по номеру, а по имени и фрагмент, который добавляет новые листы нужно исправить делать копию с "правильного листа" а не со второго, и добавленному листу присвоить "правильное имя" согласно принятого алгоритма наименования листов 2. это вообще элементарно в строке 4 макроса заменить With Worksheets(1) на With Worksheets("Сводка")
Ігор Гончаренко написал: роке 4 макроса заменить With Worksheets(1) на With Worksheets("Сводка"
1) имена всех листов известны: "см.1", "см.2", ..., "см.100". Только между ними точно будут встречаться другие листы. я хотел сделать обход этих листов суперскрытием через макрос, но, как писал выше - не удалось 2) изменил в 4 строке With Worksheets(1) на With Worksheets("Сводка"), как результат - все равно копирование начинается со второго листа.
Ігор Гончаренко написал: 1. нужно придумать какими будут имена листов и чуть поправить макрос и обращаться к листам не по номеру, а по имени и фрагмент, который добавляет новые листы нужно исправить делать копию с "правильного листа" а не со второго, и добавленному листу присвоить "правильное имя" согласно принятого алгоритма наименования листов 2. это вообще элементарно в строке 4 макроса заменить With Worksheets(1) на With Worksheets("Сводка")
Игорь, добрый день! Будьте добры помочь по вашему макросу: 1) Нужно добавить условие, чтобы копирование производилось только в листы с названием "см.1", "см.2", ..., "см.100". другими словами - между листами куда копируем данные - будут находиться еще листы, в которые не должно происходить копирование 2) Лист с исходными данными может быть не первый по очереди, обращался к нему через имя - With Worksheets(1) на With Worksheets("Сводка"), но результат не получил, копирование начинается все равно со второго листа по счету
Код
Option Explicit
Sub EstimateFill()
Dim a, adr$, b, c&, cc&, m, r&, rc&, re, s$, ws1 As Worksheet
Set re = CreateObject("VBScript.RegExp"): re.Pattern = "[A-Z]+:*[A-Z]*"
With Worksheets("Сводка")
rc = .Cells(Rows.Count, 1).End(xlUp).Row: Set ws1 = .[a1].Parent
cc = .Cells(Rows.Count, 3).End(xlUp).Row: a = .[a1].CurrentRegion
End With
For c = 3 To cc
If c - 1 > Worksheets.Count Then Worksheets(2).Copy after:=Worksheets(Worksheets.Count)
With Worksheets(c - 1)
For r = 2 To rc
Set m = re.Execute(a(r, 1))(0)
If InStr(m, ":") Then adr = Replace(m, ":", c & ":") & c Else adr = m & c
b = ws1.Range(adr)
If InStr(adr, ":") Then
.Range(a(r, 2)).Resize(UBound(b), UBound(b, 2)) = b
Else
.Range(a(r, 2)) = Replace(a(r, 1), m, b)
End If
Next
End With
Next
MsgBox "Заполнено смет: " & cc - 2 & " шт.", , "Готово!"
End Sub
Maxim, пожалуйста, прекратите нажимать на кнопку Цитировать, если не хотите процитировать какой-то отдельный текст другого пользователя. Нажимайте кнопку "Имя", она находится правее на 1 см от кнопки Цитировать. Читать тему невозможно из-за ваших цитированный целиком всего текста
Ігор Гончаренко, правильно ли я понимаю, что в момент заполнения все листы, которые находятся правее листа с исходными данными - удаляются, а потом создаются и заполняются новые?