功能:
1.能够把数据从db文件中读取到QTableView表中;
2.能够实现增、删、查、改功能;
3.能够将Excel文件中的数据导入到db文件中;
4.能够将QTableView表中的数据导出到Excel中。
用到的工具:
1.Qt5.12.9作为编码工具,其自带SQLite数据库;
2.MinGW_32bit作为调试工具,此为Qt自带;
3.SQLite Expert Professional 5 - 64bit作为创建一个db文件的工具,能够实现数据库的可视化。
创建一个db文件
1.使用SQLite Expert Professional 5 - 64bit创建一个db文件,文件名称为abbreviation;接着创建一个表,表的名称为Abbr;
2.在Design页,可以完成对表的设计。表中共有3列,它们的表头分别是Name、Complete和Chinese,三者类型都是VARCHAR。如下图所示:

3.在Data页,可以往数据库中先加几条数据,如下图所示:

代码
1.pro文件
QT += core gui
QT += sql
QT += axcontainer
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 \
mainwindow.cpp \
qwedit.cpp
HEADERS += \
mainwindow.h \
qwedit.h
FORMS += \
mainwindow.ui \
qwedit.ui
DESTDIR=../bin
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
注意:
Qt += sql是因为要操作SQLite数据库;
Qt += axcontainer是因为要操作Excel;
DESTDIR=../bin是因为要存放可执行程序和db文件。
2.在准备创建Qt工程的文件夹里新建一个名叫bin的文件夹,如下图所示:

注意:
AbbreviationList文件夹,是存放源码的文件夹;
bin文件夹,是存放exe可执行程序和db文件的文件夹;
build-AbbreviationList-Desktop_Qt_5_12_9_MinGW_32_bit-Debug文件夹,是执行Qt工程后自动生成的文件。
AbbreviationList文件夹中的文件,如下图所示:

注意:
AbbreviationList.pro.user为选择MinGW_32bit作为调试工具后,自动生成的文件。
bin文件夹中的文件,如下图所示:

