Проблемы
При попытке использовать GetObject (Microsoft Visual Basic) или GetActiveObject (Microsoft Visual C++) для автоматизации приложения Microsoft Office появляется одно из следующих сообщений об ошибке, даже если приложение Office запущено.
Сообщение об ошибке 1
Ошибка во время выполнения «429»: компонент ActiveX не может создать объект
Сообщение об ошибке 2
Ошибка: 0x800401e3 «операция недоступна»
Причина
Несмотря на то, что приложение Office запущено, оно может быть не зарегистрировано в таблице текущих объектов (ROT). Запущенный экземпляр приложения Office должен быть зарегистрирован в таблице ROT, прежде чем его можно будет присоединить к функции GetObject (Visual Basic) или GetActiveObject (Visual C++). При запуске приложения Office регистрация запущенных объектов сразу же завершается. Это оптимизирует процесс запуска приложения. Вместо того чтобы регистрироваться при запуске, приложение Office регистрирует запущенные объекты в таблице ROT после того, как он теряет фокус. Таким образом, при попытке использовать GetObject или GetActiveObject для присоединения к запущенному экземпляру приложения Office перед тем, как приложение теряет фокус, может появиться одно из описанных выше ошибок.
Решение
С помощью кода можно изменить фокус от приложения Office на свое собственное приложение (или другое приложение), чтобы позволить ему зарегистрироваться в таблице ROT. Кроме того, если ваш код запускает exe-файл приложения Office, может потребоваться дождаться завершения загрузки приложения Office, прежде чем пытаться присоединиться к запущенному экземпляру. Пример кода предлагается в разделе «Дополнительные сведения».
Статус
Такое поведение является особенностью данного продукта.
Дополнительная информация
В большинстве случаев разработчикам, которые хотят автоматизировать приложение Office, нужно использовать CreateObject (Visual Basic) или CoCreateInstance (Visual C++) для запуска нового экземпляра приложения Office. Однако в некоторых случаях может потребоваться автоматизировать приложение Office, которое уже запущено: например, если пользователь ранее запустил приложение Office. Или, если вы запустили исполняемый файл приложения Office с помощью кода, так что вы можете указать параметры командной строки для приложения. Для автоматизации работающего приложения Office необходимо использовать GetObject или GetActiveObject.
Действия по воспроизведению поведения
-
Запустите Microsoft Visual Basic и создайте новый стандартный проект EXE. По умолчанию создается форма Form1.
-
Добавьте в форму Form1 элемент управления CommandButton .
-
Добавьте следующий код в модуль кода формы.
Private Sub Command1_Click() Dim oExcel As Object ' Launch a new instance of Microsoft Excel: Shell "C:Program FilesMicrosoft OfficeOfficeExcel.EXE", _ vbMinimizedNoFocus ' An error 429 occurs on the following line: Set oExcel = GetObject(, "Excel.Application") MsgBox oExcel.Name Set oExcel = NothingEnd Sub
-
Убедитесь, что правильно задано расположение Excel. exe в примере кода.
-
Закройте приложение Microsoft Excel, если оно уже запущено.
-
Нажмите клавишу F5, чтобы запустить проект, и выберите пункт Command1.
Обходное решение
Чтобы обойти эту проблему, можно выполнить указанные ниже действия.
-
Передавайте фокус приложению Office, изменив второй аргумент функции Shell на vbMinimizedFocus, vbMaximizedFocusили vbNormalFocus.
-
Присвойте форме Visual Basic фокус.
-
Попробуйте выполнить операцию GetObject при выполнении учета во время загрузки приложения Office.
Следующий пересмотренный код иллюстрирует это временное решение.
Private Declare Sub Sleep Lib "kernel32" _ (ByVal dwMilliseconds As Long)Private Sub Command1_Click() Dim intSection As Integer Dim intTries As Integer Dim oExcel As Object ' Enable error handler for this procedure: On Error GoTo ErrorHandler ' Launch Microsoft Excel, giving it focus: Shell "C:Program FilesMicrosoft OfficeOfficeExcel.EXE", _ vbMinimizedFocus 'other options for starting with 'focus: vbMaximizedFocus and vbNormalFocus ' Move focus back to this form. (This ensures the Office ' application registers itself in the ROT, allowing ' GetObject to find it.) Me.SetFocus ' Attempt to use GetObject to reference the running ' Office application: intSection = 1 'attempting GetObject... Set oExcel = GetObject(, "Excel.Application") intSection = 0 'resume normal error handling ' Now you can automate Microsoft Excel: MsgBox oExcel.Name & ": able to GetObject after " & _ intTries + 1 & " tries.", vbMsgBoxSetForeground ' Finished with automation so release your reference: Set oExcel = Nothing ' Exit procedure: Exit Sub ErrorHandler: If intSection = 1 Then 'GetObject may have failed because the 'Shell function is asynchronous; enough time has not elapsed 'for GetObject to find the running Office application. Wait 'wait 1/2 seconds and retry the GetObject. If you try 20 times 'and GetObject still fails, assume some other reason 'for GetObject failing and exit the procedure. intTries = intTries + 1 If intTries < 20 Then Sleep 500 ' wait 1/2 seconds Resume 'resume code at the GetObject line Else MsgBox "GetObject still failing. Process ended.", _ vbMsgBoxSetForeground End If Else 'intSection = 0 so use normal error handling: MsgBox Error$ End IfEnd Sub
Временное решение для C++
Если вы используете C++, в следующем образце кода показан аналогичный метод обхода, показанный в приведенном выше примере Visual Basic. Обратите внимание, что SetForegroundWindow используется для перемещения фокуса из Excel, позволяя ему регистрировать запущенные объекты.
//Store the handle of the currently active window...HWND hwndCurrent = ::GetForegroundWindow();//Launch Excel and wait until it is waiting for//user input...STARTUPINFO Start;PROCESS_INFORMATION ProcInfo;ZeroMemory(&Start,sizeof(STARTUPINFO));Start.cb=sizeof(Start);Start.dwFlags = STARTF_USESHOWWINDOW;Start.wShowWindow = SW_SHOWMINIMIZED;//Change the path to Excel as needed...LPSTR pszExcelPath = "c:\program files\microsoft office\office\excel.exe";::CreateProcess(NULL, pszExcelPath, 0, 0, 1, NORMAL_PRIORITY_CLASS, 0, NULL, &Start, &ProcInfo);if((::WaitForInputIdle(ProcInfo.hProcess, 10000))==WAIT_TIMEOUT){ ::MessageBox(NULL, "Timed out waiting for Excel.", NULL, MB_OK);}//Restore the active window to the foreground...// NOTE: If you comment out this line, the code will fail!::SetForegroundWindow(hwndCurrent);//Initialize COM library...::CoInitialize(NULL);//Attach to the running instance...CLSID clsid;CLSIDFromProgID(L"Excel.Application", &clsid); IUnknown *pUnk = NULL;IDispatch *pDisp = NULL;for(int i=1;i<=5;i++) //try attaching for up to 5 attempts{ HRESULT hr = GetActiveObject(clsid, NULL, (IUnknown**)&pUnk); if(SUCCEEDED(hr)) { hr = pUnk->QueryInterface(IID_IDispatch, (void **)&pDisp); break; } ::Sleep(1000);} if (!pDisp) { ::MessageBox(NULL, "Failed to find instance!!", "Error", MB_ICONHAND);}else { ::MessageBox(NULL, "Got instance of Excel!", "Success", MB_OK);}//Release the no-longer-needed IUnknown...if (pUnk) pUnk->Release();//... Add your automation code for Excel here ...//Release pDisp when no longer needed...if (pDisp) pDisp->Release();//Cleanup COM...CoUninitialize();
Ссылки
Для получения дополнительной информации щелкните приведенные ниже номера статей базы знаний Майкрософт:
192919 Автоматизация защищенной базы данных Access с помощью Visual Basic
237338 Сообщение об ошибке с помощью WordMail: «Этот метод или свойство недоступно»
240794 Определение пути для приложения Office
- Remove From My Forums
-
Вопрос
-
-

