Страницы: 1 2 След.
RSS
Переименование листов из нескольких книг на основе данных ячейки, Рекурсивно, основой переименования служит таблица с данными.
 
Добрый вечер.

Необходимо автоматически переименовывать листы книг из нескольких книг на основе ячеек таблицы.Данные по файлам и листам создаются на основе макросов.
Файл-пример приведен во вложении. Есть 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 - 12.07.2017 09:59:33
"Все гениальное просто, а все простое гениально!!!"
 
Как-то так, не проверял:
Удалено, кросс:
http://www.excelworld.ru/forum/10-34449-1
Изменено: kuklp - 12.07.2017 08:45:26
Я сам - дурнее всякого примера! ...
 
Коллеги, спасибо за идеи
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
Плюс надо учесть, что перед переименованием лист должен быть соответствующий лист должен быть открыт, что я попытался добавить в код
Изменено: Piddy - 13.07.2017 00:33:57
 
Переименовываться должны только те листы которые выделены желтым в 1столбце или во втором? 2
"Все гениальное просто, а все простое гениально!!!"
 
Nordheim,Во втором столбце. То есть например в строке 4 "false_sample_ad" должен замениться на "true sample". И так ещё для трёх строк.
 
И соответственно изменения только в тех файлах и только те листы которые выделены желтым?
"Все гениальное просто, а все простое гениально!!!"
 
Nordheim,изменения только в тех файлах, содержащих листы, переименование которых требуется согласно жёлтым ячейкам столбца B. Возможно я переборщил с желтым цветом, но на желтизну стоит смотреть только для ячеек в столбце В.
Изменено: Piddy - 13.07.2017 08:36:29
 
т.е. за критерий берется желтый цвет? или неравенство значений  в ячейках A и B одной строки, это важно!
"Все гениальное просто, а все простое гениально!!!"
 
Я для себя выделял в рабочем файле листы для переименования и соотвествующие им ячейки желтым, и в столбце A добавлял наименования листов которые должны быть, поэтому рационально взять в качестве критерия несовпадение.

Добавил файл, чтобы вы поняли.
Изменено: Piddy - 13.07.2017 09:40:20
 
Так в итоге на что нужно ориентироваться цвет или несовпадение?
"Все гениальное просто, а все простое гениально!!!"
 
Nordheim,несовпадение, см. файл. example (1).xlsx  
 
Пример: Есть файл abc 132.xlsx что нужно в нем поменять и на что?
"Все гениальное просто, а все простое гениально!!!"
 
бывает ситуация когда в одном файле нужно менять наименование 2 листов?
"Все гениальное просто, а все простое гениально!!!"
 
Nordheim,да, бывает, пример смотрите в строках 44-46
 
для изменения одного листа!
Код
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 - 13.07.2017 10:13:10
"Все гениальное просто, а все простое гениально!!!"
 
если бывает больше одного листа то нужен пример во что.
И это совсем другой код и переменные!
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
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 - 13.07.2017 10:31:51
 
Имелись ввиду именно  листы.
"Все гениальное просто, а все простое гениально!!!"
 
Nordheim,значит мы оба идентично рассуждаем.
Цитата
Piddy написал:
есть книга "abc 215_215.2.xlsx" у него листы false_sample_2016, false_sample 2017, false_sample_2018 и каждому из них присваивается свое наименование, указанное в столбце A.
Прочитайте пожалуйста измененный комментарий выше.
Изменено: Piddy - 13.07.2017 10:33:42
 
Пробуйте!
Код
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
"Все гениальное просто, а все простое гениально!!!"
 
По сообщению №18. По столбцам код пробегает один раз и забирает значения в память по условию, все остальное делается не ссылаясь на лист.
"Все гениальное просто, а все простое гениально!!!"
 
Nordheim,я проверил макрос, он работает, спасибо Вам за ваши труды. Сейчас буду детально разбираться в коде.
Что касается ситуации, когда для одной книги необходимо переименование нескольких листов, то здесь на реальных файлах следующая картина. Существует порядка 30 масок в столбце A, которые подставляются в качестве переименования листов, указанных в столбце B. В столбце B возможно порядка 200 различных наименований листов, которые должны быть обработаны.
Есть вариант отфильтровывать строки по каждой маске, создавать новый лист, содержащий в столбце A именно данную маску и применять к нему Ваш макрос. Но идея состояла в том, чтобы иметь возможность переименовывать имена листов по всем маскам разово, так как файлы приходят ко мне каждый день и я их обновляю.
 
т.е. все нормально, тему можно закрывать?
"Все гениальное просто, а все простое гениально!!!"
 
Nordheim,пока не знаю. Я правильно понял, что реализовать переименование сразу нескольких листов для всех книг - задача технически сложная и проще сделать ее ручками?
 
Вопрос не понял, последний код переименовывает несколько листов (которые необходимо переименовать) во всех книгах  исходя из условия описанного в сообщении №18
Изменено: Nordheim - 13.07.2017 11:24:25
"Все гениальное просто, а все простое гениально!!!"
 
Nordheim,понял, сейчас проверю.
 
Цитата
Piddy написал:
файлы приходят ко мне каждый день
Может, если необходимо хранить/накапливать/анализировать информацию целесообразнее будет использовать базу данных (Access)?..
 
Nordheim,макрос работает успешно. Заметил только, что 5% не обрабатываются, но это какие-то специфические книги. Имена у их листов не совсем стандартные.
yozhik, а access позволяет проводить аналогичные преобразования с именами листов до импорта в базу данных?
 
Цитата
Piddy написал:
Заметил только, что 5% не обрабатываются, но это какие-то специфические книги. Имена у их листов не совсем стандартные.
Разобрался, дело было в том, что наименования листов имели длину выше нормы. Спасибо Вам за 100% рабочее решение.

Тему пока не закрывайте, так как есть предложения усовершенствовать макрос, чтобы им могли пользоваться и остальные форумчане. Я уверен, что у кого-то точно была потребность в соответствующем макросе.
Страницы: 1 2 След.
Читают тему
Наверх