Qt操作Excel
1. 库的下载与安装
由于xlsxwriter
库是跨平台的,支持读写操作的,所以我选择该第三方库来操作excel
该库的镜像地址如下:
https://gitcode.com/gh_mirrors/qt/QtXlsxWriter/overview?utm_source=csdn_github_accelerator
克隆命令为:
git clone https://gitcode.com/gh_mirrors/qt/QtXlsxWriter.git
克隆完成后有两种使用方式,我只记录一种:往工程里导pri的方式,这种方式使用简单粗暴,但是需要每一个工程都放进去。
1.1 建文件夹
第一步:在项目的目录下新建一个xlsxwriter的文件夹,在其内部再新建一个src的子文件夹;
第二步:将克隆下来的src文件夹里的内容复制到上一步新建的文件夹中;
第三步:在工程文件pro文件中加入pri文件,即
include(XlsxWriter/src/xlsx/qtxlsx.pri)
工程就变成了这样目录
就可以在其他文件引用相应的头文件
2. Qt具体操作Excel方式
直接把代码放过来一行一行注释自己看
点击查看代码
#include "dailyreport.h"
#include "ui_dailyreport.h"
#include "xlsxdocument.h"
#include "xlsxformat.h"
#include "readfile.h"
void DailyReport::on_pushButton_chaxun_3_clicked()
{
selectedMonth = ui->dateEdit->date(); // 假设你的界面上有一个日期选择器
generateDailyReport(selectedMonth);
}
void DailyReport::generateDailyReport(const QDate &daily)
{
SQLHelper sqlhelper;
sqlhelper.openDataBase();
QSqlQuery sqlquery;
QString queryString = QString("SELECT DateTime, liuliang FROM shuiwei WHERE DATE(DateTime) = '%1'").arg(daily.toString("yyyy-MM-dd"));
if (!sqlquery.exec(queryString))
{
QMessageBox::critical(this,"错误","数据查询失败");
return;
}
QMap<QDate, QMap<int, QList<float>>> hourlyData;
while (sqlquery.next())
{
QDateTime datetime = sqlquery.value("DateTime").toDateTime();
float liuliang = sqlquery.value("liuliang").toFloat();
QDate date = datetime.date(); // 获取日期
// qDebug() << date;
int hour = datetime.time().hour(); // 获取小时
// qDebug() << hour;
hourlyData[date][hour].append(liuliang);
}
// qDebug() << hourlyData;
displayHourlyDataInTable(hourlyData);
}
void DailyReport::displayHourlyDataInTable(const QMap<QDate, QMap<int, QList<float> > > &hourlyData)
{
model->clear();
// 设置表头
QStringList horizontalHeader;
horizontalHeader << "序号" << "监测日期" << "监测时间" << "实测数据(m³/s)" << "累计流量(m³)" << "生态流量异常原因";
model->setHorizontalHeaderLabels(horizontalHeader);
// 向模型填充数据
int row = 0;
for (auto dayIt = hourlyData.begin(); dayIt != hourlyData.end(); dayIt++, row++)
{
const QDate &date = dayIt.key(); // 获取外层键 也就是日期 QDate("2024-09-03")
const QMap<int, QList<float>> &hoursData = dayIt.value(); // 获取值 QMap(0, (8.149))
// QStandardItem *dateItem = new QStandardItem(date.toString("yyyy-MM-dd"));
for (int hour = 0; hour < 24; hour++)
{
QStandardItem *timeItem = new QStandardItem(QString("%1:00").arg(hour,2,10,QChar('0')));
QStandardItem *hours = new QStandardItem(QString::number(hour + 1));
QStandardItem *dateItem = new QStandardItem(date.toString("yyyy-MM-dd"));
model->setItem(hour,0, hours); // 强转
model->setItem(hour, 1, dateItem); // 第一列 日期
model->setItem(hour,2,timeItem);
timeItem->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
hours->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
dateItem->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
if (hoursData.contains(hour))
{
const float &data = hoursData[hour][0];
QString data_string = QString::number(data,'f',4);
QStandardItem *hourlyData = new QStandardItem(data_string);
model->setItem(hour,3,hourlyData);
hourlyData->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
const float &data_total = data_string.toFloat() * 3600;
QStandardItem *hourlyData_total = new QStandardItem(QString::number(data_total,'f',2));
model->setItem(hour,4,hourlyData_total);
hourlyData_total->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
}
else
{
QStandardItem hourItem("N/A");
model->setItem(row, hour + 1, &hourItem);
}
}
}
}
void DailyReport::initTableView()
{
ui->tableView->setModel(model);
ui->tableView->resizeColumnsToContents();
ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); //设置表格的单元为只读属性,即不能编辑
ui->tableView->verticalHeader()->hide(); //隐藏行头
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); //设置列的宽度
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows); // 设置表格的选择行为为选择整行 而不是单个单元格
}
void DailyReport::exportToXls(QStandardItemModel *model, const QString &fileName, const QString &powerName, const QString &exportDate)
{
// 创建excel表对象
QXlsx::Document xls;
// 创建标题格式的对象
QXlsx::Format format_title;
// 设置水平居中
format_title.setHorizontalAlignment(QXlsx::Format::AlignHCenter);
// 设置垂直居中
format_title.setVerticalAlignment(QXlsx::Format::AlignVCenter);
// 设置字体大小
format_title.setFontSize(36);
// 设置字体加粗
format_title.setFontBold(true);
// 写excel
xls.write("A1","生态流量日报表");
// 合并单元格
xls.mergeCells("A1:F7",format_title);
// 创建电站名称格式对象
QXlsx::Format format_powerName;
// 设置水平居中
format_powerName.setHorizontalAlignment(QXlsx::Format::AlignHCenter);
// 设置垂直居中
format_powerName.setVerticalAlignment(QXlsx::Format::AlignVCenter);
// 设置字体大小
format_powerName.setFontSize(36);
// 设置边框
format_powerName.setBorderStyle(QXlsx::Format::BorderStyle::BorderThin);
// 写入数据
xls.write("A8",QString("%1(%2)").arg(powerName).arg(exportDate));
// 合并单元格 A8:F14
xls.mergeCells("A8:F14",format_powerName);
// 创建表头的格式对象
QXlsx::Format format_TableTitle;
// 设置垂直居中
format_TableTitle.setVerticalAlignment(QXlsx::Format::AlignVCenter);
// 设置水平居中
format_TableTitle.setHorizontalAlignment(QXlsx::Format::AlignHCenter);
// 设置字体大小
format_TableTitle.setFontSize(22);
// 设置字体加粗
format_TableTitle.setFontBold(true);
// 设置行高 第几行 行高 注意这里用的是xls对象
xls.setRowHeight(15,47.4);
// 设置边框样式
format_TableTitle.setBorderStyle(QXlsx::Format::BorderStyle::BorderThin);
// 设置列宽 第几列 宽度
xls.setColumnWidth(1,11.33);
xls.setColumnWidth(2,25.22);
xls.setColumnWidth(3,21.00);
xls.setColumnWidth(4,34.78);
xls.setColumnWidth(5,29.33);
xls.setColumnWidth(6,54.33);
// 写入数据 第几行 第几列 内容 格式
xls.write(15,1,"序号",format_TableTitle);
xls.write(15,2,"监测日期",format_TableTitle);
xls.write(15,3,"监测时间",format_TableTitle);
xls.write(15,4,"实测流量(m³/s)",format_TableTitle);
xls.write(15,5,"累计流量(m³)",format_TableTitle);
xls.write(15,6,"生态流量异常原因",format_TableTitle);
// 创建表格内容的单元格格式
QXlsx::Format format_Table;
// 设置字体大小
format_Table.setFontSize(22);
// 设置垂直居中
format_Table.setVerticalAlignment(QXlsx::Format::AlignVCenter);
// 设置水平居中
format_Table.setHorizontalAlignment(QXlsx::Format::AlignHCenter);
// 设置边框格式
format_Table.setBorderStyle(QXlsx::Format::BorderStyle::BorderThin);
// 循环遍历模型中的数据
for (int row = 0; row < model->rowCount(); row++)
{
for (int col = 0; col < model->columnCount(); col++)
{
// 获取具体格子的数据
QModelIndex index = model->index(row, col);
// 转换格式
QString data = index.data(Qt::DisplayRole).toString();
// 向excel写入数据
xls.write(row+16,col+1,data,format_Table);
// 调整行高
xls.setRowHeight(row + 16, 47.4);
}
}
QXlsx::Format format_bottom;
format_bottom.setHorizontalAlignment(QXlsx::Format::AlignLeft);
format_bottom.setVerticalAlignment(QXlsx::Format::AlignVCenter);
format_bottom.setFontSize(22);
xls.write("A40"," 部门负责人: 值长: 值班人员: ",format_bottom);
xls.mergeCells("A40:F47");
// 保存文件
xls.saveAs(fileName + ".xlsx");
}
void DailyReport::on_save_clicked()
{
if (model->rowCount() == 0)
{
QMessageBox::critical(this,"错误","没有要导出的数据");
return;
}
if (!model)
{
QMessageBox::critical(this,"错误","数据模型未准备好");
return;
}
// 提示用户选择保存位置和文件名
QString fileName = QFileDialog::getSaveFileName(this,tr("Save File"),QDir::homePath(),tr("xls Files (*.xls);;All Files (*)"));
if (fileName.isEmpty())
{
return;
}
ReadFile readFile;
// 调用导出函数保存数据到CSV文件
// exportToCSV(model, fileName);
exportToXls(model,fileName,readFile.powerName, selectedMonth.toString("yyyy-MM-dd"));
}
3. 好的参考网站
这个博客给出了官方的例子 包括生成图像
https://blog.csdn.net/u014779536/article/details/111769792