文章目錄
- 0 背景
- 1 準備QXlsx環境
- 1.1 cmake安裝使用
- 1.2 qmake使用
- 2 把excel數據導出到mysql數據庫
- 3 把mysql數據庫的數據寫入到excel
- 4 完整代碼
- 5 項目代碼倉庫
0 背景
因為需要批量導入和導出數據,所以需要用到excel。實現把數據庫的數據導入到excel中,把excel中的數據導出到數據庫。這里使用了開源代碼庫QXlsx。
1 準備QXlsx環境
官網中的qmake的使用方法,cmake的使用方法。
1.1 cmake安裝使用
- 1,輸入下列指令安裝:
mkdir build
cd build
cmake ../QXlsx/ -DCMAKE_INSTALL_PREFIX=... -DCMAKE_BUILD_TYPE=Release
cmake --build .
cmake --install .
在CMakeLists.txt中添加如下內容:
find_package(QXlsxQt5 REQUIRED) # or QXlsxQt6
target_link_libraries(myapp PRIVATE QXlsx::QXlsx)
- 2,下面是無需安裝的兩種使用方法:
使用cmake的子目錄在 CMakeLists.txt:
add_subdirectory(QXlsx)
target_link_libraries(myapp PRIVATE QXlsx::QXlsx)
使用 cmake FetchContent 在 CMakeLists.txt:
FetchContent_Declare(QXlsxGIT_REPOSITORY https://github.com/QtExcel/QXlsx.gitGIT_TAG sha-of-the-commitSOURCE_SUBDIR QXlsx
)
FetchContent_MakeAvailable(QXlsx)
target_link_libraries(myapp PRIVATE QXlsx::QXlsx)
如果 QT_VERSION_MAJOR
沒有設置, QXlsx’s的 CMakeLists.txt 將嘗試自己尋找 Qt 版本(5 或 6)。
1.2 qmake使用
下載QXsx的github項目代碼。
- 1,把QXsx項目中的代碼(選中的三個項目)復制到自己項目下;
復制到自己項目下(新建一個QXlxs文件夾,存儲文件):
- 2,在pro中添加如下代碼;
QXLSX_PARENTPATH=./ # current QXlsx path is . (. means curret directory)
QXLSX_HEADERPATH=./QXlsx/header/ # current QXlsx header path is ./header/
QXLSX_SOURCEPATH=./QXlsx/source/ # current QXlsx source path is ./source/
include(./QXlsx/QXlsx.pri)
- 3,編譯文件后,會自動把文件添加到項目中(綠色的那一部分);
- 4,添加如下頭文件,就可以開始項目編寫;
#include "xlsxdocument.h"
#include "xlsxchartsheet.h"
#include "xlsxcellrange.h"
#include "xlsxchart.h"
#include "xlsxrichstring.h"
#include "xlsxworkbook.h"
測試程序:
// main.cpp#include <QCoreApplication>#include "xlsxdocument.h"
#include "xlsxchartsheet.h"
#include "xlsxcellrange.h"
#include "xlsxchart.h"
#include "xlsxrichstring.h"
#include "xlsxworkbook.h"
using namespace QXlsx;int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QXlsx::Document xlsx;xlsx.write("A1", "Hello Qt!"); // write "Hello Qt!" to cell(A,1). it's shared string.xlsx.saveAs("Test.xlsx"); // save the document as 'Test.xlsx'return 0;// return a.exec();
}
2 把excel數據導出到mysql數據庫
- 1,準備要導入的賬號和密碼的excel表(第一行為數據庫的字段名,必須一樣;如果數據庫中字段值不能為空,excel中數據也不能為空);
賬號信息.xlsx
數據庫中的login_information表
- 2,在數據庫中創建表格;
DROP TABLE IF EXISTS `login_information`;
CREATE TABLE `login_information` (`account` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,PRIMARY KEY (`account`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC;
- 3,建立數據庫連接;
方法:
static bool CreateConnection(){// qDebug()<<"查看目前可用驅動";// QStringList drivers = QSqlDatabase::drivers();// for(auto driver: drivers){// qDebug()<<driver<<" ";// }//設置數據庫驅動QSqlDatabase mysqlDB = QSqlDatabase::addDatabase("QMYSQL", "mysql_connection1");mysqlDB.setHostName("192.168.0.104");mysqlDB.setUserName("root");mysqlDB.setPassword("password");mysqlDB.setPort(8889);mysqlDB.setDatabaseName("test_db");//根據系統環境設計數據庫路徑// Q_OS_LINUX:Q_OS_WIN: Q_OS_MAC Q_OS_WIN32//如果遠程mysql數據庫沒有打開if(!mysqlDB.open()){return false;}else{// #ifdef Q_OS_WINmysqlDB.exec("SET NAMES 'GBK'");// #endif// #ifdef Q_OS_MAC// #endif}//QSqlDatabase sqliteDB = QSqlDatabase::addDatabase("QSQLITE", "sqlite_connection1");// #ifdef Q_OS_WIN //Q_OS_WIN32// qDebug()<<"QCoreApplication::applicationDirPath():"<<QCoreApplication::applicationDirPath();// sqliteDB.setDatabaseName(QCoreApplication::applicationDirPath() + QString("/database/LocalSystemDatabse.db"));// #endif//如果本地sqlite數據庫沒有打開// if(!sqliteDB.open()){// QMessageBox* databaseInformationBox = new QMessageBox(QMessageBox::Critical, ("信息提示"), ("不能建立本地數據庫連接!"), QMessageBox::Yes);// auto button = databaseInformationBox->exec();// if(button == QMessageBox::Yes){// databaseInformationBox->deleteLater();// }// return false;// }return true;}
調用:
//main中創建數據庫連接
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);//連接數據庫if (!CreateConnection()){qDebug()<<"數據庫連接失敗";}return a.exec();
}
- 4,把excel中的數據導入到數據庫中;
bool exportExcel2Database(QStringList filePaths, QString xlsxName, QString sqlSentence){QList<bool> execResultList;//操作的結果集bool execResult = false;QSqlDatabase db = QSqlDatabase::database("mysql_connection1");QSqlQuery query(db);if(db.transaction()){foreach(QString filePath, filePaths) {QXlsx::Document xlsx(filePath);if(!xlsx.selectSheet(xlsxName)){/*在當前打開的xlsx文件中,找一個名字為ziv的sheet*///xlsx.addSheet(xlsxName);//找不到的話就添加一個名為ziv的sheetqDebug()<<"沒有對應的xlsx表";return false;}else{}QQueue<QString> tableFieldQueue;QHash<QString, QVariantList> tableAlterFiledValue;for(int row = 1; row <= xlsx.dimension().rowCount(); row++) {// 獲取每行的數據并插入到數據庫中for(int col = 1; col <= xlsx.dimension().columnCount();col++){if(row == 1){tableFieldQueue.enqueue(xlsx.read(row, col).toString());}else{tableAlterFiledValue[tableFieldQueue[col-1]].append(xlsx.read(row, col));}}}query.prepare(sqlSentence);foreach (QString tableFiled, tableFieldQueue) {query.addBindValue(tableAlterFiledValue[tableFiled]);}execResult = query.execBatch();execResultList.append(execResult);if(!execResult) {//批量執行數據插入qDebug() << query.lastError().databaseText();}}foreach (bool result, execResultList) {if(result == false){if(!db.rollback()){qDebug() << "數據庫回滾失敗"<<db.lastError().databaseText(); //回滾}else{qDebug()<<"數據庫回滾成功";}return false;}}if(db.commit()){return true;}else{return false;}}return false;
}
調用:
QStringList filePaths;filePaths<<"D:/test/賬號信息.xlsx";//考試細節步驟QString sql2 = QString("INSERT INTO login_information(account, password) VALUES (?, ?)");QString xlsxName2 = "賬號信息";// qDebug()<<sql2;if(exportExcel2Database(filePaths, xlsxName2, sql2)){qDebug()<<"導入成功";}else{qDebug()<<"導入失敗";}
,
3 把mysql數據庫的數據寫入到excel
-
1,建立數據庫連接,同上;
-
2,把數據庫中表的數據導出到excel中;
bool exportData2XLSX(QString fileName, QString tableName)
{QXlsx::Document xlsx;QXlsx::Format format1;/*設置標題單元的樣式*/format1.setFontSize(12);/*設置字體大小*/format1.setHorizontalAlignment(QXlsx::Format::AlignHCenter);/*橫向居中*///format1.setBorderStyle(QXlsx::Format::BorderThin);/*邊框樣式*///format1.setFontBold(true);/*設置加粗*/if(!xlsx.selectSheet("表格數據")){/*在當前打開的xlsx文件中,找一個名字為ziv的sheet*/xlsx.addSheet("表格數據");//找不到的話就添加一個名為ziv的sheet}QSqlDatabase db = QSqlDatabase::database("mysql_connection1");QString tmpSql = QString("SELECT * FROM %1").arg(tableName);QSqlQuery query(db);if(query.exec(tmpSql)){//表頭列QSqlRecord queryRecord(query.record());qDebug()<<"queryRecord.count():"<<queryRecord.count();for(int colNum = 0; colNum < queryRecord.count(); colNum++){//qDebug() << queryRecord.fieldName(colNum);xlsx.write(1, colNum+1, queryRecord.fieldName(colNum),format1);}//表格數據int rowNum = 2;while(query.next()){for(int colNum = 0; colNum < queryRecord.count(); colNum++){xlsx.write(rowNum, colNum + 1, query.value(colNum),format1);}rowNum++;}}else{return false;}if(fileName.isEmpty())return false;xlsx.saveAs(fileName);//保存文件return true;
}
調用:
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);//連接數據庫if (!CreateConnection()){qDebug()<<"數據庫連接失敗";}QString tableName = "login_information";QString fileName = "D:/賬號.xlsx";if(exportData2XLSX(fileName, tableName)){qDebug()<<"導入excel成功";}else{qDebug()<<"導入excel失敗";}return a.exec();
}
4 完整代碼
#include <QCoreApplication>#include "create_connection.h"#include "xlsxdocument.h"
#include "xlsxchartsheet.h"
#include "xlsxcellrange.h"
#include "xlsxchart.h"
#include "xlsxrichstring.h"
#include "xlsxworkbook.h"#include <QSqlError>
#include <QQueue>
#include <QHash>
#include <QSqlRecord>bool exportExcel2Database(QStringList filePaths, QString xlsxName, QString sqlSentence){QList<bool> execResultList;bool execResult = false;QSqlDatabase db = QSqlDatabase::database("mysql_connection1");QSqlQuery query(db);if(db.transaction()){foreach(QString filePath, filePaths) {QXlsx::Document xlsx(filePath);if(!xlsx.selectSheet(xlsxName)){/*在當前打開的xlsx文件中,找一個名字為ziv的sheet*///xlsx.addSheet(xlsxName);//找不到的話就添加一個名為ziv的sheetqDebug()<<"沒有對應的xlsx表";return false;}else{}QQueue<QString> tableFieldQueue;QHash<QString, QVariantList> tableAlterFiledValue;for(int row = 1; row <= xlsx.dimension().rowCount(); row++) {// 獲取每行的數據并插入到數據庫中for(int col = 1; col <= xlsx.dimension().columnCount();col++){if(row == 1){tableFieldQueue.enqueue(xlsx.read(row, col).toString());}else{tableAlterFiledValue[tableFieldQueue[col-1]].append(xlsx.read(row, col));}}}query.prepare(sqlSentence);foreach (QString tableFiled, tableFieldQueue) {query.addBindValue(tableAlterFiledValue[tableFiled]);}execResult = query.execBatch();execResultList.append(execResult);if(!execResult) {//批量執行數據插入qDebug() << query.lastError().databaseText();}}foreach (bool result, execResultList) {if(result == false){if(!db.rollback()){qDebug() << "數據庫回滾失敗"<<db.lastError().databaseText(); //回滾}else{qDebug()<<"數據庫回滾成功";}return false;}}if(db.commit()){return true;}else{return false;}}return false;
}bool exportData2XLSX(QString fileName, QString tableName)
{QXlsx::Document xlsx;QXlsx::Format format1;/*設置標題單元的樣式*/format1.setFontSize(12);/*設置字體大小*/format1.setHorizontalAlignment(QXlsx::Format::AlignHCenter);/*橫向居中*///format1.setBorderStyle(QXlsx::Format::BorderThin);/*邊框樣式*///format1.setFontBold(true);/*設置加粗*/if(!xlsx.selectSheet("表格數據")){/*在當前打開的xlsx文件中,找一個名字為ziv的sheet*/xlsx.addSheet("表格數據");//找不到的話就添加一個名為ziv的sheet}QSqlDatabase db = QSqlDatabase::database("mysql_connection1");QString tmpSql = QString("SELECT * FROM %1").arg(tableName);QSqlQuery query(db);if(query.exec(tmpSql)){//表頭列QSqlRecord queryRecord(query.record());qDebug()<<"queryRecord.count():"<<queryRecord.count();for(int colNum = 0; colNum < queryRecord.count(); colNum++){//qDebug() << queryRecord.fieldName(colNum);xlsx.write(1, colNum+1, queryRecord.fieldName(colNum),format1);}//表格數據int rowNum = 2;while(query.next()){for(int colNum = 0; colNum < queryRecord.count(); colNum++){xlsx.write(rowNum, colNum + 1, query.value(colNum),format1);}rowNum++;}}else{return false;}if(fileName.isEmpty())return false;xlsx.saveAs(fileName);//保存文件return true;
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);//連接數據庫if (!CreateConnection()){qDebug()<<"數據庫連接失敗";}QString tableName = "login_information";QString fileName = "D:/賬號.xlsx";if(exportData2XLSX(fileName, tableName)){qDebug()<<"導入excel成功";}else{qDebug()<<"導入excel失敗";}return a.exec();
}
5 項目代碼倉庫
代碼倉庫(歡迎star):
github倉庫
碼云