【Qt QAxObject】使用 QAxObject 高效任意读写 Excel 表

1. 用什么操作 Excel 表

  Qt 的官网库中是不包含 Microsoft Excel 的操作库,关于对 Microsoft Excel 的操作库可选的有很多,包含基于 Windows 系统本身的 ActiveXQt XlsxxlsLibLibXLqtXLSBasicExcelNumber Duck

.xls.xlsx平台
Qt Xlsx✔️✔️✔️跨平台
xls✔️✔️跨平台
libxls✔️✔️跨平台
libXL✔️✔️✔️✔️跨平台
ActiveX✔️✔️✔️✔️Windows原生
qtXLS✔️✔️✔️Windows
BasicExcel✔️✔️✔️Windows
Number Duck✔️✔️✔️WindowsLinux

  本文采用基于 WindowsActiveX 对象,在 Qt 中也就是 QAxObjcet 实现读写 Excel 表。

2. QAxObject 简介

  在介绍 QAxObject 之前,首先简单了解一下 Windows 上的 COM 组件对象模型,COM 是一个独立于平台的分布式面向对象的系统,用于创建可以交互的二进制软件组件。 COMMicrosoftOLE (复合文档的基础技术,) 和 ActiveX (支持 Internet 的组件) 技术。可以使用各种编程语言创建 COM 对象。 面向对象的语言(如 C++)提供了简化 COM 对象的实现的编程机制。 这些对象可以位于单个进程中、其他进程中,甚至在远程计算机上也是如此。

COM 组件模型对象相信介绍可查看:https://download.csdn.net/download/qq_36393978/88268235

  而在 Qt 中的 QAxObject 是对 COM 组件模型对象的封装,QAxObject 派生自QAxBaseQAxBase 提供了一组 API 通过 IUnknown 指针直接访问 COM 对象,具体结构如下图。

在这里插入图片描述

  而在 Windows 上的 Excel 也是一个这样的 COM 对象,因此,可以采用在 Qt 中使用 QAxObjcet 实现对 Excel 的操作,其基本的操作流程如下:

在这里插入图片描述

  如上图描述了 Excel 的层次结构,Excel.Application 对象 → WorkBooks 对象 → WorkBook 对象 → WorkSheet 对象 → Range 对象,1excel 有一个 Application 对象,1Application 对象有多个 Workbook 对象组成,这些 Workbook 对象由 Workbooks 对象统一管理,Workbook 对象下包含若干个 WorkSheet,这些 WorkSheet 对象由 WorkSheets 对象统一管理,WorkSheet 下面的 Range 对象,对应这 WorkSheet 里面的表格单元了。箭头表示获取其子对象,获取方式需调用 querySubObject() 函数获取子对象实例,各个子对象调用 dynamicCall() 函数执行对各自的具体操作。

3. 基本使用方法

3.1. 包含相关文件

  要使用 QAxObject 首先要在 .pro 文件中添加其模块名称 axcontainer,这样工程文件在编译的时候就会加载该模块。

// project.pro
QT       += axcontainer

在头文件中需要包含如下几个头文件

#include <QString>
#include <QFileDialog>
#include <QAxObject>
#include <QVariant>
#include <QVariantList>

3.2. 创建 Excel 进程,获取 Excel 工作簿集

打开文件夹选择 Excel 文件,创建 Excel 进程:

// 打开文件夹
QString strFilePathName = QFileDialog::getOpenFileName(this, QStringLiteral("选择Excel文件"),"", tr("Exel file(*.xls *.xlsx)"));
if(strFilePathName.isNull()) {return ;
}
QAxObject *excel = new QAxObject(this)if (excel->setControl("Excel.Application")) {	// 加载 Microsoft Excel 控件
} else {excel->setControl("ket.Application");  // 加载 WPS Excel 控件
}excel->setProperty("Visible", false);  // 不显示 Excel 窗体
QAxObject* workBooks = excel->querySubObject("WorkBooks");  //获取工作簿集合
workBooks->dynamicCall("Open(const QString&)", strFilePathName); //打开打开已存在的工作簿
QAxObject* workBook = excel->querySubObject("ActiveWorkBook"); //获取当前工作簿

3.3. 获取电子表格集

每个 Excel 工作簿中都可以包含若干电子表格 Sheet

QAxObject* sheets = workBook->querySubObject("Sheets");  //获取工作表集合,Sheets也可换用WorkSheets

获取需要操作的工作表:

QAxObject* sheet = workBook->querySubObject("WorkSheets(int)", 1);//获取工作表集合的工作表1,即sheet1

3.4. 选取需要操作的单元格范围

每页电子表格包含多个单元格,在操作之前需要选取所要操作的单元格范围:
选取当前页面所有已使用单元格:

//获取该sheet的使用范围对象(一般读取 Excel 时会选取全部范围)
QAxObject* usedRange = sheet->querySubObject("UsedRange"); 

选取指定范围的单元格:

//获取 sheet 的指定范围(一般写入数据时,会选取指定范围)
QAxObject* usedRange = sheet->querySubObject("Range(const QString)", "A1:C12");

这里的 A1:C12 则表示选取,AC 列的 1~12 行单元格;若写成 A1:A12 则表示选取,A 列的 1~12 行单元格;当然你也可以写成 A1:A1 则表示只选取 A1 这一个单元格。

选择指定单元格:

//获取 sheet 的指定范围(一般修改数据时,会选取指定单元格)
QAxObject* usedRange = sheet->querySubObject("Range(QVariant,QVariant)", "A6");

