Ubuntu系统下通过第三方库QtXlsx输出Excel(图文详解)

Ubuntu系统下通过第三方库QtXlsx输出Excel

  • 1、前言
  • 2、安装QXlsx库
    • [2.1 安装必要开发工具](#2.1 安装必要开发工具)
    • [2.2 获取 QtXlsx 源代码](#2.2 获取 QtXlsx 源代码)
    • [2.3 编译QXlsx库](#2.3 编译QXlsx库)
    • [2.4 把库添加进项目文件](#2.4 把库添加进项目文件)
  • 3、编写Qt程序
    • [3.1 添加静态库和头文件路径](#3.1 添加静态库和头文件路径)
    • [3.2 引入头文件](#3.2 引入头文件)
    • [3.3 创建 output 目录 + 创建 Excel 文档](#3.3 创建 output 目录 + 创建 Excel 文档)
    • [3.4 初始化 Excel 工作表并写入表头](#3.4 初始化 Excel 工作表并写入表头)
    • [3.5 启动 Excel 自动保存定时器(每 5 秒)](#3.5 启动 Excel 自动保存定时器(每 5 秒))
    • [3.6 初始化 Modbus RTU 温度设备](#3.6 初始化 Modbus RTU 温度设备)
    • [3.7 启动每秒读取温度的定时器](#3.7 启动每秒读取温度的定时器)
    • [3.8 发送读取温度的 Modbus 指令](#3.8 发送读取温度的 Modbus 指令)
    • [3.9 把温度写入 Excel](#3.9 把温度写入 Excel)
    • [3.10 程序退出前最终保存 Excel](#3.10 程序退出前最终保存 Excel)
    • [3.11 生成Excel](#3.11 生成Excel)
  • 4、安装Linux端的Excel软件
  • 5、.h文件和.cpp文件
    • [5.1 .h文件](#5.1 .h文件)
    • [5.2 .cpp文件](#5.2 .cpp文件)
  • [6、 总结](#6、 总结)

1、前言

|-------------------------------------------------------------|
| 记录一下Ubuntu系统下通过第三方库QtXlsx输出Excel的实现方法,方便自己回顾,也可以给有需要的人提供帮助。 |

2、安装QXlsx库

2.1 安装必要开发工具

|-----------------------------------|
| 我安装了Qt Creator,可以通过指令查看,下面那个是查看指令 |

bash 复制代码
qmake --version

2.2 获取 QtXlsx 源代码

|-------------------|
| 通过git克隆QtXlsx库源代码 |

bash 复制代码
git clone https://github.com/QtExcel/QtXlsx.git

|------|
| 成功下载 |

2.3 编译QXlsx库

|-----------|
| 进入QXlsx路径 |

bash 复制代码
cd QXlsx/QXlsx/

|------------------------------------|
| 注: 因为QXlsx文件夹后面还有个QXlsx文件夹,一定要进入两次 |

|-------------|
| 进入后执行下面指令编译 |

bash 复制代码
qmake QXlsx.pro
bash 复制代码
ls

|------------------------------|
| ls看一下有没有生成,可以看到生成了Makefile文件 |

bash 复制代码
make

|----------|
| make进行编译 |

2.4 把库添加进项目文件

bash 复制代码
ls

|--------------------------|
| s看一下当前路径下有哪些文件,可以看到静态库文件 |

l

bash 复制代码
pwd

|-----------------------------------|
| pwd是输出当前路径的指令,可以看到当前路径,这个就是静态库路径了 |

|------------|
| 头文件也在这个路径下 |

3、编写Qt程序

|---------------------|
| 接下来就是编写Qt程序输出excel了 |

3.1 添加静态库和头文件路径

|---------------|
| 在项目的.pro文件中添加 |

3.2 引入头文件

cpp 复制代码
#include <xlsxdocument.h>
#include <xlsxworkbook.h>
#include <xlsxcell.h>

|----------------------------|
| 引入QXlsx库的相关头文件,用于操作Excel文件 |

3.3 创建 output 目录 + 创建 Excel 文档

cpp 复制代码
QDir dir;
if (!dir.exists("output")) {
    dir.mkdir("output");        // 创建 output 文件夹
}

xlsx = new QXlsx::Document();   // 创建 Excel 文档对象

excelFilename = "output/" +
                QDateTime::currentDateTime()
                    .toString("'temperature_'yyyyMMdd_HHmmss'.xlsx'");

|-------------------------------------------------------|
| 确保 Excel 文件可以写入到 output/ 文件夹;创建一个新的 Excel 文档,后续用于追加数据 |

3.4 初始化 Excel 工作表并写入表头

cpp 复制代码
xlsx->addSheet("TemperatureData");  // 添加工作表

xlsx->write("A1", "日期");
xlsx->write("B1", "时间");
xlsx->write("C1", "温度 (°C)");

|--------------------------------------------|
| 在Excel文件的第一行(A1, B1, C1)中写入表头,分别表示日期、时间和温度 |

3.5 启动 Excel 自动保存定时器(每 5 秒)

cpp 复制代码
excelFlushTimer = new QTimer(this);
excelFlushTimer->setInterval(5000);     // 5 秒保存一次
connect(excelFlushTimer, &QTimer::timeout, this, [this]() {
    xlsx->saveAs(excelFilename);        // 自动保存 Excel
});
excelFlushTimer->start();

|------------------------|
| 避免突然断电或异常导致 Excel 数据丢失 |

3.6 初始化 Modbus RTU 温度设备

cpp 复制代码
temperatureDevice = new QModbusRtuSerialMaster(this);

temperatureDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, "/dev/ttyS0");
temperatureDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::NoParity);
temperatureDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, 9600);
temperatureDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, 8);
temperatureDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop);

if (!temperatureDevice->connectDevice())
{
    qCritical() << "无法连接到设备:" << temperatureDevice->errorString();
    return;
}

|--------------------------|
| 配置串口参数,建立 Modbus RTU 通讯) |

3.7 启动每秒读取温度的定时器

cpp 复制代码
temperatureReadTimer = new QTimer(this);
temperatureReadTimer->setInterval(1000);  // 每秒读取
temperatureReadTimer->start();

connect(temperatureReadTimer, &QTimer::timeout, this, &Widget::temperatureRead);

|-------------|
| 温度以 1 秒频率采集 |

3.8 发送读取温度的 Modbus 指令

cpp 复制代码
QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters, 0, 1);

if (QModbusReply *reply = temperatureDevice->sendReadRequest(readUnit, 1))
{
    connect(reply, &QModbusReply::finished, this, &Widget::temperatureReplyFinished);
}

|----------------------------|
| 通过 Modbus RTU 向从站请求读取温度寄存器 |

3.9 把温度写入 Excel

cpp 复制代码
xlsx->write(QString("A%1").arg(rowNum), datePart);
xlsx->write(QString("B%1").arg(rowNum), timePart);
xlsx->write(QString("C%1").arg(rowNum), formattedTemperature);
rowNum++;  // 下一行

3.10 程序退出前最终保存 Excel

cpp 复制代码
xlsx->saveAs(excelFilename);

|----------------|
| 确保在程序关闭前文件最终落盘 |

3.11 生成Excel

|--------------------------|
| 可以看到在output文件夹下有生成的Excel |

4、安装Linux端的Excel软件

|---------|
| 更新软件包索引 |

bash 复制代码
sudo apt update

|----------------|
| 安装支持Excel文件的程序 |

bash 复制代码
sudo apt install libreoffice

|----------------------------------------------------|
| 安装成功,点击开始菜单就能看到,到时候想打开我们生成的Excel文件,直接点击文件就会用这个软件打开 |

5、.h文件和.cpp文件

|--------------------|
| 粘贴.h和.cpp文件给大家参考一下 |

5.1 .h文件

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QModbusRtuSerialMaster>
#include <QSerialPort>
#include <QTimer>
#include <QModbusReply>
#include <xlsxdocument.h>
#include <xlsxworkbook.h>
#include <QDir>
#include <xlsxcell.h>
#include "signalfilter.h"

QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;

    QModbusRtuSerialMaster *temperatureDevice = nullptr;
    QTimer *temperatureReadTimer = nullptr;
    QXlsx::Document *xlsx;                                       // Excel 文档对象
    int rowNum = 2;                                                  // 当前行号,用于记录数据

    void initTemperatureDevice();                               // 初始化温度设备
    void temperatureRead();                                     // 读取温度

    void temperatureReplyFinished();                            // 读取温度完毕
    void handleTemperatureRead(qint16 rawValue);                               // 处理读取温度
    void onModbusError(QModbusDevice::Error error);             // 处理 Modbus 错误

    SignalFilter temperatureFilter;
    QString excelFilename;
    QTimer *excelFlushTimer = nullptr;


};
#endif // WIDGET_H

5.2 .cpp文件

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QDateTime>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    initTemperatureDevice();
    temperatureFilter.setWindowSizeFloat(5);

    QDir dir;
    if (!dir.exists("output")) {
        dir.mkdir("output");
    }

    // 创建 Excel 文件对象
    xlsx = new QXlsx::Document();       // 创建一个新的 Excel 文档

    excelFilename = "output/" +
                    QDateTime::currentDateTime()
                        .toString("'temperature_'yyyyMMdd_HHmmss'.xlsx'");

    xlsx->addSheet("TemperatureData");  // 添加一个工作表

    // 写入表头(时间和温度)
    xlsx->write("A1", "日期");
    xlsx->write("B1", "时间");
    xlsx->write("C1", "温度 (°C)");

    excelFlushTimer = new QTimer(this);
    excelFlushTimer->setInterval(5000); // 5 秒刷新一次
    connect(excelFlushTimer, &QTimer::timeout, this, [this]() {
        xlsx->saveAs(excelFilename);
        // qDebug() << "Excel 自动刷新保存:" << excelFilename;
    });
    excelFlushTimer->start();
}

Widget::~Widget()
{
    delete ui;

    if (xlsx) {
        xlsx->saveAs(excelFilename); // 最终保存一次
        delete xlsx;
    }
}

void Widget::initTemperatureDevice()
{
    temperatureDevice = new QModbusRtuSerialMaster(this);

    // 设置 Modbus RTU 的串口参数
    temperatureDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, "/dev/ttyS0");
    temperatureDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::NoParity);
    temperatureDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, 9600);
    temperatureDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, 8);
    temperatureDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop);

    // 连接 Modbus 设备
    if (!temperatureDevice->connectDevice())
    {
        qCritical() << "无法连接到设备:" << temperatureDevice->errorString();
        return;  // 设备未连接,返回
    }
    else
    {
        qDebug() << "设备已连接!";
    }

    // 连接 Modbus 错误信号
    connect(temperatureDevice, &QModbusClient::errorOccurred, this, &Widget::onModbusError);

    // 创建定时器
    temperatureReadTimer = new QTimer(this);
    temperatureReadTimer->setInterval(1000);
    temperatureReadTimer->start();
    connect(temperatureReadTimer, &QTimer::timeout, this, &Widget::temperatureRead);  // 每秒钟读取温度

}

void Widget::temperatureRead()
{
    QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters, 0 ,1);

    if(QModbusReply *reply = temperatureDevice->sendReadRequest(readUnit, 1))
    {
        connect(reply, &QModbusReply::finished, this, &Widget::temperatureReplyFinished);
    }
    else
    {
        qCritical() << "发送读取请求失败: " << temperatureDevice->errorString();
    }


}



// 读取温度完毕
void Widget::temperatureReplyFinished()
{
    QModbusReply *reply = qobject_cast<QModbusReply *>(sender());
    if(!reply)
        return;

    if(reply->error() == QModbusDevice::NoError)
    {
        const QModbusDataUnit unit = reply->result();
        int datasize = unit.values().size();

        if(datasize > 0 && !unit.values().isEmpty())
        {
            quint16 rawUnit = unit.values().at(0);
            qint16 rawData = static_cast<qint16>(rawUnit);
            handleTemperatureRead(rawData);
        }
        else
        {
            qCritical() << "接收数据错误";
        }
    }

    // 删除回复对象
    reply->deleteLater();
}

void Widget::handleTemperatureRead(qint16 rawValue)
{
    float temperature = static_cast<qint16>(rawValue) / 10.0;
    float formattedTemperature = qRound(temperature * 10) / 10.0;

    // float temperatureFilterDate = temperatureFilter.medianFilterFloat(formattedTemperature);
    ui->temperatureLable->setText(QString::number(formattedTemperature));

    // 获取时间
    QString datePart = QDateTime::currentDateTime().toString("MM-dd-yyyy");  // 格式化为 MM-dd-yyyy
    QString timePart = QDateTime::currentDateTime().toString("HH:mm:ss");    // 格式化为 HH:mm:ss

    // 写入 Excel 文件(时间和温度)
    xlsx->write(QString("A%1").arg(rowNum), datePart);   // 写入日期
    xlsx->write(QString("B%1").arg(rowNum), timePart);   // 写入时间
    // xlsx->write(QString("C%1").arg(rowNum), temperatureFilterDate);  // 写入温度(保留一位小数)
    xlsx->write(QString("C%1").arg(rowNum), formattedTemperature);  // 写入温度(保留一位小数)


    rowNum++;  // 增加行号

    // 保存 Excel 文件
    // xlsx->saveAs("temperature_data.xls");
}

void Widget::onModbusError(QModbusDevice::Error error)
{
    qCritical() << "Modbus error:" << error;
}

6、 总结

|------------------------------------------------------------------------------------------------------------------|
| 以上就是Ubuntu系统下通过第三方库QtXlsx输出Excel的整个过程了,浏览过程中,如若发现错误,欢迎大家指正,有问题的可以评论区留言或者私信。最后,如果大家觉得有所帮助的话,可以点个赞,谢谢大家!祉猷并茂,顺遂无虞! |

相关推荐
祝威廉41 分钟前
InfiniSynapse: 把PDF里的表格和Excel/业务数据联合分析
pdf·excel
承缘丶42 分钟前
Excel字段清单转各类数据库建表语句的工具(开箱即用)
数据库·excel·excel转数据库建表语句
爱吃萝卜的美羊羊12 小时前
ubuntu下国内升级ollama
linux·运维·ubuntu
HIT_Weston13 小时前
47、【Ubuntu】【Gitlab】拉出内网 Web 服务:Nginx 事件驱动分析(一)
前端·ubuntu·gitlab
w***153114 小时前
ubuntu 安装 Redis
linux·redis·ubuntu
弓弧名家_玄真君15 小时前
Ubuntu 20.04.3 LTS 安装vnc (Xfce4 + Xvfb)
linux·运维·ubuntu
唐·柯里昂79815 小时前
野火鲁班猫5使用正点原子 RTL8188EUS Wifi模块驱动移植(Linux5.10 Debian系统) 解决zsh报错
linux·c语言·mcu·物联网·ubuntu·硬件工程·软件构建
Evan芙18 小时前
用fping编写脚本扫描10.0.0.0/24网段在线主机
linux·运维·网络·excel
Evan芙20 小时前
Ubuntu 24.04 双网卡 bond0 绑定
ubuntu·postgresql·php