多线程极速导出/9字段10W行只需2秒/导入导出打印组件/功能丰富简单易用

news/2024/9/28 1:06:30

一、功能特点

  1. 组件同时集成了导出数据到csv、xls、pdf和打印数据。
  2. 所有操作全部提供静态方法无需new,数据和属性等各种参数设置采用结构体数据,极为方便。
  3. 同时支持QTableView、QTableWidget、QStandardItemModel、QSqlTableModel等数据源。
  4. 提供静态方法直接传入QTableView、QTableWidget控件,自动识别列名、列宽和数据内容。
  5. 每组功能都提供单独的完整的示例,注释详细,非常适合各阶段Qter程序员。
  6. 原创导出数据机制,不依赖任何office组件或者操作系统等第三方库,支持嵌入式linux。
  7. 速度超快,9个字段10万行数据只需要2秒钟完成。
  8. 只需要四个步骤即可开始急速导出海量数据比如100W条记录到Excel。
  9. 同时提供直接写入数据接口和多线程写入数据接口,不卡主界面。
  10. 可设置标题、副标题、表名。
  11. 可设置导出数据的字段名、列名、列宽。
  12. 可设置末尾列自动拉伸填充,默认拉伸更美观。
  13. 可设置是否启用校验过滤数据,启用后符合规则的数据特殊颜色显示。
  14. 可指定校验的列、校验规则、校验值、校验值数据类型。
  15. 校验规则支持 精确等于==、大于>、大于等于>=、小于<、小于等于<=、不等于!=、包含contains。
  16. 校验值数据类型支持 整型int、浮点型float、双精度型double,默认文本字符串类型。
  17. 可设置随机背景颜色及需要随机背景色的列集合。
  18. 支持分组输出数据,比如按照设备分组输出数据,方便查看。
  19. 可设置csv分隔符、行内容分隔符、子内容分隔符。
  20. 可设置边框宽度、自动填数据类型,默认自动数据类型开启。
  21. 可设置是否开启数据单元格样式,默认不开启,不开启可以节约大概30%的文件体积。
  22. 可设置横向排版、纸张边距等,比如导出到pdf以及打印数据。
  23. 提供图文混排导出数据到pdf以及打印示例,自动分页,支持多图。
  24. 提供一个打印样板中同时包括横向纵向排版示例。
  25. 提供静态函数将控件截图导出到pdf文件。
  26. 提供静态函数将图片转成pdf文件。
  27. 提供静态函数将csv文件转成xls文件,支持列宽表名等参数设置。
  28. 针对每列可分别设置字段对齐样式、内容对齐样式,包括左对齐、居中对齐、右对齐。
  29. 灵活性超高,可自由更改源码设置对齐方式、文字颜色、背景颜色等。
  30. 支持任意excel表格软件,包括但不限于excel2003-2021、wps、openoffice等。
  31. 纯Qt编写,支持任意Qt版本+任意编译器+任意系统。

二、相关链接

  1. 体验地址:https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A 提取码:o05q 文件名:bin_dataout.zip
  2. 国内站点:https://gitee.com/feiyangqingyun
  3. 国际站点:https://github.com/feiyangqingyun

三、使用方法

3.1 第一步:引入组件

  • 组件中所有代码文件是一个整体,不支持单个代码文件拆分使用,因为很多通用的方法都放在一个代码文件中,复用很多代码。
  • datehead是本组件用到的头文件以及通用的数据结构体。
  • datahelper是通用的校验列函数和数据导出打印函数。
  • datacreat用于创建html格式的数据,用来导出到pdf和打印数据。
  • datacsv用于导入导出文件csv格式。
  • dataxls是数据导出到xls的核心。
  • dataprint是数据导出到pdf和打印数据。
  1. 将core_dataout整个目录拷贝到你的项目文件夹同级目录。
  2. 打开你的项目的pro文件,引入组件。
INCLUDEPATH += $$PWD/../core_dataout
include ($$PWD/../core_dataout/core_dataout.pri)
  1. 此时在项目树状结构图中可以看到 core_dataout 组件代码。
  2. 演示代码中的quihelper各种函数等,都在core_base组件中,如果需要使用的话,需要先引入该组件。

3.2 第二步:获取数据

  • 无论是导出到xls还是pdf或者打印,前提是都要拿到需要处理的数据集合。
  • 拿到数据的方式基本上两种,一种是数据库查询比如QSqlTableModel,一种是界面控件取数据比如QTableView、QTableWidget、QStandardItemModel。
  • QTableView一般有两种数据源,一个是QSqlTableModel,一个是QStandardItemModel。
  • 数据集合按照一行行数据来,中间用英文的 分号 ; 隔开,最后统一放到QStringList中。

3.2.1 示例QSqlTableModel

