Qt快速读取Excel,QVariant 转QList MyType

参考好多博客,天下博客一大抄,有人不会抄!导致没有得到结果。

故此,写文档用于记录两部分内容:

1、Qt读取Excel的两种方法:1.1、逐单元格读取(慢),1.2、整体范围读取(快)

2、Qt读取Excel之后,数据存储在QVariant  var中,如何将 QVariant 中的数据,读进QList<QList<MyType> >,然后读进QList<MyType>。

3、Qt写入Excel的方法,还没有完成,后续补充。。。没法直接写 .xlsx文件,但是可以直接写 .csv文件,而且很方便。

链接如下:https://blog.csdn.net/qq_34732729/article/details/101070546

新建一个demo 界面有点丑,凑合着看,主要是记录代码

在demo.pro文件中,加入如下代码:

QT       += core gui
QT       += axcontainer            # 添加此行代码

在mainwindow.h(也有人在mainwindow.cpp)中,添加相应的头文件:

#include<QAxObject>

文件构成如下:

   

方法的.h文件

// readExcel.h

typedef struct orderInfo
{
    QString serialNum;
    int ID;
    QString product;
    int stockSum;
    int soldSum;
    double singlePrice;
    double totalPrice;
}orderInfo;


class readExcel
{
public:

    readExcel();

    bool openFile_slow(QString fileName);
    bool openFile_fase(QString fileName);

    void castVariant2ListListVariant(QVariant &var, QList<orderInfo> &orderlst);

private:
    orderInfo order;
    QList<orderInfo> order_lst;
};

 1.1、逐单元格读取(慢),一并转换到MyType

 1.2、逐单元格读取(快)

 2、 转换到MyType数据结构

//readExcel.cpp
bool readExcel::openFile_slow(QString fileName)
{
    bool flag = false;
    QAxObject excel("Excel.Application");            //加载Excel驱动
    excel.setProperty("Visible", false);                    //不显示Excel界面,如果为true会看到启动的Excel界面
    QAxObject *work_books = excel.querySubObject("WorkBooks");          // 父类
    work_books->dynamicCall("Open (const QString&)", fileName);         //打开指定路径文件QString("D:/QtProject/ReadExcel/test.xlsx")
    QVariant title_value = excel.property("Caption");                                   // 获取标题
    QAxObject *work_book = excel.querySubObject("ActiveWorkBook");         // 激活当前工作簿
    QAxObject *work_sheets = work_book->querySubObject("Sheets");           // 获取工作表,sheets也可以换成WorkSheets
    int sheet_count = work_sheets->property("Count").toInt();                    // 获取工作表数目
    for(int i = 1; i <= sheet_count; ++i)           // 从1开始计算
    {
        QAxObject *work_sheet = work_book->querySubObject("Sheets(int)", i);        // 挨个输出sheet表。由于此文件只有一个,所以只输出一个
        QString  work_sheet_name = work_sheet->property("Name").toString();            // 获取工作表名称
        QString message = QString("sheet") + QString::number(i, 10) + QString(" name");             // 整型,10进制
//        qDebug() << message << work_sheet_name;
    }

    // 开始读取
    if(sheet_count > 0)
    {
        QAxObject *work_sheet = work_book->querySubObject("Sheets(int)", 1);        // 只输出第一个sheet表
        QAxObject *used_range = work_sheet->querySubObject("UsedRange");            // 范围
        QAxObject *rows = used_range->querySubObject("Rows");               // 行
        QAxObject *columns = used_range->querySubObject("Columns");     // 列
        int row_start = used_range->property("Row").toInt();            // 起始行
//        qDebug() << "start_row: " << row_start;     // 1
        int column_start = used_range->property("Columns").toInt();         // 起始列
//        qDebug() << "start_column: " << column_start;       // 0
        int row_count = rows->property("Count").toInt();            // 获取行数
//        qDebug() << "row_count : " << row_count;        // 输出行数
        int column_count = columns->property("Count").toInt();      // 获取列数
//        qDebug() << "column_count : " << column_count;      // 输出列数

        QAxObject *cell;        // 用于定位的指针
        QVariant cell_value;    // 存储值信息
        int j = 0;
        for(int i = row_start + 2; i <= row_count; ++i)     // 跳过首行和标题
        {
            j = column_start + 1;       // 由于列是从0开始,但是cells()不能输入0,所以得加1

            cell = work_sheet->querySubObject("Cells(int, int)", i, j);
            cell_value = cell->property("Value");       // 获取单元格内容
            order.serialNum = cell_value.toString();
            ++j;

            cell = work_sheet->querySubObject("Cells(int, int)", i, j);
            cell_value = cell->property("Value");       // 获取单元格内容
            order.ID = cell_value.toInt();
            ++j;

            cell = work_sheet->querySubObject("Cells(int, int)", i, j);
            cell_value = cell->property("Value");       // 获取单元格内容
            order.product = cell_value.toString();
            ++j;

            cell = work_sheet->querySubObject("Cells(int, int)", i, j);
            cell_value = cell->property("Value");       // 获取单元格内容
            order.stockSum = cell_value.toInt();
            ++j;

            cell = work_sheet->querySubObject("Cells(int, int)", i, j);
            cell_value = cell->property("Value");       // 获取单元格内容
            order.soldSum = cell_value.toInt();
            ++j;

            cell = work_sheet->querySubObject("Cells(int, int)", i, j);
            cell_value = cell->property("Value");       // 获取单元格内容
            order.singlePrice = cell_value.toDouble();
            ++j;

            cell = work_sheet->querySubObject("Cells(int, int)", i, j);
            cell_value = cell->property("Value");       // 获取单元格内容
            order.totalPrice = cell_value.toDouble();

            order_lst.push_back(order);
        }
        work_books->dynamicCall("Close()");
        flag = true;
    }
    return flag;
}

