QT 语言的学习 day10 数据库的学习 增删改 (QT 自带的数据库 QSqlDatabase数据库)

2023-11-16

1.基本知识的学习

Qt 提供了 QtSql 模块来提供平台独立的基于 SQL 的数据库操作。这里我们所说的“平台独立”,既包括操作系统平台,有包括各个数据库平台。另外,我们强调了“基于 SQL”,因为 NoSQL 数据库至今没有一个通用查询方法,所以不可能提供一种通用的 NoSQL 数据库的操作。Qt 的数据库操作还可以很方便的与 model/view 架构进行整合。通常来说,我们对数据库的操作更多地在于对数据库表的操作,而这正是 model/view 架构的长项。

Qt 使用QSqlDatabase表示一个数据库连接。更底层上,Qt 使用驱动(drivers)来与不同的数据库 API 进行交互。Qt 桌面版本提供了如下几种驱动:


 2.小细节

找到系统中所有可用的数据库驱动的名字列表。我们只能使用出现在列表中的驱动。由于默认情况下,QtSql 是作为 Qt 的一个模块提供的。为了使用有关数据库的类,我们必须早 .pro 文件中添加这么一句:


3.QT 的数据库的使用  :qt----QSqlDatabase数据库

建立一个类:


class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;
    QSqlDatabase database;//建立了数据库的对象
    void connectDb();//数据库的初始化
    void createTable();//建表
    bool isStudentExist(int);//判断 这个id 是否存在
    int beforeId;
    int beforeAge;

    QString beforeName;
private slots:
    void btnInsterSlot();//添加信息的按键槽函数
    void btnDeleteSlot();//删除信息的按键槽函数
    void btnUpdateSlot();//根据学生信息里面的id  来进行  数据更改
    void btnSelectSlot();//更新ui 设计界面的数据
};


 4.数据库的初始化:

void Dialog::connectDb()//数据库 初始化函数
{
    //使用Sqlite的驱动获得数据库连接的对象
  database = QSqlDatabase::addDatabase("QSQLITE");
    //设置数据库文件的名称
  database.setDatabaseName("Student_info.db");
    //设置用户名 密码
  database.setUserName("she001");//用户名
  database.setPassword("123");//密码
  if(database.open())
  {
      qDebug() << "数据库连接成功";
      //连接成功,建表
    createTable();
  }
  else
  {
      //连接失败
    QSqlError error = database.lastError();
    QMessageBox::critical(this,"错误",error.text());
  }
}

5.增加数据

void Dialog::btnInsterSlot()//添加信息的按键槽函数
{
    QString name = ui->lineEdit_name->text();//提取输入框的信息  (姓名)
    if (name == "")//判断信息是否为空
    {
        QMessageBox::warning(this,"警告","请输入完整的信息");//警告的提示框
        return;
    }
    int id = ui->spinBox_id->value();//提取id 的大小
    int age = ui->spinBox_age->value();//提取的 年龄的大小
    QSqlQuery sq;//创建分类表

    //防止sql注入问题,预处理(:id,:name,:age)
    QString sql = "INSERT INTO student VALUES(?,?,?)";
    //预处理
    sq.prepare(sql);//绑定函数  因为在prepare()中虽然是标准的SQL指令,但是对于具体的数值类的量不可能在string表示出来
    //占位符数据替换
    sq.addBindValue(id);
    sq.addBindValue(name);
    sq.addBindValue(age);


    //执行sql语句
    if(sq.exec())//绑定成功后调用exec()就可以执行插入操作,写入数据库,成功与否就看exec()返回值了。
    {
        btnSelectSlot();//更新ui 设计界面的数据
        QMessageBox::information(this,"通知","添加成功");
    }
    else
    {
        QString errorMsg = sq.lastError().text();
        QMessageBox::critical(this,"错误",errorMsg);
    }

}

6.删除数据

void Dialog::btnDeleteSlot()//删除学生的信息
{

    int id = ui->spinBox_id->value();//提取  数据库里面 唯一的key  这个是 删除数据的关键
   //判断是否存在
    if(!isStudentExist(id))
    {
        QMessageBox::warning(this,"警告","此学号的学生不存在");
        return;
    }
    QSqlQuery sq;
    //防止sql注入问题,预处理(:id,:name,:age)
    QString sql = "DELETE FROM student WHERE id=:id";
    //预处理
    sq.prepare(sql);
    //占位符数据替换
    sq.addBindValue(id);
    //执行sql语句
    if(sq.exec())
    {
         btnSelectSlot();//更新ui 设计界面的数据
        QMessageBox::information(this,"通知","删除成功");
    }
    else
    {
        QString errorMsg = sq.lastError().text();//信息错误的字符串
        QMessageBox::critical(this,"删除失败",errorMsg);//错误提示框   加载错误提示信息字符串  弹出提示框
    }
}

