服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - Qt数据库应用之实现数据的导入与导出

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

2022-08-14 10:51feiyangqingyun C/C++

QT中涉及到数据库相关的项目,几乎都需要将少量的信息数据导出到文件保存好,然后用户可以打开该表格进行编辑,编辑完成后保存,再重新导入到软件中。所以本文将具体为大家介绍一下这一功能如何实现,感兴趣的可以跟随小

一、前言

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

导入导出数据可以选择xls、也可以选择csv,为什么最后选择的是csv,因为xls很容易依赖本地office软件,就算用什么libxls啥的也没用,毕竟excel本身就不是标准的数据库,单元格数据可以任意指定的,一旦用户破坏了原有的格式要求,你要想按照规则读取导入数据几乎异想天开,而csv语法极其简单,就是按照指定的分隔符比如 ; 分割字符串就行,同理按照这个规则解析也是极其简单,所以在跨平台的场景下csv是首选,当然如果对格式有特殊的需要比如边框、对齐、颜色、分组等情况就必须用到xls了,本组件也封装了。

最开始做项目的时候遇到导入导出,都是直接功能源码写在对应的功能按钮函数中,后面随着项目数量的增多,就算是拷贝也是费时间的,而且这个功能还是不断改进的,一旦某个项目改进了,那相关这个功能的项目都想去改进,代码改动真大,不光是跨项目,就算是在同一个项目中,都会有多处多个信息表会要这个功能,于是想着把这个功能单独做一个通用的类,提供静态函数接口,可以指定分隔符、文件名、文件拓展名、过滤条件、表名、字段集合等。用法极其简单速度极快,导出的数据支持任意表格软件比如excel、wps等,导入数据直接到数据库,自动组织插入sql语句并执行。

二、功能特点

组件同时集成了导出数据到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以及打印数据,自动分页。

灵活性超高,可自由更改源码设置对齐方式、文字颜色、背景颜色等。

支持任意excel表格软件,包括但不限于excel2003-2021、wps、openoffice等。

纯Qt编写,支持任意Qt版本+任意编译器+任意系统。

三、体验地址

体验地址:https://pan.baidu.com/s/15ZKAlptW-rDcNq8zlzdYLg  提取码:uyes 文件名:bin_dataout.zip

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

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

四、效果图

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

五、相关代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
bool DataCsv::inputData(int columnCount,
                        const QString &columnNames,
                        const QString &tableName,
                        QString &fileName,
                        const QString &defaultDir,
                        bool existTitle)
{
    fileName = QFileDialog::getOpenFileName(0, "选择文件", defaultDir, DataCsv::CsvFilter);
    if (fileName.isEmpty()) {
        return false;
    }
 
    QFile file(fileName);
    bool ok = file.open(QIODevice::ReadOnly | QFile::Text);
    if (!ok) {
        return false;
    }
 
    //传入了字段集合则取字段
    if (!columnNames.isEmpty()) {
        columnCount = columnNames.split(",").count();
    }
 
    //先读取第一行判断列数是否和目标列数一致,不一致则返回
    QString line = QString::fromUtf8(file.readLine());
    QStringList list = line.split(DataCsv::CsvSpliter);
    if (list.count() != columnCount) {
        return false;
    }
 
    //先删除原来的数据
    QString sql = QString("delete from %1").arg(tableName);
    QSqlQuery query;
    query.exec(sql);
 
    //cvs格式需要gbk编码才能正常
    QTextStream in(&file);
    in.seek(0);
    if (fileName.endsWith(".csv")) {
#if (QT_VERSION < QT_VERSION_CHECK(6,0,0))
        in.setCodec("gbk");
#endif
    }
 
    //开启数据库事务加速处理
    QSqlDatabase::database().transaction();
 
    bool isremoveTitle = false;
    while (!in.atEnd()) {
        QString line = in.readLine();
        QStringList list = line.split(DataCsv::CsvSpliter);
 
        //如果存在标题则不需要处理第一行标题
        if (existTitle && !isremoveTitle) {
            isremoveTitle = true;
            continue;
        }
 
        //列数必须完全一致才行
        if (list.count() == columnCount) {
            if (!columnNames.isEmpty()) {
                sql = QString("insert into %1(%2) values('").arg(tableName).arg(columnNames);
            } else {
                sql = QString("insert into %1 values('").arg(tableName);
            }
 
            for (int i = 0; i < columnCount - 1; i++) {
                sql = sql + list.at(i).trimmed() + "','";
            }
 
            sql = sql + list.at(columnCount - 1).trimmed() + "')";
            query.clear();
            query.exec(sql);
        }
    }
 
    //提交数据库事务
    if (!QSqlDatabase::database().commit()) {
        QSqlDatabase::database().rollback();
        return false;
    }
 
    file.close();
    return true;
}
 
