I'm using Microsoft's DSOFramer
control to allow me to embed an Excel file in my dialog so the user can choose his sheet, then select his range of cells; it's used with an import button on my dialog.
The problem is that when I call the DSOFramer's OPEN
function, if I have Excel open in another window, it closes the Excel document (but leaves Excel running). If the document it tries to close has unsaved data, I get a dialog boxclosing Excel doc in another window. If unsaved data in file, dsoframer
fails to open with a messagebox: Attempt to access invalid address
.
I built the source, and stepped through, and its making a call in its CDsoDocObject::CreateFromFile
function, calling BindToObject
on an object of class IMoniker. The HR
is 0x8001010a
The message filter indicated that the application is busy
. On that failure, it tries to InstantiateDocObjectServer
by classid
of CLSID
Microsoft Excel Worksheet... this fails with an HRESULT
of 0x80040154
Class not registered
. The InstantiateDocObjectServer
just calls CoCreateInstance
on the classid
, first with CLSCTX_LOCAL_SERVER
, then (if that fails) with CLSCTX_INPROC_SERVER
.
I know DSOFramer
is a popular sample project for embedding Office apps in various dialog and forms. I'm hoping someone else has had this problem and might have some insight on how I can solve this. I really don't want it to close any other open Excel documents, and I really don't want it to error-out if it can't close the document due to unsaved data.
Update 1: I've tried changing the classid
that's passed in to Excel.Application
(I know that class will resolve), but that didn't work. In CDsoDocObject
, it tries to open key HKEY_CLASSES_ROOT\CLSID\{00024500-0000-0000-C000-000000000046}\DocObject
, but fails. I've visually confirmed that the key is not present in my registry; The key is present for the guide, but there's no DocObject
subkey. It then produces an error message box: The associated COM server does not support ActiveX document embedding
. I get similar (different key, of course) results when I try to use the Excel.Workbook programid
.
Update 2: I tried starting a 2nd instance of Excel, hoping that my automation would bind to it (being the most recently invoked) instead of the problem Excel instance, but it didn't seem to do that. Results were the same. My problem seems to have boiled down to this: I'm calling the BindToObject
on an object of class IMoniker
, and receiving 0x8001010A (RPC_E_SERVERCALL_RETRYLATER)
The message filter indicated that the application is busy
. I've tried playing with the flags passed to the BindToObject
(via the SetBindOptions
), but nothing seems to make any difference.
Update 3: It first tries to bind using an IMoniker class. If that fails, it calls CoCreateInstance
for the clsid
as a fallback
method. This may work for other MS Office objects, but when it's Excel, the class is for the Worksheet. I modified the sample to CoCreateInstance _Application
, then got the workbooks, then called the Workbooks::Open
for the target file, which returns a Worksheet object. I then returned that pointer and merged back with the original sample code path. All working now.