这里的 A6,则表示选取 A6 这个单元格。

[注]:获取 UsedRange 操作将会得到一个动态创建 (new) 出来的对象。

3.5. 读取单元格范围内容

  当选取好要操作的单元各范围后,那么这里介绍如何读取选取范围内所有的单元格内容:

QVariant var = usedRange->dynamicCall("Value");
delete usedRange;

  需要注意的是上文代码中除了获取单元格范围 (UsedRange) 操作之外,其余得到的都是该对象的引用,不会占用内存空间,不需要释放,而获取单元格适用范围 (UsedRange) 则得到一个 new 出来新分配的对象,因此在读取或写入操作结束后需要手动释放该对象。

  QVariant 类是一个数据联合体,用来存放读取到的 Excel 数据。而事实上通过调用 dynamicCall("Value") 读到的数据类型是 QList<QList<QVariant>> 类型的,因此要将读到的 var 转换为该类型的数据。

QList<QList<QVariant>> xls_data;QVariantList varRows = var.toList();
if (varRows.isEmpty()) {return;
}const int rowCount = varRows.size();
this->excel.rowCount = rowCount;QVariantList rowData;for (int i = 0; i < rowCount; i++){rowData = varRows[i].toList();if (rowData.count() > this->excel.columnCount) {this->excel.columnCount = rowData.count();}this->xls_data.push_back(rowData);
}

3.6. 将读取到的数据用 QTableView 展示出来

  这里的 TbleView_table1 是在 Forms 中的直接拖拽的 QTableView 控件。

QStandardItemModel *tab_model;
for (int i = 0; i < xls_data.count(); i++) {for (int j = 0; j < xls_data.at(i).count(); j++) {QStandardItem *item = new QStandardItem(QString(xls_data.at(i).at(j).toByteArray()));tab_model->setItem(i, j, item);//delete item;}
}
this->ui->TbleView_table1->setModel(tab_model);

3.7. 向选取的单元格范围写入数据

  想必各位也注意到了,在 Excel 中横轴坐标都是用 A~Z 字母表示为了与纵轴的表示方式区别开来,而我们在操作是常用的则是以数字形式,或者说在设置循环中用数字方式更为方便,因此这里需要实现一个数字转 Excel 横坐标的函数,如下。

QString ExcelProcess::to26AlphabetString(int data)
{QChar ch = (QChar)(data + 0x40);//A对应0x41return QString(ch);
}void ExcelProcess::convertToColName(int data, QString &res)
{Q_ASSERT(data > 0 && data < 65535);int tempData = data / 26;if (tempData > 0) {int mode = data % 26;convertToColName(mode, res);convertToColName(tempData, res);} else {res=(to26AlphabetString(data) + res);}
}

按照指定行、列,一行一行的添加要写入的数据。

QList<QList<QVariant>> data_total;int row = 50 - 30, col = 100 - 10;	// 表示:选取范围为,30~50 行,10~100 列for (int i = 0; i < row; i++) {QList<QVariant> data_row;for (int j = 0; j < col; j++) {data_row.append("ImagineMiracle");}data_total.append(QVariant(data_row));
}
QString row_s, row_e, col_s, col_e, targetRange;
convertToColName(30, row_s);
convertToColName(50, row_e);
convertToColName(10, col_s);
convertToColName(100, col_e);
targetRange= col_s + row_s + ":" + col_e + row_e ;QAxObject* sheet = workBook->querySubObject("WorkSheets(int)", 1);//获取工作表集合的工作表1,即sheet1QAxObject* usedRange = sheet->querySubObject("Range(const QString)", target);
usedRange->setProperty("NumberFormat", "@");    //  设置所有单元格为文本属性
usedRange->dynamicCall("SetValue(const QVariant&", QVariant(data_total));
workBook->dynamicCall("Save()");	// 保存文件
delete usedRange;

3.8. 退出操作

  当执行完所有操作后,需要关闭并退出 Excel,代码如下:

workBook->dynamicCall("Close()"); //关闭工作簿 
excel->dynamicCall("Quit()"); //退出进程delete excel;

4. 示例演示

  下面是笔者写的一个简单的 Excel 表操作的代码,其功能包含
1.打开并读取 Excel 表内容;
2.根据指定表格中数据的范围计算范围内数据量并写入表格;
3.根据数据量计算数据的所在范围。

完成工程下载链接:ExcelProcess.zip

文件列表如下:

在这里插入图片描述

运行效果演示。
在这里插入图片描述

5. 附

这里贴出所有源文件的代码:

5.1. ExcelPrecess.pro

QT       += core gui axcontainergreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++17
RC_ICONS += pic/ExcelTool.ico# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0SOURCES += \main.cpp \excelprocess.cppHEADERS += \excelprocess.hFORMS += \excelprocess.ui# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += targetRESOURCES += \pic.qrc

5.2. excelprocess.h