bool DataCsv::outputData(const QString &defaultName,
                         const QStringList &content,
                         QString &fileName,
                         const QString &defaultDir)
{
    bool result = true;
    QString defaultPath = QString("%1/%2").arg(defaultDir).arg(defaultName);
    fileName = QFileDialog::getSaveFileName(0, "选择文件", defaultPath, DataCsv::CsvFilter);
    outputData(fileName, content);
    return result;
}
 
bool DataCsv::outputData(QString &fileName, const QStringList &content)
{
    if (fileName.isEmpty()) {
        return false;
    }
 
    int rowCount = content.count();
    if (rowCount == 0) {
        fileName.clear();
        return false;
    }
 
    QFile file(fileName);
    if (file.open(QIODevice::WriteOnly | QFile::Text)) {
        //cvs格式需要gbk编码才能正常
        QTextStream out(&file);
        if (fileName.endsWith(".csv")) {
#if (QT_VERSION < QT_VERSION_CHECK(6,0,0))
            out.setCodec("gbk");
#endif
        }
 
        for (int i = 0; i < rowCount; i++) {
            out << content.at(i) << "\n";
        }
 
        file.close();
    }
 
    return true;
}
 
//最简单使用方法
void frmSimple::on_btnCsv1_clicked()
{
    QString file = QUIHelper::appPath() + "/db/dataout_tableview.csv";
    DataHelper::DataOut(ui->tableView, model, 0, file, "测试标题", "测试信息");
    //打开刚才导出的文件
    QUIHelper::openFile(file, "导出测试信息");
}

以上就是Qt数据库应用之实现数据的导入与导出的详细内容,更多关于Qt数据导入与导出的资料请关注服务器之家其它相关文章!

原文链接:https://blog.csdn.net/feiyangqingyun/article/details/122403702

延伸 · 阅读

精彩推荐
  • C/C++Qt自定义控件实现简易仪表盘

    Qt自定义控件实现简易仪表盘

    这篇文章主要为大家详细介绍了Qt自定义控件实现简易仪表盘,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    parkchorong3922021-08-10
  • C/C++C++ 标准模板库 STL 顺序容器详解

    C++ 标准模板库 STL 顺序容器详解

    这篇文章主要介绍了C++ 标准模板库 STL 顺序容器详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    海华啊4042021-11-05
  • C/C++关于C++的强制类型转换浅析

    关于C++的强制类型转换浅析

    C++的强制类型转换是我们在日常开发中经常会遇到的,下面这篇文章主要给大家介绍了关于C++强制类型转换的相关资料,文中通过示例代码介绍的非常详细...

    Dawn_sf5922021-06-01
  • C/C++C++ STL容器详解之红黑树部分模拟实现

    C++ STL容器详解之红黑树部分模拟实现

    本文主要对红黑树进行了详细介绍,并对其核心功能进行了模拟实现。文中的代码对我们的学习或工作有一定的价值,感兴趣的小伙伴可以了解一下...

    TT在长大4452022-03-10
  • C/C++C语言二叉树常见操作详解【前序,中序,后序,层次遍历及非递归查找,统计个数,比较,求深度】

    C语言二叉树常见操作详解【前序,中序,后序,层次遍历及非递归查

    这篇文章主要介绍了C语言二叉树常见操作,结合实例形式详细分析了基于C语言的二叉树前序,中序,后序,层次遍历及非递归查找,统计个数,比较,求深度等相关...

    松阳9632021-06-23
  • C/C++c++类和对象基本概念

    c++类和对象基本概念

    这篇文章主要为大家介绍了c++类和对象,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助...

    Huang Jason8102022-03-02
  • C/C++C++常用字符串函数大全(2)

    C++常用字符串函数大全(2)

    这篇文章主要给大家分享的是C++常用字符串函数的大全,cstring.h库即C语言中的string.h库,它是C语言中为字符串提供的标准库。C++对此进行了兼容,所以我们...

    梁唐5882022-02-20
  • C/C++解析bitmap处理海量数据及其实现方法分析

    解析bitmap处理海量数据及其实现方法分析

    本篇文章是对bitmap处理海量数据及其实现的方法进行了详细的分析介绍,需要的朋友参考下...

    C++教程网5212020-12-12