INFO: Error or Unexpected Behavior with Office Automation When You Use Early Binding in Visual Basic (319832)



The information in this article applies to:

  • Microsoft Office Excel 2003
  • Microsoft Excel 2002
  • Microsoft Excel 2000
  • Microsoft Visual Basic Professional Edition for Windows 6.0
  • Microsoft Visual Basic Professional Edition for Windows 5.0
  • Microsoft Office PowerPoint 2003
  • Microsoft PowerPoint 2002
  • Microsoft PowerPoint 2000
  • Microsoft Office Word 2003
  • Microsoft Word 2002
  • Microsoft Word 2000

This article was previously published under Q319832

SUMMARY

When you automate a Microsoft Office application, you may receive an error message or you may experience unexpected behavior, as follows.

You may receive one of the following error messages:

Error 91: Object variable or With block variable not set.
Error 462: The remote server machine does not exist or is unavailable.
Error -2147417848 (&H80010108): The object invoked has disconnected from its clients.
You may receive one of the following unexpected behaviors:
  • The property call or the method call seems to succeed, but no results appear in the document that is being modified.
  • A property or a method returns incorrect results.
  • An object that exists returns Nothing when referenced. For example, an empty object reference may appear for ActiveDocument, which you know exists.
  • The Office application continues to run, even if all object variables are set to Nothing.
These issues may occur if the Automation uses early binding in Microsoft Visual Basic 5.0 or Microsoft Visual Basic 6.0. These issues occur when the code makes an unqualified method call or property call to an Office object.

This article gives you advice on how to avoid the problem. The article assumes you are familiar with both Office development and the Visual Basic product.

MORE INFORMATION

Automation clients may use early binding in Visual Basic (VB) to programmatically work with a Microsoft Office application. When Automation clients do so, they may inadvertently use unqualified property or method calls in their code. This may lead to errors or to unexpected behaviors.

Programmers who use an Office application type library in their VB project must be sensitive to this issue when they write code.

Unqualified References in Visual Basic

Visual Basic is designed to make programming simple and intuitive for programmers of all skill levels. VB introduced the concept of the Global object to make the coding for a particular component easier and more user-friendly. Programmers who use the object can call its properties and methods without the need to explicitly dimension and create a new instance of the object. In other words, the object itself can be called from anywhere in the code. Therefore, it is "global." Programmers do not have to explicitly write code on their own to do this.

NOTE: The Global object is differentiated by setting the appobject attribute on the coclass in the type library of the object. It is typically, but not necessarily, called "Global."

For example, consider the LoadPicture method in VB. This method is frequently called without qualification, as follows:

Dim pic As StdPicture
Set pic = LoadPicture("C:\sometestpicture.bmp")
				

However, if you view the LoadPicture function in the Visual Basic Object Browser, you see that the function is really a method on a Global object. VB keeps this Global object loaded for the life of the program. You do not have to dimension or create the object before calling the method. Nor do you have to qualify the call with the object name. VB handles that the first time that the object is accessed. This simplifies the code. VB programmers can focus more on the task at hand than on the objects that are necessary to complete the task.

NOTE: Developers who are familiar with writing ActiveX components in VB will recognize this behavior as the same behavior that you get if you set the instancing property of a Public class to GlobalMultiUse. In fact, a GlobalMultiUse class is a Global object.

When the VB compiler encounters a function or a subroutine that does not appear to belong to the current project, the VB compiler searches the list of Global objects that are referenced in the project. The VB compiler looks for a matching function name and a matching signature among the properties and methods of the object. If the VB compiler finds a match, VB sets the code to call that function or property on the Global object.

When the code is called, VB creates the object if the object has not been created before. VB then sets a reference to that object in a hidden variable. The reference is not released until the project is ended. Projects are typically ended when the application shuts down.

Any unqualified method or property call on that object is invoked on the hidden reference. You do not have access to this hidden variable. You cannot change it or release it from VB code.

Global Objects in Microsoft Office Applications

Microsoft Office is designed to use Global objects in much the same way that VB uses them for its native functions. This makes coding easier for macros written in Microsoft Visual Basic for Applications (VBA). VBA code makes wide use of unqualified property and method calls to keep the code simple and to keep the code understandable for beginners.

