Qt快速读取Excel并用Eigen对数据进行矩阵运算处理

Qt快速读取Excel并用Eigen对数据进行矩阵运算处理

前言

这个是做matlab移植C++时的一个子程序,为的是利用Eigen库使matlab程序移植过程更加平滑,可以调用Eigen库丰富强大的功能进行矩阵运算,前后也解决了不少问题(主要是一些使用方法的错误 ,hhh),现在读表速度还可以,十万数据量左右的表格读取加存储大概3ms。
应该还能优化,比如读取后直接转矩阵而不是逐个读入,蹲评论区dalao

Qt快速读取Excel数据

使用QAxObject存储Excel对象内容

要想打开Excel对应接口,Qt要在编译文件里头加上axcontainer,写法详见Qt的 “.pro” 文件写法

QT       += core gui

CONFIG += axcontainer
QT += axcontainer

然后可以用QAxObject存储Excel对象内容
头文件

	QAxObject* excel;                            //操作Excel文件对象(open-save-close-quit)
    QAxObject* workbooks;                        //总工作薄对象
    QAxObject* workbook;                         //操作当前工作薄对象
    QAxObject* worksheets;                       //文件中所有<Sheet>表页	     QAxObject* worksheet;                        //存储第n个sheet对象
    QAxObject* usedrange;                        //存储当前sheet的数据对象
    QAxObject* pWorkBooks;

    QVariant qvar;

.cpp

ExcelRead::ExcelRead()
{
    excel = NULL;			//在构造函数中进行初始化操作
    workbooks = NULL;
    workbook = NULL;
    worksheets = NULL;
    worksheet = NULL;
    usedrange = NULL;
    //pWorkBooks = NULL;
}

bool ExcelRead::datarange_init(QString &filename, int& totalRow, int& totalCol)
{
    excel = new QAxObject("Excel.Application");									//创建Excel对象连接驱动
    excel->dynamicCall("SetVisible(bool)",false);								//ture的打开Excel表 false不打开Excel表
    excel->setProperty("DisplayAlerts",false);

    workbooks = excel->querySubObject("WorkBooks");
    workbook = workbooks->querySubObject("Open(const QString&)",filename);		//打开指定Excel
    worksheets = workbook->querySubObject("WorkSheets");            			//获取表页对象
    worksheet = worksheets->querySubObject("Item(int)",1);          			//获取第1个sheet表
    usedrange = worksheet->querySubObject("Usedrange");							//获取权限

    iRow = usedrange->property("Row").toInt();             					    //数据起始行数和列数(可以解决不规则Excel)
    iCol = usedrange->property("Column").toInt();
    //cout<<"start_row= "<<iRow<<"\t start_col="<<iCol<<endl;
    totalRow = usedrange->querySubObject("Rows")->property("Count").toInt();    //获取数据总行数
    totalCol = usedrange->querySubObject("Columns")->property("Count").toInt();
    //
    //qvar = usedrange->dynamicCall("Value");
    qvar = usedrange->dynamicCall("Value2");
    delete usedrange;
    //pWorkBooks->dynamicCall("Close(Boolean)",false);
    excel->dynamicCall("Quit(void)");
    delete excel;
    return true;
}

querySubObject调用一次就足够,反复调用会导致内存堆积读取速度大幅降低。
excel对象在打开后要记得退出,如果不退出,该excel文档后台会一直显示为占用状态

excel->dynamicCall("Quit(void)");

数据格式转换

主要是用 QVar -> Qlist -> float

void ExcelRead::Var2Qlist(QVariant var, QList<QList<QVariant> > &qlist)
{
    QVariantList varRows = var.toList();
    const int rowCount = varRows.size();
    QVariantList rowData;
    for(int i=0;i<rowCount;++i)
    {
        rowData = varRows[i].toList();
        qlist.push_back(rowData);
    }
}

QVarient转换部分参考了其他开发者的博客
在Qlist基础上用 “.toFloat ” 转换为float型可处理数据

bool ExcelRead::readExcelData(QString& filename,MatrixXf& m)    //读了全表数据
{

    if(datarange_init(filename,totalrow,totalcol))
        cout<<"excel_init successed !"<<endl;
    m = MatrixXf::Zero(totalrow,totalcol);
    QList<QList<QVariant> > vec;
//    QElapsedTimer timer;
//    timer.start();
    QTime startTime = QTime::currentTime();
    // 逐行读取主表
    Var2Qlist(qvar,vec);
    for (int i = iRow+1; i <= totalrow; i++){
        for(int j = iCol; j <= totalcol; j++){
            //m(i-1,j-1) = worksheet->querySubObject("Cells(int,int)",i,j)->dynamicCall(("Value2()")).value<float>();
            m(i-1,j-1) = vec[i-1][j-1].toFloat();
        }
    }
    QTime stopTime = QTime::currentTime();
    int elapsed = startTime.msecsTo(stopTime);
    //qDebug()<<filename<<" data has been put in Matrix, it took: "<<timer.elapsed()<<"ms";
    qDebug()<<filename<<" data has been put in Matrix, it took: "<<elapsed<<"ms";
    qvar.clear();
//    vec.clear();
    //cout << m.rows()<<endl;
    return true;
}

后记

十分感谢csdn和github上丰富的资源,在解决问题时借鉴和学习到了很多。
这里附上小项目源码:
https://github.com/mhw-Parker/Qt_FastReadExcel.git
欢迎评论区提出更高效读取方案。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值