乐趣区

Qt创建excel示例

用 Qt5 写了个生成 excel 数据的程序,发现生成数据速度很慢,
经查证,
在单元格很多的时候,按单元格写入很慢,按范围批量读写速度快很多 ,excel 部分代码片段如下,
初学者代码不好,另外 设置页面和单元格格式有更好具体意见建议者,欢迎留言指导

这段代码生成同一种格式的 7 页数据,最终结果如下:

void mainwindow::produce_excel()    
{
    // 获取桌面路径,设置为表格的绝对路径
    QString excel_file_path = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)
                             + "/baodi.xlsx";  
    // 把 "/baodi.xlsx" 中 // 替换成所在系统分隔符,否则路径读取会失败
    excel_file_path = QDir::toNativeSeparators(excel_file_path);    

    QAxObject *excel = new QAxObject(this);
    excel->setControl("Excel.Application"); // 连接 EXCEL 控件
    excel->setProperty("DisplayAlerts", true);  // 显示窗体
    QAxObject *workbooks = excel->querySubObject("WorkBooks");  //  获取工作薄(EXCEL 文件)集合
    workbooks->dynamicCall("Add");  // 创建新工作薄
    //workbooks->dynamicCall("Open(const QString&)", excel_file_path);
    QAxObject *workbook = excel->querySubObject("ActiveWorkBook");  // 获取当前工作薄
    workbook->dynamicCall("SaveAs(const QString&, int, const QString&, const QString&, bool,bool)",
                          excel_file_path, 51, QString(""),QString(""),false,false);//51xlsx,56xls

    QAxObject *worksheet = workbook->querySubObject("WorkSheets(int)", 1);
    // 根据序号获取 EXCEL 下方第 int 张工作表

