QT读取Excel表格内容到Table Widget

QT读取Excel表格内容到Table Widget

前言

有一个需求是要把Excel的数据导入到QT的Table Widget表格中。我是一个QT新手,在网上找了很多方法,在这里汇总记录一下。

导读

目前总共有四种方法:

一、ODBC 导入
二、QAxObject 导入
三、QXlsx 导入
四、复制导入

其中方法一至三适用于不加密的Excel文件,如果公司的Excel文件是加密过的,这三个方法是处理不了的,在我使用时是这样,如果有大佬懂的话请多指教。复制导入加密的Excel也能处理的,除非连复制黏贴都加密了,那真是离谱。

一、ODBC 导入

首先需要确认是否存在处理Excel的DSN
我们可以在C:\Windows\SysWOW64文件夹中找到odbcad32.exe,打开
如果有下面这个就可以了,没有的话看看添加里面有没有,还是没有就再找其他文章安装对应的东西吧,这里就不扩展了
在这里插入图片描述
然后就直接写代码就好了,先随便建个QT项目,随便搞个界面
在这里插入图片描述

在.pro文件中加入sql
在这里插入图片描述
头文件中加入这些

#include <QStandardPaths>
#include <QFileDialog>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlError>
#include <QMessageBox>
#include <QDebug>

随便在界面中加个按钮,然后创建一个**clicked()**的槽函数
函数代码如下:

void MainWindow::on_pushButton_clicked()
{
    //桌面打开//Qt4
    //QString desktopDir=QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
    //Qt 5
    QString desktopDir=QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
    //选择Excel文件,并获取路径
    QString filePath=QFileDialog::getOpenFileName(NULL,"选择Excel",desktopDir,"*.xlsx *.xls");
    if(filePath.isNull()){
        QMessageBox::warning(NULL, "错误提示", "无法打开excel文件");
        return;
    }
    
    //读取excel
    QSqlDatabase db = QSqlDatabase::addDatabase("QODBC","excel");
    if(!db.isValid())
    {
        QMessageBox::warning(NULL, "错误提示", "数据库驱动异常");
        db.close();
        return;
    }

    QString dsn = QString("Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};Readonly=TRUE;DBQ=%1;").arg(filePath);
    db.setDatabaseName(dsn);
    if(!db.open())
    {
        QMessageBox::warning(NULL, "错误提示", "无法打开数据库");
        db.close();
        return;
    }
    QSqlQuery query(db);
    QString tableName = "Sheet1$"; //sheet名,$是必须的
    QString sql="select * from ["+tableName+"]";
    query.exec(sql);

    int row = 1; //行号
    while (query.next()) {
        //每次query就是一行数据
        for (int i = 0; i < ui->tableWidget->columnCount() - 1; i++)
        {
            QTableWidgetItem *item = new QTableWidgetItem(QString::number(query.value(i).toDouble(), 'f', 2));
            ui->tableWidget->setItem(row, i + 1, item);
        }
        row++;
    }
    query.clear();
    db.close();
}

使用ODBC时,Excel中的数据格式:
在这里插入图片描述
第一行是字段名,格式比较固定

二、QAxObject 导入

这个需要在.pro文件中加入axcontainer
在这里插入图片描述
头文件中需要加入

#include <QStandardPaths>
#include <QFileDialog>
#include <QMessageBox>
#include <QDebug>
#include <QAxObject>

代码:

