Немного запутался в теме про обработчик ошибок, хотя, скорее всего, я нашёл ответ на вопрос в этой теме, просто не могу его понять до конца.
Необходимо, чтобы в случае ошибки, которая возникает в определенный момент в коде, часть кода пропускалась, появлялся MsgBox с определенным текстом, после чего макрос продолжал бы работать в нормальном режиме (если будет какая-нибудь другая ошибка далее - выскочит диалоговое окно).
Знаю, что задача простая, ну вот туплю что-то...
Код
On Error GoTo ErrorHandler
Set iWb = GetObject("C:\Users\A670669\Desktop\SCR_Managers.xlsx")
iLastRowSCR = iWb.Sheets(1).Cells(Rows.Count, 1).End(xlUp).row
Set iBodySCR = iWb.Sheets(1).Range("B2:M" & iLastRowSCR)
iWb.Names.Add Name:="BodySCR", RefersTo:=iBodySCR
With .ListColumns("Rate").DataBodyRange
.Formula = "=IFERROR(VLOOKUP(A3,SCR_Managers.xlsx!BodySCR,12,0),0)"
.Cells.Value = .Cells.Value
End With
iWb.Close False
ErrorHandler:
MsgBox "Произошла ошибка"
On Error Resume Next
На данный момент все как надо, только вот когда даже ошибки нет вылезает MsgBox.
Заранее спасибо.
P.S. Как-то криво написал название темы, должна была быть VBA: Обработчик ошибок, пропуск кода и продолжение выполнения макроса.
On Error Resume Next
MsgBox "Произошла ошибка"
If Err Then GoTo ErrorHandler
Set iWb = GetObject("C:\Users\A670669\Desktop\SCR_Managers.xlsx")
iLastRowSCR = iWb.Sheets(1).Cells(Rows.Count, 1).End(xlUp).row
Set iBodySCR = iWb.Sheets(1).Range("B2:M" & iLastRowSCR)
iWb.Names.Add Name:="BodySCR", RefersTo:=iBodySCR
With .ListColumns("Rate").DataBodyRange
.Formula = "=IFERROR(VLOOKUP(A3,SCR_Managers.xlsx!BodySCR,12,0),0)"
.Cells.Value = .Cells.Value
End With
iWb.Close False
ErrorHandler:
Framed написал: только вот когда даже ошибки нет вылезает MsgBox
Обработчик ошибок поместите в самый конец кода, а перед ним должна быть строка Exit Sub
Код
On Error GoTo ErrorHandler
Set iWb = GetObject("C:\Users\A670669\Desktop\SCR_Managers.xlsx")
iLastRowSCR = iWb.Sheets(1).Cells(Rows.Count, 1).End(xlUp).Row
Set iBodySCR = iWb.Sheets(1).Range("B2:M" & iLastRowSCR)
iWb.Names.Add Name:="BodySCR", RefersTo:=iBodySCR
With .ListColumns("Rate").DataBodyRange
.Formula = "=IFERROR(VLOOKUP(A3,SCR_Managers.xlsx!BodySCR,12,0),0)"
.Cells.Value = .Cells.Value
End With
iWb.Close False
Exit Sub
'обработчик ошибок
ErrorHandler:
MsgBox "Произошла ошибка"
End Sub
Согласие есть продукт при полном непротивлении сторон
Sanja, спасибо, но разве Exit Sub не остановит выполнение всего макроса, если ошибки не будет?
Я уточню, а то мне кажется, я плохо объяснил в шапке.
Код
'Код
'Код
'Код
On Error GoTo ErrorHandler
Set iWb = GetObject("C:\Users\A670669\Desktop\SCR_Managers.xlsx")
iLastRowSCR = iWb.Sheets(1).Cells(Rows.Count, 1).End(xlUp).row
Set iBodySCR = iWb.Sheets(1).Range("B2:M" & iLastRowSCR)
iWb.Names.Add Name:="BodySCR", RefersTo:=iBodySCR
With .ListColumns("Rate").DataBodyRange
.Formula = "=IFERROR(VLOOKUP(A3,SCR_Managers.xlsx!BodySCR,12,0),0)"
.Cells.Value = .Cells.Value
End With
iWb.Close False
ErrorHandler:
MsgBox "Произошла ошибка"
'Код
'Код
'Код
Выполняется макрос, и вот на 5 строке может выскочить ошибка, например, если файла нет, или его имя неверное. Мне нужно, чтобы в этом случае, часть кода 5-13 строка игнорировалась, не выполнялась и выскочил бы MsgBox c текстом, например, "Нет файла или имя некорректно". Далее код, который идет после ErrorHandler должен выполняться в обычном режиме (обычный режим для меня - это когда дальнейшие ошибки не вернут меня к ErrorHandler, простите за убогое объяснение).
В случае же, если ошибки на 5 строке моего примера не возникнет - код работает в штатном режиме.
'Код
'Код
'Код
On Error resume next
Set iWb = GetObject("C:\Users\A670669\Desktop\SCR_Managers.xlsx")
if err =0 then
iLastRowSCR = iWb.Sheets(1).Cells(Rows.Count, 1).End(xlUp).row
Set iBodySCR = iWb.Sheets(1).Range("B2:M" & iLastRowSCR)
iWb.Names.Add Name:="BodySCR", RefersTo:=iBodySCR
With .ListColumns("Rate").DataBodyRange
.Formula = "=IFERROR(VLOOKUP(A3,SCR_Managers.xlsx!BodySCR,12,0),0)"
.Cells.Value = .Cells.Value
End With
iWb.Close False
else
MsgBox "Произошла ошибка"
err.clear ' или on error goto 0
end if
'Код
'Код
'Код
БМВ, спасибо, все отлично, только теперь в случае ошибки ниже End If, VBA продолжит выполнение кода, даже если, к примеру, название листа out of range и так далее.
Framed, я не зря там написал ' или on error goto 0 В зависимости от потребностей или сбросить ошибку или и сбросить и прекратить обработку ошибок. Конечно и через переход на метки можно сделать, но я отвык.
Nordheim, потенциально ошибка в том, что файл с таким названием может отсутствовать на рабочем столе у юзера. Этот файл (если он есть) в моем коде открывается, оттуда ВПР-ом подтягивается информация, после чего он закрывается. Если такого файла нет - мне нужно было, чтобы:
1. Выводилось сообщение со специальным текстом, т.е. MsgBox; 2. Пропускался кусок кода (который открывает файл, создает именной диапазон для ВПР, подтягивает куда надо данные с этого листа с помощью ВПР, превращает формулы в значения и закрывает книгу); 3. Макрос снова бы работал в обычном режиме (то есть в режиме "on error go to 0").
Вообще, мне помогли и тему можно было закрывать, но раз уж вы спросили
БМВ, да, и я даже прочитал это несколько раз перед тем, как создать тему. Просто, откровенно говоря, не доходило до меня, как это правильно использовать; примеры из гугла не добавили ясности. Одним словом, еще учиться и учиться.
Framed написал: Nordheim , потенциально ошибка в том, что файл с таким названием может отсутствовать на рабочем столе у юзера.
А если так:
Код
Sub test()
Dim fname$, iPath$
iPath = "C:\Users\A670669\Desktop\SCR_Managers.xlsx"
fname = Dir(iPath)
If fname <> "" Then
'обработка если файл существует
Else: MsgBox "Произошла ошибка"
End If
End Sub
Никакого On Error
PS: Обработчик ошибок это конечно хорошо, вставил в начало и никаких проблем с кодом, зато потом вылезет какая ни-будь "бяка" в отчетах.
Framed, очень много чего вам посоветовали - лень читать всё)) 1. В большинстве случаев от меток можно абсолютно безболезненно избавится, но иногда они помогают. Например, можно избежать "ветвления" кода далеко "вправо" — вот ссылка на тему с холиваром)))
Итак, в чём проблема… Всё просто — код доходит до строки ErrorHandler: MsgBox "Произошла ошибка" и выводит сообщение об ошибке (как и должен). Чтобы этого избежать, я обычно делаю, как в #4 (Sanja), но можно и "в лоб" обойти:
— в таком случае, если мы дошли до GoTo nx, то просто "перепрыгиваем" ErrorHandler на метку nx. Если же произойдёт ошибка, то макрос "перепрыгнет" уже к метке ErrorHandler, минуя GoTo nx.
P.S.: скорее всего, в вашем случае никакого On Error GoTo ErrorHandler не нужно — это подтверждает и наличие примеров, где легко без него можно обойтись. Я использую метки в основном, если нужно вернуться "выше по коду" (повтор ввода информации пользователем в случае ошибки) или, как уже сказал, чтобы избежать "ветвления" (многоуровневых вложенных "If—Else—End If"). Но дело (как кодить) исключительно ВАШЕ
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Nordheim, тут есть подвох, я с таким встречаюсь регулярно (правда не со скриптамии, но не суть)
Код
iPath = "C:\Users\A670669\Desktop\Год 2019\Документы раздолбая\" _
& "Результаты совещания по вопросам бездумного использования длинных имен файлов и каталогов\" _
& "Выступление главного систематизатора\……\SCR_Managers.xlsx"
Короче, при полном пути более 260 символов, файл есть, он виден, но открыть его не возможно, впрочем как и скопировать или удалить, понятно что лучше в этом случае обработать длину пути, но порой проще просто обратится и обработать ошибку. Вариант 2, это уже последствия сетевого доступа к общим файлам. При переносе файлов или каталогов права не наследуются от каталога в который поместили файлы , а сохраняются прежними. Это может привести к тому что также видеть видно, а вот прочесть никак. И в этом случае без обработки ошибки не обойтись.
Но в целом я полностью согласен, что обрабатывать ошибку надо там, где избежать её не возможно другими методами.
Jack Famous, так как я родом из VBS, а там нет Resume, то перешел на метку по ошибке, обратно не вернешься, что означает не продолжить с того же места. а это означает или куча меток и отдельные обработчики для каждой ошибки или …..
а я, стало быть, из VBA и могу использовать крутые штуки типа возврата наверх))
Вот такая, например
Код
' Пример использования
Sub t()
Dim temp
temp=18
If Not PRDX_InputNumberAsText(temp,"сколько вам годиков")Then exit Sub Else MsgBox "Годиков: " & temp
End Sub
' Функция "Ввод числа"
Public Function PRDX_InputNumberAsText(varNum, Optional txtTitle$ = "ЧИСЛО", Optional AfterComma As Byte = 0, Optional MoreThanZero As Boolean = True) As Boolean
Dim temp, txtPromt$
If MoreThanZero Then txtPromt = "Введите положительное число с " & AfterComma & " знаками после запятой" Else txtPromt = "Введите число с " & AfterComma & " знаками после запятой…"
GoTo inp
reinp: MsgBox "Некорректное ЧИСЛО!", vbCritical, "ОШИБКА ВВОДА"
inp: temp = Application.InputBox(txtPromt, "Введите " & txtTitle, CStr(varNum), Type:=2)
If temp = "False" Then Exit Function
If Not PRDX_IsCorrectNumber(temp, AfterComma, MoreThanZero) Then GoTo reinp Else varNum = --temp: PRDX_InputNumberAsText = True: Exit Function
End Function
' Функция "Проверка числа на корректность"
Public Function PRDX_IsCorrectNumber(ByVal num, Optional AfterComma As Byte = 0, Optional MoreThanZero As Boolean = True) As Boolean
Dim temp
If TypeName(num) = "Range" And IsDate(num) Then Exit Function
On Error Resume Next: temp = --num * 1: If Err.Number > 0 Then Exit Function
If Not IsNumeric(temp) Then Exit Function
On Error GoTo er
If temp <> WorksheetFunction.Round(temp, AfterComma) Then Exit Function
If MoreThanZero And temp <= 0 Then Exit Function
PRDX_IsCorrectNumber = True
er: End Function
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
БМВ, На сколько я понимаю в данном случае путь прописывается руками, и визуально видно сколько символов.
Цитата
БМВ написал: при полном пути более 260 символов, файл есть, он виден, но открыть его не возможно
Не сталкивался, потому наверное, что c Excel работаю постольку поскольку, это больше для саморазвития (интересные задания иногда встречаются). Но теперь буду знать, а обработчиками в основном пользуюсь либо для заполнения коллекции либо в цикле где неправильный тип данных указывают и цикл не завершается пока ошибка не будет устранена.
"Все гениальное просто, а все простое гениально!!!"
Jack Famous, спасибо за разъяснения; Nordheim, вам тоже большое спасибо, на самом деле, мне очень понравилось это решение, как и решение участника БМВ. БМВ, спасибо за полезную информацию про ограничение.
Все-таки поясню: планируется, что файл, наличие которого проверяется, я буду высылать юзерам ежемесячно. У него относительно постоянная форма, меняются лишь данные. Соответственно, название файлу задаю тоже я. Файл носит вспомогательный характер. Вряд ли юзеры будут его переименовывать (я обязательно скажу, чтобы этого не делали) - их задача состоит лишь в том, чтобы один раз скопировать этот файл из Аутлука и куда-нибудь его закинуть, а после прописать корректный путь в VBA (а вот это им придется делать в любом случае самим, увы).
Framed написал: (а вот это им придется делать в любом случае самим, увы)
А если написать юзерам что бы сохранили файл с макросом и файл из которого берутся данные, в одну папку, то и прописывать ничего не нужно. Как вариант, можно сделать выбор файла.
"Все гениальное просто, а все простое гениально!!!"
This behavior is based on a 256-character limitation in Excel for creating links to another file. This limit of 218 characters for the path name is based on the following:•Up to 31 characters in a sheet name.
•Apostrophes and brackets used to denote the workbook name.
•An exclamation point.
•A cell reference.
For example, the path for a file might resemple the following:
Если перевести кратко, то, для работы с другой книгой, ссылка не может быть больше 256 символов, включая дополнительные символы (скобки,апострофы, восклицательный знак), имя листа и диапазон. если учесть что Адрес может быть $AAA$1000000 (12 сим) +31 на имя листа + 5 на спец символы, то на путь останется менее 218ти 256-12-31-5=208
Nordheim написал: А если написать юзерам что бы сохранили файл с макросом и файл из которого берутся данные, в одну папку
Вариант файла с макросом при открытии запрашивает папку для сохранения, затем сохраняет текущую книгу в указанную папку, и удаляет модуль с процедурой сохранения. создал доп. модуль в котором дублировал код из удаляемого модуля, потому что после первого открытия его больше не будет. Может понадобится.
Коллеги, прошу прощения заранее, что поднимаю старую тему и задаю в ней вопрос, но он связан с тем же макросом и с тем, что мне ответил пользователь Nordheim.
Цитата
Nordheim написал: А если написать юзерам что бы сохранили файл с макросом
Файлы не с макросом, потому что модуль с ним находится в личной книге макросов.
Цитата
Nordheim написал: Как вариант, можно сделать выбор файла.
Вот тут я хотел бы уточнить, если вы не против. Можно ли сделать такой алгоритм (но я точно не знаю, в самом макросе, или сделать отдельный), который поможет юзеру выбрать вспомогательный файл (как с сохранением, с помощью окна), а основной макрос бы ссылался на выбранный файл.
Зачем это нужно: планируются, что такие вспомогательные файлы будут отправляться юзерам раз в месяц, соответственно, можно их просто назвать одним именем и заменять один другим (как и реализованно в данный момент), но было бы лучше, если бы они сохранялись в специально созданной для этого папке, а юзеры могли бы просто "переключаться" между файлами, из которых нужно брать инфу.
Framed, если вопрос не связан с темой (Обработчик ошибок, пропуск куска кода), то создавайте новую
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