Необходимо автоматически переименовывать листы книг из нескольких книг на основе ячеек таблицы.Данные по файлам и листам создаются на основе макросов. Файл-пример приведен во вложении. Есть 4000 excel файлов с разным именованием листов книг. Я создаю структуру файлов книг и листов в таблице на основе макроса, но не знаю как реализовать рекурсивное переименование листов книг на основе критерия в таблице. Критерий следующий.
В столбце G указаны пути к файлам. Столбец B содержит имена листов в соответствии с именем файла. Некоторые файлы содержат более одного листа. Листы, названия которых должны быть переименованы подсвечены желтым. Например, лист в именем "false_sample_ad" должен быть переименован в "true_sample". НО. Есть листы, которые называются "false_sample 2017", поэтому они должны быть переименованы в "true_sample_2"
Пока получилось набросать только вариант с переименованием листов текущей книги на основе одной ячейки. Как это оформить в виде цикла для пробега по столбцам - не додумал.
Код
Sub RS()
For i = 1 To Sheets.Count
If Worksheets(i).Range("A1").Value <> "" Then
Sheets(i).Name = Worksheets(i).Range("A1").Value
End If
Next
End Sub
Есть ли какие-то идеи? Сам процесс также тяжело проделать вручную, так как файлов очень много.
Все что смог, над переименованием сами подумайте, я честно ничего не понял, что во что нужно переименовывать.
Код
Sub test()
Dim i&, x&
Dim dicOb As Object, dicOb1 As Object
Dim book1 As Workbook, book2 As Workbook, sht1 As Worksheet
Dim arr1(), arr2$(), ikey, jkey
Application.ScreenUpdating = False
Set dicOb = CreateObject("Scripting.Dictionary")
Set dicOb1 = CreateObject("Scripting.Dictionary")
dicOb1.comparemode = 1
Set book1 = ThisWorkbook
With book1
Set sht1 = .Sheets(1)
With sht1
i = .Cells(.Rows.Count, "g").End(xlUp).Row
arr1 = .Range(.Range("b2"), .Range("g" & i))
For i = LBound(arr1) To UBound(arr1)
dicOb.Item(CStr(arr1(i, UBound(arr1, 2)))) = dicOb.Item(CStr(arr1(i, UBound(arr1, 2)))) & arr1(i, 2) & ","
Next i
End With
End With
For Each ikey In dicOb.keys
x = 0
arr2 = Split(Left(dicOb.Item(ikey), Len(dicOb.Item(ikey)) - 1), ",")
dicOb1.RemoveAll
For Each jkey In arr2
dicOb1.Item(CStr(jkey)) = dicOb1.Item(CStr(jkey))
Next jkey
Set book2 = Workbooks.Open(Filename:=ikey)
With book2
Do Until .Sheets.Count >= dicOb1.Count
.Sheets.Add
Loop
For Each jkey In dicOb1.keys
x = x + 1
.Sheets(x).Name = jkey
Next jkey
.Close True
End With
Next ikey
Application.ScreenUpdating = True
End Sub
Коллеги, спасибо за идеи Nordheim,разобрался в Вашем коде. Насколько я понял, код работает для значения ячейки b2, но суть в том, что сначала макрос должен пробегать по всем 51 строкам столбца B и если они помечены желтым/содержат заполенную ячейку в столбце A, то такому листу присваивается имя kuklp, я пробовал запустить Ваш код
Код
Public Sub www()
Dim wb As Workbook, i&
On Error Resume Next
For i = 2 To 52
If Cells(i, 2).Interior.ColorIndex = 6 Then
Set wb = Workbooks.Open(Cells(i, 7).Value, False)
wb.Sheets(Cells(i, 2).Value).Name Cells(i, 1).Value
wb.Close -1: Set wb = Nothing
End If
Next
End Sub
Он правильно запускает цикл по файлам, но не делает (судя по Debug) цикл по всем листам на предмет соответствия имен листов значению столбца B. Я попытался добавить цикл переименования листов по критерию, но пока получилось только так.
Код
Public Sub www()
Dim wb As Workbook, i&
On Error Resume Next
For i = 2 To 52
If Cells(i, 2).Interior.ColorIndex = 6 Then
Set wb = Workbooks.Open(Cells(i, 7).Value, , False, , , , , , , True)
For Each sh In wb.Worksheets
sh(Cells(i, 2).Value).Name.Activate = Cells(i, 1).Value
Next
wb.Close 0
End If
Next
End Sub
Плюс надо учесть, что перед переименованием лист должен быть соответствующий лист должен быть открыт, что я попытался добавить в код
Nordheim,изменения только в тех файлах, содержащих листы, переименование которых требуется согласно жёлтым ячейкам столбца B. Возможно я переборщил с желтым цветом, но на желтизну стоит смотреть только для ячеек в столбце В.
Я для себя выделял в рабочем файле листы для переименования и соотвествующие им ячейки желтым, и в столбце A добавлял наименования листов которые должны быть, поэтому рационально взять в качестве критерия несовпадение.
Sub test()
Dim i&, j&, ikey
Dim dicOb As Object, dicOb1 As Object, sh As Worksheet
Dim book1 As Workbook, book2 As Workbook, sht1 As Worksheet
Application.ScreenUpdating = False
Set dicOb = CreateObject("Scripting.Dictionary")
Set dicOb1 = CreateObject("Scripting.Dictionary")
Set book1 = ThisWorkbook
With book1
Set sht1 = .Sheets(1)
With sht1
j = .Cells(.Rows.Count, "g").End(xlUp).Row
For i = 2 To j
If .Range("a" & i) <> .Range("b" & i) Then
dicOb.Item(CStr(.Range("g" & i))) = .Range("b" & i)
dicOb1.Item(CStr(.Range("g" & i))) = .Range("a" & i)
End If
Next i
End With
End With
For Each ikey In dicOb.keys
Set book2 = Workbooks.Open(Filename:=ikey)
With book2
For Each sh In .Worksheets
If sh.Name = dicOb.Item(ikey) Then sh.Name = dicOb1.Item(ikey)
Next sh
.Close True
End With
Next ikey
Application.ScreenUpdating = True
End Sub
Про 44-46 строки, там тоже один лист, разве не так?
Nordheim написал: бывает ситуация когда в одном файле нужно менять наименование 2 листов?
Я правильно вас понял, что вы имеете в виду изменять наименование 2 листов в одной книге? Объясню на примере, есть книга "abc 215_215.2.xlsx" у него листы false_sample_2016, false_sample 2017, false_sample_2018 и каждому из них присваивается свое наименование, указанное в столбце A. И может быть несколько таких файлов. Или же вы имеете в виду ситуацию, когда нужно присвоить имена листам в одной книге, и получается, что им возможно могут присвоиться одинаковые имена?
Цитата
Nordheim написал: если бывает больше одного листа то нужен пример во что. И это совсем другой код и переменные!
Да, но ведь цикл в коде у вас пробегает по все листам книги
Код
With book2
For Each sh In .Worksheets
If sh.Name = dicOb.Item(ikey) Then sh.Name = dicOb1.Item(ikey)
Next sh
.Close True
End With
Значит теоретически если он еще раз пробежится по столбцам A,B, то сможет присвоить новое наименования оставшимся листам.
Цитата
Nordheim написал: Про 44-46 строки, там тоже один лист, разве не так?
Извините, не перезалил файл. См. к этому сообщению вложение.
Piddy написал: есть книга "abc 215_215.2.xlsx" у него листы false_sample_2016, false_sample 2017, false_sample_2018 и каждому из них присваивается свое наименование, указанное в столбце A.
Sub test()
Dim i&, j&, ikey, arr$(), iarr$()
Dim dicOb As Object, dicOb1 As Object, sh As Worksheet
Dim book1 As Workbook, book2 As Workbook, sht1 As Worksheet
On Error Resume Next
Application.ScreenUpdating = False
Set dicOb = CreateObject("Scripting.Dictionary")
Set dicOb1 = CreateObject("Scripting.Dictionary")
Set book1 = ThisWorkbook
With book1
Set sht1 = .Sheets(1)
With sht1
j = .Cells(.Rows.Count, "g").End(xlUp).Row
For i = 2 To j
If .Range("a" & i) <> "" Then
dicOb.Item(CStr(.Range("g" & i))) = dicOb.Item(CStr(.Range("g" & i))) & .Range("b" & i) & ","
dicOb1.Item(CStr(.Range("g" & i))) = dicOb1.Item(CStr(.Range("g" & i))) & .Range("a" & i) & ","
End If
Next i
End With
End With
For Each ikey In dicOb.keys
arr = Split(Left(dicOb.Item(ikey), Len(dicOb.Item(ikey)) - 1), ",")
iarr = Split(Left(dicOb1.Item(ikey), Len(dicOb1.Item(ikey)) - 1), ",")
Set book2 = Workbooks.Open(Filename:=ikey)
With book2
For i = LBound(arr) To UBound(arr)
.Sheets(arr(i)).Name = iarr(i)
Next i
.Close True
End With
Next ikey
On Error GoTo 0
Application.ScreenUpdating = True
End Sub
"Все гениальное просто, а все простое гениально!!!"
Nordheim,я проверил макрос, он работает, спасибо Вам за ваши труды. Сейчас буду детально разбираться в коде. Что касается ситуации, когда для одной книги необходимо переименование нескольких листов, то здесь на реальных файлах следующая картина. Существует порядка 30 масок в столбце A, которые подставляются в качестве переименования листов, указанных в столбце B. В столбце B возможно порядка 200 различных наименований листов, которые должны быть обработаны. Есть вариант отфильтровывать строки по каждой маске, создавать новый лист, содержащий в столбце A именно данную маску и применять к нему Ваш макрос. Но идея состояла в том, чтобы иметь возможность переименовывать имена листов по всем маскам разово, так как файлы приходят ко мне каждый день и я их обновляю.
Nordheim,пока не знаю. Я правильно понял, что реализовать переименование сразу нескольких листов для всех книг - задача технически сложная и проще сделать ее ручками?
Вопрос не понял, последний код переименовывает несколько листов (которые необходимо переименовать) во всех книгах исходя из условия описанного в сообщении №18
Nordheim,макрос работает успешно. Заметил только, что 5% не обрабатываются, но это какие-то специфические книги. Имена у их листов не совсем стандартные. yozhik, а access позволяет проводить аналогичные преобразования с именами листов до импорта в базу данных?
Piddy написал: Заметил только, что 5% не обрабатываются, но это какие-то специфические книги. Имена у их листов не совсем стандартные.
Разобрался, дело было в том, что наименования листов имели длину выше нормы. Спасибо Вам за 100% рабочее решение.
Тему пока не закрывайте, так как есть предложения усовершенствовать макрос, чтобы им могли пользоваться и остальные форумчане. Я уверен, что у кого-то точно была потребность в соответствующем макросе.