• Qt数据库应用1数据导入导出csv


    一、前言

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

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

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

    二、功能特点

    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. 支持任意excel表格软件,包括但不限于excel2003-2021、wps、openoffice等。
    26. 纯Qt编写,支持任意Qt版本+任意编译器+任意系统。

    三、体验地址

    1. 体验地址:https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A 提取码:o05q 文件名:bin_dataout.zip
    2. 国内站点:https://gitee.com/feiyangqingyun
    3. 国际站点:https://github.com/feiyangqingyun
    4. 个人主页:https://blog.csdn.net/feiyangqingyun
    5. 知乎主页:https://www.zhihu.com/people/feiyangqingyun/

    四、效果图

    五、相关代码

    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, "导出测试信息");
    }
    
  • 相关阅读:
    从零开始入门 K8s | 应用编排与管理
    209. Minimum Size Subarray Sum
    208. Implement Trie (Prefix Tree)
    207. Course Schedule
    203. Remove Linked List Elements
    183. Customers Who Never Order
    182. Duplicate Emails
    181. Employees Earning More Than Their Managers
    1261. Find Elements in a Contaminated Binary Tree
    1260. Shift 2D Grid
  • 原文地址:https://www.cnblogs.com/feiyangqingyun/p/15783160.html
Copyright © 2020-2023  润新知