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的整个过程了,浏览过程中,如若发现错误,欢迎大家指正,有问题的可以评论区留言或者私信。最后,如果大家觉得有所帮助的话,可以点个赞,谢谢大家!祉猷并茂,顺遂无虞! |