Sub Serge_007() Application.ScreenUpdating = False Application.DisplayAlerts = False Rows("1:2").UnMerge Range("O1:R1") = Range("O2:R2") Rows("2:2").Delete Shift:=xlUp For Each sh In Worksheets If sh.Name = "Справочник" Then sh.Delete Next Set wb = GetObject("d:\Excel_Макрос\0.xls") wb.Sheets("Справочник").Copy After:=Sheets(Sheets.Count) wb.Close False Sheets("Рабочий").Activate arr = Sheets("Справочник").Range("A1").CurrentRegion.Value With CreateObject("Scripting.Dictionary") For i = 1 To UBound(arr) .Item(arr(i, 1)) = arr(i, 2) Next arr = Range(Cells(1, "S"), Cells(Rows.Count, "X").End(xlUp)).Value For i = 1 To UBound(arr) For j = 1 To UBound(arr, 2) If .exists(arr(i, j)) Then arr(i, j) = .Item(arr(i, j)) Else Cells(i, 18 + j).Interior.Color = vbRed End If Next: Next End With Range(Cells(1, "S"), Cells(Rows.Count, "X").End(xlUp)) = arr Application.DisplayAlerts = True Application.ScreenUpdating = True End Sub
[/vba]
Лови [vba]
Code
Sub Serge_007() Application.ScreenUpdating = False Application.DisplayAlerts = False Rows("1:2").UnMerge Range("O1:R1") = Range("O2:R2") Rows("2:2").Delete Shift:=xlUp For Each sh In Worksheets If sh.Name = "Справочник" Then sh.Delete Next Set wb = GetObject("d:\Excel_Макрос\0.xls") wb.Sheets("Справочник").Copy After:=Sheets(Sheets.Count) wb.Close False Sheets("Рабочий").Activate arr = Sheets("Справочник").Range("A1").CurrentRegion.Value With CreateObject("Scripting.Dictionary") For i = 1 To UBound(arr) .Item(arr(i, 1)) = arr(i, 2) Next arr = Range(Cells(1, "S"), Cells(Rows.Count, "X").End(xlUp)).Value For i = 1 To UBound(arr) For j = 1 To UBound(arr, 2) If .exists(arr(i, j)) Then arr(i, j) = .Item(arr(i, j)) Else Cells(i, 18 + j).Interior.Color = vbRed End If Next: Next End With Range(Cells(1, "S"), Cells(Rows.Count, "X").End(xlUp)) = arr Application.DisplayAlerts = True Application.ScreenUpdating = True End Sub
Я немного иначе написал - сначала проверка на существование книги и листа "Справочник" в ней, а потом уже удаление своего листа "Справочник" и операции с шапкой. А то может получиться так, что поудаляем всё, а листа "Справочник" не будет. И чего тогда - и свой лист убили, и чужой не вставили. И еще - в сообщении не стал адреса ячеек выводить. Зачем? Все равно оттуда не скопировать и будешь искать красные. [vba]
Code
Sub tt() Application.ScreenUpdating = 0 Application.DisplayAlerts = 0 fp_ = "D:\Мои_\Стереть\" ' путь fn_ = "Для_справочника.xls" ' название файла sn_ = "Справочник" ' название листа asn_ = ThisWorkbook.ActiveSheet.Name On Error Resume Next Workbooks.Open Filename:=fp_ & fn_ ThisWorkbook.Activate q = Workbooks(fn_).Sheets(sn_).Range("A1") If Err.Number Then MsgBox "Нет или книги " & fp_ & fn_ & ", или листа " & sn_ Exit Sub End If ThisWorkbook.Sheets("Справочник").Delete Workbooks(fn_).Sheets(sn_).Copy After:=ThisWorkbook.Sheets(Sheets.Count) Worksheets(asn_).Activate Windows("Для_справочника.xls").Close Err = "" On Error GoTo 0 With ThisWorkbook.Sheets(asn_) .Rows("1:2").UnMerge .Range("O2:R2").Cut Destination:=.Range("O1:R1") .Rows("2:2").Delete Shift:=xlUp c_ = .Cells(1, Columns.Count).End(xlToLeft).Column If c_ > 18 Then r_ = Sheets(sn_).Range("A" & Rows.Count).End(xlUp).Row For i = 19 To c_ On Error Resume Next .Cells(1, i) = WorksheetFunction.VLookup(.Cells(1, i), Sheets(sn_).Range("A1:B" & r_), 2, 0) If Err.Number Then .Cells(1, i).Interior.Color = 255 e_ = e_ + 1 Err = "" End If On Error GoTo 0 Next i If e_ Then MsgBox "Фигня какая-то в шапке. Посмотри в красных ячейках." End If End With Application.ScreenUpdating = 1 Application.DisplayAlerts = 1 End Sub
[/vba]
Я немного иначе написал - сначала проверка на существование книги и листа "Справочник" в ней, а потом уже удаление своего листа "Справочник" и операции с шапкой. А то может получиться так, что поудаляем всё, а листа "Справочник" не будет. И чего тогда - и свой лист убили, и чужой не вставили. И еще - в сообщении не стал адреса ячеек выводить. Зачем? Все равно оттуда не скопировать и будешь искать красные. [vba]
Code
Sub tt() Application.ScreenUpdating = 0 Application.DisplayAlerts = 0 fp_ = "D:\Мои_\Стереть\" ' путь fn_ = "Для_справочника.xls" ' название файла sn_ = "Справочник" ' название листа asn_ = ThisWorkbook.ActiveSheet.Name On Error Resume Next Workbooks.Open Filename:=fp_ & fn_ ThisWorkbook.Activate q = Workbooks(fn_).Sheets(sn_).Range("A1") If Err.Number Then MsgBox "Нет или книги " & fp_ & fn_ & ", или листа " & sn_ Exit Sub End If ThisWorkbook.Sheets("Справочник").Delete Workbooks(fn_).Sheets(sn_).Copy After:=ThisWorkbook.Sheets(Sheets.Count) Worksheets(asn_).Activate Windows("Для_справочника.xls").Close Err = "" On Error GoTo 0 With ThisWorkbook.Sheets(asn_) .Rows("1:2").UnMerge .Range("O2:R2").Cut Destination:=.Range("O1:R1") .Rows("2:2").Delete Shift:=xlUp c_ = .Cells(1, Columns.Count).End(xlToLeft).Column If c_ > 18 Then r_ = Sheets(sn_).Range("A" & Rows.Count).End(xlUp).Row For i = 19 To c_ On Error Resume Next .Cells(1, i) = WorksheetFunction.VLookup(.Cells(1, i), Sheets(sn_).Range("A1:B" & r_), 2, 0) If Err.Number Then .Cells(1, i).Interior.Color = 255 e_ = e_ + 1 Err = "" End If On Error GoTo 0 Next i If e_ Then MsgBox "Фигня какая-то в шапке. Посмотри в красных ячейках." End If End With Application.ScreenUpdating = 1 Application.DisplayAlerts = 1 End Sub
_Boroda_, Наверное действительно с проверкой на существование файла лучше Изменить блок так [vba]
Code
Rows("2:2").Delete Shift:=xlUp On Error GoTo error_S Set wb = GetObject("d:\Excel_Макрос\0.xls") Set sh = wb.Sheets("Справочник"): Set sh = Nothing For Each sh In ThisWorkbook.Worksheets If sh.Name = "Справочник" Then sh.Delete Next wb.Sheets("Справочник").Copy After:=Sheets(Sheets.Count) wb.Close False: Set wb = Nothing error_S: On Error GoTo 0 Sheets("Рабочий").Activate
[/vba]
_Boroda_, Наверное действительно с проверкой на существование файла лучше Изменить блок так [vba]
Code
Rows("2:2").Delete Shift:=xlUp On Error GoTo error_S Set wb = GetObject("d:\Excel_Макрос\0.xls") Set sh = wb.Sheets("Справочник"): Set sh = Nothing For Each sh In ThisWorkbook.Worksheets If sh.Name = "Справочник" Then sh.Delete Next wb.Sheets("Справочник").Copy After:=Sheets(Sheets.Count) wb.Close False: Set wb = Nothing error_S: On Error GoTo 0 Sheets("Рабочий").Activate
2. Если в справочнике, в столбце В, отсутствует соответствие, то msgBox всё-равно без указания ячейки с ошибкой, а сама ячейка остаётся пустой
3. Если добавить столбец в лист Рабочий, то даже при отсутствии соответствия в справочнике этот столбец остётся с тем значением, которое в нём было раньше и ячейка не указывается в сообщении и не окрашивается
Quote (_Boroda_)
сначала проверка на существование книги и листа "Справочник" в ней
Это лишнее. Если не будет той книги, в которой находится исходный справочник, то и не будет того отчёта, который мы, собственно, обрабатываем
Quote (_Boroda_)
адреса ячеек выводить. Зачем?
Предполагается, что такие случаи будут редко и не более одной-двух ячеек. Есть смысл, увидев адрес, вбить его в поле имя и сразу её (ячейку) увидеть
Quote (Формуляр)
Предлагаю с шапкой не париться, а брать готовую
Не понял, откуда она будет браться? Она ведь одна, постоянно изменяемая, и только на листе Рабочий
Сколько вариантов, спасибо!
Попробовал вариант Андрея. Три момента: 1. O1:R1 остается пустым. Понял почему, [vba]
2. Если в справочнике, в столбце В, отсутствует соответствие, то msgBox всё-равно без указания ячейки с ошибкой, а сама ячейка остаётся пустой
3. Если добавить столбец в лист Рабочий, то даже при отсутствии соответствия в справочнике этот столбец остётся с тем значением, которое в нём было раньше и ячейка не указывается в сообщении и не окрашивается
Quote (_Boroda_)
сначала проверка на существование книги и листа "Справочник" в ней
Это лишнее. Если не будет той книги, в которой находится исходный справочник, то и не будет того отчёта, который мы, собственно, обрабатываем
Quote (_Boroda_)
адреса ячеек выводить. Зачем?
Предполагается, что такие случаи будут редко и не более одной-двух ячеек. Есть смысл, увидев адрес, вбить его в поле имя и сразу её (ячейку) увидеть
Quote (Формуляр)
Предлагаю с шапкой не париться, а брать готовую
Не понял, откуда она будет браться? Она ведь одна, постоянно изменяемая, и только на листе РабочийSerge_007
Не понял, откуда она будет браться? Она ведь одна, постоянно изменяемая, и только на листе Рабочий
Ну, можно её в том же Справочнике хранить (его проще сделать постоянным, чем каждый раз проверять: есть-нет). А то, что изменяемая - так она изменяемая и получится.
Да, с копированием в предыдущем макросе накосячил маненько.
Quote (Serge_007)
Не понял, откуда она будет браться? Она ведь одна, постоянно изменяемая, и только на листе Рабочий
Ну, можно её в том же Справочнике хранить (его проще сделать постоянным, чем каждый раз проверять: есть-нет). А то, что изменяемая - так она изменяемая и получится.
Да, с копированием в предыдущем макросе накосячил маненько.Формуляр
Этот блок шапки всегда одинаков, остальная часть меняется постоянно. Что нужно сделать. 1. Отменить объединение шапки 2. Переместить О2:R2 в О1:R1
Зачем постоянную часть каждый раз трансформировать с одним и тем же результатом? А переменная часть - на формулах. Только вот переменное кол-во ст-цов я не учёл, но это уже решено у коллег.
Quote (Serge_007)
Этот блок шапки всегда одинаков, остальная часть меняется постоянно. Что нужно сделать. 1. Отменить объединение шапки 2. Переместить О2:R2 в О1:R1
Зачем постоянную часть каждый раз трансформировать с одним и тем же результатом? А переменная часть - на формулах. Только вот переменное кол-во ст-цов я не учёл, но это уже решено у коллег.Формуляр
Serge_007, кинь пример поподробнее (строк полста). И желательно с данными, на которых пустой msgbox выскакивает. Не понял про автозаполнение. А добавление столбцов вообще заказано не было. Где добавлять хочешь?
Serge_007, кинь пример поподробнее (строк полста). И желательно с данными, на которых пустой msgbox выскакивает. Не понял про автозаполнение. А добавление столбцов вообще заказано не было. Где добавлять хочешь?RAN
Sub tt() Application.ScreenUpdating = 0 Application.DisplayAlerts = 0 fp_ = "D:\Мои_\Стереть\" ' путь fn_ = "Для_справочника.xls" ' название файла sn_ = "Справочник" ' название листа asn_ = ThisWorkbook.ActiveSheet.Name On Error Resume Next Workbooks.Open Filename:=fp_ & fn_ ThisWorkbook.Activate q = Workbooks(fn_).Sheets(sn_).Range("A1") If Err.Number Then MsgBox "Нет или книги " & fp_ & fn_ & ", или листа " & sn_ Exit Sub End If ThisWorkbook.Sheets("Справочник").Delete Workbooks(fn_).Sheets(sn_).Copy After:=ThisWorkbook.Sheets(Sheets.Count) Worksheets(asn_).Activate Windows("Для_справочника.xls").Close Err = "" On Error GoTo 0 With ThisWorkbook.Sheets(asn_) .Rows("1:2").UnMerge .Range("O2:R2").Cut Destination:=.Range("O1:R1") .Rows("2:2").Delete Shift:=xlUp c_ = .Cells(1, Columns.Count).End(xlToLeft).Column If c_ > 18 Then r_ = Sheets(sn_).Range("A" & Rows.Count).End(xlUp).Row For i = 19 To c_ On Error Resume Next .Cells(1, i) = WorksheetFunction.VLookup(.Cells(1, i), Sheets(sn_).Range("A1:B" & r_), 2, 0) If Err.Number Then .Cells(1, i).Interior.Color = 255 e_ = e_ & .Cells(1, i).Address(0, 0) & ", " Err = "" End If On Error GoTo 0 Next i If e_ <> "" Then MsgBox "Фигня какая-то в шапке. Посмотри в ячейках " & e_ & "они красные." End If End With Application.ScreenUpdating = 1 Application.DisplayAlerts = 1 End Sub
[/vba]
Серег, посмотри так (выводит адреса) [vba]
Code
Sub tt() Application.ScreenUpdating = 0 Application.DisplayAlerts = 0 fp_ = "D:\Мои_\Стереть\" ' путь fn_ = "Для_справочника.xls" ' название файла sn_ = "Справочник" ' название листа asn_ = ThisWorkbook.ActiveSheet.Name On Error Resume Next Workbooks.Open Filename:=fp_ & fn_ ThisWorkbook.Activate q = Workbooks(fn_).Sheets(sn_).Range("A1") If Err.Number Then MsgBox "Нет или книги " & fp_ & fn_ & ", или листа " & sn_ Exit Sub End If ThisWorkbook.Sheets("Справочник").Delete Workbooks(fn_).Sheets(sn_).Copy After:=ThisWorkbook.Sheets(Sheets.Count) Worksheets(asn_).Activate Windows("Для_справочника.xls").Close Err = "" On Error GoTo 0 With ThisWorkbook.Sheets(asn_) .Rows("1:2").UnMerge .Range("O2:R2").Cut Destination:=.Range("O1:R1") .Rows("2:2").Delete Shift:=xlUp c_ = .Cells(1, Columns.Count).End(xlToLeft).Column If c_ > 18 Then r_ = Sheets(sn_).Range("A" & Rows.Count).End(xlUp).Row For i = 19 To c_ On Error Resume Next .Cells(1, i) = WorksheetFunction.VLookup(.Cells(1, i), Sheets(sn_).Range("A1:B" & r_), 2, 0) If Err.Number Then .Cells(1, i).Interior.Color = 255 e_ = e_ & .Cells(1, i).Address(0, 0) & ", " Err = "" End If On Error GoTo 0 Next i If e_ <> "" Then MsgBox "Фигня какая-то в шапке. Посмотри в ячейках " & e_ & "они красные." End If End With Application.ScreenUpdating = 1 Application.DisplayAlerts = 1 End Sub
On Error GoTo error_S Set wb = GetObject(bookName) Set sh = wb.Sheets("Справочник") For Each sh In ThisWorkbook.Worksheets If sh.Name = "Справочник" Then sh.Delete Next wb.Sheets("Справочник").Copy After:=Sheets(Sheets.Count) wb.Close False: Set sh = Nothing: Set wb = Nothing error_S: On Error GoTo 0 Sheets("Рабочий").Activate
arr = Sheets("Справочник").Range("A1").CurrentRegion.Value With CreateObject("Scripting.Dictionary") For i = 1 To UBound(arr) .Item(arr(i, 1)) = arr(i, 2) Next arr = Range(Cells(1, "S"), Cells(Rows.Count, lastCol).End(xlUp)).Value For i = 1 To UBound(arr) For j = 1 To UBound(arr, 2) If .exists(arr(i, j)) Then arr(i, j) = .Item(arr(i, j)) Else Cells(i, 18 + j).Interior.Color = vbRed Strc = Strc & "; " & Cells(i, 18 + j).Address End If Next: Next End With Range(Cells(1, "S"), Cells(Rows.Count, lastCol).End(xlUp)) = arr Application.DisplayAlerts = True Application.ShowWindowsInTaskbar = True Application.ScreenUpdating = True If Len(Strc) Then MsgBox Mid$(Strc, 2)
End Sub
[/vba]
Подправил код. [vba]
Code
Sub Serge_007() Dim wb As Workbook, sh As Worksheet, arr Dim bookName As String, Strc As String Dim i As Long, j As Long, lastCol As Long
On Error GoTo error_S Set wb = GetObject(bookName) Set sh = wb.Sheets("Справочник") For Each sh In ThisWorkbook.Worksheets If sh.Name = "Справочник" Then sh.Delete Next wb.Sheets("Справочник").Copy After:=Sheets(Sheets.Count) wb.Close False: Set sh = Nothing: Set wb = Nothing error_S: On Error GoTo 0 Sheets("Рабочий").Activate
arr = Sheets("Справочник").Range("A1").CurrentRegion.Value With CreateObject("Scripting.Dictionary") For i = 1 To UBound(arr) .Item(arr(i, 1)) = arr(i, 2) Next arr = Range(Cells(1, "S"), Cells(Rows.Count, lastCol).End(xlUp)).Value For i = 1 To UBound(arr) For j = 1 To UBound(arr, 2) If .exists(arr(i, j)) Then arr(i, j) = .Item(arr(i, j)) Else Cells(i, 18 + j).Interior.Color = vbRed Strc = Strc & "; " & Cells(i, 18 + j).Address End If Next: Next End With Range(Cells(1, "S"), Cells(Rows.Count, lastCol).End(xlUp)) = arr Application.DisplayAlerts = True Application.ShowWindowsInTaskbar = True Application.ScreenUpdating = True If Len(Strc) Then MsgBox Mid$(Strc, 2)