Click here to Skip to main content
16,016,623 members
Home / Discussions / C / C++ / MFC
   

C / C++ / MFC

 
QuestionIs there any way to subclass excel? Pin
SNI25-Feb-09 5:56
SNI25-Feb-09 5:56 
AnswerRe: Is there any way to subclass excel? Pin
Stuart Dootson25-Feb-09 8:35
professionalStuart Dootson25-Feb-09 8:35 
GeneralRe: Is there any way to subclass excel? Pin
SNI25-Feb-09 17:21
SNI25-Feb-09 17:21 
GeneralRe: Is there any way to subclass excel? Pin
Stuart Dootson25-Feb-09 21:59
professionalStuart Dootson25-Feb-09 21:59 
GeneralRe: Is there any way to subclass excel? Pin
SNI25-Feb-09 22:56
SNI25-Feb-09 22:56 
GeneralRe: Is there any way to subclass excel? Pin
Stuart Dootson25-Feb-09 23:14
professionalStuart Dootson25-Feb-09 23:14 
GeneralRe: Is there any way to subclass excel? Pin
SNI25-Feb-09 23:44
SNI25-Feb-09 23:44 
GeneralRe: Is there any way to subclass excel? Pin
Stuart Dootson26-Feb-09 2:20
professionalStuart Dootson26-Feb-09 2:20 
I see now. I tried this little program to interrogate the running instance of Excel (2007 in my case as well):

#include <iostream>
#import "libid:00020813-0000-0000-C000-000000000046" version("1.6") auto_search no_dual_interfaces raw_dispinterfaces rename("DialogBox", "excelDialogBox") rename("RGB", "excelRGB") rename("DocumentProperties", "excelDocumentProperties") rename("SearchPath", "excelSearchPath") rename("CopyFile", "excelCopyFile") rename("ReplaceText", "excelReplaceText")


int _tmain(int argc, _TCHAR* argv[])
{
   CoInitializeEx(0, COINIT_MULTITHREADED);
   try
   {
      Excel::_ApplicationPtr xl;
      if (SUCCEEDED(xl.GetActiveObject(__uuidof(Excel::Application))))
      {
         if (Excel::_WorkbookPtr wb = xl->ActiveWorkbook)
         {
            std::cout << "Getting name\n";
            _bstr_t xlName = wb->FullName;
            std::cout << xlName << std::endl;
            if (Excel::SheetsPtr sheets = wb->Worksheets)
            {
               std::cout << sheets->Count << std::endl;
            }
         }
      }
   }
   catch(_com_error& e)
   {
      std::cout << "EXCEPTION!!!\n";
      std::cerr << CT2CA(e.ErrorMessage()) << std::endl;
   }
   CoUninitialize();
	return 0;
}


When you're NOT editing a cell, this program works fine, printing the active workbook's file name and number of worksheets.

When you ARE editing a cell, it throws an exception (indicating an error status) when you interrogate the workbook object. That exception's text is "The message filter indicated that the application is busy". Now, I think that indicates that Excel is in a modal message loop and will not respond to any COM calls. Which means that Excel's window procedure isn't being called, so sub-classing Excel's window class won't help you at all anyway.

What you can do is (if Excel is busy) catch the Excel application's events. I think you'll find that Excel's SheetChange and AfterCalculate events are raised when you finish editing a cell. At that point, Excel won't be busy, so you can get the workbook's filename.

The resultant code could look something like this:

#include <iostream>
#include <atlcom.h>
#import "libid:00020813-0000-0000-C000-000000000046" version("1.6") auto_search no_dual_interfaces raw_dispinterfaces rename("DialogBox", "excelDialogBox") rename("RGB", "excelRGB") rename("DocumentProperties", "excelDocumentProperties") rename("SearchPath", "excelSearchPath") rename("CopyFile", "excelCopyFile") rename("ReplaceText", "excelReplaceText")

_ATL_FUNC_INFO SheetChangeInfo = { CC_CDECL, VT_EMPTY, 2, { VT_DISPATCH, VT_DISPATCH } };

class ExcelAppEventHandler : public IDispEventSimpleImpl<1, ExcelAppEventHandler, &__uuidof(Excel::AppEvents)>
{
public:
   ExcelAppEventHandler(bool& doneFlag) : done_(doneFlag) { done_ = false; }
   BEGIN_SINK_MAP(ExcelAppEventHandler)
      SINK_ENTRY_INFO(1, __uuidof(Excel::AppEvents), 0x0000061c, &ExcelAppEventHandler::SheetChange, &SheetChangeInfo)
   END_SINK_MAP()

