Я использую элемент управления Microsoft's DSOFramer
, чтобы позволить мне встроить файл Excel в мой диалог, чтобы пользователь мог выбрать свой лист, а затем выбрать диапазон ячеек; он используется с кнопкой импорта в моем диалоговом окне.
Проблема в том, что когда я вызываю функцию DSOFramer's OPEN
, если я открываю Excel в другом окне, он закрывает документ Excel (но оставляет его в рабочем состоянии). Если документ, который он пытается закрыть, содержит несохраненные данные, я получаю диалоговое окно, закрывающее документ Excel в другом окне. Если несохраненные данные в файле, dsoframer
не открывается с окном сообщения: Attempt to access invalid address
.
Я собрал исходный код и прошел через него, и он выполняет вызов в своей функции CDsoDocObject::CreateFromFile
, вызывая BindToObject
для объекта класса IMoniker. HR
- это 0x8001010a
The message filter indicated that the application is busy
. В случае этой ошибки он пытается InstantiateDocObjectServer
на classid
из CLSID
Microsoft Excel Worksheet ... это происходит с HRESULT
из 0x80040154
Class not registered
. InstantiateDocObjectServer
просто вызывает CoCreateInstance
на classid
, сначала с CLSCTX_LOCAL_SERVER
, затем (если это не удается) с CLSCTX_INPROC_SERVER
.
Я знаю, DSOFramer
- это популярный пример проекта для встраивания приложений Office в различные диалоги и формы. Я надеюсь, что у кого-то еще была эта проблема и, возможно, есть некоторое представление о том, как я могу решить эту проблему. Я действительно не хочу, чтобы он закрывал любые другие открытые документы Excel, и я действительно не хочу, чтобы он выводил ошибку, если он не может закрыть документ из-за несохраненных данных.
Обновление 1: я пытался изменить classid
, который был передан, на Excel.Application
(я знаю, что класс разрешится), но это не сработало. В CDsoDocObject
он пытается открыть ключ HKEY_CLASSES_ROOT\CLSID\{00024500-0000-0000-C000-000000000046}\DocObject
, но не удается. Я визуально подтвердил, что ключ отсутствует в моем реестре; Ключ указан для руководства, но здесь нет подключа DocObject
. Затем он выдает сообщение об ошибке: The associated COM server does not support ActiveX document embedding
. Я получаю похожие (разные ключи, конечно) результаты, когда пытаюсь использовать Excel.Workbook programid
.
Обновление 2: я попытался запустить второй экземпляр Excel, надеясь, что моя автоматизация свяжется с ним (будучи последним вызванным) вместо проблемного экземпляра Excel, но, похоже, этого не произошло Результаты были одинаковыми. Кажется, моя проблема сводится к следующему: я вызываю BindToObject
для объекта класса IMoniker
и получаю 0x8001010A (RPC_E_SERVERCALL_RETRYLATER)
The message filter indicated that the application is busy
. Я пытался играть с флагами, переданными на BindToObject
(через SetBindOptions
), но, похоже, ничего не изменилось.
Обновление 3: Сначала он пытается выполнить привязку с помощью класса IMoniker. Если это не удается, он вызывает CoCreateInstance
для clsid
как fallback
метод. Это может работать для других объектов MS Office, но когда это Excel, класс предназначен для рабочего листа. Я изменил образец на CoCreateInstance _Application
, затем получил рабочие книги, затем назвал Workbooks::Open
для целевого файла, который возвращает объект Worksheet. Затем я вернул этот указатель и слил обратно с исходным путем образца кода. Все работают сейчас.