For example, the following Microsoft Word VBA code sets some text after the third paragraph in a document:
Sub AddSomeText()
   ActiveDocument.Paragraphs(3).Range.Select
   Selection.Collapse wdCollapseEnd
   Selection.TypeText "Some new text."
End Sub
				

The code uses two objects, ActiveDocument and Selection. Both objects are native to Word VBA. To access these objects, the code makes unqualified method calls on two property procedures on the Word Global object. (The property procedures use the same name and return the respective object.) The process is equivalent to the following:

Public oGlobalWordApp As Word.Application
Sub AddSomeText()
   If oGlobalWordApp Is Nothing Then
    ' Sets variable to the running instance of the Word
    ' Global object (which is nearly the same as Word.Application)...
      Set oGlobalWordApp = Word.Global
   End If
   oGlobalWordApp.ActiveDocument.Paragraphs(3).Range.Select
   oGlobalWordApp.Selection.Collapse wdCollapseEnd
   oGlobalWordApp.Selection.TypeText "Some new text."
End Sub
				

Look at the two code samples. You can see why most developers prefer to use unqualified code. Unqualified code is easier to understand and is less trouble to write. Additionally, when unqualified code is used in the native container for which it is designed, it is also completely safe.

The Problems in Using Unqualified Code with Office

Problems may occur when you reference a Global object that does not live inside your process space. In this situation, many of the assumptions about global objects break down. These assumptions include things such as the following: that there is only one instance; that calls to the object are native to the host; or that calls are kept alive for the length of the host application. When these assumptions break down, buggy behavior may result.

Office applications use Global objects and live out-of-process. Therefore, VB code that uses early binding to automate these applications is especially vulnerable to problems involving unqualified method calls. Note that unqualified method calls only occur if you reference the type library for the Office application in the References dialog box. You typically do this when you use early binding. Code that uses late binding is always qualified. It does not experience these problems if you do not reference the type library.

In itself, unqualified code frequently runs just fine in VB, even when it references out-of-process objects. This makes the problems that you experience harder to deal with, because the code appears to work successfully some of the time. There is, however, one warning sign to look for, as follows:

If the code always appears to work the first time that it is run, and if the errors or the unexpected behaviors occur only during subsequent calls to the same code, an unqualified method call is the cause.

This problem occurs because the code creates a new instance of the Office application each time that it runs, but the unqualified code caused VB to set a hidden reference to the old instance. Therefore, subsequent calls on the hidden variable (for an unqualified method) are made to the wrong server.

Some of the errors or unexpected behaviors that you might experience if you make an unqualified call to an Office object are as follow:
  • Error 462 or Error -2147417848: The code uses an unqualified method on an Office instance that has been ended (for example, by calling the Quit method). If the code is structured to create a new Office application instance each time that it is run, it will typically close the instance at the end of the task. If this code is run a second time, the unqualified call is unsuccessful. VB calls the previous instance, but the remote server has unloaded.
  • Application Does Not Shut Down: Unqualified calls in VB set a hidden variable reference to the Office Global object. Therefore, an Office application may fail to shut down, even if you call the Quit method, because it still has outstanding references. This behavior typically occurs on the first instance that the code uses. However, complex programs may cause it to occur with multiple instances.
  • Error 91 or Object is Missing Errors: You may see errors or unexpected results relating to the application state. You may also see unexpected results relating to an empty object. These behaviors occur if the code creates a new Office instance each time that it is run and if it does not quit the previous instance properly. Or, these behaviors occur if the code creates a new Office instance each time that it is run and if the Office application does not shut down, as mentioned in the preceding issue. These errors occur if the document or other objects that you are trying to access are located in another instance of the application than the Global object that VB has referenced, and if the objects (such as ActiveDocument or ActiveChart) do not exist in the global instance.
  • Code Runs Without Error, But Document Is Incorrect: Unqualified calls can be invoked for an instance other than the one that you explicitly set up. Therefore, some tasks (especially those calls to Selection or Range) may be successfully performed, but these tasks are performed on the wrong document. Avoid the use of non-specific range or non-specific selection objects that can run on any document.