/*
    // 按单元格写入,数据多时,速度很慢,真的很慢,十分不推荐,已经注释掉了,按范围写入在后面
    QAxObject *usedRange = worksheet->querySubObject("UsedRange"); //sheet 范围
    int Row = usedRange->property("Row").toInt();// 获得起始行数
    int Col = usedRange->property("Column").toInt();// 获得起始列数

    QAxObject *cell = worksheet->querySubObject("Cells(int,int)", Row, Col);
    const int ROW_NUM {30};
    const int COL_NUM {3};
    const int HIGHT {26};
    const int WIDE {10};
    long t = 0;// 用于选择时间 time
    for(auto d:day)
    {
        // 输入表头
        //auto t = time.begin();
        cell->setProperty("Value", d);
        cell->setProperty("RowHeight", HIGHT+9);// 设置行高
        //cell->setProperty("ColumnWidth", WIDE-4);  // 设置单元格列宽
        //cell->setProperty("HorizontalAlignment", -4108); 
        // 左对齐(xlLeft):-4131  居中(xlCenter):-4108  右对齐(xlRight):-4152

        cell = worksheet->querySubObject("Cells(int,int)", ++Row, Col);
        cell->setProperty("Value", sn);
        cell->setProperty("RowHeight", HIGHT);
        cell->setProperty("ColumnWidth", WIDE-4);  // 设置单元格列宽
        cell->setProperty("HorizontalAlignment", -4108); 

        cell = worksheet->querySubObject("Cells(int,int)", Row, ++Col);
        cell->setProperty("Value", time[t++%6]);
        //cell->setProperty("RowHeight", HIGHT);
        cell->setProperty("ColumnWidth", WIDE);  // 设置单元格列宽

        cell = worksheet->querySubObject("Cells(int,int)", Row, ++Col);
        //cell->setProperty("Value", sn);
        //cell->setProperty("RowHeight", HIGHT);
        cell->setProperty("ColumnWidth", WIDE);  // 设置单元格列宽

        cell = worksheet->querySubObject("Cells(int,int)", Row, ++Col);
        cell->setProperty("Value", sn);
        //cell->setProperty("RowHeight", HIGHT);
        cell->setProperty("ColumnWidth", WIDE-4);  // 设置单元格列宽
        cell->setProperty("HorizontalAlignment", -4108); 

        cell = worksheet->querySubObject("Cells(int,int)", Row, ++Col);
        cell->setProperty("Value", time[t++%6]);
        //cell->setProperty("RowHeight", HIGHT);
        cell->setProperty("ColumnWidth", WIDE);  // 设置单元格列宽
        cell->setProperty("HorizontalAlignment", -4108);

        cell = worksheet->querySubObject("Cells(int,int)", Row, ++Col);
        //cell->setProperty("Value", sn);
        //cell->setProperty("RowHeight", HIGHT);
        cell->setProperty("ColumnWidth", WIDE);  // 设置单元格列宽

        cell = worksheet->querySubObject("Cells(int,int)", Row, ++Col);
        cell->setProperty("Value", sn);
        //cell->setProperty("RowHeight", HIGHT);
        cell->setProperty("ColumnWidth", WIDE-4);  // 设置单元格列宽
        cell->setProperty("HorizontalAlignment", -4108); 

        cell = worksheet->querySubObject("Cells(int,int)", Row, ++Col);
        cell->setProperty("Value", time[t++%6]);
        //cell->setProperty("RowHeight", HIGHT);
        cell->setProperty("ColumnWidth", WIDE);  // 设置单元格列宽
        cell->setProperty("HorizontalAlignment", -4108); 

        Col = usedRange->property("Column").toInt();// 获得起始列数
        cell = worksheet->querySubObject("Cells(int,int)", ++Row, Col);
        // 输入数据
        for(int i=0; i<ROW_NUM; i++)
        {for(int j=0; j<COL_NUM; j++)
            {cell = worksheet->querySubObject("Cells(int,int)", Row, Col++);
                cell->setProperty("Value", i+1);
                cell->setProperty("RowHeight", HIGHT);
                //cell->setProperty("ColumnWidth", WIDE);  // 设置单元格列宽
                cell->setProperty("HorizontalAlignment", -4108); 

                cell = worksheet->querySubObject("Cells(int,int)", Row, Col++);
                cell->setProperty("Value", rand());
                //cell->setProperty("RowHeight", HIGHT);
               // cell->setProperty("ColumnWidth", WIDE);  // 设置单元格列宽
                cell->setProperty("HorizontalAlignment", -4108); 

                cell = worksheet->querySubObject("Cells(int,int)", Row, Col++);
                cell->setProperty("Value", right_model(model));
                //cell->setProperty("RowHeight", HIGHT);
                //cell->setProperty("ColumnWidth", WIDE);  // 设置单元格列宽
                cell->setProperty("HorizontalAlignment", -4108); 

            }
            Col = usedRange->property("Column").toInt();// 获得起始列数
            cell = worksheet->querySubObject("Cells(int,int)", ++Row, Col);
        }



    }
*/


    // 按范围写入,因为不用重复调用 QAxObject,比按单元格写入的方式速度提升巨大
    const int HIGHT{26};
    const int ROW_NUM {224};
    const int COL_NUM {3};
    unsigned int d = 0;
    unsigned int t = 0;

    // 以二维数组的形式存储预写入数据
    QList<QList<QVariant>>datas;
    for(int i=0;i<ROW_NUM;i++)
    {

        QList<QVariant> rows;
        switch (i%32)// 确定是第几行
        {
            case 0 :
                rows.append(day[d++]);
                for(int k=0;k<COL_NUM*3-1;k++)
                {

                    // 该方法必须输入整个矩形区域,空的地方不输入最后写入结果会异常
                    rows.append("");

                }
            break; //  确定是第几篇报文
            case 1 :
                for(int k=0;k<COL_NUM;k++)
                {rows.append(sn);
                    rows.append(time[t++%6]);
                    rows.append("");

                }
            break;


            default:
                for(int k=0;k<COL_NUM;k++)
                {rows.append(i%32?  i%32-1 : 30);
                    rows.append(rand());
                    rows.append(right_model(model));
                }
            break;
        }
        datas.append(rows);

    }

    /*
     *QVariant 封装绝大多数 Qt 提供的数据类型,只要放入和取出类型对应即可,* 相当于一个普遍的类型联合,* canConvert 可以查询是否能转换当前类型,转换类型以 toT()命名
     * 以下为类型 list<list<qvariant>> 到 qvariant 的转换过程
     
     * 待写入区域内,每行存为一个 QList<QVariant>,         
     * tjgcQList<QVariant> row1,row2,row3;
     
     * 将 QList<QVariant> 转换为 QVariant 类型,* QVariant r1(row1),r2(row2),r3(row3);
     
     * 整个写入区域当作一个 QList<QVariant>, 存入上述 QVariant 类型 r1,r2,r3
     * 得到 QList<QVariant> r
     
     * 整个写入区域从 QList<QVariant> 转换为 QVariant 类型
     * QVariant v(r); *
    */


    // 二维数组转一维
    QList<QVariant> vars;

    for(auto v:datas)
    {vars.append(QVariant(v));
    }
    // 一维数组转变量
    QVariant var = QVariant(vars);


    QAxObject *user_range = worksheet->querySubObject("Range(const QString&)", "A1:I224");// 指定范围
    user_range->setProperty("Value", var);// 调用一次 QAxObject 即可完成写入
    user_range->setProperty("RowHeight", HIGHT);// 设置行高
    user_range->setProperty("HorizontalAlignment", -4108); 
    // 左对齐(xlLeft):-4131  居中(xlCenter):-4108  右对齐(xlRight):-4152



    workbook->dynamicCall("Save()");    // 保存文件
    workbook->dynamicCall("Close(Boolean)", false);
    excel->dynamicCall("Quit(void)");  //EXE 结束前需要关闭 EXCEL
    delete excel;

    //wait->close();
    //delete wait;
    QMessageBox::information(this,tr("注意"),QStringLiteral("报底已保存在桌面"),QMessageBox::Ok);



}

退出移动版