注意:
将刚才用SQLite Expert Professional 5 - 64bit创建的db文件,复制到bin文件夹中;AbbreviationList.exe文件,为运行Qt工程后自动生成的文件。
3.mainwindow.h文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSqlDatabase>
#include <QSqlQueryModel>
#include <QItemSelectionModel>
#include <QMenu>
#include <QContextMenuEvent>
#include <QAction>
#include <QAxObject>
#include "qwedit.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
/*打开数据库*/
void openDatabase();
/*打开数据表*/
void openTable();
/*判断数据库中是否存在该表*/
bool isTableExists(QString &table);
/*在数据库中创建表格*/
void createNewTable(QAxObject *work_sheet);
/*在表格中插入数据*/
void insertData(QAxObject *work_sheet);
private slots:
/*导入,将xls或xlsx文件中数据导入到数据库*/
void on_act_input_triggered();
/*导出,将数据库中数据导出为xls或xlsx文件*/
void on_act_output_triggered();
/*新增一个词条*/
void on_btnAdd_clicked();
/*搜索*/
void on_editSearch_textChanged(const QString &arg1);
/*创建右键快捷菜单*/
void on_tableView_customContextMenuRequested(const QPoint &pos);
/*删除某一词条*/
void delList();
/*修改某一词条*/
void editList();
private:
Ui::MainWindow *ui;
QSqlDatabase DB;
QSqlQueryModel *qryModel;
QItemSelectionModel *theSelection;
};
#endif // MAINWINDOW_H
4.mainwindow.cpp文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QSqlError>
#include <QMessageBox>
#include <QDir>
#include <QDebug>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QFileDialog>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->editAbbreviation->setPlaceholderText("英文缩写");
ui->editComplete->setPlaceholderText("英文全拼");
ui->editChina->setPlaceholderText("汉语翻译");
ui->editSearch->setPlaceholderText("搜索");
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableView->setAlternatingRowColors(true);
ui->tableView->horizontalHeader()->setStretchLastSection(true);
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
/*如果没有这一行,右击不会显示快捷菜单*/
ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
openDatabase();
}
MainWindow::~MainWindow()
{
delete ui;
}
/*打开数据库*/
void MainWindow::openDatabase()
{
/*数据库db文件存放于运行文件exe所在处*/
QString aFile=QDir::cleanPath(QCoreApplication::applicationDirPath()+
QDir::separator()+QString("/abbreviation.db"));
if (aFile.isEmpty())
{
return;
}
DB=QSqlDatabase::addDatabase("QSQLITE"); //添加 SQL LITE数据库驱动
DB.setDatabaseName(aFile);
if (!DB.open()) //打开数据库
{
QMessageBox::warning(this, "错误", "打开数据库失败",
QMessageBox::Ok,QMessageBox::NoButton);
return;
}
openTable();
}
/*将数据库里的词条映射到数据表*/
void MainWindow::openTable()
{
qryModel=new QSqlQueryModel(this);
theSelection=new QItemSelectionModel(qryModel);
qryModel->setQuery("SELECT Name, Complete, Chinese FROM Abbr ORDER BY Name");
if (qryModel->lastError().isValid())
{
QMessageBox::information(this, "错误", "数据表查询错误,错误信息\n"+qryModel->lastError().text(),
QMessageBox::Ok,QMessageBox::NoButton);
return;
}
qryModel->setHeaderData(0,Qt::Horizontal,"英文缩写");
qryModel->setHeaderData(1,Qt::Horizontal,"英文全拼");
qryModel->setHeaderData(2,Qt::Horizontal,"汉语翻译");
ui->tableView->setModel(qryModel);
ui->tableView->setSelectionModel(theSelection);
}
/*将xls或xlsx文件里的数据导入到数据库*/
void MainWindow::on_act_input_triggered()
{
/*打开选择文件窗口*/
QString filePath=QFileDialog::getOpenFileName(this,tr("Open Excel file"),"",
tr("Excel Files (*.xlsx *.xls)"));
if(!filePath.isEmpty())
{
qDebug()<<"当前打开的文件路径为"<<filePath;
}
QAxObject *excel=new QAxObject("Excel.Application");
/*不显示Excel窗体*/
excel->setProperty("Visible",false);
/*获取工作簿集合*/
QAxObject *work_books=excel->querySubObject("WorkBooks");
/*打开已存在的工作簿*/
work_books->dynamicCall("Open (const QString&)",filePath);
/*获取当前的工作簿*/
QAxObject *work_book=excel->querySubObject("ActiveWorkBook");
/*获取当前的工作表*/
QAxObject *work_sheets=work_book->querySubObject("Sheets");
/*获取工作表的数量*/
int sheet_count=work_sheets->property("Count").toInt();
qDebug()<<"当前文件有"<<sheet_count<<"张sheet";
/*仅将第一张工作表里的数据导入数据库*/
QAxObject *work_sheet=work_book->querySubObject("Sheets(int)",1);
/*获取工作表名称*/
QString work_sheet_name=work_sheet->property("Name").toString();
qDebug()<<"工作表的名称为:"<<work_sheet_name;
if(isTableExists(work_sheet_name))
{
int ok=QMessageBox::warning(this,tr("提示:"),
tr("当前数据库中已存在该表,确认替换吗?"),
QMessageBox::Yes,QMessageBox::No);
if(ok==QMessageBox::No)
{
/*不替换*/
}
else
{
/*替换*/
QSqlQuery query;
query.exec(QString("DROP TABLE IF EXISTS %1").arg(work_sheet_name));
createNewTable(work_sheet);
insertData(work_sheet);
}
}
else
{
createNewTable(work_sheet);
insertData(work_sheet);
}
/*关闭工作簿*/
work_book->dynamicCall("Close()");
/*关闭excel*/
excel->dynamicCall("Quit()");
delete excel;
excel=nullptr;
qryModel->setQuery("SELECT Name, Complete, Chinese FROM Abbr ORDER BY Name");
ui->tableView->setModel(qryModel);
}
/*判断数据库中是否存在该表*/
bool MainWindow::isTableExists(QString &table)
{
QSqlQuery query;
/*sqlite_master里存储了sqlite的所有表名*/
query.exec("SELECT * FROM sqlite_master");
while(query.next())
{
/*trimmed 去掉首尾的空白符;value(0)为type;value(1)为表的名称*/
QString tableName=query.value(1).toString().trimmed();
qDebug()<<"数据库中已存在:"<<tableName;
/*CaseInSensitive 大小写不敏感*/
if(QString::compare(tableName,table,Qt::CaseInsensitive))
{
/*不存在*/
}
else
{
/*存在*/
return true;
}
}
return false;
}
/*在数据库中创建表格*/
void MainWindow::createNewTable(QAxObject *work_sheet)
{
/*获取工作表名称*/
QString work_sheet_name=work_sheet->property("Name").toString();
/*选取当前页面所有已使用单元格*/
QAxObject *used_range=work_sheet->querySubObject("UsedRange");
/*获取起始列*/
int column_start=used_range->property("Column").toInt();
/*获取列数*/
//int column_count=used_range->property("Count").toInt();
/*表头数列*/
QString keyType[3];
/*获取表头*/
for(int i=column_start;i<3+column_start;++i)
{
QAxObject *cell=work_sheet->querySubObject("Cells(int,int)",1,i);
QString value=cell->dynamicCall("Value2()").toString();
keyType[i-column_start]=value;
qDebug()<<i-column_start<<":"<<keyType[i-column_start];
}
/*按表头在sqlite中创建新表*/
QString createsql=QString("CREATE TABLE %1(").arg(work_sheet_name);
for(int i=0;i<=2;++i)
{
createsql=createsql+QString("%1").arg(keyType[i]);
if(i<2)
{
createsql=createsql+QString(" VARCHAR,");
}
else
{
createsql=createsql+QString(" VARCHAR)");
}
}
qDebug()<<createsql;
QSqlQuery query;
if(query.exec(createsql))
{
qDebug()<<"成功创建表格:"<<work_sheet_name;
}
else
{
qDebug()<<"创建表格"<<work_sheet_name<<"失败";
}
}
/*在表格中插入数据*/
void MainWindow::insertData(QAxObject *work_sheet)
{
/*获取工作表名称*/
QString work_sheet_name=work_sheet->property("Name").toString();
/*选取当前页面所有已使用单元格*/
QAxObject *used_range=work_sheet->querySubObject("UsedRange");
QAxObject *rows=used_range->querySubObject("Rows");
/*获取起始行*/
int row_start=used_range->property("Row").toInt();
/*获取起始列*/
int column_start=used_range->property("Column").toInt();
/*获取行数*/
int row_count=rows->property("Count").toInt();
QSqlQuery query;
/*从行开始,row_start初始值为1*/
for(int i=row_start;i<row_count+row_start-1;++i)
{
QString strSql=QString("INSERT INTO %1 VALUES(").arg(work_sheet_name);
for(int j=column_start;j<3+column_start;++j)
{
/*去除第一行表头*/
QAxObject *cell=work_sheet->querySubObject("Cells(int,int)",i+1,j);
QString value=cell->dynamicCall("Value2()").toString();
strSql=strSql+QString("'%1'").arg(value);
if(j<3)
{
strSql=strSql+QString(",");
}
else
{
strSql=strSql+QString(")");
}
}
qDebug()<<strSql;
/*调用写数据函数,将一行数据插入数据库*/
query.exec(strSql);
}
/*获取当前行数*/
QString resuresql=QString("SELECT COUNT(1) FROM %1").arg(work_sheet_name);
query.exec(resuresql);
query.next();
/*验证是否缺少行,不缺少则导入成功*/
if(query.value(0).toInt())
{
QMessageBox::warning(this,tr("提示:"),tr("数据导入成功"));
}
else
{
QMessageBox::warning(this,tr("提示:"),tr("数据缺失,请重新导入"));
}
}
/*将表里的数据导出到xls或xlsx文件*/
void MainWindow::on_act_output_triggered()
{
/*创建了一个QAxObject对象,用于访问Excel应用程序的COM接口*/
QAxObject *excel=new QAxObject("Excel.Application");
/*判断是否存在excel*/
if(excel->isNull())
{
if(excel!=nullptr)
{
excel->dynamicCall("Quit()"); //关闭
delete excel;
}
QMessageBox::critical(0,"错误信息","没有找到excel应用程序");
return;
}
QAxObject *workbooks=nullptr;
QAxObject *workbook=nullptr;
QAxObject *worksheets=nullptr;
QAxObject *worksheet=nullptr;
excel->dynamicCall("SetVisible (bool)",false); //不显示窗体
/*不显示任何警告信息,如果为true在关闭时会出现“文件已修改,是否保存”的提示*/
excel->setProperty("DisplayAlerts",false);
workbooks=excel->querySubObject("WorkBooks"); //获取工作簿集合
QString filePath=QFileDialog::getSaveFileName(this,tr("Save File"),
"",tr("Excel Files (*.xlsx *.xls)"));
if(QFile::exists(filePath))
{
workbook=workbooks->querySubObject("Open(const QString &)",filePath);
}
else
{
workbooks->dynamicCall("Add"); //新建一个工作簿
workbook=excel->querySubObject("ActiveWorkBook"); //获取当前的工作簿
}
worksheets=workbook->querySubObject("Sheets"); //获取工作表集合
worksheet=worksheets->querySubObject("Item(int)",1); //获取工作表集合的工作表1,即sheet1
worksheet->setProperty("Name","Abbr");
QAxObject *usedrange=worksheet->querySubObject("UsedRange"); //获取该sheet的使用范围对象
QAxObject *rows=usedrange->querySubObject("Rows");
QAxObject *columns=usedrange->querySubObject("Columns");
int intRowStart=usedrange->property("Row").toInt();
int intColStart=usedrange->property("Column").toInt();
int intCols=columns->property("Count").toInt();
int intRows=rows->property("Count").toUInt();
QAxObject *cell=NULL;
int rowCount=ui->tableView->model()->rowCount();
int colCount=ui->tableView->model()->columnCount();
/*清空数据*/
for(int i=intRowStart;i<intRowStart+intRows;++i)
{
for(int j=intColStart;j<intColStart+intCols;++j)
{
cell=worksheet->querySubObject("Cells(int,int)",i,j); //获取单元格
cell->dynamicCall("setValue(const QString&)","");
}
}
/*插入表头*/
QString str[3]={"Name","Complete","Chinese"};
for(int i=1;i<4;++i)
{
cell=worksheet->querySubObject("Cells(int,int)",1,i);
cell->dynamicCall("setValue(const QString&)",str[i-1]);
}
/*插入数据*/
for(int i=intRowStart;i<intRowStart+rowCount;++i)
{
for(int j=intColStart;j<intColStart+colCount;++j)
{
QModelIndex indextemp=ui->tableView->model()->index(i-intRowStart,j-intColStart);
QVariant str=ui->tableView->model()->data(indextemp);
cell=worksheet->querySubObject("Cells(int,int)",i+1,j);
cell->dynamicCall("setValue(const QString&)",str);
}
}
QMessageBox::information(this,"提示","数据导出完毕");
/*保存至filePath,使用QDir::toNativeSeparators将路径中的"/"转换为"\",不然一定保存不了*/
workbook->dynamicCall("SaveAs(const QString&)",QDir::toNativeSeparators(filePath));
qDebug()<<"保存路径为:"<<QDir::toNativeSeparators(filePath);
workbook->dynamicCall("Close()"); //关闭工作簿
excel->dynamicCall("Quit()"); //关闭excel
delete excel;
excel=nullptr;
}
/*增加一个词条*/
void MainWindow::on_btnAdd_clicked()
{
QString curAbbr=ui->editAbbreviation->text();
QString curComp=ui->editComplete->text();
QString curChinese=ui->editChina->text();
/*判断表中是否存在该词条的英文缩写*/
QSqlQuery query;
query.prepare("SELECT * FROM Abbr WHERE Name = :Name");
query.bindValue(":Name",curAbbr);
query.exec();
if(query.next())
{
QMessageBox *msgBox=new QMessageBox();
msgBox->setWindowTitle("提示");
msgBox->setText("表中已存在此英文缩写");
msgBox->show();
}
else
{
query.prepare("INSERT INTO Abbr (Name, Complete, Chinese) VALUES(:Name, :Complete, :Chinese)");
query.bindValue(":Name",curAbbr);
query.bindValue(":Complete", curComp);
query.bindValue(":Chinese", curChinese);
if (!query.exec())
{
QMessageBox::critical(this, "错误", "插入记录错误\n"+query.lastError().text(),
QMessageBox::Ok,QMessageBox::NoButton);
}
else
{
QString sqlStr=qryModel->query().executedQuery(); //执行过的SELECT语句
qryModel->setQuery(sqlStr); //重新查询数据
}
}
ui->editAbbreviation->clear();
ui->editComplete->clear();
ui->editChina->clear();
}
/*搜索一个词条*/
void MainWindow::on_editSearch_textChanged(const QString &arg1)
{
QString curChoose=ui->cboxChoose->currentText();
QSqlQuery query;
if(curChoose=="英文缩写")
{
query.prepare("SELECT * FROM Abbr WHERE Name LIKE :Name ORDER BY Name");
query.bindValue(":Name",QString("%%1%").arg(arg1));
}
else if(curChoose=="英文全拼")
{
query.prepare("SELECT * FROM Abbr WHERE Complete LIKE :Complete ORDER BY Name");
query.bindValue(":Complete",QString("%%1%").arg(arg1));
}
else if(curChoose=="汉语翻译")
{
query.prepare("SELECT * FROM Abbr WHERE Chinese LIKE :Chinese ORDER BY Name");
query.bindValue(":Chinese",QString("%%1%").arg(arg1));
}
query.exec();
qryModel->setQuery(query);
}
/*创建右键快捷菜单*/
void MainWindow::on_tableView_customContextMenuRequested(const QPoint &pos)
{
Q_UNUSED(pos);
QMenu *menuList=new QMenu(this);
QAction *del=new QAction("删除");
connect(del,&QAction::triggered,this,&MainWindow::delList);
QAction *edit=new QAction("编辑");
connect(edit,&QAction::triggered,this,&MainWindow::editList);
menuList->addAction(del);
menuList->addAction(edit);
menuList->exec(QCursor::pos());
delete edit;
delete del;
delete menuList;
menuList=nullptr;
}
/*删除某一词条*/
void MainWindow::delList()
{
int curRecNo=theSelection->currentIndex().row();
QSqlRecord curRec=qryModel->record(curRecNo); //获取当前记录
if (curRec.isEmpty()) //当前为空记录
{
return;
}
QString curName=curRec.value("Name").toString();
QSqlQuery query;
query.prepare("DELETE FROM Abbr WHERE Name = :Name");
query.bindValue(":Name",curName);
if (!query.exec())
{
QMessageBox::critical(this, "错误", "删除记录出现错误\n"+query.lastError().text(),
QMessageBox::Ok,QMessageBox::NoButton);
}
else //插入,删除记录后需要重新设置SQL语句查询
{
QString sqlStr=qryModel->query().executedQuery();//执行过的SELECT语句
qryModel->setQuery(sqlStr); //重新查询数据
}
}
/*修改某一词条*/
void MainWindow::editList()
{
int curRecNo=theSelection->currentIndex().row();
QSqlRecord curRec=qryModel->record(curRecNo);
QString curName=curRec.value("Name").toString();
QSqlQuery query;
query.prepare("SELECT * FROM Abbr WHERE Name = :Name");
query.bindValue(":Name",curName);
query.exec();
query.first();
if (!query.isValid()) //是否为有效记录
{
return;
}
curRec=query.record();//获取当前记录的数据
QWedit *modifyList=new QWedit(this);
modifyList->setUpdateRecord(curRec);
int ret=modifyList->exec();
if(ret==QDialog::Accepted)
{
QSqlRecord recData=modifyList->getRecordData();
query.prepare("UPDATE Abbr SET Name = :Name, Complete = :Complete, Chinese = :Chinese WHERE Name = :Name");
query.bindValue(":Name",recData.value("Name"));
query.bindValue(":Complete",recData.value("Complete"));
query.bindValue(":Chinese",recData.value("Chinese"));
if (!query.exec())
QMessageBox::critical(this, "错误", "记录更新错误\n"+query.lastError().text(),
QMessageBox::Ok,QMessageBox::NoButton);
else
qryModel->query().exec();//数据模型重新查询数据,更新tableView显示
}
delete modifyList;
}
5.qwedit.h文件
#ifndef QWEDIT_H
#define QWEDIT_H
#include <QDialog>
#include <QSqlRecord>
namespace Ui {
class QWedit;
}
class QWedit : public QDialog
{
Q_OBJECT
public:
explicit QWedit(QWidget *parent = nullptr);
~QWedit();
/*更新记录*/
void setUpdateRecord(QSqlRecord &recData);
/*获取录入的数据*/
QSqlRecord getRecordData();
private:
QSqlRecord mRecord;
private:
Ui::QWedit *ui;
};
#endif // QWEDIT_H
6.qwedit.cpp文件
#include "qwedit.h"
#include "ui_qwedit.h"
QWedit::QWedit(QWidget *parent) :
QDialog(parent),
ui(new Ui::QWedit)
{
ui->setupUi(this);
ui->editAbbreviation->setPlaceholderText("英文缩写");
ui->editComplete->setPlaceholderText("英文全拼");
ui->editChina->setPlaceholderText("汉语翻译");
}
QWedit::~QWedit()
{
delete ui;
}
/*更新记录*/
void QWedit::setUpdateRecord(QSqlRecord &recData)
{
mRecord=recData;
ui->editAbbreviation->setText(recData.value("Name").toString());
ui->editComplete->setText(recData.value("Complete").toString());
ui->editChina->setText(recData.value("Chinese").toString());
}
/*获取录入的数据*/
QSqlRecord QWedit::getRecordData()
{
mRecord.setValue("Name",ui->editAbbreviation->text());
mRecord.setValue("Complete",ui->editComplete->text());
mRecord.setValue("Chinese",ui->editChina->text());
return mRecord;
}
7.main.cpp文件
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
8.mainwindow.ui文件

9.qwedit.ui文件

注意:
在导入Excel文件时,表头必须为Name、Complete和Chinese,Sheet1必须重命名为Abbr。这是在代码中写死的。如下图所示:


1107

被折叠的 条评论
为什么被折叠?