// 快方法读取
bool readExcel::openFile_fase(QString fileName)
{
    bool flag = false;
    QAxObject excel("Excel.Application");            //加载Excel驱动
    excel.setProperty("Visible", false);                    //不显示Excel界面,如果为true会看到启动的Excel界面
    QAxObject *work_books = excel.querySubObject("WorkBooks");          // 父类
    work_books->dynamicCall("Open (const QString&)", fileName);         //打开指定路径文件QString("D:/QtProject/ReadExcel/test.xlsx")
    QVariant title_value = excel.property("Caption");                                   // 获取标题
    QAxObject *work_book = excel.querySubObject("ActiveWorkBook");         // 激活当前工作簿
    QAxObject *work_sheets = work_book->querySubObject("Sheets");           // 获取工作表,sheets也可以换成WorkSheets
    int sheet_count = work_sheets->property("Count").toInt();                    // 获取工作表数目
    for(int i = 1; i <= sheet_count; ++i)           // 从1开始计算
    {
        QAxObject *work_sheet = work_book->querySubObject("Sheets(int)", i);        // 挨个输出sheet表。由于此文件只有一个,所以只输出一个
        QString  work_sheet_name = work_sheet->property("Name").toString();            // 获取工作表名称
        QString message = QString("sheet") + QString::number(i, 10) + QString(" name");             // 整型,10进制
//        qDebug() << message << work_sheet_name;
    }

    if(sheet_count > 0)
    {
        QAxObject *work_sheet = work_book->querySubObject("Sheets(int)", 1);        // 只输出第一个sheet表
        QVariant var;
        if(work_sheet != NULL && !work_sheet->isNull())
        {
            QAxObject *used_range = work_sheet->querySubObject("UsedRange");            // 范围
            if(NULL == used_range || used_range->isNull())
            {
                return flag;
            }
            var = used_range->dynamicCall("Value");
            QList<QList<QVariant> > res;
            castVariant2ListListVariant(var, order_lst);      // 此函数将var读进QList<MyType>
            flag = true;
            delete used_range;
        }
    }
    return flag;
}

// 转换
void readExcel::castVariant2ListListVariant(QVariant &var, QList<orderInfo> &orderlst)
{
    QVariantList varRows = var.toList();
    if(varRows.isEmpty())
    {
        return;
    }
    const int rowCount = varRows.size();
    QVariantList rowData;
    for(int i = 2; i < rowCount; ++i)       // 除去第一行注释和第二行表头
    {
        rowData = varRows[i].toList();
        order.serialNum = rowData.value(0).toString();
        order.ID = rowData.value(1).toInt();
        order.product = rowData.value(2).toString();
        order.stockSum = rowData.value(3).toInt();
        order.soldSum = rowData.value(4).toInt();
        order.singlePrice = rowData.value(5).toDouble();
        order.totalPrice = rowData.value(6).toDouble();
        orderlst.push_back(order);
    }
}

 主函数调用方法:

// mainwindow.cpp 方法如下
// 打开Excel
void MainWindow::on_pushButton_clicked()
{
    fileName = getFileName();
    ui->lineEdit->setText(fileName);
}

// 慢方法读取Excel到var
void MainWindow::on_pushButton_2_clicked()
{
    QElapsedTimer mstimer;
    mstimer.start();
    readData.openFile_slow(fileName);        // 执行代码
    float time = (double)mstimer.nsecsElapsed()/(double)1000000;
    QString strTime = QString("%1").arg(time);
    ui->lineEdit_2->setText(strTime);
}

// 快方法读取Excel到var
void MainWindow::on_pushButton_3_clicked()
{
    QElapsedTimer mstimer;
    mstimer.start();
    readData.openFile_fase(fileName);        // 执行代码
    float time = (double)mstimer.nsecsElapsed()/(double)1000000;
    QString strTime = QString("%1").arg(time);
    ui->lineEdit_3->setText(strTime);
}

成果如下:

以上耗时,都加上了转换到MyType的时间,比较慢。如果不加,还是挺快的。

参考博客:

https://blog.csdn.net/x85371169/article/details/79268258

https://blog.csdn.net/qq_34732729/article/details/98864769

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值