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

2023-10-30

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对应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);
    }
}

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

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. 退出操作

  当执行完所有操作后,需要关闭并退出 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 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>

#完

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Qt QAxObject】使用 QAxObject 高效任意读写 Excel 表 的相关文章

  • Excel 自动填充列 X++++..Y++..Z+

    如何自动填充之间的值 选择 A 列 CTRL G gt Blanks gt OK Type press UpArrow 然后按CTRL ENTER See 这个链接 http www techrepublic com blog msoffi
  • Interop.Excel 和 Tools.Excel 之间的区别?

    我目前正在开发 Microsoft Excel 的插件 但我对某些事情有点困惑 两者有什么区别Interop Excel and Tools Excel 例如 之间Interop Excel Workbook and Tools Excel
  • 将图表导出为图像有时会生成空文件

    I m doing a macro that exports all the charts in the sheet and then opens Outlook and attaches them However I ve noticed
  • 根据当前工作簿中的匹配值编辑主工作簿中的单元格

    这里的目标是比较两个工作簿之间 A 列中的值 当前工作簿是 xlsm 目标工作簿是 xlsx 如果找到任何匹配项 匹配值同一行的 E 列中的值在目标工作簿中发生更改 在这种情况下 必须将工作簿分开 我决定通过选择当前工作簿 A2 中的第一个
  • 更改列标签?例如:将“A”列更改为“名称”列

    谁能告诉我如何更改列标签 例如 我想将列 A 更改为列 名称 Excel Excel 的版本是什么 一般来说 您无法更改列字母 它们是 Excel 系统的一部分 您可以使用工作表中的一行来输入您正在使用的表格的标题 表标题可以是描述性列名称
  • 从“查找”结果中出现“下标超出范围”错误

    我想在 Excel 工作表中查找一个字符串 Excel 单元格值是使用公式计算的 当我运行这段代码时 Set firstExcel CreateObject Excel application firstExcel Workbooks Op
  • 如何在 Qt 应用程序中嵌入 Python 解释器?

    有没有一种简单的方法可以将 Python 解释器嵌入到 Qt 应用程序中 如果可能的话 我希望有一个跨平台的解决方案 这就是目的PythonQt http pythonqt sourceforge net 它支持 Windows Linux
  • 使用VBA复制垂直列并沿对角线粘贴

    我有一列数据 我们称之为 A 列 其中有 35 行数据 如何在此列上循环 然后将每个数据点粘贴到另一张工作表中 同时为每个循环循环增加列和行 换句话说 我寻求对角粘贴在第二张纸中 有没有一种简单的方法可以在 VBA 中执行此类操作 不要循环
  • VBA - HTML 抓取问题

    我正在尝试从网站上抓取拍卖数据https www rbauction com heavy equipment auctions https www rbauction com heavy equipment auctions 我当前的尝试是
  • 是否有 Qt 小部件可以浏览应用程序中小部件的层次结构(类似于 Spy++)?

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

    我有一个 150MB 的单页 Excel 文件 在一台非常强大的机器上使用以下命令打开大约需要 7 分钟 using python import xlrd wb xlrd open workbook file sh wb sheet by
  • Countif 不适用于小时和/或日期

    您好 我有 3 列内的数据 A 目的地 例如洛杉矶 B 承运人 例如 Ups C 发货时间 预计 4 00 使用的时间是24小时时间 不含Am Pm 我需要进行计数才能知道在特定时间我们有多少批货物 尝试过 COUNTIF A1 A100
  • 无法在我的抓取工具中设置超时选项以防止无限循环

    我已经使用 IE 在 vba 中编写了一个脚本 在其搜索框中的网页中启动搜索 通过点击搜索按钮根据搜索填充结果 网页加载它是searchbox几秒钟后它就会打开 但是 我的下面的脚本可以处理这个障碍并以正确的方式执行搜索 现在 我有一个稍微
  • xlwings: 删除一个列 | Excel 中的行

    如何删除 Excel 中的一行 wb xw Book Shipment xlsx wb sheets Page1 1 range 1 1 clear clear 用于删除内容 我想删除该行 我很惊讶 clear 函数有效 但 delete
  • 如何将自定义 Qt 类型与 QML 信号一起使用?

    我在 Qt 5 2 qml 应用程序中创建了一个自定义类型 class Setting public QObject Q OBJECT Q PROPERTY QString key READ key WRITE setKey Q PROPE
  • 了解 Qt3D 创建的网格

    我创建了一个 Qt3D 网格 如下所示 Qt3DCore QEntity newEntity new Qt3DCore QEntity Qt3DExtras QConeMesh mesh new Qt3DExtras QConeMesh m
  • 在合并的单元格中选择、插入照片并将其居中

    我是一名研发面包师 正在为我的团队制作食谱模板 模板中有照片 但我需要轻松地允许他们单击一个按钮 打开照片的文件选择器 然后将该照片放在合并的单元格中 我其实不太擅长做这个 Sub InsertPhotoMacro Dim photoNam
  • SQL Server,插入 Excel“链接服务器”时出现“无效列名”错误

    我有一个简单的 Excel 电子表格文档 运行 Office 2013 我使用 Microsoft Office 15 0 Access 数据库引擎 OLE DB 提供程序 将其用作数据库 我可以使用 MS SQL Server Manag
  • JasperReports 中每个工作表属性一页

    我有一个要求 我必须在 JasperReports 中设计一个报告 该报告有 4 页 第一张纸有 5 页 类似的其他纸有一页或两页 我面临的问题是 如果我使用net sf jasperreports export xls one page
  • 两个日期之间的小时数在 Excel 中不起作用

    根据要求 我提供了一张简化的屏幕截图来说明该问题 如您所见 我减去了两个日期并将其格式化为 h mm ss 为什么这不能提供两个日期之间经过的总小时数 有一个更好的方法吗 下面有一个很好的答案 但我试图弄清楚为什么按照此屏幕截图中所示的方式