void MainWindow::on_pushButton_2_clicked()
{
    QString desktopDir=QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
    QString path=QFileDialog::getOpenFileName(NULL,"选择Excel",desktopDir,"*.xlsx *.xls");
    QAxObject *excel = NULL;
    QAxObject *workbooks = NULL;
    QAxObject *workbook = NULL;
    excel = new QAxObject(this);
    if (!excel->setControl("Excel.Application"))
    {
        excel->setControl("ket.Application");
    }
    if (!excel)
    {
        QMessageBox::critical(NULL, "错误信息", "EXCEL对象丢失");
        return;
    }
    excel->dynamicCall("SetVisible(bool)", false);
    workbooks = excel->querySubObject("WorkBooks");
    workbook = workbooks->querySubObject("Open(const QString&)",path);
    QAxObject * worksheet = workbook->querySubObject("WorkSheets(int)", 1); // 获取第一个工作sheet
    QAxObject * usedrange = worksheet->querySubObject("UsedRange");//获取该sheet的使用范围对象
    QAxObject * rows = usedrange->querySubObject("Rows");
    QAxObject * columns = usedrange->querySubObject("Columns");

    /*获取行数和列数*/
    int intCols = columns->property("Count").toInt();
    int intRows = rows->property("Count").toInt();
    int intRowStart = usedrange->property("Row").toInt();
    int intColStart = usedrange->property("Column").toInt();

    /*获取excel内容*/
    for (int i = intRowStart; i < intRowStart + intRows; i++)  //行
    {
        for (int j = intColStart; j < intColStart + intCols; j++)
        {
            QAxObject *cell = worksheet->querySubObject("Cells(int,int)", i, j);
            QTableWidgetItem *item = new QTableWidgetItem(QString::number(cell->dynamicCall("Value2()").toDouble(), 'f', 2));
            ui->tableWidget->setItem(i, j, item);
            delete cell;
        }
    }
    // 关闭excel
    workbook->dynamicCall("Close(Boolean)",true);
    excel->dynamicCall("Quit(void)");
    delete excel;
    excel = NULL;
}

wps使用的是ket.Application
使用这个时Excel表格的数据格式是这样的:
在这里插入图片描述
不需要第一行那个字段名了,直接全是数据就行,但是这种方法处理的速度很慢,可以说是四种方法中最慢的了

三、QXlsx导入

这是QT官方推荐的一个开源项目,看github上好像是一个韩国人开发的
项目的github地址:https://github.com/QtExcel/QXlsx
当然他也有告诉我们安装的步骤:https://github.com/QtExcel/QXlsx/blob/master/HowToSetProject.md
那我就大致翻译一下吧
首先我们先把项目克隆到本地
在一个新建的文件夹中打开cmd
在这里插入图片描述
然后在字符界面中输入下面的命令,回车

git clone https://github.com/j2doll/QXlsx.git

在这里插入图片描述
下载完成就是一个QXlsx的文件夹
在这里插入图片描述
然后打开这个文件夹,里面还有一个QXlsx,把里面的
在这里插入图片描述
复制到自己项目的主目录下面
在这里插入图片描述
在自己项目的.pro文件中添加

# QXlsx code for Application Qt project
QXLSX_PARENTPATH=./         # current QXlsx path is . (. means curret directory)
QXLSX_HEADERPATH=./header/  # current QXlsx header path is ./header/
QXLSX_SOURCEPATH=./source/  # current QXlsx source path is ./source/
include(./QXlsx.pri)

在这里插入图片描述
然后头文件添加

#include "xlsxdocument.h"
#include "xlsxchartsheet.h"
#include "xlsxcellrange.h"
#include "xlsxchart.h"
#include "xlsxrichstring.h"
#include "xlsxworkbook.h"
using namespace QXlsx;

完整代码:

void MainWindow::on_pushButton_3_clicked()
{
    QString desktopDir = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
    QString filepath = QFileDialog::getOpenFileName(NULL,"选择Excel",desktopDir,"*.xlsx *.xls");
    Document xlsxR(filepath);
    if (xlsxR.load()) //加载Excel文件
    {
        for (int row = 1; row <= 4; row++)
        {
            for (int col = 1; col <= 4; col++)
            {
                Cell* cell = xlsxR.cellAt(row, col); //获取具体位置单元格
                if (cell != NULL)
                {
                    QVariant var = cell->readValue(); // 读取单元格的内容
                    QTableWidgetItem *item = new QTableWidgetItem(QString::number(var.toDouble(), 'f', 2));
                    ui->tableWidget->setItem(row, col, item);
                }
                else
                {
                    QMessageBox::warning(NULL, "错误提示", "Excel表格数据格式错误");
                    return;
                }
            }
        }
    }
}

注意:它的第一个数据的下标是从1开始的
这种方法的代码量比前面的少,看起来很简洁,速度也快

四、复制导入

我用上面的三种方法都发现无法处理公司的加密Excel。虽然可以先解密再导入,但是解密要申请太麻烦了,所以我就想到这种逆天的做法:直接手动复制Excel中想要导入的内容,然后处理系统剪切板中复制到的内容形成一个数组,再依次绘制在表格中,这样就不用管加不加密了。不过面对连复制黏贴都加密的,也是没用的。而且逼格看起来就没用前面那些看起来高级,显得有点low,哈哈哈
需要导入的头文件:

