我正在尝试使用 QAxObject 打开一个 Excel 文件并读取其数据。我已经在主线程中成功完成了这项工作,但是现在,我想在 2 个单独的线程中执行“打开”和“读取”操作。为此,我创建了 2 个继承自 QThread 的类。'OpenerThread' 打开文件没有任何问题。一旦这个线程结束,'ReadManagerThread' 开始工作。
但是,应用程序在“QAxObject * rows = range->querySubObject( "Rows" );" 行中崩溃
我收到错误“QAxBase::dynamicCallHelper:对象不支持自动化”。
此错误的原因是什么,我该如何解决?
ExcelManager.h
// Note: The pointers used to open and read the Excel file are global and wrapped in this namespace.
// Therefore, they're supposed to be accessible by different threads.
namespace ExcelManager {
extern QAxObject* excel;
extern QAxObject* workbooks;
extern QAxObject* workbook;
extern QAxObject* sheets;
extern QAxObject* sheet;
extern int fileRowCount;
void openExcelFile();
void setFileRowCount();
}
ExcelManager.cpp
QAxObject* ExcelManager::excel;
QAxObject* ExcelManager::workbooks;
QAxObject* ExcelManager::workbook;
QAxObject* ExcelManager::sheets;
QAxObject* ExcelManager::sheet;
void ExcelManager::openExcelFile(){
ExcelManager::excel = new QAxObject("Excel.Application");
ExcelManager::workbooks = excel->querySubObject("Workbooks");
ExcelManager::workbook = workbooks->querySubObject("Open(const QString&)" ,"AppAddress\\Book2.xlsx");
ExcelManager::sheets = workbook->querySubObject("Worksheets");
ExcelManager::sheet = sheets->querySubObject("Item(int)", 1);
}
void ExcelManager::setFileRowCount(){
QAxObject * range = ExcelManager::sheet->querySubObject("UsedRange");
QAxObject * rows = range->querySubObject( "Rows" );
// After ReadManagerThread calls this function,
// this is the line on which the app crashes. Based on debugging results,
// 'range' does not point to anything at this moment, but why?
ExcelManager::fileRowCount = rows->dynamicCall( "Count()" ).toInt();
}
OpenerThread.h
#include <QThread>
#include <Ole2.h>
#include "ExcelManager.h"
class OpenerThread : public QThread{
public:
OpenerThread();
void run() override
{
CoInitialize(0);
CoInitializeEx(NULL, COINIT_MULTITHREADED);
ExcelManager::openExcelFile(); // This works successfully.
}
};
ReadManagerThread.h
#include <QThread>
#include <Ole2.h>
#include "ExcelManager.h"
class ReadManagerThread : public QThread{
public:
ReadManagerThread();
void run() override
{
CoInitialize(0);
CoInitializeEx(NULL, COINIT_MULTITHREADED);
ExcelManager::setFileRowCount(); // This results in error.
// Proceed to read and extract data.
}
};
这两个线程通过以下代码在我的一个类中开始:
OpenerThread* openerThread = new OpenerThread();
ReadManagerThread* readManagerThread = new ReadManagerThread();
openerThread->start();
connect(openerThread, SIGNAL(finished()),
readManagerThread, SLOT(start()));
更新: 经过大量研究,我明白不可能在不同线程之间共享一个 QAxObject*。换句话说,只有创建 QAxObject 的线程才能使用它。建议创建一个 QThread 并在其中打开 Excel 文件,然后在该线程中创建必要的插槽,然后从其他线程发出信号。这样,多个线程可以访问 COM 对象,而无需直接调用它。当我实现这个目标时,我会更新这篇文章。