Qt Excel读写 - QXlsx读取Excel文件显示到QTableWidget

Qt Excel读写 - QXlsx读取Excel文件显示到QTableWidget

引言

在这里插入图片描述

QXlsx官方显示的例子中,有一个XlsxFactory可以Load xlsx file and display on Qt widgets.但是其包含商业许可…自己写了一个简化版本:可以读取Excel文件,显示到QTableWidget上 (如上图所示),也可在QTableWidget上进行修改,再保存到Excel文件中。

  • 本文只考虑了单元格合并情况,其他格式问题暂未处理 (字体、颜色等)

一、设计思路

    1. 考虑单元格合并的情况,先读取所有合并的单元格
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();   // 获取所有合并的单元格
    1. 根据读取的文件信息,初始化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);
}
    1. 遍历进行数据读取,无脑读取即可 (需注意索引从0开始还是1开始). 被合并的单元格内容为空 (合并的大单元格,只有左上角单元格有值 - 详见Debug输出信息)
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());
    }
}

在这里插入图片描述

    1. 修改数据,然后保存到文件中
      设置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

  • 22
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要在Qt读写Excel,并显示到tablewidget,可以使用QAxObject类。下面是一个简单的示例代码: ``` QAxObject* excel = new QAxObject("Excel.Application", this); excel->setProperty("Visible", false); QAxObject* workbooks = excel->querySubObject("Workbooks"); QAxObject* workbook = workbooks->querySubObject("Open(const QString&)", "path/to/excel/file"); QAxObject* sheets = workbook->querySubObject("Sheets"); QAxObject* sheet = sheets->querySubObject("Item(int)", 1); // 读取第一个sheet QAxObject* used_range = sheet->querySubObject("UsedRange"); QAxObject* rows = used_range->querySubObject("Rows"); QAxObject* columns = used_range->querySubObject("Columns"); int row_count = rows->property("Count").toInt(); int column_count = columns->property("Count").toInt(); QTableWidget* table = new QTableWidget(row_count, column_count, this); for (int row = 1; row <= row_count; ++row) { for (int column = 1; column <= column_count; ++column) { QAxObject* cell = sheet->querySubObject("Cells(int,int)", row, column); QString value = cell->property("Value").toString(); table->setItem(row - 1, column - 1, new QTableWidgetItem(value)); cell->clear(); delete cell; } } used_range->clear(); delete used_range; delete sheet; delete sheets; delete workbook; delete workbooks; delete excel; ``` 这段代码首先创建一个Excel对象,并打开指定的Excel文件。然后,它读取文件中的第一个sheet,并将其数据显示QTableWidget中。注意,在读取单元格的值后,我们需要清除QAxObject对象并删除它,以避免内存泄漏。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大米粥哥哥

感谢认可!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值