7.修改个别的数据

void Dialog::btnUpdateSlot()//根据学生信息里面的id  来进行  数据更改
{
    QString name = ui->lineEdit_name->text();//提取学生的名字
    if (name == "")
    {
        QMessageBox::warning(this,"警告","请输入完整的信息");
        return;
    }
    int id = ui->spinBox_id->value();//提取信息
    int age = ui->spinBox_age->value();
    //判断是否存在
     if(!isStudentExist(id))
     {
         QMessageBox::warning(this,"警告","此学号的学生不存在");
         return;
     }
    QSqlQuery sq;
    //防止sql注入问题,预处理(:id,:name,:age)
    QString sql = "UPDATE student SET name=:name,age=:age WHERE id=:id";
    //预处理
    sq.prepare(sql);//绑定函数
    //占位符数据替换
    sq.addBindValue(name);
    sq.addBindValue(age);
    sq.addBindValue(id);
    //执行sql语句
    if(sq.exec())
    {
         btnSelectSlot();
        QMessageBox::information(this,"通知","修改成功");
    }
    else
    {
        QString errorMsg = sq.lastError().text();
        QMessageBox::critical(this,"修改失败",errorMsg);
    }
}

8.所有的代码:

ui 设计界面

SOL .pro

QT       += core gui sql

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    dialog.cpp

HEADERS += \
    dialog.h

FORMS += \
    dialog.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

 dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QDebug>          //输出文字
#include <QSqlDatabase>   //qt有关数据库操作常用QSqlDatabase这个类来操作,使用这个类时,首先在模块中添加  Qt += sql 然后再添加头文件 #include <QtSql>
#include <QSqlError>      //错误信息提示
#include <QSqlQuery>     //
#include <QMessageBox>    //信息框

//Qt中使用QDialog来实现对话框,QDialog继承自QWidget
//,对话框分为两种,一种是模态对话框、 另一种是非模态对话框。即阻塞和非阻塞对话框,而模态对话框又有两种:
//应用程序级别的和窗口级别的,分别指完成对话框之前阻塞整个应用和阻塞关联窗口。
//exec() 和  open() 分别为应用程序级别和窗口级别的模态对话框,show()则为非模态对话框。

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;
    QSqlDatabase database;//建立了数据库的对象
    void connectDb();//数据库的初始化
    void createTable();//建表
    bool isStudentExist(int);//判断 这个id 是否存在
    int beforeId;
    int beforeAge;

    QString beforeName;
private slots:
    void btnInsterSlot();//添加信息的按键槽函数
    void btnDeleteSlot();//删除信息的按键槽函数
    void btnUpdateSlot();//根据学生信息里面的id  来进行  数据更改
    void btnSelectSlot();//更新ui 设计界面的数据
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) ://构造函数
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    setWindowTitle("数据库增删改查");//改变ui界面窗口的题目
    QWidget::setWindowState(Qt::WindowActive);
    setWindowFlags(Qt::WindowStaysOnTopHint);
    connectDb();//数据库 初始化函数
    connect(ui->pushButton_insert,SIGNAL(clicked()),this,SLOT(btnInsterSlot()));//按键与槽函数连接
    connect(ui->pushButton_delete,SIGNAL(clicked()),this,SLOT(btnDeleteSlot()));
    connect(ui->pushButton_select,SIGNAL(clicked()),this,SLOT(btnSelectSlot()));
    connect(ui->pushButton_update,SIGNAL(clicked()),this,SLOT(btnUpdateSlot()));
    ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
}

Dialog::~Dialog()//析构函数
{
    //关闭数据库
    if(database.isOpen())
        database.close();
    delete ui;
}

void Dialog::connectDb()//数据库 初始化函数
{
    //使用Sqlite的驱动获得数据库连接的对象
  database = QSqlDatabase::addDatabase("QSQLITE");
    //设置数据库文件的名称
  database.setDatabaseName("Student_info.db");
    //设置用户名 密码
  database.setUserName("she001");//用户名
  database.setPassword("123");//密码
  if(database.open())
  {
      qDebug() << "数据库连接成功";
      //连接成功,建表
    createTable();
  }
  else
  {
      //连接失败
    QSqlError error = database.lastError();
    QMessageBox::critical(this,"错误",error.text());
  }
}

void Dialog::createTable()//建立一个数据表
{
    //创建一个数据库操作对象
    QSqlQuery sq; //创建分类表
    QString sql = "CREATE TABLE Student(id INTEGER PRIMARY KEY,\
                     name TEXT NOT NULL,age INTEGER)";
    if(sq.exec(sql))
        qDebug() << "建表成功";
    else
        qDebug() << sq.lastError().text();//输出错误的原因
}


