How can I find out if user has closed an Excel application opened from Qt with a QAxObject
I have written an app that opens an excel file like this:
QAxWidget *excel1 = new QAxWidget("Excel.Application");
ExceptReceiver er1; QObject::connect(excel1,SIGNAL(exception(int, QString, QString, QString)), &er1,SLOT(debugError(int,QString,QString,QString))); QObject::connect(excel1,SIGNAL(destroyed(QObject*)), &er1,SLOT(objectDestroyed(QObject*))); excel1->setProperty("Visible",true); QAxObject *workbooks1=excel1->querySubObject("WorkBooks"); workbooks1->dynamicCall("Open (const QString&)",QString(ui->lineEdit_path_1->text())); QAxObject *workbook1=excel1->querySubObject("ActiveWorkBook"); QAxObject *worksheets1=workbook1->querySubObject("WorkSheets(int)", 1); (...)
The user can then modify the excel document, and when he is done I can close it from a button click in my app like this:
The problem happens when the user closes the Excel document without using my button. My app does not notice and when it does a "querySubObject" it crashes badly, and is catched by my exception receiver:
"The inferior stopped because it received a signal from the operating system.
Signal name: SIGSEGV
Signal meaning: Segmentation fault"
As you can see in the code above I tried catching an object destroyed signal, but that never happens, of course the QAxObject doesn't get destroyed by the user closing Excel. So how can my app tell if Excel is still open or the user has already closed it?
Hi, if you check the QAxObjects before using them, you can avoid a crash. For example, say you want to retrieve the text in a cell:
QAxObject* cell = worksheets1->querySubObject("Cells(int,int)",1,1); QString cellValue = cell->dynamicCall("Value()").toString();
The worksheets1 object will still be valid after the user closes the Excel document, but it will return a null pointer, and that's what causes the crash. so try something like this:
QAxObject* cell = worksheets1->querySubObject("Cells(int,int)",1,1); QString cellValue = ""; if (cell) cellValue = cell->dynamicCall("Value()").toString();
Thank you hskoglund, your suggestion worked! It was so simple that I could not even think about that, thank you very much for your help.