   void _stdcall SheetChange(IDispatch * Sh, struct Excel::Range * Target)
   {
      done_ = true;
   }
private:
   bool& done_;
};

_bstr_t GetActiveWorkbookName(Excel::_ApplicationPtr xl)
{
   if (Excel::_WorkbookPtr wb = xl->ActiveWorkbook)
   {
      try
      {
         return wb->FullName;
      }
      catch(_com_error& e)
      {
         std::cout << "EXCEPTION!!!\n";
         std::cerr << CT2CA(e.ErrorMessage()) << std::endl;

         bool done;
         ExcelAppEventHandler app(done);
         if (SUCCEEDED(app.DispEventAdvise(xl)))
         {
            MSG msg;
            while (!done && GetMessage(&msg, NULL, 0, 0) > 0) {
               TranslateMessage(&msg);
               DispatchMessage(&msg);
            }            
            app.DispEventUnadvise(xl);
            return GetActiveWorkbookName(xl);
         }
      }
   }
   return _bstr_t();
}

int _tmain(int argc, _TCHAR* argv[])
{
   CoInitializeEx(0, COINIT_APARTMENTTHREADED);
   {
      Excel::_ApplicationPtr xl;
      if (SUCCEEDED(xl.GetActiveObject(__uuidof(Excel::Application))))
      {
         std::cout << "Getting name\n";
         std::cout << GetActiveWorkbookName(xl) << std::endl;
      }
   }
   CoUninitialize();
	return 0;
}


The GetActiveWorkbookName function attempts to get the workbook name. If it fails, it tells Excel that it wants events, then when it gets SheetChange it returns, as Excel is no longer busy.

Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

GeneralRe: Is there any way to subclass excel? Pin
SNI8-Mar-09 23:23
SNI8-Mar-09 23:23 
GeneralRe: Is there any way to subclass excel? Pin
Stuart Dootson9-Mar-09 3:32
professionalStuart Dootson9-Mar-09 3:32 
QuestionHow to remove path of Executable debug session in VS2005 Pin
pandit8425-Feb-09 4:55
pandit8425-Feb-09 4:55 
AnswerRe: How to remove path of Executable debug session in VS2005 Pin
«_Superman_»25-Feb-09 5:01
professional«_Superman_»25-Feb-09 5:01 
QuestionCMDIChildWnd maximizing and merging with main window Pin
prithaa25-Feb-09 4:52
prithaa25-Feb-09 4:52 
AnswerRe: CMDIChildWnd maximizing and merging with main window Pin
Stuart Dootson25-Feb-09 8:39
professionalStuart Dootson25-Feb-09 8:39 
AnswerRe: CMDIChildWnd maximizing and merging with main window Pin
Iain Clarke, Warrior Programmer25-Feb-09 8:43
Iain Clarke, Warrior Programmer25-Feb-09 8:43 
GeneralRe: CMDIChildWnd maximizing and merging with main window Pin
prithaa25-Feb-09 19:59
prithaa25-Feb-09 19:59 
GeneralRe: CMDIChildWnd maximizing and merging with main window Pin
Iain Clarke, Warrior Programmer25-Feb-09 21:53
Iain Clarke, Warrior Programmer25-Feb-09 21:53 
GeneralRe: CMDIChildWnd maximizing and merging with main window Pin
prithaa25-Feb-09 22:12
prithaa25-Feb-09 22:12 
GeneralRe: CMDIChildWnd maximizing and merging with main window Pin
Iain Clarke, Warrior Programmer25-Feb-09 22:23
Iain Clarke, Warrior Programmer25-Feb-09 22:23 
GeneralRe: CMDIChildWnd maximizing and merging with main window Pin
prithaa25-Feb-09 22:33
prithaa25-Feb-09 22:33 
QuestionWhy is TCP/IP Faster than Shared Memory Pin
Steve Thresher25-Feb-09 4:18
Steve Thresher25-Feb-09 4:18 
AnswerRe: Why is TCP/IP Faster than Shared Memory Pin
Richard Andrew x6425-Feb-09 13:51
professionalRichard Andrew x6425-Feb-09 13:51 
GeneralRe: Why is TCP/IP Faster than Shared Memory Pin
Steve Thresher25-Feb-09 21:42
Steve Thresher25-Feb-09 21:42 
Questionobject life cycle question Pin
tyr200025-Feb-09 3:01
tyr200025-Feb-09 3:01 
AnswerRe: object life cycle question Pin
Cedric Moonen25-Feb-09 3:03
Cedric Moonen25-Feb-09 3:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.