1. How to operate Excel table
Qt
The official website library does not include Microsoft Excel
the operation library of . Microsoft Excel
There are many options for the operation library of , including those based on the Windows
system itself ActiveX
, , Qt Xlsx
, xlsLib
, LibXL
, qtXLS
, BasicExcel
.Number Duck
Library | .xls | .xlsx | read | Write | platform |
---|---|---|---|---|---|
Qt Xlsx | ❌ | ✔️ | ✔️ | ✔️ | Cross-platform |
xls | ✔️ | ❌ | ❌ | ✔️ | Cross-platform |
libxls | ✔️ | ❌ | ❌ | ✔️ | Cross-platform |
libXL | ✔️ | ✔️ | ✔️ | ✔️ | Cross-platform |
ActiveX | ✔️ | ✔️ | ✔️ | ✔️ | Windows native |
qtXLS | ✔️ | ❌ | ✔️ | ✔️ | Windows |
BasicExcel | ✔️ | ❌ | ✔️ | ✔️ | Windows |
Number Duck | ✔️ | ❌ | ✔️ | ✔️ | Windows,Linux |
This article uses objects based on , which Windows
is to implement reading and writing tables.ActiveX
Qt
QAxObjcet
Excel
2. Introduction to QAxObject
Before introducing QAxObject
, let's first take a brief look at the Windows
Component COM
Object Model, which COM
is a platform-independent distributed object-oriented system used to create binary software components that can interact. COM
Is (the underlying technology for compound documents,) and (the component that supports Microsoft
) technology. Objects can be created using a variety of programming languages . Object-oriented languages (such as ) provide programming mechanisms that simplify the implementation of objects. These objects can be located in a single process, in other processes, or even on remote computers.OLE
ActiveX
Internet
COM
C++
COM
COM
You can view the introduction of component model objects at: https://download.csdn.net/download/qq_36393978/88268235
Qt
The in is QAxObject
an COM
encapsulation of the component model object, QAxObject
derived from QAxBase
, QAxBase
providing a set of objects that can be directly accessed API
through IUnknown
pointers COM
. The specific structure is as shown below.
The Windows
on Excel
is also such an COM
object. Therefore, you can use in Qt
to QAxObjcet
implement Excel
the operation on. The basic operation process is as follows:
As shown in the figure above Excel
, the hierarchical structure of , Excel.Application
object → WorkBooks
object → WorkBook
object → WorkSheet
object → Range
object, 1
each object excel
has one Application
object, and 1
each Application
object consists of multiple Workbook
objects. These objects are uniformly managed Workbook
by the object. There are several objects under the object . These objects are uniformly managed by the object. , the object below corresponds to the table unit inside. The arrow indicates obtaining its sub-object. The acquisition method requires calling the function to obtain the sub-object instance. Each sub-object calls the function to perform its own specific operation.Workbooks
Workbook
WorkSheet
WorkSheet
WorkSheets
WorkSheet
Range
WorkSheet
querySubObject()
dynamicCall()
3. Basic usage
3.1. Include relevant documents
To use it QAxObject
, first .pro
add its module name in the file axcontainer
, so that the module will be loaded when the project file is compiled.
// project.pro
QT += axcontainer
The following header files need to be included in the header file:
#include <QString>
#include <QFileDialog>
#include <QAxObject>
#include <QVariant>
#include <QVariantList>
3.2. Create Excel process and obtain Excel workbook set
Open the folder, select Excel
the file, and create Excel
the process:
// 打开文件夹
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. Get spreadsheet set
Each Excel
workbook can contain several spreadsheets Sheet
:
QAxObject* sheets = workBook->querySubObject("Sheets"); //获取工作表集合,Sheets也可换用WorkSheets
Get the worksheet that requires operation:
QAxObject* sheet = workBook->querySubObject("WorkSheets(int)", 1);//获取工作表集合的工作表1,即sheet1
3.4. Select the cell range to be operated on
Each page of the spreadsheet contains multiple cells. Before operating, you need to select the cell range to be operated:
select all used cells on the current page:
//获取该sheet的使用范围对象(一般读取 Excel 时会选取全部范围)
QAxObject* usedRange = sheet->querySubObject("UsedRange");
Select a specified range of cells:
//获取 sheet 的指定范围(一般写入数据时,会选取指定范围)
QAxObject* usedRange = sheet->querySubObject("Range(const QString)", "A1:C12");
Here A1:C12
means to select the cell A
in the row C
of the column; if written as, it means to select the cell in the row of the column; of course, you can also write it to mean to select only this cell.1~12
A1:A12
A
1~12
A1:A1
A1
Select specific cells:
//获取 sheet 的指定范围(一般修改数据时,会选取指定单元格)
QAxObject* usedRange = sheet->querySubObject("Range(QVariant,QVariant)", "A6");
Here A6
, it means selecting A6
this cell.
[注]:获取 UsedRange 操作将会得到一个动态创建 (new) 出来的对象。
3.5. Read the contents of the cell range
After selecting each range of cells to be operated on, here is how to read the contents of all cells within the selected range:
QVariant var = usedRange->dynamicCall("Value");
delete usedRange;
It should be noted that in the above code, except for the operation of getting the cell range ( ), the rest are referencesUsedRange
to the object , which will not occupy memory space and do not need to be released. However, getting the applicable range of the cell ( ) will get a new creates a newly allocated object, so the object needs to be released manually after the read or write operation ends.UsedRange
QVariant
A class is a data union used to store read Excel
data. In fact, dynamicCall("Value")
the data type read by calling is QList<QList<QVariant>>
of type, so the read must be var
converted into data of this type.
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. Display the read data using QTableView
Here TbleView_table1
is the control Forms
directly dragged in 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. Write data to the selected cell range
You must have noticed that in , Excel
the horizontal axis coordinates are A~Z
expressed in letters to distinguish them from the vertical axis. However, we often use numbers in operation, or use numbers in the setting loop to change. For convenience, we need to implement a Excel
function to convert numbers to abscissas, as follows.
QString ExcelProcess::to26AlphabetString(int data)
{
QChar ch = (QChar)(data + 0x40);//A对应0x41
return 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);
}
}
Add the data to be written row by row according to the specified rows and columns.
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,即sheet1
QAxObject* 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. Exit operation
After all operations have been performed, you need to close and exit Excel
. The code is as follows:
workBook->dynamicCall("Close()"); //关闭工作簿
excel->dynamicCall("Quit()"); //退出进程
delete excel;
4. Sample Demonstration
The following is a simple Excel
table operation code written by the author. Its functions include
1. Open and read Excel
table contents;
2. Calculate the amount of data in the range based on the range of data in the specified table and write it to the table;
3. Calculate based on the amount of data. The range of the data.
Complete project download link: ExcelProcess.zip
The file list is as follows:
Run the effect demonstration.
5. Attachment
The code for all source files is posted here:
5.1. ExcelPrecess.pro
QT += core gui axcontainer
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += 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.0
SOURCES += \
main.cpp \
excelprocess.cpp
HEADERS += \
excelprocess.h
FORMS += \
excelprocess.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${
TARGET}/bin
else: unix:!android: target.path = /opt/$${
TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RESOURCES += \
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_OBJECT
private 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;
}
// 读取一个 sheet
this->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对应0x41
return 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>