//获取剪切板内容
#include <QClipboard>
#include <QApplication>
#include <QMimeData>
#include <QMessageBox>

代码:

void MainWindow::on_pushButton_4_clicked()
{
    //获取剪切板内容
    QClipboard *clipboard = QApplication::clipboard();
    QString copyContent = clipboard->text();
	
	//更新 2022-08-03 :在实际应用中出现复制到粘贴板的数据是以"\n"和"\t"连接,少了一个空格,所以会有两种情况
	//我们需要先判断能否使用" \n"分割,若不匹配则改为使用"\n"分割
	QString regex1 = " \n";
	QString regex2 = " \t";
	if (copyContent.split(" \n").size() <= 1)
	{
		regex1 = "\n";
		regex2 = "\t";
	}
    QStringList splitList = copyContent.split(regex1);
    QStringList dataList;
    for (int i = 0; i < splitList.size() - 1; i++)
    {
        dataList.append(splitList.at(i).split(regex2));
    }
    if (dataList.size() != 4 * 4)
    {
        QMessageBox::warning(NULL, "错误提示", "请复制正确的表格内容");
        return;
    }
    for (int i = 0; i < dataList.size(); i++)
    {
        qDebug()<<dataList.at(i);
    }

    for (int i = 0; i < ui->tableWidget->rowCount() - 1; i++)
    {
        for (int j = 0; j < ui->tableWidget->columnCount() - 1; j++)
        {
            QTableWidgetItem *item = new QTableWidgetItem(dataList.at(i * 4 + j));
            ui->tableWidget->setItem(i + 1, j + 1, item);
        }
    }
}

剪切板中的内容是这样的:
注意:可能会出现"\t","\n"前面没有空格的情况

"2.00 \t5.00 \t10.00 \t9.00 \n10.00 \t0.00 \t0.00 \t11.00 \n0.00 \t0.00 \t0.00 \t12.00 \n6.00 \t7.00 \t8.00 \t88.00 \n"

所以就先用 \n 来分割成每一行,再用 \t 分割成每个单元格存入数组列表中,注意前面还有个空格
由于是复制的,所以数据在哪个位置都没问题
在这里插入图片描述
我这个操作是先手动复制数据,然后点击界面的按钮进行处理
在这里插入图片描述

结尾

ok,就这么多了,不知道大伙儿还有什么其他方法吗?如果对我这篇文章有不解和建议的话,可以直接评论或者私信我哦。

补充-QT选cmake创建的项目如何使用QXlsx

首先我是直接用Qt自带的IDE选cmake创建的项目。创建完成后编译运行看看有没有问题(一般都不会有问题吧,我选的mingw编译)。
确认项目正常后,从克隆下来的QXlsx项目文件夹中,把QXlsx文件夹拷到我们的项目目录下:
在这里插入图片描述
在QXlsx中也有一个CMakeLists.txt文件,把里面include(CPackConfig)这一句#注释掉并保存,不然后面编译的时候会报错:
在这里插入图片描述在这里插入图片描述
现在回到我们自己项目的CMakeLists.txt中,在add_executable之前添加一句add_subdirectory(QXlsx),在自动生成的target_link_libraries({您的项目名称} PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)中空格添加QXlsx,如:target_link_libraries({您的项目名称} PRIVATE Qt${QT_VERSION_MAJOR}::Widgets QXlsx)
在这里插入图片描述
在这里插入图片描述
OK,现在我们再尝试编译项目,如果没有报错,那么就成功连接了QXlsx项目了,项目结构也会多出来QXlsx
在这里插入图片描述
这边也提供了简单的Demo,大家可以看看有没有用,QT版本是5.15.2的,在下面附件中

附件

这个演示的项目下载地址(免费的免费的)
https://download.csdn.net/download/qq_16186465/85847594
QXlsx资源下载地址(这是我自己上传的,也可以去github正版官网下)
https://download.csdn.net/download/qq_16186465/85847616
QT选择cmake创建的项目使用QXlsx Demo
https://download.csdn.net/download/qq_16186465/89695939

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

1594231563

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值