#ifndef EXCELPROCESS_H
#define EXCELPROCESS_H#include "ui_excelprocess.h"
#include <QMainWindow>
#include <QLineEdit>
#include <QPushButton>
#include <QString>
#include <QLabel>
#include <QFileDialog>
#include <QStandardPaths>
#include <QDebug>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QMimeData>
#include <QMovie>
#include <QScopedPointer>
#include <QList>
#include <QAxObject>
#include <QVariant>
#include <QVariantList>
#include <QStandardItemModel>
#include <QThread>
#include <QIcon>QT_BEGIN_NAMESPACE
namespace Ui { class ExcelProcess; }
QT_END_NAMESPACE#define APPNAME ("ExcelTool v1.3.0 build 20230828")typedef struct {QAxObject *excel;QAxObject *workBooks;QAxObject *current_workBook;QAxObject *workSheets;QAxObject *current_workSheet;QAxObject *usedRange;QAxObject *rows;QAxObject *columns;int sheetCount, rowCount, columnCount;}ExcelFile;#define MODECOUNT (3)
static QString excel_mode[MODECOUNT] = {"Null", "Calc", "Range"};typedef struct {int sheet;int col_src;//int col;int col_dest;
} CalcMode;class ExcelProcess : public QMainWindow
{Q_OBJECTprivate slots:void showFiles(void);void on_PBtn_View_clicked();void on_ComBox_Mode_currentIndexChanged(int index);void on_Btn_CalcRun_clicked();void on_LEdit_FilePath_textChanged(const QString &arg1);void on_Btn_RangeRun_clicked();protected:void dragEnterEvent(QDragEnterEvent *event);    // 拖动进入事件void dropEvent(QDropEvent *event);      // 放下事件public:ExcelProcess(QWidget *parent = nullptr);~ExcelProcess();void openExcelFile();void closeExcelFile();void readExcel_OneSheet(int sheet_num);void showOneSheet(int sheet_num);void excelModeDisplay_00(void);void excelModeDisplay_01(void);void excelModeDisplay_02(void);void convertToColName(int data, QString &res);QString to26AlphabetString(int data);void castListListVariant2Variant(const QList<QList<QVariant> > &cells, QVariant &res);private:Ui::ExcelProcess *ui;QString *fileName;QMovie *movie_01;ExcelFile excel;QList<QList<QVariant>> xls_data;    // excel 表数据CalcMode calcMode;QStandardItemModel *tab_model;void initUi(void);void initExcel(void);};
#endif // EXCELPROCESS_H

5.3. excelprocess.cpp

#include "excelprocess.h"
#include "ui_excelprocess.h"void ExcelProcess::showFiles()
{QString str = QFileDialog::getOpenFileName(this, "File Explorer", QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation),"Excel 文件(*.xls *.xlsx);;All file(*.*)");this->ui->LEdit_FilePath->setText(str.toUtf8());*this->fileName = this->ui->LEdit_FilePath->text();qDebug() << *this->fileName << "\n";return ;
}void ExcelProcess::dragEnterEvent(QDragEnterEvent *event)
{if ((!event->mimeData()->urls()[0].fileName().right(3).compare("xls")) || (!event->mimeData()->urls()[0].fileName().right(4).compare("xlsx"))) {event->acceptProposedAction();} else {event->ignore();}return ;
}void ExcelProcess::dropEvent(QDropEvent *event)
{const QMimeData *qm = event->mimeData();*this->fileName = qm->urls()[0].toLocalFile();  // 获取拖入的文件名this->ui->LEdit_FilePath->clear();this->ui->LEdit_FilePath->setText(*this->fileName);return ;
}ExcelProcess::ExcelProcess(QWidget *parent): QMainWindow(parent), ui(new Ui::ExcelProcess)
{ui->setupUi(this);this->fileName = new QString;this->tab_model = new QStandardItemModel();this->setAcceptDrops(true);     // 设置主界面接收拖动进来的文件this->initUi();this->initExcel();return ;
}ExcelProcess::~ExcelProcess()
{delete ui;delete fileName;this->tab_model->clear();delete this->tab_model;if (this->excel.current_workBook != nullptr) {this->excel.current_workBook->dynamicCall("Save()");this->excel.current_workBook->dynamicCall("Close()"); //关闭文件}if (this->excel.workBooks != nullptr) {this->excel.workBooks->dynamicCall("Close()"); //关闭文件}this->excel.excel->dynamicCall("Quit(void)");   // 退出delete this->excel.workBooks;delete this->excel.excel;return ;
}void ExcelProcess::openExcelFile()
{//this->initExcel();if (this->excel.excel == nullptr) {return ;}this->excel.workBooks->dynamicCall("Open (const QString&)", *this->fileName);this->excel.current_workBook = this->excel.excel->querySubObject("ActiveWorkBook");this->excel.workSheets = this->excel.current_workBook->querySubObject("Sheets");this->excel.rowCount = 0;this->excel.columnCount = 0;this->excel.sheetCount = this->excel.workSheets->property("Count").toInt();qDebug() << "Sheet num: " << this->excel.sheetCount << "\n";}void ExcelProcess::closeExcelFile()
{if (this->excel.current_workBook != nullptr) {this->excel.current_workBook->dynamicCall("Save()");this->excel.current_workBook->dynamicCall("Close()"); //关闭文件}if (this->excel.workBooks != nullptr) {this->excel.workBooks->dynamicCall("Close()"); //关闭文件}this->excel.excel->dynamicCall("Quit(void)");   // 退出delete this->excel.workBooks;delete this->excel.excel;this->initExcel();return ;
}void ExcelProcess::readExcel_OneSheet(int sheet_num)
{if (sheet_num > this->excel.sheetCount) {return;}// 读取一个 sheetthis->excel.current_workSheet = this->excel.current_workBook->querySubObject("Sheets(int)", sheet_num);this->excel.usedRange = this->excel.current_workSheet->querySubObject("UsedRange");if (nullptr == this->excel.usedRange || this->excel.usedRange->isNull()) {return;}QVariant var = this->excel.usedRange->dynamicCall("Value");delete this->excel.usedRange;this->excel.usedRange = nullptr;// 读取一个 sheet 结束for (int i = 0; i < this->xls_data.count(); i++) {this->xls_data.value(i).clear();}this->xls_data.clear();QVariantList varRows = var.toList();if (varRows.isEmpty()) {return;}const int rowCount = varRows.size();this->excel.rowCount = rowCount;QVariantList rowData;for (int i = 0; i < rowCount; i++){rowData = varRows[i].toList();if (rowData.count() > this->excel.columnCount) {this->excel.columnCount = rowData.count();}this->xls_data.push_back(rowData);}//this->excel.current_workBook->dynamicCall("Close()");qDebug() << "Sheet:: row:" << this->excel.rowCount << "colum:" << this->excel.columnCount << "\n";this->ui->ComBox_Sheet->clear();for (int i = 1; i <= this->excel.sheetCount; i++) {this->ui->ComBox_Sheet->addItem(QString::number(i));}this->ui->ComBox_Row->clear();for (int i = 1; i <= this->excel.rowCount; i++) {this->ui->ComBox_Row->addItem(QString::number(i));}this->ui->ComBox_Column->clear();for (int i = 1; i <= this->excel.columnCount; i++) {this->ui->ComBox_Column->addItem(QString::number(i));}}void ExcelProcess::showOneSheet(int sheet_num)
{this->readExcel_OneSheet(sheet_num);this->tab_model->clear();for (int i = 0; i < this->xls_data.count(); i++) {for (int j = 0; j < this->xls_data.at(i).count(); j++) {QStandardItem *item = new QStandardItem(QString(this->xls_data.at(i).at(j).toByteArray()));this->tab_model->setItem(i, j, item);//delete item;}}this->ui->TbleView_table1->setModel(this->tab_model);//this->ui->TbleView_table1->setSectionResizeMode(QHeaderView::Stretch);//delete model;
}void ExcelProcess::excelModeDisplay_00()
{this->ui->Lab_Row->setText("Row:");this->ui->Lab_Column->setText("Row:");this->ui->ComBox_Column->clear();for (int i = 1; i <= this->excel.columnCount; i++) {this->ui->ComBox_Column->addItem(QString::number(i));}this->ui->TbleView_table1->show();this->ui->Lab_Sheet->hide();this->ui->Lab_Row->hide();this->ui->Lab_Column->hide();this->ui->ComBox_Sheet->hide();this->ui->ComBox_Row->hide();this->ui->ComBox_Column->hide();this->ui->Btn_CalcRun->hide();this->ui->Btn_RangeRun->hide();this->ui->ComBox_Mode->setCurrentIndex(0);
}void ExcelProcess::excelModeDisplay_01()
{this->ui->Lab_Row->setText("Col_s:");this->ui->Lab_Column->setText("Col_d:");this->ui->ComBox_Mode->setCurrentIndex(1);this->ui->ComBox_Row->clear();this->ui->ComBox_Column->clear();for (int i = 1; i <= this->excel.columnCount; i++) {this->ui->ComBox_Row->addItem(QString::number(i));}for (int i = 1; i <= this->excel.columnCount + 1; i++) {this->ui->ComBox_Column->addItem(QString::number(i));}this->ui->ComBox_Column->setCurrentIndex(this->ui->ComBox_Column->count() - 1);this->ui->Lab_Sheet->show();this->ui->Lab_Row->show();this->ui->Lab_Column->show();this->ui->TbleView_table1->show();this->ui->ComBox_Sheet->show();this->ui->ComBox_Row->show();this->ui->ComBox_Column->show();this->ui->Btn_CalcRun->show();this->ui->Btn_RangeRun->hide();
}void ExcelProcess::excelModeDisplay_02()
{this->ui->Lab_Row->setText("Col_s:");this->ui->Lab_Column->setText("Col_d:");this->ui->ComBox_Mode->setCurrentIndex(2);this->ui->ComBox_Row->clear();this->ui->ComBox_Column->clear();for (int i = 1; i <= this->excel.columnCount; i++) {this->ui->ComBox_Row->addItem(QString::number(i));}for (int i = 1; i <= this->excel.columnCount + 1; i++) {this->ui->ComBox_Column->addItem(QString::number(i));}this->ui->ComBox_Column->setCurrentIndex(this->ui->ComBox_Column->count() - 1);this->ui->Lab_Sheet->show();this->ui->Lab_Row->show();this->ui->Lab_Column->show();this->ui->TbleView_table1->show();this->ui->ComBox_Sheet->show();this->ui->ComBox_Row->show();this->ui->ComBox_Column->show();this->ui->Btn_CalcRun->hide();this->ui->Btn_RangeRun->show();
}void ExcelProcess::convertToColName(int data, QString &res)
{Q_ASSERT(data>0 && data<65535);int tempData = data / 26;if(tempData > 0) {int mode = data % 26;convertToColName(mode,res);convertToColName(tempData,res);} else {res=(to26AlphabetString(data)+res);}
}QString ExcelProcess::to26AlphabetString(int data)
{QChar ch = (QChar)(data + 0x40);//A对应0x41return QString(ch);
}void ExcelProcess::castListListVariant2Variant(const QList<QList<QVariant> > &cells, QVariant &res)
{QVariantList vars;const int rows = cells.size();      //获取行数for(int i = 0; i < rows; ++i){vars.append(QVariant(cells[i]));    //将list(i)添加到QVariantList中 QVariant(cells[i])强制转换}res = QVariant(vars);   //强制转换
}void ExcelProcess::initUi()
{this->setWindowTitle(APPNAME);this->setWindowIcon(QIcon(":/bk/pic/ExcelTool.ico"));this->ui->Lab_FilePath->setText("File Path:");this->ui->PBtn_View->setText("Open File");//this->ui->Lab_BottomBar->setText("");this->ui->Lab_Background->setText("");movie_01 = new QMovie(":/bk/pic/bk_01.gif");this->ui->Lab_Background->setGeometry(0, 0, 700, 500);this->ui->Lab_Background->setMovie(movie_01);movie_01->setScaledSize(this->ui->Lab_Background->size());movie_01->start();this->ui->Lab_Sheet->hide();this->ui->Lab_Row->hide();this->ui->Lab_Column->hide();this->ui->ComBox_Sheet->hide();this->ui->ComBox_Row->hide();this->ui->ComBox_Column->hide();this->ui->Lab_Mode->hide();this->ui->ComBox_Mode->hide();this->ui->Btn_CalcRun->hide();this->ui->Btn_RangeRun->hide();for (int i = 0; i < MODECOUNT; i++) {this->ui->ComBox_Mode->addItem(excel_mode[i]);}this->ui->ComBox_Mode->setCurrentIndex(0);this->ui->TbleView_table1->hide();return ;}void ExcelProcess::initExcel()
{this->excel.excel = new QAxObject("Excel.Application");   // 加载 excel 驱动this->excel.excel->setProperty("Visible", false);//不显示Excel界面,如果为true会看到启动的Excel界面//this->excel.excel->setProperty("Visible", true);this->excel.workBooks = this->excel.excel->querySubObject("WorkBooks");
}void ExcelProcess::on_PBtn_View_clicked()
{*this->fileName = this->ui->LEdit_FilePath->text();if ((0 == this->fileName->right(3).compare("xls")) || (0 == this->fileName->right(4).compare("xlsx")) || this->fileName->isEmpty()) {;} else {this->movie_01->stop();this->movie_01->setFileName(":/bk/pic/bk_04.gif");this->ui->Lab_Background->setMovie(movie_01);movie_01->setScaledSize(this->ui->Lab_Background->size());movie_01->start();return ;}if ("Done" == this->ui->PBtn_View->text()) {//QThread::usleep(5);this->ui->LEdit_FilePath->setEnabled(true);this->ui->PBtn_View->setText("Open File");this->tab_model->clear();this->ui->Lab_Sheet->hide();this->ui->Lab_Row->hide();this->ui->Lab_Column->hide();this->ui->ComBox_Sheet->hide();this->ui->ComBox_Row->hide();this->ui->ComBox_Column->hide();this->ui->Lab_Mode->hide();this->ui->ComBox_Mode->hide();this->ui->Btn_CalcRun->hide();this->ui->Btn_RangeRun->hide();this->ui->TbleView_table1->hide();this->movie_01->stop();this->movie_01->setFileName(":/bk/pic/bk_01.gif");this->ui->Lab_Background->setMovie(movie_01);movie_01->setScaledSize(this->ui->Lab_Background->size());movie_01->start();this->closeExcelFile();} else {if (this->ui->LEdit_FilePath->text().isEmpty()) {this->showFiles();} else {//QThread::usleep(5);this->excelModeDisplay_00();this->ui->LEdit_FilePath->setEnabled(false);this->ui->PBtn_View->setText("Done");this->movie_01->stop();this->movie_01->setFileName(":/bk/pic/bk_02.gif");this->ui->Lab_Background->setMovie(movie_01);movie_01->setScaledSize(this->ui->Lab_Background->size());movie_01->start();this->openExcelFile();this->showOneSheet(1);this->ui->TbleView_table1->setStyleSheet("background-color:transparent");this->ui->TbleView_table1->horizontalHeader()->setStyleSheet("QHeaderView::section{background:transparent},QHeaderView::Stretch");this->ui->TbleView_table1->verticalHeader()->setStyleSheet("QHeaderView::section{background:transparent}");this->ui->TbleView_table1->setCornerButtonEnabled(false);this->ui->Lab_Mode->show();this->ui->ComBox_Mode->show();this->ui->TbleView_table1->show();}}}void ExcelProcess::on_ComBox_Mode_currentIndexChanged(int index)
{switch(index) {case 0: {this->excelModeDisplay_00();break;}case 1: {this->excelModeDisplay_01();break;}case 2: {this->excelModeDisplay_02();break;}default: {break;}}return ;
}void ExcelProcess::on_Btn_CalcRun_clicked()
{this->calcMode.sheet = this->ui->ComBox_Sheet->currentText().toInt();this->calcMode.col_src = this->ui->ComBox_Row->currentText().toInt();this->calcMode.col_dest = this->ui->ComBox_Column->currentText().toInt();QString data, num1, num2, result;qDebug() << "Sheet::" << this->calcMode.sheet;this->showOneSheet(this->calcMode.sheet);QList<QVariant> data_total;for (int i = 0; i < this->excel.rowCount; i++) {data = this->xls_data.at(i).at(this->calcMode.col_src - 1).toByteArray();bool flag = true;num1.clear();num2.clear();for (int i_d = 0; i_d < data.length(); i_d++) {if ('-' == data.at(i_d)) {flag = false;continue;}if (flag) {num1 += data.at(i_d);} else {num2 += data.at(i_d);}}QList<QVariant> data_row;result = QString::number(num2.toInt() - num1.toInt());qDebug() << "num1:" << num1 << "num2:" << num2 << "res:" << result << "\n";data_row.append(QString::number(num2.toInt() - num1.toInt() + 1));data_total.append(QVariant(data_row));}QString col_num, target;this->convertToColName(this->calcMode.col_dest, col_num);qDebug() << "Col:" << col_num << "\n";target = col_num + "1:" + col_num + QString::number(this->excel.rowCount);qDebug() << target ;this->excel.current_workSheet = this->excel.current_workBook->querySubObject("Sheets(int)", this->calcMode.sheet);this->excel.usedRange = this->excel.current_workSheet->querySubObject("Range(const QString)", target);this->excel.usedRange->setProperty("NumberFormat", "@");    //  设置所有单元格为文本属性this->excel.usedRange->dynamicCall("SetValue(const QVariant&", QVariant(data_total));this->excel.current_workBook->dynamicCall("Save()");//this->excel.current_workBook->dynamicCall("Close()");this->showOneSheet(this->calcMode.sheet);delete this->excel.usedRange;}void ExcelProcess::on_LEdit_FilePath_textChanged(const QString &arg1)
{if (arg1.isEmpty()) {this->movie_01->stop();this->movie_01->setFileName(":/bk/pic/bk_01.gif");this->ui->Lab_Background->setMovie(movie_01);movie_01->setScaledSize(this->ui->Lab_Background->size());movie_01->start();*this->fileName = "";} else if ((0 == arg1.right(3).compare("xls")) || (0 == arg1.right(4).compare("xlsx"))) {this->movie_01->stop();this->movie_01->setFileName(":/bk/pic/bk_03.gif");this->ui->Lab_Background->setMovie(movie_01);movie_01->setScaledSize(this->ui->Lab_Background->size());movie_01->start();*this->fileName = this->ui->LEdit_FilePath->text();} else {this->movie_01->stop();this->movie_01->setFileName(":/bk/pic/bk_04.gif");this->ui->Lab_Background->setMovie(movie_01);movie_01->setScaledSize(this->ui->Lab_Background->size());movie_01->start();}return ;
}void ExcelProcess::on_Btn_RangeRun_clicked()
{this->calcMode.sheet = this->ui->ComBox_Sheet->currentText().toInt();this->calcMode.col_src = this->ui->ComBox_Row->currentText().toInt();this->calcMode.col_dest = this->ui->ComBox_Column->currentText().toInt();QString data;int num_src = 0, num1 = 0, num2 = 0;qDebug() << "Sheet::" << this->calcMode.sheet;this->showOneSheet(this->calcMode.sheet);QList<QVariant> data_total;for (int i = 0; i < this->excel.rowCount; i++) {data = this->xls_data.at(i).at(this->calcMode.col_src - 1).toByteArray();num_src = data.toInt();num1 = num2 + 1;num2 = num_src + num1 - 1;QList<QVariant> data_row;qDebug() << "src:" << num_src << "num1:" << num1 << "num2:" << num2 << "\n";qDebug() << "range:" << (QString::number(num1) + "-" + QString::number(num2)) << "\n";data_row.append(QString::number(num1) + "-" + QString::number(num2));data_total.append(QVariant(data_row));}QString col_num, target;this->convertToColName(this->calcMode.col_dest, col_num);qDebug() << "Col:" << col_num << "\n";target = col_num + "1:" + col_num + QString::number(this->excel.rowCount);qDebug() << target ;this->excel.current_workSheet = this->excel.current_workBook->querySubObject("Sheets(int)", this->calcMode.sheet);this->excel.usedRange = this->excel.current_workSheet->querySubObject("Range(const QString)", target);this->excel.usedRange->setProperty("NumberFormat", "@");    //  设置所有单元格为文本属性this->excel.usedRange->dynamicCall("SetValue(const QVariant&", QVariant(data_total));this->excel.current_workBook->dynamicCall("Save()");//this->excel.current_workBook->dynamicCall("Close()");this->showOneSheet(this->calcMode.sheet);delete this->excel.usedRange;}

5.4. main.cpp

#include "excelprocess.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);ExcelProcess w;w.show();return a.exec();
}

5.5. excelprocess.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>ExcelProcess</class><widget class="QMainWindow" name="ExcelProcess"><property name="geometry"><rect><x>0</x><y>0</y><width>700</width><height>500</height></rect></property><property name="windowTitle"><string>ExcelProcess</string></property><widget class="QWidget" name="centralwidget"><widget class="QLineEdit" name="LEdit_FilePath"><property name="geometry"><rect><x>80</x><y>420</y><width>490</width><height>24</height></rect></property></widget><widget class="QPushButton" name="PBtn_View"><property name="geometry"><rect><x>590</x><y>417</y><width>80</width><height>30</height></rect></property><property name="text"><string>Open File</string></property></widget><widget class="QLabel" name="Lab_FilePath"><property name="geometry"><rect><x>10</x><y>420</y><width>60</width><height>24</height></rect></property><property name="text"><string>File Path:</string></property></widget><widget class="QLabel" name="Lab_Background"><property name="geometry"><rect><x>700</x><y>500</y><width>53</width><height>16</height></rect></property><property name="text"><string>TextLabel</string></property></widget><widget class="QTableView" name="TbleView_table1"><property name="geometry"><rect><x>19</x><y>280</y><width>531</width><height>100</height></rect></property></widget><widget class="QComboBox" name="ComBox_Sheet"><property name="geometry"><rect><x>80</x><y>390</y><width>60</width><height>24</height></rect></property></widget><widget class="QLabel" name="Lab_Sheet"><property name="geometry"><rect><x>30</x><y>390</y><width>50</width><height>24</height></rect></property><property name="text"><string>Sheet:</string></property></widget><widget class="QLabel" name="Lab_Row"><property name="geometry"><rect><x>170</x><y>390</y><width>50</width><height>24</height></rect></property><property name="text"><string>Row_s:</string></property></widget><widget class="QComboBox" name="ComBox_Row"><property name="geometry"><rect><x>220</x><y>390</y><width>50</width><height>24</height></rect></property></widget><widget class="QLabel" name="Lab_Column"><property name="geometry"><rect><x>280</x><y>390</y><width>50</width><height>24</height></rect></property><property name="text"><string>Col_d:</string></property></widget><widget class="QComboBox" name="ComBox_Column"><property name="geometry"><rect><x>330</x><y>390</y><width>50</width><height>24</height></rect></property></widget><widget class="QComboBox" name="ComBox_Mode"><property name="geometry"><rect><x>620</x><y>280</y><width>70</width><height>24</height></rect></property></widget><widget class="QLabel" name="Lab_Mode"><property name="geometry"><rect><x>565</x><y>280</y><width>50</width><height>24</height></rect></property><property name="text"><string>Mode:</string></property></widget><widget class="QPushButton" name="Btn_CalcRun"><property name="geometry"><rect><x>620</x><y>350</y><width>70</width><height>30</height></rect></property><property name="text"><string>Run</string></property></widget><widget class="QPushButton" name="Btn_RangeRun"><property name="geometry"><rect><x>620</x><y>350</y><width>70</width><height>30</height></rect></property><property name="text"><string>Run</string></property></widget><zorder>Lab_Background</zorder><zorder>Lab_FilePath</zorder><zorder>PBtn_View</zorder><zorder>LEdit_FilePath</zorder><zorder>TbleView_table1</zorder><zorder>ComBox_Sheet</zorder><zorder>Lab_Sheet</zorder><zorder>Lab_Row</zorder><zorder>ComBox_Row</zorder><zorder>Lab_Column</zorder><zorder>ComBox_Column</zorder><zorder>ComBox_Mode</zorder><zorder>Lab_Mode</zorder><zorder>Btn_CalcRun</zorder><zorder>Btn_RangeRun</zorder></widget><widget class="QMenuBar" name="menubar"><property name="geometry"><rect><x>0</x><y>0</y><width>700</width><height>26</height></rect></property></widget><widget class="QStatusBar" name="statusbar"/></widget><resources/><connections/>
</ui>

#完

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/116792.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

猫头虎博主赠书一期:《Kubernetes原生微服务开发》

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

Android 动画之插值器PathInterpolator

Android 的View动画、属性动画都可以设置动画插值器&#xff0c;以此来实现不同的动画效果。 这篇文章 Android View动画整理 有介绍各种插值器的效果&#xff0c;这一篇专访 PathInterpolator 。 参考官网 添加曲线动作 &#xff0c; PathInterpolator 基于 贝塞尔曲线 或 …

数据结构——哈希表

哈希表 这里没有讲哈希表底层的概念&#xff0c;什么转红黑树&#xff0c;什么链表的&#xff0c;这篇文章主要讲的是如何用C实现哈希表&#xff0c;以及哈希表的基本概念。后面我会出一篇文章来讲C中hashmap中的底层逻辑的知识。 哈希表的概念 哈希表是一种数据结构&#xff0…

python爬虫-数据解析BeautifulSoup

1、基本简介 BeautifulSoup简称bs4,BeautifulSoup和lxml一样是一个html的解析器&#xff0c;主要功能也是解析和提取数据。 BeautifulSoup和lxml类似&#xff0c;既可以解析本地文件也可以响应服务器文件。 缺点&#xff1a;效率没有lxml的效率高 。 优点&#xff1a;接口设…

java遇到java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver该如何解决

普通的Java项目&#xff0c;利用servlet实现登录页面跳转出现下列问题。该如何解决&#xff1f;&#xff1f;&#xff1f; 首先你要先加载驱动&#xff0c;idea通过项目结构添加的依赖包是无法正常加载驱动的。我们要在 WEB-INF目录下建立lib目录在lib目录下添加MySQL驱动。

stm32之IIC协议

主要通过两个层面来讲&#xff1a;物理层、协议层。 IIC是一个同步半双工串行总线协议。 一、物理层&#xff08;通信模型&#xff09; 1、最早是飞利浦公司开发的这个协议&#xff0c;最早应用到其产品上去。 2、两线制&#xff08;两根信号线&#xff09; 其中SCL为时钟…

贝叶斯神经网络 - 捕捉现实世界的不确定性

贝叶斯神经网络 - 捕捉现实世界的不确定性 Bayesian Neural Networks 生活本质上是不确定性和概率性的&#xff0c;贝叶斯神经网络 (BNN) 旨在捕获和量化这种不确定性 在许多现实世界的应用中&#xff0c;仅仅做出预测是不够的&#xff1b;您还想知道您对该预测的信心有多大。例…

SparkCore

第1章 RDD概述 1.1 什么是RDD RDD&#xff08;Resilient Distributed Dataset&#xff09;叫做弹性分布式数据集&#xff0c;是Spark中最基本的数据抽象。代码中是一个抽象类&#xff0c;它代表一个弹性的、不可变、可分区、里面的元素可并行计算的集合。 RDD类比工厂生产。 …

图:有向无环图(DAG)

1.有向无环图的定义 有向无环图:若一个有向图中不存在环&#xff0c;则称为有向无环图。 简称DAG图(Directed Acyclic Graph) 顶点中不可能出现重复的操作数。 2.有向无环图的应用 1.描述算数表达式 用有向无环图描述算术表达式。 解题步骤&#xff1a; 把各个操作数不重…

C++网狐服务器引入开源日志库spdlog

很多人对日志库不以为然&#xff0c;包括网狐这种十几年的公司都不重视&#xff0c;其实日志库记录的东西能在线上出问题时高效解决&#xff0c;特别是别人写的东西&#xff0c;人又走了&#xff0c;出了问题&#xff0c;还可以用日志分析快速解决。要是没有日志记录&#xff0…

Seaborn绘制热力图的子图

Seaborn绘制热力图的子图 提示&#xff1a;如何绘制三张子图 绘制的时候&#xff0c;会出现如下问题 &#xff08;1&#xff09;如何绘制1*3的子图 &#xff08;2&#xff09;三个显示条&#xff0c;如何只显示最后一个 提示&#xff1a;下面就展示详细步骤 Seaborn绘制热力…

el-table实现纯前端导出(适用于el-table任意表格)

2023.9.1今天我学习了如何使用el-table实现前端的导出功能&#xff0c;该方法的好处有无论你的el-table长什么样子&#xff0c;导出之后就是什么样子。 1.安装三个插件 npm install file-save npm install xlsx npm install xlx-style 2.创建Export2Excel.js // 根据dom导出表…

【100天精通python】Day47:python网络编程_Web开发:web服务器,前端基础以及静态服务器

目录 1 网络编程与web编程 1.1 网络编程 1.2 web编程 1.3 前后端交互的基本原理 2 Web开发基础 2.1 HTTP协议 2.2 Web服务器 2.3 前端基础 2.3.1 HTML&#xff08;超文本标记语言&#xff09; 2. 3.2 CSS&#xff08;层叠样式表&#xff09; 2.3.3 JavaScript 2.…

【网络安全带你练爬虫-100练】第17练:分割字符串

目录 一、目标1&#xff1a;使用函数分割 二、目标2&#xff1a;使用函数模块 三、目标3&#xff1a;使用正则匹配 一、目标1&#xff1a;使用函数分割 目标&#xff1a;x.x.x.x[中国北京 xx云] 方法&#xff1a;split函数replace函数 1、分割&#xff1a;使用split()方法将…

如何有效进行RLHF的数据标注?

编者按&#xff1a;随着大语言模型在自然语言处理领域的广泛应用&#xff0c;如何从人类反馈进行强化学习&#xff08;RLHF&#xff09;已成为一个重要的技术挑战。并且RLHF需要大量高质量的人工数据标注&#xff0c;这是一个非常费力的过程。 本文作者在数据标注领域具有丰富经…

线性代数的学习和整理18:矩阵的秩的各种定理, 秩和维度(未完成)

目录 1 矩阵的秩 矩阵的秩 2 求秩的方法 矩阵的维度秩 矩阵的维度 向量的模&#xff0c;矩阵的模-没有把&#xff0c;难道是面积&#xff1f; 矩阵的平直概念 5 矩阵的初等变换&#xff08;矩阵等价概念的引出&#xff09; 1 为什么要引入矩阵的“秩” 这个概念&#x…

STM32+RTThread配置以太网无法ping通,无法获取动态ip的问题

记录一个非常蠢的问题&#xff0c;今天在移植rtthread的以太网驱动的时候出现无法获取动态ip的问题&#xff0c;问题如下&#xff1a; 设置为动态ip时不管是连接路由器还是电脑主机都无法ping通&#xff0c;也无法获取dns地址。 设置为静态ip时无法ping通主机。 使用wireshark…

爬虫--爬取自己想去的目的的车票信息

前言&#xff1a; 本篇文章主要作为一个爬虫项目的小练习&#xff0c;来给大家进行一下爬虫的大致分析过程以及来帮助大家在以后的爬虫编写中有一个更加清晰的认识。 一&#xff1a;环境配置 Python版本&#xff1a;3.7 IDE:PyCharm 所需库&#xff1a;requests&#xff0…

使用python,生成数字在图片上的验证码

许多网站在注册时都要求输入验证码&#xff0c;这样做为了防止被程序恶意注册和保证网站安全 1. Pillow PIL(Python Imaging Library)是一个强大的python图像处理库&#xff0c;只是支持到python2.7, Pillow虽说是PIL的一个分支&#xff0c;但是pillow支持python3.x&#xff…

【python爬虫】7.爬到的数据存到哪里?

文章目录 前言存储数据的方式存储数据的基础知识基础知识&#xff1a;Excel写入与读取基础知识&#xff1a;csv写入与读取项目&#xff1a;存储周杰伦的歌曲信息 复习 前言 上一关我们以QQ音乐为例&#xff0c;主要学习了如何带参数地请求数据&#xff08;get请求&#xff09;…