The short version of this is I want to control via automation an embedded
excel worksheet.
The long version:
I have a COleClientItem derived class which uses CreateNewItem to create an
Excel worksheet.
eg.
CLSID clsid;
if ( CLSIDFromProgID(LPOLESTR("Excel.Spreadsheet",&clsid) == S_OK )
m_pSelectedItem->CreateNewItem(&clsid)
The thing is that I believe that I should be able to QueryInterface the
m_pSelectedItem's m_lpObject member
and obtain for an IDISPATCH and get the dispatch interface of an ?? Excel
Spreadsheet ??.
So I create a COleDispatchDriver from the _Worksheet class in the Excel8
type library and attach the
COleDispatchDriver to the obtained LPDISPATCH from the QueryInterface call.
Now I call _Spreadsheet methods via the COleDispatch driver derived class
and none of them are defined at run-time.
What has gone wrong ?
The running object table viewer does not seem to have the appropriate
clsids.
Robert,
I don't know much, but here is some code that seems to work. I pieced it
together from a number of sources I found on the web, mostly on Microsoft's
web site.
To create a spreadsheet (which Excel calls a workbook), you need to get a
pointer to the Workbooks object of the Application instance, and call the
method Add, giving it an optional variable. To get the application
instance, you call, in order, CLSIDFromProgID, GetActiveObject, and then
QueryInterface.
Hope this helps -- good luck.
Jim D'Ambrosia
=== cut here ===
// works in Visual C++ 6.0 using the AppWizard and MFC
HRESULT hr;
// try to attach to a running instance of Excel
// Translate server ProgID into a CLSID. ClsidFromProgID
// gets this information from the registry.
CLSID clsid;
CLSIDFromProgID(L"Excel.Application", &clsid);
// Get an interface to the running instance, if any..
IUnknown *pUnk;
hr = GetActiveObject(clsid, NULL, (IUnknown**)&pUnk);
if ( FAILED(hr) ) {
return -1;
}
// Get IDispatch interface for Automation...
IDispatch *pDisp;
hr = pUnk->QueryInterface(IID_IDispatch, (void **)&pDisp);
if ( FAILED(hr) ) {
return -1;
}
// Release the no-longer-needed IUnknown...
pUnk->Release();
COleVariant covOptional ( (long) DISP_E_PARAMNOTFOUND, VT_ERROR);
// Now create the application object
_Application app( pDisp );
// get at the Workbooks collection
Workbooks wbs( app.GetWorkbooks() );
// Add a workbook
wbs.Add(COleVariant(covOptional)); // optional argument
// Grab the first workbook (the one that was just created)
_Workbook wb( wbs.GetItem(COleVariant(static_cast<long>(1))) );
// Get the Worksheets collection for that workbook
Worksheets wss( wb.GetWorksheets() );
// Grab the first worksheet in that book
_Worksheet ws( wss.GetItem(COleVariant(static_cast<long>(1)) ) );
Range my_range( ws.GetRange( COleVariant("A1"), COleVariant("A1") ) );
my_range.SetValue( COleVariant("Hi There") );
=== stop here ===
We wrote a report generation tool embedding excel and word in a container.
To control the embedded server (excel and word) via Automation we added the
following member function in a COleDocObjectItem derived class. Note
COleDocObjectItem is derived from COleClientItem.
Implementation:
// We use QueryInterface on m_lpObject to get the dispatch interface.
// m_lpObject is a public member of COleClientItem
// LPUNKNOWN lpUnk = m_lpObject;
// LPDISPATCH lpDispatch = NULL;
// lpUnk->QueryInterface(IID_IDispatch, (void **) &lpDispatch)
LPDISPATCH CReportCntrItem::GetIDispatch() // CReportCntrItem is derived
from COleDocObjectItem
{
ASSERT_VALID(this);
ASSERT(m_lpObject != NULL);
LPUNKNOWN lpUnk = m_lpObject;
Run(); // Server (in this case excel) must be running
// In case of linking
LPOLELINK lpOleLink = NULL;
if (m_lpObject->QueryInterface(IID_IOleLink,
(LPVOID FAR*)&lpOleLink) == NOERROR)
{
ASSERT(lpOleLink != NULL);
lpUnk = NULL;
if (lpOleLink->GetBoundSource(&lpUnk) != NOERROR)
{
TRACE0("Warning: Link is not connected!\n");
lpOleLink->Release();
return NULL;
}
ASSERT(lpUnk != NULL);
}
// Get the dispatch interface for the server
LPDISPATCH lpDispatch = NULL;
if (lpUnk->QueryInterface(IID_IDispatch, (void **) &lpDispatch)
!= NOERROR)
{
TRACE0("Warning: does not support IDispatch!\n");
return NULL;
}
ASSERT(lpDispatch != NULL);
return lpDispatch;
}
Hope this will help solve your problem.
Eirik Grønsund