Qt Excel读写 - QXlsx读取Excel文件显示到QTableWidget
- 引言
- 一、设计思路
- 二、核心源码
- 三、其他参考链接
引言
QXlsx
官方显示的例子中,有一个XlsxFactory
可以Load xlsx file and display on Qt widgets.但是其包含商业许可…自己写了一个简化版本:可以读取Excel文件,显示到QTableWidget上 (如上图所示),也可在QTableWidget上进行修改,再保存到Excel文件中。
本文只考虑了单元格合并情况,其他格式问题暂未处理 (字体、颜色等)
一、设计思路
-
- 考虑单元格合并的情况,先读取所有合并的单元格
xlsx = new QXlsx::Document(filename);
CellRange cellrange = xlsx->dimension();
Worksheet *wst = static_cast<QXlsx::Worksheet *>(xlsx->workbook()->sheet(0));
QList<QXlsx::CellRange> qMergedCellsList = wst->mergedCells(); // 获取所有合并的单元格
-
- 根据读取的文件信息,初始化tableWidget (行列数),在tableWidget相同位置执行合并操作
ui->tableWidget->setColumnCount(cellrange.columnCount());
ui->tableWidget->setRowCount(cellrange.rowCount());
for(CellRange c : qMergedCellsList) { // 合并单元格处理
ui->tableWidget->setSpan(c.firstRow() - 1, c.firstColumn() - 1,
c.lastRow() - c.firstRow() + 1, c.lastColumn() - c.firstColumn() + 1);
}
-
- 遍历进行数据读取,无脑读取即可 (需注意索引从0开始还是1开始). 被合并的单元格内容为空 (
合并的大单元格,只有左上角单元格有值 - 详见Debug输出信息
)
- 遍历进行数据读取,无脑读取即可 (需注意索引从0开始还是1开始). 被合并的单元格内容为空 (
for(int i = 1; i <= cellrange.lastRow(); i++){
for(int j = 1; j <= cellrange.lastColumn(); j++){
QTableWidgetItem *it = new QTableWidgetItem();
it->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
it->setText(wst->read(i, j).toString());
ui->tableWidget->setItem(i-1, j-1, it);
qDebug("%d,%d: %s",i,j,wst->read(i,j).toString().toStdString().c_str());
}
}
-
- 修改数据,然后保存到文件中
设置Table可编辑:setEditTriggers(QAbstractItemView::AllEditTriggers); // 可编辑
- 修改数据,然后保存到文件中
for(int i = 1; i <= cellrange.lastRow(); i++){
for(int j = 1; j <= cellrange.lastColumn(); j++){
qDebug("%d,%d: %s",i,j,ui->tableWidget->item(i-1, j-1)->text().toStdString().c_str());
qDebug("%d,%d: %s",i,j,ui->tableWidget->itemAt(i-1, j-1)->text().toStdString().c_str());
wst->write(i, j, ui->tableWidget->item(i-1, j-1)->text());
}
}
xlsx->saveAs(file);
使用setSpan
合并QTableWidget单元格,会造成itemAt
函数一直返回0,使用item
获取每一个单元格即可。
QTableWidget表格合并若干问题及解决方法:https://www.cnblogs.com/findumars/p/5422995.html
QTableWidget 成员函数itemAt与item的区别与疑问:https://blog.csdn.net/sddzycnqjn/article/details/24968763/
QTableWidget的获取指定位置项的item和itemAt方法:https://www.cnblogs.com/LaoYuanStudyPython/p/12949250.html
二、核心源码
- Excel文件的读取和保存
connect(ui->action_open, &QAction::triggered, [this](){
filename = QFileDialog::getOpenFileName(this, "打开", nullptr, "*.xlsx (*.xlsx)");
if(!filename.isEmpty()){
// 打开xlsx文件,获取相关信息
xlsx = new QXlsx::Document(filename);
CellRange cellrange = xlsx->dimension();
Worksheet *wst = static_cast<QXlsx::Worksheet *>(xlsx->workbook()->sheet(0));
QList<QXlsx::CellRange> qMergedCellsList = wst->mergedCells(); // 获取所有合并的单元格
// Cell c = wst->cellAt(1, 1);
// c.format();
/// 根据信息初始化Qtablewidget
ui->tableWidget->setColumnCount(cellrange.columnCount());
ui->tableWidget->setRowCount(cellrange.rowCount());
ui->tableWidget->resizeColumnsToContents();
ui->tableWidget->setEditTriggers(QAbstractItemView::AllEditTriggers);
ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->tableWidget->horizontalHeader()->setDefaultAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
//ui->tableWidget->verticalHeader()->hide();
for(CellRange c : qMergedCellsList) { // 合并单元格处理
ui->tableWidget->setSpan(c.firstRow() - 1, c.firstColumn() - 1,
c.lastRow() - c.firstRow() + 1, c.lastColumn() - c.firstColumn() + 1);
}
for(int i = 1; i <= cellrange.lastRow(); i++){
for(int j = 1; j <= cellrange.lastColumn(); j++){
QTableWidgetItem *it = new QTableWidgetItem();
it->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
it->setText(wst->read(i, j).toString());
ui->tableWidget->setItem(i-1, j-1, it);
qDebug("%d,%d: %s",i,j,wst->read(i,j).toString().toStdString().c_str());
}
}
}
});
connect(ui->action_save, &QAction::triggered, [this](){
if(!xlsx){
return;
}
QString file = QFileDialog::getSaveFileName(this, "打开", filename, "*.xlsx (*.xlsx)");
if(!file.isEmpty()){
// 打开xlsx文件,获取相关信息
CellRange cellrange = xlsx->dimension();
Worksheet *wst = static_cast<QXlsx::Worksheet *>(xlsx->workbook()->sheet(0));
for(int i = 1; i <= cellrange.lastRow(); i++){
for(int j = 1; j <= cellrange.lastColumn(); j++){
qDebug("%d,%d: %s",i,j,ui->tableWidget->item(i-1, j-1)->text().toStdString().c_str());
qDebug("%d,%d: %s",i,j,ui->tableWidget->itemAt(i-1, j-1)->text().toStdString().c_str());
wst->write(i, j, ui->tableWidget->item(i-1, j-1)->text());
}
}
xlsx->saveAs(file);
}
});
三、其他参考链接
官方例子:https://gitcode.com/qtexcel/qxlsx/blob/master/Example.md
QT读取Excel表格内容到Table Widget:https://blog.csdn.net/qq_16186465/article/details/125555628
QXlsx对合并单元格的处理:https://blog.csdn.net/qq_36391817/article/details/84032788
Qt-QXLS应用 读写Excel常用函数 (包括表单、样式、图、宏操作等,比较全):https://www.cnblogs.com/fengye2021/p/15363391.html