The exact error or behavior may differ depending on the Office application that is involved and depending on the context in which the problem occurs.

Qualifying the Code to Avoid Errors

The best guideline is to avoid using any Office object that you do not explicitly call from a parent object that you set in a specific variable. In other words, look for code that uses Office objects without qualifying which Office instance or document that it is supposed to refer to. For example, this code uses an unqualified call to display the count of open workbooks in Microsoft Excel:

Sub CreateThreeBooks()
   Dim oXL As Excel.Application
   Dim i As Long

 ' Create Excel instance (make it visible for test)...
   Set oXL = New Excel.Application
   oXL.Visible = True
 
 ' Open a few empty workbooks...
   For i = 1 To 3
      oXL.Workbooks.Add
   Next i

 ' How many books did we open?
   MsgBox "Number of workbooks: " & Workbooks.Count, vbMsgBoxSetForeground
   
 ' Shutdown Excel (or do we?)...
   oXL.Quit
   Set oXL = Nothing
 ' Check the Processes list. Excel.exe is still running!
End Sub
				

When you run the code, it appears to run correctly the first time. However, Excel continues to run, even though you called the Quit method. If you call the code again, the message box now incorrectly displays 0 for the workbook count. Your code may now fail where you would expect it to succeed.

To resolve both problems, you must fully qualify the Workbooks object that you reference for the count, as follows:

   MsgBox "Number of workbooks: " & oXL.Workbooks.Count, vbMsgBoxSetForeground
				

Some Office objects and functions are typically unqualified in VBA code. They can cause problems if you use that same code in VB and if you do not add the appropriate qualifications. Here is a list of common objects and functions that are typically unqualified in VBA code.

Application Commonly Used Method/Properties on Global Object
Excel ActiveCell, ActiveChart, ActiveSheet, ActiveWorkbook, Selection, Cells, Charts, Range, Rows, Columns, Sheets, Worksheets, Calculate, Run
PowerPoint ActivePresentation, Presentations, SlideShowWindows, CommandBars, Dialogs
Word ActiveDocument, ActiveWindow, Selection, Documents, Dialogs, FileConverters, InchesToPoints, WordBasic


What to Do If You Experience These Problems

If you have an existing project that no longer works because of one of the problems in this article, here are a few things you can do to fix it:

  • Make sure that you set Option Explicit at the top of each file in your project. This setting makes sure that VB generates a compile-time error and that VB does not automatically use a zero value for constants that it does not recognize.
  • If the project is relatively simple, or if the Office Automation code is brief, remove the Office type library from your list of references, and then recompile the project. You then receive errors about unknown types for each object declaration that you used for an Office type. Change these to type Object. You may also have to change any New statements to use CreateObject instead. If you use any enumeration values or constants from the Office type library, you have to replace them with their numeric value. After you have finished that, the only compile errors that you receive are for unqualified methods. Find each error, and then qualify the call with the application or document object, as appropriate.
  • If the program is complex, try to find the unqualified calls by explicitly forcing the remote Office application to quit after the code runs for the first time. If the code explicitly creates a new instance each time, it should be able to run even if the previous instance was ended. To do so, follow these steps:
    1. Run the code one time to make sure it runs the first time (even if unqualified).
    2. Check the Processes list in the Task Manager window, and then quit the instance of the Office application that you started during the first run.
    3. Rerun the code with VB set to Break on All Errors. If VB breaks and displays Error 462 (or Error -2147417848) during the second run, that line probably contains an unqualified method or property call.
NOTE: Unqualified calls may appear as parameter values to a function or a property that is itself fully qualified. Therefore, examine carefully the parameters that you are passing, especially when you use a named-argument syntax. After you find an unqualified object or function that is not native to Visual Basic, qualify it with the variable name of the Application object that you used to start the Office application.

REFERENCES

For additional information, click the following article numbers to view the articles in the Microsoft Knowledge Base:

178510 PRB: Excel Automation Fails Second Time Code Runs

189618 PRB: Automation Error Calling Unqualified Method or Property

For more information about Office Development in general, visit the following Microsoft Developer Network (MSDN) Web page:

Modification Type:MajorLast Reviewed:1/19/2006
Keywords:kbAutomation kbinfo KB319832