0
The following code works fine on my Windows 10 64 computer, running Visual Basic 2013 and Excel 2010
Dim oExcel As Excel.Workbook = Nothing
oExcel = GetObject(path + filename)
oExcel.Application.Visible = True
oExcel.Windows(1).Visible = True
However, when I run the same code after having installed Office 2016, when the filename workbook is not opened, it opens two Excel windows, which are blank (no worksheets are displayed) and unresponsive. They have to be closed ending the task in Task
Manager.The code throws an error message saying index out of range, which is due to Windows.Count being 0.
I have added to my project the Microsoft Office 16 and Microsoft Excel 16 references, removing the Office 14 and Excel 16 previous references.
I reported this fault over a year ago and have avoided Office 2016 since in the hope that it would get fixed, as Microsoft told me they would. However, after installing Office 2016 again I see that the problem persits.
-
Any solution?
Many thanks.
-
GetObject([Pathname] [Class])
Возвращает ссылку на объект, обеспечиваемый компонентом ActiveX
Параметры
Функция содержит именованные аргументы
| Pathname | Необязательный аргумент-значение типа Variant(String). Полная спецификация пути и имя файла, содержащего отыскиваемый объект. В случае, если аргумент опущен, параметр Class является обязательным |
| Class | Необязательный аргумент-значение типа Variant(String).Строка, отражающая класс объекта |
Параметр Class имеет синтаксис appname.objecttype, в котором присутствуют следующие элементы:
| Appname | Обязательный. Значение типа Variant(String). Имя приложения, предоставляющего объект |
| ObjectType | Обязательный. Значение типа Variant(String). Tип или класс создаваемого объекта |
Примечания
Функция GetObject применяется для доступа в объекту ActiveX, находящемуся в файле, и для присваивания этого объекта объектной переменной. Для присваивания объекта, возвращенного функцией GetObject, объектной переменной используется оператор Set. Например:
Dim CADObject As Object
Set CADObject = GetObject("C:CADSCHEMA.CAD")
При исполнении данного кода производится запуск приложения, указанного параметром pathname, и активизация объекта в заданном файле.
Если значением параметра pathname является пустая строка («»), функция GetObject возвращает новый экземпляр объекта заданного типа. В случае, если параметр pathname опущен, функция GetObject возвращает активный в данный момент объект заданного типа. Если объекта указанного типа не существует, возникает ошибка.
Ряд приложений допускают активизацию части файла. Для этого нужно добавить после имени файла восклицательный знак (!) и поместить вслед за ним строку, задающую ту часть файла, которую требуется активизировать. Дополнительные сведения относительно составления такой строки смотрите в документации на то приложение, которое создает объект.
К примеру, в графическом приложении может присутствовать несколько уровней рисования, хранящихся в файле. Для активизации уровня под названием SCHEMA.CAD можно воспользоваться следующим кодом:
Set LayerObject = GetObject("C:CADSCHEMA.CAD!Layer3")
В тех случаях, когда не указан класс объекта (параметр class), автоматизация (Automation) находит приложение, которое нужно запустить, на основе заданного имени файла. Однако ряд файлов могут поддерживать несколько классов объектов. Например, приложение для рисования может поддерживать три различных типа объектов: объект Application, объект Drawing и объект Toolbar, которые являются частью одного файла. Для указания требуемого объекта нужно указать необязательный параметр class. Например:
Dim MyObject As Object
Set MyObject = GetObject("C:DRAWINGSSAMPLE.DRW", "FIGMENT.DRAWING")
В приведенном примере FIGMENT – это имя графического приложения, а DRAWING – один из поддерживаемых этим приложением типов объектов.
После активизации объекта, производится ссылка на него в коде с использованием определенной объектной переменной,. В предыдущем примере доступ к свойствам и методам нового объекта осуществляется с помощью объектной переменной MyObject. Например:
MyObject.Line 9, 90
MyObject.InsertText 9, 100, "Hello, world."
MyObject.SaveAs "C:DRAWINGSSAMPLE.DRW"
Замечание Функцию GetObject полезно использовать в тех случаях, когда уже имеется текущий экземпляр объекта, или при необходимости создать объект из уже загруженного файла. Если же текущий экземпляр объекта отсутствует и нежелательно запускать объект из загруженного файла, применяется функция CreateObject.
Если объект производит само регистрацию в качестве объекта с единственным экземпляром, то, независимо от числа обращений к функции CreateObject, будет создан только один экземпляр такого объекта. В случае наличия только одного экземпляра объекта, функция GetObject, при ее вызове с использованием синтаксиса с указанием пустой строки («»), всегда возвращает один и тот же экземпляр, а при отсутствии параметра pathname возникает ошибка. Функцию GetObject можно применять для получения ссылки на класс, созданный в Visual Basic.
Пример
'Пример использования функции GetObject
' В данном примере функция GetObject создает ссылку
' на конкретный лист (MyXL) в Microsoft Excel.
' Для того, чтобы сделать Microsoft Excel видимым,
'закрыть его и т. д., используется свойство
' Application рабочего листа.
' С помощью двух вызовов API процедура
' Sub DetectExcel ищет Microsoft Excel и,
' если он выполняется, вводит его в таблицу выполняемых
' объектов (Running Object Table).
' Первый вызов GetObject приводит к ошибке,
' если Microsoft Excel еще не запущен.
' В этой программе ошибка приводит к установке значения True для флага ExcelWasNotRunning.
' Второй вызов GetObject указывает открываемый
' файл. Если Microsoft Excel не был запущен, то в
' результате второго вызова функции это приложение
' запускается, при этом возвращается ссылка на лист,
' соответствующий указанному файлу. Файл mytest.xls
' должен существовать в указанном каталоге; в противном ' случае возникает ошибка Visual Basic «Automation error»
' (Ошибка автоматизации). Далее в программе делаются
' видимыми окно Microsoft Excel и окно, содержащее
' указанный лист. И наконец, если Microsoft Excel
' не выполнялся при запуске этой программы,
' метод Quit объекта Application
' закрывает Microsoft Excel. Если это приложение
' выполнялось до запуска данной программы, попытка
' закрыть его не предпринимается. Ссылка на лист
' освобождается путем установки ее значения в Nothing
' Описываем необходимые процедуры API:
Declare Function FindWindow Lib "user32" Alias _
"FindWindowA" (ByVal lpClassName as String, _
ByVal lpWindowName As Long) As Long
Declare Function SendMessage Lib "user32" Alias _
"SendMessageA" (ByVal hWnd as Long,ByVal wMsg as Long, _
ByVal wParam as Long, _
ByVal lParam As Long) As Long
Sub GetExcel()
Dim MyXL As Object ' Переменная для сохранения
' ссылки на Microsoft Excel
Dim ExcelWasNotRunning As Boolean ' Флаг для окончательного освобождения.
' Проверка, выполняется ли Microsoft Excel
On Error Resume Next ' Отложенный перехват ошибок.
' Функция GetObject, вызванная без указания первого параметра,
' возвращает ссылку на экземпляр приложения. Если приложение
' не запущено, возвращается ошибка
Set MyXL = Getobject(, "Excel.Application")
If Err.Number <> 0 Then ExcelWasNotRunning = True
Err.Clear ' Очищаем объект Err на случай ошибки.
' Проверка Microsoft Excel. Если Microsoft Excel выполняется,
' он вводится в таблицу выполняемых объектов (Running Object table)
DetectExcel
' Задаем в объектной переменной ссылку на открываемый файл
Set MyXL = Getobject("c:vb4MYTEST.XLS")
' Делаем видимым Microsoft Excel с помощью его свойства Application.
' Делаем видимым окно, содержащее файл, с помощью
' коллекции Windows, задаваемой объектной ссылкой MyXL
MyXL.Application.Visible = True
MyXL.Parent.Windows(1).Visible = True
Do manipulations of your file here.
' ...
' Если этот экземпляр Microsoft Excel не выполнялся при запуске данной
' программы, закрываем его с помощью метода Quit свойства Application.
' Отметим, что при попытке выхода из Microsoft Excel
' появляется мерцание строки заголовка и отображается сообщение, запрашивающее вас
' о необходимости сохранения файлов
If ExcelWasNotRunning = True Then
MyXL.Application.Quit
End IF
Set MyXL = Nothing ' Освобождаем ссылку на
' приложение и электронную таблицу
End Sub
Sub DetectExcel()
' Процедура находит выполняемый Excel и регистрирует его
Const WM_USER = 1024
Dim hWnd As Long
' Если Excel выполняется, этот вызов API возвращает его дескриптор
hWnd = FindWindow("XLMAIN", 0)
If hWnd = 0 Then ' 0 означает, что Excel не выполняется
Exit Sub
Else
' Excel выполняется, поэтому используйте
функцию API SendMessage, чтобы ввести его в таблицу выполняемых объектов (Running Object Table)
SendMessage hWnd, WM_USER + 18, 0, 0
End If
End Sub
Категория
Функции работы с объектами
GetObject(FName) opens a file or connects to a file if it already opened (and if class is specified use that class to open it) OR GetObject(,»Appname») connects to a running instance of an application. You are creating a blank file.
Visual Basic Scripting Edition
GetObject Function
See Also CreateObject Function
Requirements
Version 5
Returns a reference to an Automation object from a file.
GetObject([pathname] [, class])
Arguments
pathname
Optional; String. Full path and name of the file containing the object to retrieve.
If pathname is omitted, class is required.
class
Optional; String. Class of the object.
The class argument uses the syntax appname.objectype and has these
parts:
Use the GetObject function to access an Automation object from a file
and assign the object to an object variable. Use the Set statement to
assign the object returned by GetObject to the object variable. For
example:
Dim CADObject
Set CADObject = GetObject("C:CADSCHEMA.CAD")
When this code is executed, the application associated with the
specified pathname is started and the object in the specified file is
activated. If pathname is a zero-length string («»), GetObject
returns a new object instance of the specified type. If the pathname
argument is omitted, GetObject returns a currently active object of
the specified type. If no object of the specified type exists, an
error occurs.
Some applications allow you to activate part of a file. Add an
exclamation point (!) to the end of the file name and follow it with a
string that identifies the part of the file you want to activate. For
information on how to create this string, see the documentation for
the application that created the object.
For example, in a drawing application you might have multiple layers
to a drawing stored in a file. You could use the following code to
activate a layer within a drawing called SCHEMA.CAD:
Set LayerObject = GetObject("C:CADSCHEMA.CAD!Layer3")
If you don’t specify the object’s class, Automation determines the application to start and the object to activate, based on the file
name you provide. Some files, however, may support more than one class
of object. For example, a drawing might support three different types
of objects: an Application object, a Drawing object, and a Toolbar
object, all of which are part of the same file. To specify which
object in a file you want to activate, use the optional class
argument. For example:
Dim MyObject
Set MyObject = GetObject("C:DRAWINGSSAMPLE.DRW", "FIGMENT.DRAWING")
In the preceding example, FIGMENT is the name of a drawing application
and DRAWING is one of the object types it supports. Once an object is
activated, you reference it in code using the object variable you
defined. In the preceding example, you access properties and methods
of the new object using the object variable MyObject. For example:
MyObject.Line 9, 90
MyObject.InsertText 9, 100, "Hello, world."
MyObject.SaveAs "C:DRAWINGSSAMPLE.DRW"
Note Use the GetObject function when there is a current instance
of the object or if you want to create the object with a file already
loaded. If there is no current instance, and you don’t want the
object started with a file loaded, use the CreateObject function.
If an object has registered itself as a single-instance object, only
one instance of the object is created, no matter how many times
CreateObject is executed. With a single-instance object, GetObject
always returns the same instance when called with the zero-length
string («») syntax, and it causes an error if the pathname argument is
omitted.
Requirements Version 5
See Also CreateObject Function
© 2001 Microsoft Corporation. All rights reserved.
Build: Topic Version 5.6.9309.1546
Also these are the COM API calls that each form makes. From the Automation part of the COM docs.
|
mentos_has_arisen 0 / 0 / 0 Регистрация: 26.11.2009 Сообщений: 243 |
||||||||
|
1 |
||||||||
|
13.04.2011, 15:17. Показов 7237. Ответов 3 Метки нет (Все метки)
на 3-й строке выдает ошибку.. меняю строку на
выдает ошибку: Соль конечно не в этом.. GetObject посоветовали использовать для того, чтоб при обращении к Excel.Application не вбивать его в задачник.. ато сколько нажимаешь кнопку, столько и остается хвостов…
0 |
|
90 / 37 / 14 Регистрация: 03.11.2010 Сообщений: 429 |
|
|
13.04.2011, 19:17 |
2 |
|
Если в Excel’е открыть файл (например С:1.xls), а потом открыть файл с именем 1.xls, то появится сообщение — нельзя, такой файл уже есть.
0 |
|
Димит 90 / 37 / 14 Регистрация: 03.11.2010 Сообщений: 429 |
||||
|
13.04.2011, 21:32 |
3 |
|||
И ещё надо установить ссылку на библиотеку Microsoft Excel Object Library
0 |
|
Димит 90 / 37 / 14 Регистрация: 03.11.2010 Сообщений: 429 |
||||
|
13.04.2011, 21:35 |
4 |
|||
|
что-то не то загнал. Правильно:
Кстати, а как на этом форуме исправить своё сообщение?
0 |

(((