void Dialog::btnInsterSlot()//添加信息的按键槽函数
{
    QString name = ui->lineEdit_name->text();//提取输入框的信息  (姓名)
    if (name == "")//判断信息是否为空
    {
        QMessageBox::warning(this,"警告","请输入完整的信息");//警告的提示框
        return;
    }
    int id = ui->spinBox_id->value();//提取id 的大小
    int age = ui->spinBox_age->value();//提取的 年龄的大小
    QSqlQuery sq;//创建分类表

    //防止sql注入问题,预处理(:id,:name,:age)
    QString sql = "INSERT INTO student VALUES(?,?,?)";
    //预处理
    sq.prepare(sql);//绑定函数  因为在prepare()中虽然是标准的SQL指令,但是对于具体的数值类的量不可能在string表示出来
    //占位符数据替换
    sq.addBindValue(id);
    sq.addBindValue(name);
    sq.addBindValue(age);


    //执行sql语句
    if(sq.exec())//绑定成功后调用exec()就可以执行插入操作,写入数据库,成功与否就看exec()返回值了。
    {
        btnSelectSlot();//更新ui 设计界面的数据
        QMessageBox::information(this,"通知","添加成功");
    }
    else
    {
        QString errorMsg = sq.lastError().text();
        QMessageBox::critical(this,"错误",errorMsg);
    }

}

void Dialog::btnDeleteSlot()//删除学生的信息
{

    int id = ui->spinBox_id->value();//提取  数据库里面 唯一的key  这个是 删除数据的关键
   //判断是否存在
    if(!isStudentExist(id))
    {
        QMessageBox::warning(this,"警告","此学号的学生不存在");
        return;
    }
    QSqlQuery sq;
    //防止sql注入问题,预处理(:id,:name,:age)
    QString sql = "DELETE FROM student WHERE id=:id";
    //预处理
    sq.prepare(sql);
    //占位符数据替换
    sq.addBindValue(id);
    //执行sql语句
    if(sq.exec())
    {
         btnSelectSlot();//更新ui 设计界面的数据
        QMessageBox::information(this,"通知","删除成功");
    }
    else
    {
        QString errorMsg = sq.lastError().text();//信息错误的字符串
        QMessageBox::critical(this,"删除失败",errorMsg);//错误提示框   加载错误提示信息字符串  弹出提示框
    }
}
// 更新固定学号的人
void Dialog::btnUpdateSlot()//根据学生信息里面的id  来进行  数据更改
{
    QString name = ui->lineEdit_name->text();//提取学生的名字
    if (name == "")
    {
        QMessageBox::warning(this,"警告","请输入完整的信息");
        return;
    }
    int id = ui->spinBox_id->value();//提取信息
    int age = ui->spinBox_age->value();
    //判断是否存在
     if(!isStudentExist(id))
     {
         QMessageBox::warning(this,"警告","此学号的学生不存在");
         return;
     }
    QSqlQuery sq;
    //防止sql注入问题,预处理(:id,:name,:age)
    QString sql = "UPDATE student SET name=:name,age=:age WHERE id=:id";
    //预处理
    sq.prepare(sql);//绑定函数
    //占位符数据替换
    sq.addBindValue(name);
    sq.addBindValue(age);
    sq.addBindValue(id);
    //执行sql语句
    if(sq.exec())
    {
         btnSelectSlot();
        QMessageBox::information(this,"通知","修改成功");
    }
    else
    {
        QString errorMsg = sq.lastError().text();
        QMessageBox::critical(this,"修改失败",errorMsg);
    }
}

void Dialog::btnSelectSlot()//更新ui 设计界面的数据
{
    //清空之前的显示
   ui->tableWidget->setRowCount(0);
    QSqlQuery sq;
    QString sql = "SELECT * FROM student ";
    //执行sql语句
    if(sq.exec(sql))
    {
        //遍历
      while(sq.next())
      {
          int id = sq.value("id").toInt();//获取当前表里面的数据的值  id
          QString name =sq.value("name").toString();//获取当前表里面的数值  name
          int age =sq.value("age").toInt();//获取当前表里面的数值 age
          qDebug() << id << name << age;//在下面的数据输出框 输出当前的提取的数据
          //获取当前表格中的行数
          int rowCount = ui->tableWidget->rowCount();
          //添加空白行
          ui->tableWidget->insertRow(rowCount);
          //给空白行添加数据
          ui->tableWidget->setItem(rowCount,0,new QTableWidgetItem(QString::number(id)));//第几行 添加数据  参数1  行数   参数2 列数  参数3  QTableWidgetItem  指明QTableWidget中的一个Item。Item通常包含文本、图标、checkbox。
          ui->tableWidget->setItem(rowCount,1,new QTableWidgetItem(name));
          ui->tableWidget->setItem(rowCount,2,new QTableWidgetItem(QString::number(age)));
      }
    }
    else
    {
        QString errorMsg = sq.lastError().text();
        QMessageBox::critical(this,"执行失败",errorMsg);
    }
}



bool Dialog::isStudentExist(int id)//判断 这个id 是否存在
{
    QSqlQuery sq;
    //防止sql注入问题,预处理(:id,:name,:age)
    QString sql = "SELECT * FROM student WHERE id=:id";
    //预处理
    sq.prepare(sql);
    //占位符数据替换
    sq.addBindValue(id);
    //执行sql语句
    if(sq.exec())
    {
        return sq.next();
    }
    else
    {
        return false;
    }
}



 mian.cpp

#include "dialog.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.show();

    return a.exec();
}


9.基本操作的提示

1、创建数据库

1

2

3

4

5

6

7

QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");

db.setHostName("MyBrandDB");

db.setDatabaseName("MyDb.db");

db.setUserName("Liu");

db.setPassword("123456");

if(!db.open())

    return false;<br>在使用QSqlDatabase::addDatabase("QOCI","OracleA")函数时,第一个参数是驱动类型主键,第二个是连接名。

2、数据库的增删改查(查询命令就是SQL的通用命令)

1.创建一张表

1

2

3

4

5

6

QSqlQuery query;

 //创建分类表

 query.exec("create table type_table(id varchar primary key, name varchar)");

 query.exec("insert into type_table values('0', '请选择类型')");

 query.exec("insert into type_table values('1', '电视')");

 query.exec("insert into type_table values('2', '空调')");

2.查询/获取键值

1

2

3

4

QSqlQuert query;

query.exec(QString("select price from table_name where 条件1='' and 条件2=''"))  

query.next();//在执行完exec()之后会把指针放在记录集中的第一个记录之上,所以需要调用next()来获取第一个数据

int nPrice = query.value(0).toInt();

3.修改/写入数据库

1

2

3

4

5

6

7

8

QSqlQuery query;

QSqlDatabase::database().transaction();    //事物操作

bool bResult = query.exec(QString("update table_name set price=2 where 条件1='' and 条件2=''"));

if(bResult)

    QSqlDatabase::database().commit();      //提交

else

    QSqlDatabase::database().rollback();    //回滚


10.知识的补充

Qt中的Qt SQL模块提供了对数据库的支持,模块中类可分为三层:驱动层,sql接口层,用户层。


驱动层:(QSqlDriver,QSqlDriverCreator,QSqlDriverCreatorBase,QSqlDriverPlugin)为具体的数据库和SQL接口层之间提供了底层的桥梁;


SQL接口层:(QSqlDatabase,QSqlQuery,QSqlError,QSqlRecord)提供了对数据库的访问,其中QSqlDatabase类用来创建连接,QSqlQuery类可以使用SQL语句来实现与数据库交互;


用户接口层:(QSqlTableModel,QSqlQueryModel,QSqlRelationalTableModel)实现了将数据库中的数据链接到窗口部件上,这些类是使用模型/视图框架实现的,它们是更高层次的抽象;

创建一个数据库

格式为:create database 数据库名;

例:create database test;

创建一个表

格式为:create table 表名(内容 类型);

例:create table student(number int , name char(32), score double);

向表中插入信息

格式为:insert into 表名 values(表中的内容);

例:insert into student values(1, 'xiaoming', 99);

从表格中删除信息

格式为:delete from 表名 where 列名 = 条件;

例:delete  from student where name = 'xiaoming';

查询表中的内容

格式为:select 列名 from 表名 where 列名 = 条件;

例:select score from student where name = 'xiaoming';

我们可以用这样的语句查询所有的信息

select * from student;

修改表中的数据

格式为:update 表名 set 列名 = 新内容 where 列名 = 条件;

例:update student set score = 66 where name = 'xiaoming';

从数据库中删除一个表

格式为:drop table 表名;

例:drop table student;


11.别的版本的代码

#include "sqlitedatabase.h"

SqliteDatabase::SqliteDatabase()
{
    qDebug() << "hhh";
//    initPickNameDB();
}

void SqliteDatabase::initPickNameDB()
{
    // 创建并打开数据库
    QSqlDatabase database;
    database = QSqlDatabase::addDatabase("QSQLITE");
//    qDebug() << QApplication::applicationDirPath();

    database.setDatabaseName(QApplication::applicationDirPath() + "/CONFIG/" + "PickNameDB.sqlite3");
    if(!database.open())
    {
        qDebug() << "Error: Failed to connect database." << database.lastError();
    }
    else
    {
        qDebug() << "Succeed to connect database.";
    }

    // 创建表格 先清空一下表
    QSqlQuery sql_query = database.exec("DROP TABLE department");
    sql_query = database.exec("DROP TABLE person");

    if(!sql_query.exec("create table department (Id int primary key not null, "
                       "DeptName vchar(50) not null )"))
    {
        qDebug() << "Error: Fail to create department table." << sql_query.lastError();
    }
    else
    {
        qDebug() << "Department table created!";
    }
    if(!sql_query.exec("create table person (Id int primary key not null , "
                       "DeptID integer not null , "
                       "PerName vchar(50) not null, "
                       "foreign key(DeptID) references department (Id))"))
    {
        qDebug() << "Error: Fail to create person table." << sql_query.lastError();
    }
    // 填充表
//    sql_query.exec("insert into department (id, name) values (1, '办领导')");
//    sql_query.exec("insert into department (id, name) values (2, '综合处')");
//    sql_query.exec("insert into department (id, name) values (3, '政策法规处')");
//    sql_query.exec("insert into department (id, name) values (4, '机构改革处')");
//    sql_query.exec("insert into department (id, name) values (5, '党群政法行政机构编制管理处')");
//    sql_query.exec("insert into department (id, name) values (6, '政府行政机构编制管理处')");
//    sql_query.exec("insert into department (id, name) values (7, '市县行政机构编制管理处')");
//    sql_query.exec("insert into department (id, name) values (8, '事业机构编制管理处')");
//    sql_query.exec("insert into department (id, name) values (9, '事业单位登记管理处')");
//    sql_query.exec("insert into department (id, name) values (10, '机构编制监督检查处')");
//    sql_query.exec("insert into department (id, name) values (11, '人事处')");
//    sql_query.exec("insert into department (id, name) values (12, '机关党委')");
//    sql_query.exec("insert into department (id, name) values (13, '省机构编制电子政务中心')");
//    sql_query.exec("insert into department (id, name) values (14, '省机构编制研究中心')");

    // 批量填充表
    QStringList deptNames;
    deptNames << "办领导" << "综合处" << "政策法规处" << "机构改革处"
              << "党群政法行政机构编制管理处" << "政府行政机构编制管理处"
              << "市县行政机构编制管理处" << "事业机构编制管理处" << "事业单位登记管理处"
              << "机构编制监督检查处" << "人事处" << "机关党委"
              << "省机构编制电子政务中心" << "省机构编制研究中心";

    // 绑定关键字后才能进行操作
    sql_query.prepare("INSERT INTO department (Id, DeptName) "
                      "VALUES (:Id, :DeptName)");
    qint8 i = 0;
    foreach (QString deptName, deptNames)
    {
        sql_query.bindValue(":Id", i + 1);
        sql_query.bindValue(":DeptName", deptName);
        if(!sql_query.exec())
        {
            qDebug() << "Error: Fail." << sql_query.lastError();
        }
        i++;
    }
    // 读取sqlite
    department dept;
    QVector<department> tmpDept; // 数据库缓存
    sql_query.exec("SELECT * FROM ");
}

12.Qt实现Excel表格的读写操作(office,WPS)

