2015-06-19 3 views
1

У меня есть два метода, которые, как мне кажется, должны указывать, открыт ли файл.VBA: Два метода просмотра, если файл открыт

Метод 1 (Ошибка: Подстрочный вне диапазона):

If Not Workbooks(filename) Is Nothing Then 
    Workbooks.Open (filename) 
End If 

Способ 2:

If Not IsWorkbookOpen(filename) Then 
    Workbooks.Open (filename) 
End If 

Где IsWorkbookOpen() находится:

Private Function IsWorkbookOpen(wbname) As Boolean 

Dim wBook As Workbook 
Set wBook = Nothing 

On Error Resume Next 
Set wBook = Workbooks(wbname) 

If wBook Is Nothing Then 
    IsWorkbookOpen = False 
    Else: IsWorkbookOpen = True 
End If 

End Function 

Помимо On Error Resume Next, Способ 1 представляется практически таким же, как Способ 2.

Может ли кто-нибудь объяснить, почему Способ 1 дает ошибку?

спасибо.

ответ

5

Они оба дают ошибку индексации вне диапазона. Но в методе 2 вы подавляете эту ошибку с On Error Resume Next.

Sub SeeError() 

    On Error Resume Next 
    Debug.Print Workbooks("DoesNotExist").Name 

    Debug.Print Err.Description 

End Sub 

Отпечаток «Подстрочный индекс вне диапазона» в окне «Немедленное». Операция On Error не останавливает ошибку, она просто обрабатывает ее. Метод 1 не обрабатывает ошибки, поэтому обработка ошибок по умолчанию (прекратить выполнение и сообщить об ошибке) действует.

0

Workbooks(filename) пытается получить элемент с идентификатором (или 'index') filename из коллекции Workbooks. Если коллекция не содержит такого элемента, вы получите ошибку «Подзаголовок вне диапазона». (Итак, в двух словах: этот код будет терпеть неудачу, когда файл не будет открыт. Возможно, вы этого не хотите.)

Однако знание о том, что такой доступ завершится неудачно, если файл не открыт, то есть ошибка повышается, используется во втором методе. Код пытается получить элемент с идентификатором filename из коллекции Workbooks и присвоить его переменной wBook. Если он терпит неудачу, значение переменной wBook останется Nothing. Если он преуспеет, переменная wBook будет содержать ссылку на соответствующий объект рабочей книги.

0

VBA пытается оценить все детали, прежде чем оценивать условный оператор. Так что, если у меня есть переменная myvar = "xyz" и попробуйте запустить следующие строки ...

If IsNumeric(myvar) And Round(myvar, 1) = 3 Then 
    'you will get an error before the IF is evaluated 
End If 

он не будет работать. VBA оценит IsNumeric(myvar) штраф, затем попытайтесь оценить Round(myvar, 1) = 3 и получите сообщение об ошибке, прежде чем он проверит все условные. Таким образом, VBA сообщит вам об ошибке, прежде чем он выполнит оператор AND. Если VBA имеет short circuit evaluation, он будет работать нормально, поскольку первая часть будет оцениваться как false.

Но следующий будет работать

If IsNumeric(myvar) Then 
    If Round(myvar, 1) = 3 Then 
     'second IF statement is not touched since first IF statement evaluates to false 
    End If 
End If 

Это работает, потому что IsNumeric(myvar) принимает значение ложь, и поэтому пропускает вложенный оператор.

Таким образом, ошибка, которую он набрасывает на Workbooks(filename), просто даст ошибку, если вы не скажете ей возобновить ее. Таким образом, метод, который я использую

On Error Resume Next 
    Set wb = Workbooks(file) 
    If wb Is Nothing Then 
     Set wb = Application.Workbooks.Open(dir & "\" & file, ReadOnly:=True) 
    End If 
    On Error GoTo 0 

Edited дать более подробно и правильно захватить, что второй пример не будет оцениваться, а также обеспечить полезное решение вопроса под рукой.

+0

Не могли бы вы уточнить? Почему ваши два примера отличаются друг от друга? Я также думаю, что вы хотели использовать myvar в своей декларации, а не просто var. – ale10ander

+1

Я отредактировал мое сообщение, чтобы добавить более подробную информацию. Дайте мне знать, если вам нужно уточнить. –

+0

Спасибо! Теперь я понимаю, что вы говорите, но я смущен тем, что debug.print «покажет». Мое понимание кода и вашего объяснения состоит в том, что этот текст никогда не будет отображаться. – ale10ander