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数据库) 的相关文章

  • 仅在发布模式下使用 glGenBuffer 时出现未处理的异常 - QT

    我在 Windows 7 上使用 Qt 4 8 发布模式编译项目时遇到了一些问题 调试时一切正常 但在发布时我收到未处理的异常 0xC0000005 访问冲突 我将范围缩小到发生这种情况的行 即生成像素缓冲区的时间 我的第一个猜测是 DLL
  • QML:无法读取未定义的属性“xxx”

    ApplicationWindow id root property string rootName rootName visible true width 800 height 400 title qsTr WatchFace Maker
  • 仅在内部/外部抚摸路径?

    Given a QPainterPath http qt project org doc qt 4 8 qpainterpath html如何仅在路径的内侧或外侧边缘 或非闭合路径的左侧或右侧 描边路径 QPainter strokePat
  • 如何在 Qt Creator 中编辑 QtWebKit 的右键上下文菜单?

    好吧 这是我的困境 我正在使用 Qt Creator 制作一个使用 Webkit 的简单应用程序 我认为 Qt Creator 会有一种简单的方法来使用信号和槽编辑器编辑右键单击上下文菜单 但事实证明这不是真的 我知道 webkit 有与上
  • new 运算符(以及 malloc)无法分配约 450 MB 的内存 [重复]

    这个问题在这里已经有答案了 我正在开发一个程序 该程序在内存中存储大约 2 2 亿个短值的数组 该数据块的分配方式如下 short arrayName new short SIZE OF ARRAY 然后将文件的内容读入内存 在团队中的另一
  • 如何在 OS X 上的 Qt 应用程序中设置应用程序图标,足以进行分发?

    跟进这个答案 https stackoverflow com a 20918932 368896 to 这个问题 https stackoverflow com questions 20909341 what is the fastest
  • 使用 CMake 编译时更改头文件位置会导致缺少 vtable 错误

    对于一个大型 C 项目 我需要从 qmake 过渡到 CMake 但是在处理一个玩具示例时 我遇到了一些我不理解的行为 示例代码具有单个头文件 当该头文件移动到子目录中时 我收到 MainWindow 类缺少 vtable 的错误 CMak
  • QMainWindow 上的 Qt 布局

    我设计了一个QMainWindow with QtCreator s设计师 它由默认的中央小部件 aQWidget 其中包含一个QVBoxLayout以及其中的所有其他小部件 现在我想要的一切就是QVBoxLayout自动占据整个中央小部件
  • QML 中可重用的字体属性[重复]

    这个问题在这里已经有答案了 在 QML 中 我希望能够定义一组字体属性以进行简单的语义重用 例如 代替 Text text This is a header font family Encode Sans weight Font Black
  • QTableView 并双击一个单元格

    我正在开发测试用例编辑器 该编辑器包含 USART 传输和接收数据包格式 编辑器是一个表格视图 发送和接收数据包的长度为八个字节 例如 0x01 0x02 0x03 0x08 它在我的第五和第六栏中 现在 我希望此列中的单元格为只读 但是当
  • Mac OS X 上的 Qt 字体系列和样式

    我有一个基于 Qt PyQt 的 GUI 应用程序 在 Mac OS X 和其他平台 上运行 它允许用户选择字体并具有粗体和斜体选项的复选框 在更新到新的基于 Cocoa 的 Qt 时 用户发现QFontComboBox不再显示不同的字体样
  • 是否有 Qt 小部件可以浏览应用程序中小部件的层次结构(类似于 Spy++)?

    我们有一个具有复杂的小部件层次结构的应用程序 我希望能够以与 Spy 类似的方式浏览此层次结构 查看和编辑属性 例如大小 如果有一个小部件可以显示此信息 则它不需要在外部应用程序中运行 那么问题来了 这样的神兽存在吗 您可以使用Gammar
  • 连接到 QNetworkReply::error 信号

    我正在使用 Qt5 的新连接语法 QNetworkReply 有一个名为error http qt project org doc qt 5 0 qtnetwork qnetworkreply html error 2还有一个函数叫做err
  • Qt QML 数据模型似乎不适用于 C++

    我一直在使用中的示例http doc qt digia com 4 7 qdeclarativemodels html http doc qt digia com 4 7 qdeclarativemodels html这是 QML 声明性数
  • 通过引用传递 [C++]、[Qt]

    我写了这样的东西 class Storage public Storage QString key const int value const void add item QString int private QMap
  • Qt 支持 Windows 蓝牙 API 吗?

    谁能告诉我 Qt 是否支持 Windows 蓝牙 API 如果是这样 您能否分享一些有关如何使用它的信息 自上次答复以来 这个问题的答案发生了一些变化 Qt 5 2 版为 Linux BlueZ 和 BlackBerry 设备实现了蓝牙 A
  • Linux 上的静态 Qt5 构建:部署时如何处理字体?

    我使用这些配置选项创建了 Qt 5 2 0 库的静态版本 Ubuntu 12 04 开源 确认许可 force pkg config 发布 静止的 前缀 home juzzlin qt5 无icu opengl桌面 无油嘴滑舌 辅助功能 n
  • 如何将 QFile 与 std::iostream 一起使用?

    是否可以像 std iostream 一样使用 QFile 我很确定那里一定有一个包装纸 问题是在哪里 我有另一个库 它需要 std istream 作为输入参数 但在我的程序中 此时我只有一个 QFile 我使用以下代码提出了自己的解决方
  • Qt:更改 Mac OS X 上的应用程序 QMenuBar 内容

    我的应用程序对多个 页面 使用 QTabWidget 其中顶级菜单根据用户所在的页面而变化 我的问题是 尝试重新创建菜单栏的内容会导致严重的显示问题 它在除 Mac OS X 之外的所有平台上按预期使用第一种和第三种样式 尚未测试第二种 但
  • QT:模块“QtWebView”未安装

    我的操作系统是win10 QT版本是Qt5 7 mingw53 32 目标操作系统是win10 当我使用qmlscene执行qml文件时 发生了一些错误 qrc qml 3 模块 QtWebView 未安装 我的 qml 文件如下 impo

随机推荐

  • 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 数据库至今没有一个通用查询方