我们用QT经常会将表格的数据导入数据库或者将数据库中的数据导出为*.xls/*.xlsx。使用比较多的就是用QAxObject对象进行操作。一般首先会连接数据库:

QAxObject *excel = new QAxObject(this);	//连接Excel控件
excel->setControl("Excel.Application");

但是很多人的电脑上并没有安装office,这样会导致运行失败,如果安装了WPS,我们可以

QAxObject *excel = new QAxObject(this);	//连接Excel控件
excel->setControl("ket.Application");

这说明office和WPS是兼容的,我们只需要修改这一行代码就可以了。

另外,附上详细的代码说明:

void Window::importExcelToDatabase()
{
	QString strFilePathName = QFileDialog::getOpenFileName(this,QStringLiteral("选择Excel文件"),"",tr("Exel file(*.xls *.xlsx)"));
	if(strFilePathName.isNull())
	{
		return ;
	}
	QAxObject *excel = new QAxObject(this);	//连接Excel控件
	if (excel->setControl("Excel.Application"))
	{
 
	}
	else
	{
		excel->setControl("ket.Application");  //连接Excel控件
	}
	excel->setProperty("Visible", false);  //不显示窗体
	QAxObject* workbooks = excel->querySubObject("WorkBooks");  //获取工作簿集合
	workbooks->dynamicCall("Open(const QString&)", strFilePathName); //打开打开已存在的工作簿
	QAxObject* workbook = excel->querySubObject("ActiveWorkBook"); //获取当前工作簿 
	QAxObject* sheets = workbook->querySubObject("Sheets");  //获取工作表集合,Sheets也可换用WorkSheets
	QAxObject* sheet = workbook->querySubObject("WorkSheets(int)", 1);//获取工作表集合的工作表1,即sheet1
	QAxObject* range = sheet->querySubObject("UsedRange"); //获取该sheet的使用范围对象
	QVariant var = range->dynamicCall("Value");
	delete range;
	QVariantList varRows = var.toList();  //得到表格中的所有数据
	if(varRows.isEmpty())
	{
		return;
	}
	const int rowCount = varRows.size();
	QStringList m_userid,m_card_id,m_action;
	for(int i = 1; i < rowCount; ++i)   //
	{
		QVariantList rowData = varRows[i].toList();
		m_userid<<rowData[0].toString();
		m_card_id<<rowData[1].toString();
		m_action<<rowData[2].toString();
	}
}

注意:对Excel文档的读写操作,如果数据量很大,最好使用多线程,否则会导致主界面的假死。)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QT 语言的学习 day10 数据库的学习 增删改 (QT 自带的数据库 QSqlDatabase数据库) 的相关文章

  • Qt 计算和比较密码哈希

    目前正在 Qt 中为测验程序构建面向 Web 的身份验证服务 据我了解 在数据库中存储用户密码时 必须对其进行隐藏 以防落入坏人之手 流行的方法似乎是添加的过程Salt https en wikipedia org wiki Salt cr
  • QLineEdit:显示处理后的文本,而不是输入的文本,但保留它(自定义回显模式)

    我想要一个QLineEdit不显示输入的文本 而是显示经过处理的版本 同时保留原始文本并在通过请求时返回它text 就像密码回显模式一样 但我不希望每个字符都被屏蔽 我想虚拟化空间 例如什么时候some text with spaces i
  • qt项目如何设置安装路径

    我正在寻找与 qmake configure prefix 等效的内容 基本上 我想覆盖默认的安装 部署目录 这是如何用命令行 qmake 指定的 我还使用 QtCreator 构建了很多 gui 项目 并且我想知道如何在 QtCreato
  • 为什么下面的重叠比较总是评估为 true

    我不明白为什么以下代码有警告 指出重叠比较始终评估为真 接下来的语句永远不会被执行 QVariant MainModel data const QModelIndex index int role const if index isVali
  • 当 QML 对象不可见时防止 QML 属性绑定?

    我正在开发一个具有大量属性绑定的 QML 应用程序 数百个对象被跟踪并以不同的形式显示 例如 Qt3D QCanvas 当我在应用程序的单独页面上时 x y 位置和相对大小的属性绑定仍在发生 我怎样才能阻止他们 我知道我可以根据属性是否可视
  • 有没有办法在没有 QApplication::exec() 的情况下使用 Qt?

    有没有一种安全的方法可以在不调用 QApplication exec 的情况下使用 Qt 我有许多不同的对象正在对多个资源执行长期进程 至少其中一个正在与 Web 应用程序服务器进行通信 我正在制作一个 GUI 应用程序 提示用户在正确的时
  • Qt Creator:如何区分 win32 和 win64

    我必须在 pro 文件中执行类似的操作 win32 LIBS L 3rdparty libusb win32 lib msvc llibusb else win64 LIBS L 3rdparty libusb win32 lib msvc
  • Qt:将拖放委托给子级的最佳方式

    我在 QWidget 上使用拖放 我重新实现了 DragEnterEvent dragLeaveEvent dragMoveEvent 和 dropEvent 效果很好 在我的 QWidget 中 我有其他 QWidget 子级 我希望它们
  • QtCreator 调试暂停停在代码而不是汇编处

    如何配置 QtCreator 以便在调试并按下暂停时它会显示当前正在处理的代码 现在显示汇编 无法在任何地方找到有关此问题的答案 我使用的是 Windows 7 我在 Ubuntu 16 04 中使用 Qt Creator 4 2 2 时遇
  • GoQt 致命错误:QAbstractAnimation:没有这样的文件或目录

    我尝试编译 Qt 来开发桌面应用程序 我按照 Qt 网站上的官方 wiki 指南的说明进行操作 当我尝试go run示例文件夹中的示例 我收到错误 去运行 home pinkya rabbit workspace go1programs s
  • Qt - 如何粘合两个窗口并将它们移动在一起?

    就像qmmp Qt 音乐播放器ui设计一样 这两个或三个窗口实际上在同一个窗口中 因为只有一个dock图标 并且这些窗口可以一起移动并相互附着 我看了源码 好像有用QDockWidget 但我真的不知道如何获得它的细节 当您手动移动辅助窗口
  • PyQt:如何设置组合框项目可检查?

    为了将 GUI 小部件数量保持在最低限度 我需要找到一种方法来为用户提供下拉菜单项的选择 这些菜单项可用于过滤掉 listWidget 项中显示的内容 假设 listWidget 列出了 5 个不同类别的项目 Cat A Cat B Cat
  • 禁用 QML Slider 的鼠标滚轮

    我希望能够滚动Flickable使用鼠标滚轮 或触摸板上的两根手指 不改变Sliders它可能包含 示例代码及结果应用 import QtQuick 2 7 import QtQuick Window 2 2 import QtQuick
  • 加权 Voronoi 的 CGAL 2D APOLLONIUS 图 - 如何生成和获取面和顶点?

    我正在尝试根据阿波罗尼乌斯图生成加权沃罗诺伊 我正在使用 CGAL 库 我找不到如何从 apollonius 获取面和顶点的好例子 我有以下类型定义 typedef double NT typedef CGAL Cartesian lt N
  • 在 Qt5 中,是否需要 Q_INVOKABLE 来从 QML 调用公共 QObject 函数?

    我刚刚意识到我可以调用暴露于 QML 的对象的几乎任何函数 现在我对 Q INVOKABLE 很好奇 Qt5docs http doc qt io qt 5 qtqml cppintegration exposecppattributes
  • 如何将图像显示为缩略图

    我有一个QTreeView显示硬盘驱动器和目录 我也有一个QListView显示图像文件如下 但我想将图像显示为缩略图 如下所示 My code mainWidget mainWidget QWidget parent QWidget pa
  • Qt 插槽是否与其他代码并行运行?

    在此函数示例中 void MyClass myFunction emit MySignal1 emit MySignal2 如果我有slot1倾听MySignal1 and slot2倾听MySignal2 1 Is slot1总是会在之前
  • 将 gnuplot 嵌入现有 QtWidget 中

    我正在用 C 创建一个 伪 实时绘图应用程序 使用 gnuplot 作为绘图后端 我的要求之一是绘图必须位于现有窗口内 而不是有一个单独的绘图窗口 gnuplot 默认为 Gnuplot 有一个选项可以指定 Qt 小部件 ID 这似乎适合我
  • 如何在 QtQuick 2 中对 QML TableView 进行排序?

    我想使用 Qt 5 1 实现具有自定义角色的可排序 TableView 但我不知道当用户单击标题时该怎么做才能对其进行排序 在我的 Qt pro 文件中 我添加了 android ios blackberry qtHaveModule wi
  • Qt-Qlist 检查包含自定义类

    有没有办法覆盖加载自定义类的 Qt QList 的比较机制 即在 java 中你只需要重写一个比较方法 我有一个带有我的自定义类模型的 QList QList

随机推荐

  • Codeforces 1454B Unique Bid Auction(模拟)

    Description 题目大意 找到一个序列中唯一且是最小的那个数的下标 感叹我的语言描述真是越来越精炼了 解题思路 算法标签 模拟 记录每个数字出现的次数以及其下标 然后从1开始寻找 第一个找到的数字的下标就是答案 没什么难度 只是不想
  • Mintty(Cygwin)快速定位当前目录

    转发https blog csdn net x iya article details 78553308 方法一 新建批处理文件Cygwin bat E Cygwin bin mintty exe i Cygwin Terminal ico
  • 赛联区块链教育:对区块链技术做个普及

    区块链 比特币 加密货币在你的脑海中吗 您是否正在努力理解区块链的运作方式 您是否正在寻找该系统的学习信息以帮助您入行 下边的介绍帮你建立相关知识框架 区块链 十多年来 这个词出现在互联网 社交媒体 新闻上 并在全球范围内引起了广泛关注 1
  • Android 13 - Media框架(9)- NuPlayer::Decoder

    这一节我们将了解 NuPlayer Decoder 学习如何将 MediaCodec wrap 成一个强大的 Decoder 这一节会提前讲到 MediaCodec 相关的内容 如果看不大懂可以先跳过此篇 原先觉得 Decoder 部分简单
  • CNCF 官方大使张磊:什么是云原生?

    作者 张磊 阿里云容器平台高级技术专家 CNCF 官方大使 编者说 从 2015 年 Google 牵头成立 CNCF 以来 云原生技术开始进入公众的视线并取得快速的发展 到 2018 年包括 Google AWS Azure Alibab
  • 关于使用MSYS2安装mingw-win64下载两组包中出现ERROR导致升级全部失败的解决方案

    MSYS2网站操作 在最后一步阶段出现ERROR错误 导致升级全部失效 即使是多次重复尝试也不能解决 进行如下操作 pacman S mingw w64 x86 64 toolchain pacman S mingw w64 x86 64
  • jmeter实战案例

    一 前言 以前做了个抽奖活动的需求 需要做压测 只是简单帮助测试去做过压测 但没有自己从头到尾做过 最近再次碰到需要做压测 百度了一下使用教程 现在做个记录 以便以后做压测 直接借鉴教程 二 流程 1 启动jmeter 下载jmeter后
  • 阿里云云数据MongoDB版连接

    阿里云MongoDB连接 一 MongoDB Serverless版 1 登录进入阿里云控制台之后在搜索栏搜索mongodb进入MongoDB控制台 2 选择你所购买的资源区域 点击左侧server less实例列表找到自己的资源 如果是刚
  • 代码检查、走查与评审

    桌上检查 桌上检查是一种程序员检查自己的原程序的方法 桌上检查的目的是发现程序中的错误 桌上检查的检查项目主要有检查变量 标号的交叉引用表 检查子函数 宏 函数 等价性检查 常量检查 标准检查 风格检查 比较控制流 选择 激活路径 补充文档
  • 覆盖 Safari、Edge,主流浏览器几乎均已实现 WebGL 2.0 支持

    从 Firefox 到 Safari 所有的主流浏览器现已经全部支持 WebGL 2 0 近日 专注于制定开放标准的行业协会Khronos Group 重磅宣布当下所有主流浏览器均已实现了对WebGL 2 0的支持 简单来看 无需使用插件即
  • 照片的35x45,300dpi怎么弄

    做技术的难免会遇到一些杂活 一个35x45的照片 300dpi 要改为34x39 300dpi的图片 好像不太会 不过这样子弄 叫对方不要用微信发照片 微信强制会把照片改为96dpi 宽高都变了1个像素 因此照片压缩后再让其发过来 收到照片
  • LeetCode 108. 将有序数组转换为二叉搜索树Golang版

    LeetCode 108 将有序数组转换为二叉搜索树Golang版 1 问题描述 给你一个整数数组 nums 其中元素已经按 升序 排列 请你将其转换为一棵 高度平衡 二叉搜索树 高度平衡 二叉树是一棵满足 每个节点的左右两个子树的高度差的
  • 华为OD机试真题-积木最远距离【2023Q1】

    题目描述 小华和小薇一起通过玩积木游戏学习数学 他们有很多积木 每个积木块上都有一个数字 积木块上的数字可能相同 小华随机拿一些积木挨着排成一排 请小薇找到这排积木中数字相同且所处位置最远的2块积木块 计算他们的距离 小薇请你帮忙替她解决这
  • React & JSX 入门

    React JSX 入门 div div
  • 1600*D. Road Map(数学

    解析 记录每个点的父节点和子节点 从新的根节点开始遍历 遍历所有的非父结点即可 include
  • (一)大彩屏幕 进行串口通信

    一 简介 大彩屏幕通过串口收发信息 主要用来显示 装好软件 官网有或找技术人员要 VisualTFT 虚拟串口驱动 USB驱动 1 大彩屏幕来自大彩科技 使用该屏幕时 需要注意获取最新的软件版本 最新的Demo 这一点 你可以直接联系客服或
  • Vue刻度尺组件

    1 安装刻度尺组件 npm install cs ruler 2 在main js中全局引入组件 import CsRuler from cs ruler 刻度尺组件 Vue use CsRuler 3 组件使用
  • C#序列化和反序列化(json)

    一 什么是Json json是存储和交换文本信息的方法 类似xml 但是json比xml更小 更快 j更易于解析 并且json采用完全独立于语言的文本格式 即不依赖于各种编程语言 这些特性使json成为理想的数据交换语言 json使用Jav
  • UE4 命令工具打包

    用cmd进入UE4引擎的目录 Engine Build BatchFiles找到RunUAT bat cmd中输入以下命令 RunUAT BuildCookRun project F VidaUpdater VidaUpdater upro
  • QT 语言的学习 day10 数据库的学习 增删改 (QT 自带的数据库 QSqlDatabase数据库)

    1 基本知识的学习 Qt 提供了 QtSql 模块来提供平台独立的基于 SQL 的数据库操作 这里我们所说的 平台独立 既包括操作系统平台 有包括各个数据库平台 另外 我们强调了 基于 SQL 因为 NoSQL 数据库至今没有一个通用查询方