参考好多博客,天下博客一大抄,有人不会抄!导致没有得到结果。
故此,写文档用于记录两部分内容:
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的时间,比较慢。如果不加,还是挺快的。
参考博客: