Qt数据库应用之实现数据分组导出

目录
  • 一、前言
  • 二、功能特点
  • 三、体验地址
  • 四、效果图
  • 五、相关代码

一、前言

数据分组导出和打印这个需求并不是近期的需求,而是之前做温湿度监控系统的时候提的需求,当然也有几个系统用到了,比如啤酒保鲜监控系统。这个需求的应用场景是,有很多个设备,每个设备都产生了很多的运行日志、报警日志等,这些日志按照时间顺序存储在数据库中,用户需要按照不同设备分组导出,同时对应统计有多少行记录,开始时间和结束时间,以副标题的形式展示在文档中。

数据源有了,关键是如何组织这些数据,传入参数的时候以特定分隔符做标记,取出来生成文档的时候,按照特定分隔符分割字符串,然后循环遍历取出数据,按照html格式填充一行行表格内容,最终形成一个完整的html字符串集合,这个字符串集合既可以保存到xls文档,也可以作为打印的内容,导出到pdf就是打印到pdf文件。在分组导出的同时,还可以设置过滤条件,符合特定条件的记录不同颜色显示。

二、功能特点

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

三、体验地址

体验地址:https://pan.baidu.com/s/1eeL5MTz0rifwtVLegRpkoQ  提取码:erxm 文件名:bin_dataout.zip

国内站点:https://gitee.com/feiyangqingyun

国际站点:https://github.com/feiyangqingyun

四、效果图

五、相关代码

#include "frmdataout3.h"
#include "ui_frmdataout3.h"
#include "frmmain.h"
#include "quihelper.h"
#include "dataxls.h"
#include "dataprint.h"

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

frmDataOut3::~frmDataOut3()
{
    delete ui;
}

void frmDataOut3::showEvent(QShowEvent *)
{
    static bool isShow = false;
    if (!isShow) {
        isShow = true;
        QMetaObject::invokeMethod(this, "on_btnLoad_clicked");
    }
}

void frmDataOut3::setInfo(int type, int count)
{
    QString str1 = "生成数据";
    if (type == 1) {
        str1 = "导出数据";
    } else if (type == 2) {
        str1 = "打印数据";
    }

    ui->labInfo1->setText(str1);
    ui->labInfo2->setText(QString("共 %1 条").arg(count));
    QString msec = QString::number((float)time.elapsed() / 1000, 'f', 3);
    ui->labInfo3->setText(QString("用时 %1 秒").arg(msec));
}

void frmDataOut3::getContent(int maxCount, QStringList &content, QStringList &subTitle1, QStringList &subTitle2)
{
    content.clear();
    subTitle1.clear();
    subTitle2.clear();
    maxCount = maxCount >= rowCount ? rowCount : maxCount;

    QString sql = QString("select * from MsgInfo order by DeviceID asc,MsgTime asc limit %1").arg(maxCount);
    QSqlQuery query;
    if (!query.exec(sql)) {
        return;
    }

    int count = 0;
    int logID = 0;
    QString tempDeviceID = "0";
    QString temp = "";
    QString startTime = "";
    QString endTime = "";

    while (query.next()) {
        count++;
        logID++;

        QString deviceID = query.value(0).toString();
        QString deviceName = query.value(1).toString();
        QString deviceTel = query.value(2).toString();
        QString deviceWeight = query.value(3).toString();
        QString deviceTemp = query.value(4).toString();
        QString devicePressure = query.value(5).toString();
        QString msgType = query.value(6).toString();
        QString msgTime = query.value(7).toString();
        QString msgContent = query.value(8).toString();

        //如果是一个全新的设备,则添加子标题,添加上一个设备的数据集合后清空集合数据.
        if (deviceID != tempDeviceID) {
            subTitle1 << QString("设备编号 : %1    设备名称 : %2    设备号码 : %3").arg(deviceID).arg(deviceName).arg(deviceTel);
            //当前设备是一个新的设备,而且当前数据集合不为空,说明上一个设备数据集合已经准备完毕
            //此时添加上一个设备的子标题,因为此时才能计算得到结束时间
            if (!temp.isEmpty()) {
                content << temp.mid(0, temp.length() - 1);
                logID--;

                subTitle2 << QString("开始时间 : %1    结束时间 : %2    记录总数 : %3").arg(startTime).arg(endTime).arg(logID);
                temp = "";
                logID = 1;
            }

            tempDeviceID = deviceID;
            startTime = msgTime;
        }

        endTime =  msgTime;
        temp += QString("%1;%2;%3;%4;%5;%6;%7|").arg(logID).arg(deviceWeight).arg(deviceTemp).arg(devicePressure).arg(msgType).arg(msgTime).arg(msgContent);
    }

    //添加最后一个设备的数据
    if (!temp.isEmpty()) {
        content << temp.mid(0, temp.length() - 1);
        subTitle2 << QString("开始时间 : %1    结束时间 : %2    记录总数 : %3").arg(startTime).arg(endTime).arg(logID);
    }
}

DataContent frmDataOut3::getDataContent(int maxCount)
{
    DataContent dataContent;
    dataContent.title = "所有短信记录";
    dataContent.subTitle = QString("%1 导出短信记录").arg(DATETIME);

    QList<QString> columnNames;
    columnNames << "序号" << "重量" << "温度" << "压力" << "类型" << "接收时间" << "短信内容";
    QList<int> columnWidths;
    columnWidths << 70 << 70 << 70 << 70 << 100 << 180 << 260;
    dataContent.columnNames = columnNames;
    dataContent.columnWidths = columnWidths;

    QStringList content, subTitle1, subTitle2;
    getContent(maxCount, content, subTitle1, subTitle2);
    dataContent.content = content;
    dataContent.subTitle1 = subTitle1;
    dataContent.subTitle2 = subTitle2;

    //默认对齐方式
    dataContent.defaultAlignment = 1;
    //边框粗细
    dataContent.borderWidth = 1;
    //导出到xls有样式比如边框需要开启 cellStyle = true
    //dataContent.cellStyle = true;
    dataContent.randomColor = ui->ckRandomColor->isChecked();

    //下面表示第4列 (对应表中的 类型 字段) 值 包含 重量 关键字 则突出显示
    dataContent.checkColumn = ui->ckCheckColumn->isChecked() ? 4 : -1;
    dataContent.checkType = "contains";
    dataContent.checkValue = "重量";

    dataContent.stretchLast = ui->ckStretchLast->isChecked();
    dataContent.landscape = false;
    return dataContent;
}

void frmDataOut3::initForm()
{
    ui->frame->setFixedWidth(AppConfig::RightWidth);

    columnNames << "设备编号" << "设备名称" << "设备号码" << "重量" << "温度" << "压力" << "类型" << "接收时间" << "短信内容";
    columnWidths << 70 << 150 << 120 << 70 << 70 << 70 << 100 << 180 << 180;

    rowCount = frmMain::getCount();
    columnCount = columnNames.count();

    model = new QSqlTableModel;
    QUIHelper::initTableView(ui->tableView);
}

void frmDataOut3::on_btnLoad_clicked()
{
    time.restart();

    model->setTable("MsgInfo");
    model->setSort(0, Qt::AscendingOrder);
    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));
    }

    setInfo(0, rowCount);
}

void frmDataOut3::on_btnXls_clicked()
{
    time.restart();

    DataContent dataContent = getDataContent(AppConfig::CountXls);
    dataContent.fileName = QUIHelper::appPath() + "/db/dataout3.xls";
    dataContent.sheetName = "短信信息";
    DataXls::saveXls(dataContent);

    setInfo(1, qMin(rowCount, AppConfig::CountXls));
    QUIHelper::openFile(dataContent.fileName, "导出短信信息");
}

void frmDataOut3::on_btnPdf_clicked()
{
    time.restart();

    DataContent dataContent = getDataContent(AppConfig::CountPdf);
    dataContent.fileName = QUIHelper::appPath() + "/db/dataout3.pdf";
    DataPrint::savePdf(dataContent);

    setInfo(1, qMin(rowCount, AppConfig::CountPdf));
    QUIHelper::openFile(dataContent.fileName, "导出短信信息");
}

void frmDataOut3::on_btnPrint_clicked()
{
    DataContent dataContent = getDataContent(AppConfig::CountPrint);
    DataPrint::print(dataContent);
}

到此这篇关于Qt数据库应用之实现数据分组导出的文章就介绍到这了,更多相关Qt数据分组导出内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Qt数据库应用之实现通用数据库分页

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 数据库分页展示,在所有的涉及到数据库记录的项目中都是需要的,除了简单的设备信息表.用户信息表这种很少几条几十条数据量的表除外,其余的日志记录表等都需要分页展示数据,少量的数据可以滚动条下拉查看完,超过百条以上的一般建议要加上分页的功能处理,不然用户查看起来明显不舒服,体验不友好,最明显的例子就是网页的搜索结果,一次性展示上万条,不仅是多余的增加了查询的压力,而且用户往往只关注最前面的几页记录,再比如查询报警记录,一般

  • Qt数据库应用之实现通用数据库采集

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 数据库采集对应的就是上一篇文章的数据库同步,数据库同步到云端数据库以后,app.网页.小程序啥的要数据的话,可以通过执行http请求拿到数据,http接收应答这边程序一般最简单可以用php写,几行代码即可,比如根据请求的参数构建需要执行的sql语句,执行以后将结果json形式返回即可. 通过Qt程序去做数据库采集有多种方式,即可直接连接数据库然后绑定数据库表到QSqlTableModel,然后不断调用select方法

  • Qt数据库应用之实现通用数据库清理

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 很多项目如果需要存储很多日志记录比如运行日志,时间长了记录数量非常多,数据库体积不断增大,对应数据库表的增删改查的效率不断降低,为了消除这几个影响,需要有一套机制,不断将早期的数据清理,清理的规则比如可以指定表名.字段名.时间范围等. 日志记录的清理一方面是为了保证查询效率,毕竟数据量大了明显影响查询速度,一方面也是为了节约磁盘存储空间,毕竟存储空间有限,尤其是嵌入式板子,容量一般不会很大,记录无限制的存储下去会不断

  • Qt数据库应用之通用数据库同步

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 数据库同步的主要功能是将本地的数据库记录同步到远程的数据库,其中数据库类型不限,比如本地是sqlite数据库,远程可以是mysql数据库,本地是mysql数据库,远程也可以是postgresql数据库,只要数据库设置的时候设定好就行.这样做相当于就是通过程序的方式将数据库记录上传同步,还有一种机制是通过直接数据库上设置热备份啥的,个人还是习惯通过程序的方式,自主可控,比如可以自定义同步哪个表,哪部分数据需要同步. 有

  • Qt数据库应用之实现通用数据库请求

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 数据库请求是在数据库采集的基础上,换成http请求的形式来获取数据,这样就脱离了数据库组件,而采用的通用的http请求的形式从数据库拿数据库,这个通用性就非常广泛了,比如对方用java采集到设备的数据存入数据库,另外一个区域是用的c#采集的数据入库,然后统一规则统一规范约定一个请求机制,定时器或者线程取执行请求,拿到的json数据,挨个取出来结果,数组集合的方式发信号出去. 之前写过的可视化大屏电子看板程序,采用的也

  • Qt数据库应用之实现通用数据生成器

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 有两种应用场景需要用到数据生成器,一种是需要测试数据库性能,比如在100万条和1000万条记录的时候对比查询或更新语句执行耗时,一种是随机模拟生成一堆数据,用来测试程序的性能,看下程序中到了百万千万级别的数据量的时候,程序的代码执行是否受影响,影响有大等.很多人觉得sqlite数据库性能超过几十万就不行,于是亲自用这个数据发生器随机模拟生成了一亿条记录,测试下来发现性能有损失,但是不像传说中的垃圾,起码还是完全可用的

  • Qt数据库应用之实现数据分组导出

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 数据分组导出和打印这个需求并不是近期的需求,而是之前做温湿度监控系统的时候提的需求,当然也有几个系统用到了,比如啤酒保鲜监控系统.这个需求的应用场景是,有很多个设备,每个设备都产生了很多的运行日志.报警日志等,这些日志按照时间顺序存储在数据库中,用户需要按照不同设备分组导出,同时对应统计有多少行记录,开始时间和结束时间,以副标题的形式展示在文档中. 数据源有了,关键是如何组织这些数据,传入参数的时候以特定分隔符做标记

  • Qt数据库应用之实现数据的导入与导出

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 在经历过大大小小十几个甚至几十个纯QtWidget项目后,涉及到数据库相关的项目,几乎都有一个需求,将少量的信息数据比如设备信息.防区信息等,导出到文件保存好,然后用户可以打开该表格进行编辑,编辑完成后保存,再重新导入到软件中,这样相当于安排专人录入数据,而不是在软件中一个个新增效率低了些,甚至有些软件运行在嵌入式板子上或者一些特殊场景,不大方便现场添加编辑信息,如果是提供模板之类的让用户添加好,然后再一次性导入,这

  • Qt数据库应用之实现数据图文混排

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 除了能够打印基本的文字信息数据到pdf和纸张,越来越多的应用需求还要求能够导出图片,并且要支持图文混排,相当于doc文档类似,当然也不会是太复杂的,类似于打印报表一样,有表格形式的文字描述,也有对应的图片插入其中,图文混排的应用场景还真不少比如医疗行业输出诊断结果往往都带了图片.于是针对这个需求特意开辟了新的类DataCreat专门生成报表的数据,将生成好的数据体直接传入给DataPrint类即可,如果有各种各样的不

  • Qt数据库应用之实现数据打印到纸张

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 数据能够打印到pdf文件,当然可以打印到纸张,而且使用qprinter默认就是打印到纸张的,上一篇文章写得功能是打印到pdf,其实还要单独特殊设置打印到文件,并指定格式为pdf.不指定输出文件和格式默认就是打印到纸张,关于Qt打印内容到纸张,网上的办法非常多,比如有些直接用painter绘制,逐步控制分页打印,个人还是喜欢html格式的内容传入,因为html格式相当灵活,可控范围相当大,而且整齐,甚至可以先直接输出到

  • Qt数据库应用之数据打印到pdf

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 自从数据可以导出到xls,又有客户提出了不同的需求,比如既然可以将数据导出到xls,那是否可以导出到pdf文件呢?因为xls打开以后用户可以修改数据造假之类的,而pdf默认是不可编辑的,除非借助专业的工具,所以如果想要限定用户导出数据不能被更改,那导出pdf是最佳选择.写程序往往都是这样,一步步慢慢增加,随着用户需求的增加,程序量也越来越多,轮子组件也越来越多.往往客户提需求的时候,一定要认真聆听,尤其是一线用户,实

  • Qt物联网管理平台之实现数据查询导出打印

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 本系统存储的三大类记录,运行日志.报警日志.用户日志,这些不同类似的记录,都需要提供查询功能,可以按照记录的时间范围等条件查询,查询的记录需要做分页显示,为了分页显示还特意花了很多时间专门封装了一个通用分页控件,分两部分,一部分专门的分页UI展示,显示页码,可以单击页码直接跳转到对应页,也可以直接数码页码跳转,还可以上一页.下一页.第一页.末一页按钮跳转.一部分是分页功能,专门按照不同的数据库组合sql分页语句查询.

  • PHP实现数据库统计时间戳按天分组输出数据的方法

    本文实例讲述了PHP实现数据库统计时间戳按天分组输出数据的方法.分享给大家供大家参考,具体如下: 比如统计每天用户注册数,数据库表存了一张用户注册记录表: create table table_name(id int primary key,register_time int(10)); register_time记录的是时间戳,以前的做法是,接收查询开始时间.查询结束时间,然后循环查询每天的注册数量,代码: /* 查询2015-12-01 至 2015-12-14 */ // 开始的时间戳 $

  • MySQL数据库结构和数据的导出和导入

    正在看的db2教程是:MySQL数据库结构和数据的导出和导入. 导出要用到MySQL的mysqldump工具,基本用法是: shell> mysqldump [OPTIONS] database [tables] 如果你不给定任何表,整个数据库将被导出. 通过执行mysqldump --help,你能得到你mysqldump的版本支持的选项表. 注意,如果你运行mysqldump没有--quick或--opt选项,mysqldump将在导出结果前装载整个结果集到内存中,如果你正在导出一个大的数据

  • asp.net实现Gradview绑定数据库数据并导出Excel的方法

    本文实例讲述了asp.net实现Gradview绑定数据库数据并导出Excel的方法.分享给大家供大家参考,具体如下: protected void showData_Click(object sender, EventArgs e) { SqlConnection myConnection = new SqlConnection("Data Source=localhost;Initial Catalog=test;User ID=sa;password=sa"); SqlDataA

  • Python实现将MySQL数据库表中的数据导出生成csv格式文件的方法

    本文实例讲述了Python实现将MySQL数据库表中的数据导出生成csv格式文件的方法.分享给大家供大家参考,具体如下: #!/usr/bin/env python # -*- coding:utf-8 -*- """ Purpose: 生成日汇总对账文件 Created: 2015/4/27 Modified:2015/5/1 @author: guoyJoe """ #导入模块 import MySQLdb import time impor

随机推荐