2015-11-13 5 views
4

У меня возникла проблема с автоматизацией файла Excel. Сценарий VBA в Excel сначала открывает приложение Word, и документ Word:Обнаружение, если объект был отключен от его клиентов

Dim wordApp As Object 
    Set wordApp = CreateObject("Word.Application") 

    vPath = Application.ActiveWorkbook.Path 
    Set wordDoc = wordApp.Documents.Open(vPath & "\test.doc") 

И затем я вызвать подпрограмму в документ Word, проходя некоторые данные из файла Excel:

Call wordApp.Run("StartWithData", variable1, variable2) 

Если Excel обнаруживает, что возникает ошибка в этой подпрограмме, я закрываю документ Word, и приложение Word, Excel из в метке я называю Err1:

On Error Goto Err1 
    'all the code from above 
    Exit Sub 

    Err1: 
    wordDoc.Close wdCloseWithoutSaving 
    wordApp.Quit SaveChanges:=wdDoNotSaveChanges 
    Set wordDoc = Nothing 
    Set wordApp = Nothing 

Это отлично работает U при нормальных обстоятельствах; Однако, если документ слова или приложение закрыто до Err1 этикеток выполняются (например, пользователь вручную закрытии документа), я получаю следующее сообщение об ошибке:

Run-time error '-2147417848 (80010108)':
Automation error The object invoked has disconnected from its clients.

, который имеет смысл, потому что в wordApp и/или wordDoc переменные все еще ссылаются на объекты приложения и документа, и эти объекты больше не существуют (но также не считаются Nothing).

Так вот мой запрос: Есть ли способ проверить, был ли объект отключен от своего клиента до возникновения ошибки во время выполнения, чтобы избежать необходимости полагаться на on error resume next?

Such as: 

    If Not isDisconnected(wordDoc) Then 
    wordDoc.Close wdCloseWithoutSaving 
    End If 

    If Not isDisconnected(wordApp) Then 
    wordApp.Quit SaveChanges:=wdDoNotSaveChanges 
    End If 

Update 1:

Посмотрев на omegastripes' answer, я понял, что ошибка, приведенные выше только возникает, когда документ (wordDoc) был объект, который был отключен. Если приложение Word (wordApp) является то, что отсоединился, я получаю следующее сообщение об ошибке:

Run-time error '462':

The remote server machine does not exist or is unavailable

+0

Почему бы вам просто не проверить объект ошибки? 'Err.Number' или' Err.Description'. Если объект отключен, потому что он закрыт, то проверить нечего - так что вы не можете это проверить. –

+0

@MacroMan Это хорошая мысль; однако ошибка, которая возникает, - Ошибка 440: «Ошибка автоматизации», которая будет выбрана по нескольким причинам, включая отключенный объект, а также любую ошибку, возникающую при вызове удаленной процедуры (подпрограмма Word). – Jonathan

+0

Я предполагаю, что вы можете проверить, все ли работает приложение Word (что довольно просто), но проверка того, что что-то отключена, будет очень сложной, если вообще возможно, тот факт, что это не связано, означает, что это свойства и методы невозможно получить доступ. Только то, что вы можете попробовать, это увидеть, возвращает ли объект 'wordApp'' Nothing' –

ответ

3

Рассмотрим следующий пример:

Sub Test() 
    Dim wordApp As Object 
    Dim wordWnd As Object 
    Dim wordDoc As Object 

    Set wordApp = CreateObject("Word.Application") 
    Set wordWnd = wordApp.Windows ' choose any object property as indicator 
    wordApp.Visible = True ' debug 
    Set wordDoc = wordApp.Documents.Open(Application.ActiveWorkbook.Path & "\test.doc") 
    MsgBox IsObjectDisconnected(wordWnd) ' False with opened document 
    wordDoc.Close 
    MsgBox IsObjectDisconnected(wordWnd) ' False with closed document 
    wordApp.Quit ' disconnection 
    MsgBox IsObjectDisconnected(wordWnd) ' True with quited application 
End Sub 

Function IsObjectDisconnected(objSample As Object) As Boolean 
    On Error Resume Next 
    Do 
     IsObjectDisconnected = TypeName(objSample) = "Object" 
     If Err = 0 Then Exit Function 
     DoEvents 
     Err.Clear 
    Loop 
End Function 

Кажется любое определение типа переменной, которая ссылки на характеристическую Объекты Word, такие как .Documents, .Windows, .RecentFiles и т. Д., Сделанные сразу же после того, как были выведены команды закрытия документа или команды закрытия приложения, может возникнуть ошибка 14: из пространства строк, в то время как приложение Word обрабатывает команду. Такое же обнаружение объекта Application может также зависать приложение Excel.

В примере TypeName() вызова обернутый в петлю ОЭРНА, которые должны пропустить нерелевантные результаты получить явную обратную связь разъединения, опираясь на имени типа, но не на количестве ошибок. Чтобы избежать зависания, проверяется свойство .Windows вместо Application.

+0

Это умно! Полезно отметить, что документы (например, 'wordDoc') обычно имеют тип' Document', но при отключении они меняются на 'Object'. К сожалению, ваш ответ, полезный как есть, отвечает только на половину вопроса. Это связано с тем, что приложения (например, 'wordApp') продолжают иметь тип' Application' даже после их отключения. Поэтому, несмотря на то, что я могу обнаружить, когда документ отключен от вашего ответа, я все еще не могу обнаружить, когда приложение само отсоединяется. Однако вы заставили меня понять, что я получаю другую ошибку, когда приложение отключено (см. Обновление 1). – Jonathan

+0

@Jonathan - Так почему бы не поймать ошибку 14 в 'IsObjectDisconnected'? Я озадачен, почему вы так не склонны использовать обработчик ошибок для обнаружения ошибки. – Comintern

+0

@Jonathan, Документ нельзя отключать отдельно, так как это свойство объекта Word. Только приложение может быть отключено. Проверка типа переменной, относящейся к одному из свойств, показывает фактическое состояние приложения. Поэтому, если тип ссылки на свойство Document - «Объект», то это явно означает, что приложение отключено. – omegastripes

Смежные вопросы