void frmDataOut2::on_btnLoad_clicked()
{model->setTable("MsgInfo");model->select();ui->tableView->setModel(model);for (int i = 0; i < columnCount; i++) {model->setHeaderData(i, Qt::Horizontal, columnNames.at(i));ui->tableView->setColumnWidth(i, columnWidths.at(i));}
}QStringList frmDataOut2::getContent()
{QStringList content;QString sql = QString("select * from MsgInfo limit %1").arg(100);QSqlQuery query;if (!query.exec(sql)) {return content;}//循环遍历数据while (query.next()) {QStringList list;for (int i = 0; i < column; i++) {list << query.value(i).toString();}content << list.join(";");}return content;
}

3.2.2 示例QStandardItemModel

void frmSimple::on_btnLoad_clicked()
{//清空数据model->clear();    //设置列数及列标题和列宽model->setColumnCount(column);for (int i = 0; i < column; ++i) {model->setHeaderData(i, Qt::Horizontal, columnNames.at(i));ui->tableView->setColumnWidth(i, columnWidths.at(i));}//循环添加行数据for (int i = 0; i < row; ++i) {//循环添加一行的列QList<QStandardItem *> items;for (int j = 0; j < column; ++j) {QStandardItem *item = new QStandardItem;item->setText(QString("行%1_列%2").arg(i + 1).arg(j + 1));items << item;}model->appendRow(items);}ui->tableView->setModel(model);
}QStringList frmSimple::getContent()
{//从 QTableView 获取数据QStringList content;for (int i = 0; i < row; ++i) {QStringList list;for (int j = 0; j < column; ++j) {list << model->item(i, j)->text();}//每行数据作为一个整体字符串分割存入content << list.join(";");}return content;
}

3.2.3 示例QTableWidget