随机推荐

  • 注解 @Transactional 事务类内调用不生效问题及解决办法

    Transactional 内部调用例子 在 Spring 的 AOP 代理下 只有目标方法由外部调用 目标方法才由 Spring 生成的代理对象来管理 这会造成自调用问题 若同一类中的其他没有 Transactional 注解的方法内部调
  • 基于FPGA的卷积网络加速(1)

    vivado hls是用高级语言设计硬件电路的IDE vivado sdsoc则用于软硬件协同也就是arm传数据到FPGA FPGA把结果传回到FPGA 开发人员不需要知道繁琐的接口的写法 只需要指定硬件函数和调用就可以 卷积神经网络加速
  • [记录学习]自学动力节点老杜MyBatis笔记_02

    MyBatis自学笔记 首先感谢动力节点和杜老师的教学分享 Respect 学习来源 B站 https www bilibili com video BV1JP4y1Z73S p 1 vd source 07c8a1a7d89af39fe2
  • applicationContext.xml和dispatcher-servlet.xml的区别

    Spring 官方文档介绍如下 Spring lets you define multiple contexts in a parent child hierarchy The applicationContext xml defines
  • python简单使用pyecharts库画多饼图

    from matplotlib pyplot import title from pyecharts options global options import TitleOpts from collections import named
  • JAVA集成华为推送 服务端

    一 注册成为开发者 地址 华为开发者联盟 智能终端能力开放 共建开发者生态 注册步骤参考 文档中心 二 推送的消息形式 华为Push建立了一条从应用服务器到终端App之间的通知消息传输通道 App的开发者通过华为Push平台可以方便的向华为
  • Python机器学习笔记 K-近邻算法

    K近邻 KNN k NearestNeighbor 分类算法是数据挖掘分类技术中最简单的方法之一 所谓K最近邻 就是K个最近的邻居的意思 说的是每个样本都可以用它最接近的k个邻居来代表 KNN算法的核心思想是如果一个样本在特征空间中的K个最
  • LeetCode——动态规划篇(一)

    刷题顺序及思路来源于代码随想录 网站地址 https programmercarl com 目录 509 斐波那契数 力扣 LeetCode 70 爬楼梯 力扣 LeetCode 746 使用最小花费爬楼梯 力扣 LeetCode 62 不
  • node.js安装

    1 下载 https nodejs org en download 点击如下位置 下载下来是msi文件 2 双击mis 3 验证 cmd node 出现版本号完成
  • 基于Java web的校园宿舍管理系统(功能丰富,界面友好)

    运行环境 最好是java jdk 1 8 我们在这个平台上运行的 其他版本理论上也可以 IDE环境 Eclipse Myeclipse IDEA都可以tomcat环境 Tomcat 7 x 8 x 9 x版本均可硬件环境 windows 7
  • 纠错输出码ECOC

    纠错输出码ECOC 即Error Correcting Output Codes 是一种最常用的MvM技术 many vs many多对多 而非训练完成后再去纠错 多分类学习最经典拆分策略 一对一OvO 一对其余OvR 多对多MvM 如果纠
  • hbase的hlog原理-如何保证数据高可靠、如何恢复数据-sequenceid原理

    hbase写入数据时 为了提升写入效率 先写入缓存memory store 默认为128M 缓存满了会触发flush落盘 写入hfile文件 但这种方式并不安全 如果缓存未满之前region server挂掉 还未来得及落盘的数据就会丢失
  • linux添加用户设置密码和用户sudo权限

    下面全部为root权限下操作 添加用户 adduser 用户名 添加密码 passwd 用户名 输入密码 用户添加sudo权限需要修改 etc sudoers 配置 先增加sudoers写入权限 chmod w etc sudoers 然后
  • 使用PlantUml绘制逻辑时序图/波形图

    AgileWave已支持PlantUml在线画图 Git源码参见 https github com cc hook agileWave AgileWave介绍 1 AgileWave 一款时序图绘制神器 2 好消息 源码和验证工具已开源至G
  • web前端开发到底是自学还是去上培训班?

    web前端开发到底是自学还是去上培训班 纠结中 应届毕业生 软件技术专业 去年接触到web前端开发这个行业 但是迷迷糊糊的就知道HTML CSS JS 其他一无所知 就知道做网页加一些网页的动态效果 没有系统的学习 相应的用到就学 没用到的
  • mysql 数据库常用、比较有用的语句

    添加索引 alter table user add index id time index id createTime 删除索引 alter table user drop index id time index 删除多余的 误添加的重复数
  • Android 清除缓存

    获取本机上缓存文件大小 private String taskGetCacheSize long size 0 File file1 getCacheDir File file2 getFilesDir File files new Fil
  • 21个React性能优化技巧

    React 为高性能应用设计提供了许多优化方案 本文列举了其中的一些最佳实践 在以下场景中 父组件和子组件通常会重新渲染 在同一组件或父组件中调用 setState 时 从父级收到的 props 的值发生变化 调用组件中的 forceUpd
  • 引用 C C++

    引用 引用是一个别名 它的作用就是作为目标的别名而使用 对这个引用的改动 就是对目标的改动 定义 例如引用一个整型变量 int a 666 int ra a 引用运算符 与地址操作符使用相同的符号 虽然它们显然是彼此相关的 但它们又是不一样
  • 【Qt QAxObject】使用 QAxObject 高效任意读写 Excel 表

    1 用什么操作 Excel 表 Qt 的官网库中是不包含 Microsoft Excel 的操作库 关于对 Microsoft Excel 的操作库可选的有很多 包含基于 Windows 系统本身的 ActiveX Qt Xlsx xlsL