Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

Controlling EXCEL using CNiTimer() events

I'm having a hard time controlling Excel using CNiTimer().  I don't have any trouble writing to my Excel worksheet anywhere in my program except from within the CNiTimer() itself.  Since I want to write to Excel at specific intervals this is a problem.  Here is what I have :

.h --
public:   
    // Timer function
    void TimerEvent(CNiTimer&);

private:
        CNiTimer timer;

.cpp --

OnInitDialog()
{
.
.
    timer.InstallEventHandler(*this, TimerEvent);   
    timer.Stop();
    timer.SetInterval(2.0);
    timer.Start();
.
.
}

// Just some basic excel control code that works everywhere else but in here.
void CIRCellReadingDlg::TimerEvent(CNiTimer &timer)
{
     CNiExcelCellRange range2 = m_pieSheet.GetRange("A2");     
     range2.SetCellValue(124.5);      
}

When I exectue I get a runtime error and am dumped out when I execute the line '
NiExcelCellRange range2 = m_pieSheet.GetRange("A2");'     in TimerEvent().  I can do anything else I want from TimerEvent() but this.  Is it an OLE thing?  I'm just stealing code from the CNiTimer() help docs and everything works great except for controlling Excel from within TimerEvent().


Grant M. Johnson
Project Engineer
LECO Corporation
0 Kudos
Message 1 of 5
(3,732 Views)
It probably is an OLE thing.
 
Try calling CoInitialize(NULL) at the beginning of CIRCellReadingDlg::TimerEvent and call CoUninitialize() at the end of CIRCellReadingDlg::TimerEvent. Does this fix the problems?
Message 2 of 5
(3,729 Views)
Yes, that was it.  Thanks for your help.  If you have some time I'd appreciate knowing why I need to do this in this case. 

Thanks again,

Grant

Grant M. Johnson
Project Engineer
LECO Corporation
0 Kudos
Message 3 of 5
(3,717 Views)

CNiTimer calls your callback in a thread that CNiTimer creates and manages. This thread is different than your application main thread. You are controlling Excel through COM. The COM libraries require that you initialize COM in every thread that calls into them. You don't have to do this explicitly in your application main thread because MFC handles this for you automatically in the application startup code.

I should have mentioned before that Measurement Studio includes a class you can use to initialize COM. The advantage of the class is that it unitializes COM when the class goes out of scope, so you don't have to explicitly call CoUninitialize (even if your callback exits because of an exception).

Just add the following declaration to the top of your callback function:

CNiComInitialize comInitialize(CNiComInitialize::Apartment);

I also recommend that you add a try/catch block and handle any exceptions within the callback rather than allowing the exception to propagate to the CNiTimer code.

Message 4 of 5
(3,714 Views)

Thanks for the info.  I'll add that to my callback.

Sure appreciate the help and advice.
Grant M. Johnson
Project Engineer
LECO Corporation
0 Kudos
Message 5 of 5
(3,702 Views)