void frmDataOut1::on_btnLoad_clicked()
{QStringList list;list << "防区上线" << "防区离线" << "防区旁路" << "防区报警" << "防区故障";ui->tableWidget->clearContents();for (int i = 0; i < rowCount; i++) {//随机生成告警内容int index = rand() % 4;QTableWidgetItem *item1 = new QTableWidgetItem(QString::number(i + 1));QTableWidgetItem *item2 = new QTableWidgetItem("防区" + QString::number(i + 1));QTableWidgetItem *item3 = new QTableWidgetItem("主机上报");QTableWidgetItem *item4 = new QTableWidgetItem(list.at(index));QTableWidgetItem *item5 = new QTableWidgetItem(DATETIME);item5->setTextAlignment(Qt::AlignCenter);ui->tableWidget->setItem(i, 0, item1);ui->tableWidget->setItem(i, 1, item2);ui->tableWidget->setItem(i, 2, item3);ui->tableWidget->setItem(i, 3, item4);ui->tableWidget->setItem(i, 4, item5);}
}QStringList frmDataOut1::getContent()
{QStringList content;for (int i = 0; i < row; i++) {QStringList list;for (int j = 0; j < column; j++) {list << ui->tableWidget->item(i, j)->text();}content << list.join(";");}return content;
}

3.3 第三步:设置数据

  • 无论是导出到xls还是pdf或者打印,都需要设置数据结构体,传入列名、列宽、数据集合等信息。
  • 如果是导出到xls还需要设置文件名及表名。
  • 如果是导出到pdf需要设置文件名。
  • 打印不需要设置文件名和表名。
void frmSimple::on_btnXls_clicked()
{//设置结构体数据DataContent dataContent;//填充内容dataContent.content = getContent();//设置列名列宽dataContent.columnNames = columnNames;dataContent.columnWidths = columnWidths;//设置文件名dataContent.fileName = "d:/0.xls";//设置表名dataContent.sheetName = "测试信息";//调用静态函数保存DataXls::saveXls(dataContent);//打开刚才导出的文件QUIHelper::openFile(dataContent.fileName, "导出测试信息");
}void frmSimple::on_btnPdf_clicked()
{//设置结构体数据DataContent dataContent;//填充内容dataContent.content = getContent();//设置列名列宽dataContent.columnNames = columnNames;dataContent.columnWidths = columnWidths;//设置文件名dataContent.fileName = "d:/0.pdf";//调用静态函数保存DataPrint::savePdf(dataContent);//打开刚才导出的文件QUIHelper::openFile(dataContent.fileName, "导出测试信息");
}void frmSimple::on_btnPrint_clicked()
{//设置结构体数据DataContent dataContent;//填充内容dataContent.content = getContent();//设置列名列宽dataContent.columnNames = columnNames;dataContent.columnWidths = columnWidths;//调用静态函数打印DataPrint::print(dataContent);
}

3.4 第四步:执行操作

  • 数据导入导出组件dataout提供了统一的数据结构体用来设置数据和其他参数。
  • 封装了统一的静态函数DataXls::saveXls用来导出到xls、DataPrint::savePdf用来导出到pdf、DataPrint::print用来打印数据。
  • 支持各种详细复杂的参数设置以及海量数据导出多线程操作,具体参见详细使用demo。
//调用静态函数保存到xls
DataXls::saveXls(dataContent);
//调用静态函数保存到pdf
DataPrint::savePdf(dataContent);
//调用静态函数打印数据
DataPrint::print(dataContent);

四、最简方法

为了方便入门级的Qter(Qt程序员)也能直接上手使用,比如很多时候已经把数据加载到了QTableView、QTableWigdte中,只想直接传入这个控件及数据模型,就给我导出数据到csv/xls/pdf和打印数据就行,甚至可以不传入文件名称,弹出对话框让用户选择。立即安排。

void frmSimple::on_btnCsv1_clicked()
{QString file = QUIHelper::appPath() + "/db/dataout_tableview.csv";DataHelper::DataOut(ui->tableView, model, 0, file, "测试标题", "测试信息");//打开刚才导出的文件QUIHelper::openFile(file, "导出测试信息");
}void frmSimple::on_btnXls1_clicked()
{//通用函数直接传入控件
#if 1QString file = QUIHelper::appPath() + "/db/dataout_tableview.xls";DataHelper::DataOut(ui->tableView, model, 1, file, "测试标题", "测试信息");
#else//不传入文件名则会弹出对话框选择保存文件名QString file = DataHelper::DataOut(ui->tableView, model, 1);
#endif//打开刚才导出的文件QUIHelper::openFile(file, "导出测试信息");
}void frmSimple::on_btnPdf1_clicked()
{//通用函数直接传入控件QString file = QUIHelper::appPath() + "/db/dataout_tableview.pdf";DataHelper::DataOut(ui->tableView, model, 2, file, "测试标题", "测试信息");//打开刚才导出的文件QUIHelper::openFile(file, "导出测试信息");
}void frmSimple::on_btnPrint1_clicked()
{//通用函数直接传入控件DataHelper::DataOut(ui->tableView, model, 3, "", "测试标题");
}void frmSimple::on_btnCsv2_clicked()
{QString fileName = QUIHelper::appPath() + "/db/dataout_tablewidget.csv";DataHelper::dataout(ui->tableWidget, 0, fileName, "测试标题", "测试信息");//打开刚才导出的文件QUIHelper::openFile(fileName, "导出测试信息");
}void frmSimple::on_btnXls2_clicked()
{QString fileName = QUIHelper::appPath() + "/db/dataout_tablewidget.xls";DataHelper::dataout(ui->tableWidget, 1, fileName, "测试标题", "测试信息");//打开刚才导出的文件QUIHelper::openFile(fileName, "导出测试信息");
}void frmSimple::on_btnPdf2_clicked()
{//通用函数直接传入控件QString fileName = QUIHelper::appPath() + "/db/dataout_tablewidget.pdf";DataHelper::dataout(ui->tableWidget, 2, fileName, "测试标题", "测试信息");//打开刚才导出的文件QUIHelper::openFile(fileName, "导出测试信息");
}void frmSimple::on_btnPrint2_clicked()
{//通用函数直接传入控件DataHelper::dataout(ui->tableWidget, 3, "", "测试标题");
}

四、效果图








本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/64860.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

python-生成器

生成器(generator)其实是一类特殊的迭代器。前面博客我们每次迭代获取数据(通过next()方法)时按照特定的规律进行生成。但是我们在实现一个迭代器时,关于当前迭代到的状态需要我们自己记录,进而才能根据当前状态生成下一个数据。为了达到记录当前状态,并配合next()函数进行…

Cisco ASAv 9.22.1 发布,新增功能概览

Cisco ASAv 9.22.1 发布,新增功能概览Cisco ASAv 9.22.1 - 思科自适应安全虚拟设备 (ASAv) Cisco Adaptive Security Virtual Appliance (ASAv) 请访问原文链接:https://sysin.org/blog/cisco-asav/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org思科自适应安…

C++ 容器操作

▲ 容器操作 《C++ Primer》 P295

Day1 介值定理

介值定理 设 $ f(x) $ 是 $ [l,r] $ 上的连续函数,且 $ f(l) \le f(r) $ ,则 $ \forall \ v \in [f(l),f(r)] \ , \exists \ u \in [l,r] \ , f(u)=v $ 上午 思考题有n个物品,每个物品有重量wi和体积vi且密度均匀。 你可以切物品,每次可以选一个物品切成两部分,也就是选一…

C++ 顺序容器类型

▲ 顺序容器类型 《C++ Primer》 P294

读构建可扩展分布式系统:方法与实践15可扩展系统的基本要素

并发系统1. 可扩展系统的基本要素 1.1. 分布式系统在本质上就是复杂的,你必须考虑多种故障模式,并设计应对所有可能发生的情况的处理方式 1.2. 大规模应用程序需要协调大量的硬件和软件组件,共同实现低延迟和高吞吐量的能力 1.3. 面临的挑战是将所有活动部件组合成一个应用程…

01 看代码写结果 函数参数使用可变数据 有什么陷阱

面试题:def func(a,b=[]) 有什么陷阱?因为b是可变类型,如果不传递参数时,默认使用的同一个内存地址看代码写结果 def func(a,b=[]):b.append(a)return bl1 = func(1) l2 = func(2,[11,22]) #先打印:[11,22] ,在打印2 l3 = func(3)# [1,3] [11,22,2] [1,3] print(l1,…