目录
前言
QXlsx 是一个开源的 Qt 库,可以在不依赖 Microsoft Office 的情况下读写 Excel 文件。应该每个小伙伴都能遇到用QT导出Excel的需求,一开始大致思路都是直接用代码画出整个Excel。但是这种做法遇到简单的Excel报表还好,如果是遇到复杂的,一点变动整个代码都要重写,这就比较麻烦了。最近重新开发一个项目,看到了公司前辈解决导出Excel报告的方案,比较简单灵活,发出来给大家分享一下,下面先给大家介绍一下QXlsx的用法,后面再提方案。
一、QXlsx 库简介
QXlsx 是一个基于 Qt 实现的读写 Excel 文件的库,支持.xlsx 格式,无需安装 Microsoft Office 或 COM 组件。它提供了类似于 QString、QList 的 API,易于学习和使用。
项目地址:https://github.com/QtExcel/QXlsx
项目准备:
1.安装 Qt 开发环境(Qt 5.6 及以上版本)
2.准备 Qt Creator 开发工具
3.从 GitHub 下载 QXlsx 源码,下载方法如下图所示
二、QT项目中添加QXlsx库
我们从github下载完的压缩包里面内容很多,但是我们项目中只需要那个QXlsx文件夹。
将 QXlsx文件夹复制到我们的项目中去,然后在xxx项目名.pro的最下方添加以下内容
include($$PWD/QXlsx/QXlsx.pri)
INCLUDEPATH += $$PWD/QXlsx
添加完成后,QXlsx库就会显示到我们的QT项目中了。
三、 基本用法示例
我直接把测试代码写在了mainwindow里面,点击按钮就生成一个excel文档,下面是实现代码。
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "xlsxdocument.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QCoreApplication>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
// 创建一个新的Excel文档
QXlsx::Document xlsx;
xlsx.setColumnWidth(2,23,5);//设置2到23列宽度为5
// 写入数据到单元格
xlsx.write("A1", "Hello, QXlsx!");
xlsx.write("A2", 123);
xlsx.write("A3", 3.14);
// 设置单元格格式
QXlsx::Format format;
format.setFontBold(true);//设置加粗
format.setFontSize(20);//设置字号
format.setBorderStyle(QXlsx::Format::BorderThin);//设置边框线
xlsx.mergeCells("B2:C2");//合并单元格
format.setFontColor(Qt::red);//字体颜色
format.setHorizontalAlignment(QXlsx::Format::AlignHCenter);//水平居中
format.setVerticalAlignment(QXlsx::Format::AlignVCenter);//竖直居中
xlsx.write("B2", "666", format);
xlsx.write("C2", "", format);
// 保存文件
if (xlsx.saveAs("example.xlsx")) {
// qDebug() << "File saved successfully.";
} else {
// qDebug() << "Failed to save the file.";
}
}
最后运行点击按钮,如果生成以下文件,导出基本上就成功了。
下面我们再打开excel文件验证一下内容是否和我们导出的一致。
四、Excel报告导出方案
现在聊一聊如何简单实现导出Excel报告,可以避免大量代码去画Excel,我们可以将Excel报告中大部分不变的表格框和文字先用WPS或者Office工具先整理出一个模版,然后需要填写的变量用 功能码+"特殊符号"去代替,比如:report1, 和 report2, 是我们需要填写的两个位置,我们在打开QT的时候去读取这个模版的所有内容,过滤出带逗号的单元格,把行列和功能码记录下来放到map中,这样我们在生成报告的时候,先把模版读取下来,直接通过功能码就可以找到对应应该填充的行列数进行填充,最后save as ,就可以完成Excel报告,这样我们修改Excel报告的时候就不用大规模的动代码了,这样说可能有小伙伴不明白,下面分步骤去讲一下。
1.做一个excel模版
XXXX报告 | ||||
标题1 | 标题2 | 标题3 | 标题4 | 标题5 |
标题2 | export1, | 固定内容 | export8, | export13, |
标题3 | export2, | export7, | export9, | export14, |
标题4 | export3, | 固定内容 | 固定内容 | export15, |
标题5 | export4, | export6, | export11, | export16, |
标题6 | export5, | 固定内容 | export12, | 固定内容 |
当然,简单的直接按行列填充的Excel直接生成就可以了,我说的是需要导出那种复杂的Excel报告,里面有的需要填固定内容,有的需要程序算出一个结果或者读取一个 值填充到对应位置,有的可能合并几个单元格填充一个变量的情况。我们就可以先用WPS等工具先做出一个模版,里面包含我们需要生成报告的所有内容,需要程序填充的内容用 功能码+特殊符号代替。
2.QT读取Excel模版
在程序.h中引用 #include "xlsxdocument.h"。
在程序.cpp中读取excel模版,并将模版中带逗号的单元格的行和列以及功能码记录下来,放到一个以功能码为键,以行列的struct为值的QHash全局变量中。
//读取excel模板
if(ReportTemplate!=""){
QXlsx::Document xldx1("template/模版.xlsx");
findNonEmptyCells(xldx1,",");//调用下方代码
}
//找到模板中带,的单元格 记录下来
void mainwindow::findNonEmptyCells(QXlsx::Document& xlsx,const QString& searchText) {
for(int row=1;row<xlsx.dimension().rowCount();row++){
for(int col=1;col<xlsx.dimension().columnCount();col++){
QXlsx::Cell *cell=xlsx.cellAt(row,col).get();
if(cell && cell->value().type()==QVariant::String){
QString text=cell->value().toString();
if(text.contains(searchText)){
text=text.remove(searchText);
Report report;
report.col=col;
report.row=row;
reportMap[text]=report;
}
}
}
}
}
//用到的结构体和QHash
struct Report{
int row;
int col;
};
QHash<QString,Report> reportMap;
3. 将模版复制出来另存为一份
QXlsx::Document xldx1("template/模版.xlsx");
QString filePath="xxx的报告.xlsx";
xldx1.saveAs(filePath);
4.读取另存为的报告填充内容后保存
bool mainwindow::findById(const QString &id,int &row,int &col){
if(reportMap.contains(id)){
Report report=reportMap[id];
row=report.row;
col=report.col;
return true;
}
return false;
}
QXlsx::Document xldx1("xxx的报告.xlsx");
QString id="report1";
QString val="要填充的内容";
int row;
int col;
if(findById(id,row,col)){//如果找到功能码 就填充内容
xldx1.write(row,col,val);
}
xldx1.save();
通过功能码去找QHash中是否存在对应的键值对,找到的话就把这个功能码应该填充的内容write进去。这样的做法是比较活,Excel报告需要调整的话直接改模版就行了,程序基本上不用动,当然我们可以将功能码根据自己的业务整理成一个ini配置文件,这样就更灵活了。
总结
如果只需要简单的Excel导出,那么前三个大标题的内容就可以满足需求,但是如果是比较复杂的Excel导出报告,我建议你参考一下我第四项的Excel报告导出方式更灵活一些。大家如果有更好的方案,也可以互相交流,互相进步。