小工具知识网

当前位置: 首页 > 行业知识 > QT使用QAxObject读取Excel教程-全网最全

行业知识

QT使用QAxObject读取Excel教程-全网最全

2026-11-09 17:58:43 来源:互联网转载

文章目录

    • 一、背景
    • 二、介绍
      • 基本操作方法
        • 获取对象
        • 调用动态方法
        • 设置和获取属性
        • 更多相关
        • 三、使用要求
            • 添加模块
            • 与excel com连接的方法
            • Excel基本操作
            • 四、具体使用说明
            • 五、项目实战
              • 实战项目1
              • 实战项目2
              • 实战项目3
              • 实战项目4
              • 实战项目5-封装好的库
                • 头文件 `excelmanager.h`
                • 实现文件 `excelmanager.cpp`
                • 其他
                • 项目实战6-封装好的库
                • 六、一些小技巧
                  • 读取excel��的数据

                    一、背景

                    QT中没有操作Excel的官方库,本文章介绍的是Windows系统的ActiveX对象(QAxObject)操作Excel。

                    当然还有一些开源库可以用来操作Excel,详见:Qt处理Excel的一些库

                    本文只对QAxObject读取Excel作说明。

                    二、介绍

                    首先,我们先来解释一些概念,方面我们去理解Qt操作excel的基本流程。

                    Qt中,QAxObject对COM对象进行封装,QAObject派生自QAxBase,QAxBase提供了一组API通过IUnknown指针直接访问COM对象。具体结构如下图。

                    我们要操作的Excel也是一个COM对象,因此,可以采用上述方式实现对Excel的操作。

                    在具体操作之前,我们先了解一下excel的层次结构,如图所示,Application对象–>Workbook对象–>Worksheet对象–>Range对象。

                    1个excel有一个Application对象,1个Application对象有多个workbook对象组成,这些workbook对象由workbooks对象统一管理,workbook对象下包含若干个worksheet,这些worksheet对象由worksheets对象统一管理,worksheet下面的range对象,对应这worksheet里面的表格单元了。

                    基本操作方法

                    获取对象

                    上述对象获取某个子对象一般通过 QAxObject 的 querySubObject() 方法,比如:

                    QAxObject *excel = new QAxObject("Excel.Application");QAxObject *workbooks = excel->querySubObject("WorkBooks");QAxObject *workbook = workbooks->querySubObject("Open(QString&)", path);QAxObject *sheets = workbook->querySubObject("Sheets");QAxObject *sheet = sheets->querySubObject("Item(int)", 1);QAxObject *range = sheet->querySubObject("Cells(int,int)", row, col);

                    这其中依次得到的对象分别是:

                    • Excel 的 Application 对象。
                    • 管理 Workbook 对象的 Workbooks 对象。
                    • 路径为 path 的 Excel 文件对应的 Workbook 对象。
                    • 管理其中工作表 Sheet 的 Sheets 对象。
                    • 第一张工作表对应的 Sheet 对象。
                    • 其中第 row 行,第 col 列的表格单元的 range 对象。
                      调用动态方法

                      还可以通过 dynamicCall() 方法调用一些动作,比如:

                      workbook->dynamicCall("SaveAs(const QString &)", QDir::toNativeSeparators(path));

                      这是调用另存为 path 路径。

                      workbook->dynamicCall("Save()");

                      这是调用保存。

                      range->dynamicCall("Value", value);

                      这时设置单元格的值。

                      excel->dynamicCall("SetVisible(bool)", false);

                      这是设置打开 Excel 时不可见(也就是后台进行)。

                      workbooks->dynamicCall("Add");

                      这是新建一个 Excel 文件。

                      workbooks->dynamicCall("Close()");excel->dynamicCall("Quit()");

                      这是关闭 Excel 应用。

                      除此之外,还有很多类似的方法。

                      设置和获取属性

                      一般通过 setProperty() 方法设置属性,比如:

                      range->setProperty("VerticalAlignment", -4108);range->setProperty("HorizontalAlignment", -4108);range->setProperty("WrapText", true);range->setProperty("MergeCells", true);range->setProperty("Bold", isBold);

                      分别为设置单元格:

                      • 竖直居中。
                      • 水平居中。
                      • 文本自动换行。
                      • 单元格合并。
                      • 字体加粗。

                        而如果想获取属性就可以通过 property() 方法,会返回一个 QVariant 对象,可以根据需求通过 toString()、toInt() 等方法转为 Qt 的基本类型。

                        更多相关

                        除了上面提到的,更多的方法可以直接到微软官网查看文档。

                        三、使用要求

                        添加模块

                        在Qt Creator中使用QAxObject需要先在pro中添加:

                        QT += axcontainer

                        包含头文件ActiveQt/QAxObject

                        #include 
                        与excel com连接的方法
                        QAxObject *excel = new QAxObject("Excel.Application"); //!建立excel操作对象,并连接Excel控件excel->dynamicCall("SetVisible (bool Visible)",  "false"); //!  设置为不显示窗体excel->setProperty("DisplayAlerts", false); //! 不显示任何警告信息, 如关闭时的是否保存提示excel->dynamicCall("Quit(void)");  //! 关闭excel程序,操作完后记着关闭,由于是隐藏在后台进程中,不关闭进程会有很多excel.exe。workbook->dynamicCall("Close(Boolean)", false); //! 关闭exce程序先关闭.xls文件
                        Excel基本操作

                        只介绍简单的读写操作,需要修改单元格格式等操作,请"Excel VBA参考手册.chm"

                        excel文件操作

                        获取当前工作簿的集合,这里需要注意,工作簿就是Excel文件。

                        QAxObject *workbooks =  excel->querySubObject("Workbooks"); //! 获取工作簿(excel文件)集合

                        新建一个工作簿,新建一个工作簿就是新建一个Excel文件

                        workbooks->synamicCall("Add"); //新建一个工作簿QAxObject *workbook = excel->querySubObject("ActiveWorkBook"); //! 获取当前工作簿

                        打开一个已有的工作簿,就是打开一个Excel文件

                        QString filename = "e:/123.xlsx";QAxObject* workbook = workbooks->querySubObject("Open(const QString&)", filename);

                        保存工作簿

                        workbook->dynamicCall("Save()");   //!保存文件workbook->dynamicCall("Close(Boolean)", false);  //! 关闭文件 excel->dynamicCall("Quit()"); //! 关闭excel

                        另存为工作簿

                        QDir::toNativeSeparators,将路径中的"/"转换为"\",否则无法保存,"/"只是qt中可以识别workbook->dynamiCall("SaveAs(const QString&)",  QDit::toNativeSeparators(filename));workbook->synamicCall("Close(Boolean)", false); //! 关闭文件excel->dynamicCall("Quit()"); //! 关闭excel

                        Sheet工作表操作

                        获取所有工作表

                        QAxObject *worksheets = workbook->querySubObject("Sheets"):

                        根据序号获取某个工作表,序号顺序就是excel 打开后下方的排序

                        QAxObject *worksheet = worksheets->querySubObejct("Item(int)", 1);

                        获取表中的行数列数

                        QAxObject* usedrange = worksheet->querySubObject("UsedRange"); //!  sheet 范围int intRowStart = usedrange->property("Row").toInt(); //!  起始行数int intColStart = usedrange->property("Column").toInt(); //!  起始列数 QAxObject *rows, *columns;rows = usedrange->querySubObject("Rows"): //! 行 columns = usedrange->querySubObject("Columns"); //! 列int intRow = rows->property("Count").toInt(); //! 行数int intCol = columns->property("Count").toInt();  //!  列数

                        内容操作

                        数据内容操作–获取单元格–基于坐标

                        QAxObject *cell = worksheet->querySubObject("Cells(int, int)", i,  j);

                        数据内容操作–获取单元格–基于行列名称

                        QAxObject *cell = worksheet->querySubObject("Range(QVariant, QVariant)", "A1");

                        数据内容操作–读单元格内容

                        QVariant cell_value = cell->property("Value");

                        数据内容操作-- 写单元格内容

                        cell->setProperty("Value",  "内容");

                        大数据量读取

                        读取所有单元格内容-数据量大,只需要进行一次操作即可读取所有内容,避免重复对每个单元格进行QAxObect操作

                        QVariant var;QAxObject * usedRange = sheet->querySubObject("UseRange"); //! 获取用户区域范围if(NULL == usedRange || usedRange->isNull()){    return  var;}var = usedRange->dynamicCall("Value"); // 读取区域内所有值delete usedRange;

                        此时结果以QVariant保存,需要自行转化为QList

                        QList excel_list;auto rows = var.toList();for(auto row:rows) {    excel_list.append(row.toList());}

                        大数据写入

                        以QList存储,需要限定范围

                        QAxObject *user_rang = this->sheet->querySubObject("Rang(const QString&)", "A1:D100");

                        写入数据

                        rang->setProperty("Value", var); 

                        四、具体使用说明

                        一般我们使用QAxObject操作Excel分为以下的步骤:

                        1. 连接控件Excel
                        2. 打开工作簿(新建或打开Excel文件)
                        3. 打开sheet
                        4. 获取行数,列数
                        5. 读和写
                        6. 设置样式
                        7. 保存文件
                        8. 另存为
                        9. 关闭文件

                        下面我们就具体的说明一下怎么完成上面的操作。

                        1:连接控件Excel2: 打开工作簿(新建或打开Excel文件)3: 打开sheet4: 获取行数,列数5: 读和写6:设置样式7: 保存文件8:另存为9:关闭文件 1:连接控件ExcelQAxObject excel("Excel.Application");//连接Excel控件excel.setProperty("Visible", false);// 不显示窗体excel->setProperty("DisplayAlerts", false);  // 不显示任何警告信息。如果为true, 那么关闭时会出现类似"文件已修改,是否保存"的提示 2: 打开工作簿(新建或打开Excel文件)  QAxObject* workbooks = excel->querySubObject("WorkBooks"); // 获取工作簿集合  2.1新建  workbooks->dynamicCall("Add"); // 新建一个工作簿  QAxObject* workbook = excel->querySubObject("ActiveWorkBook"); // 获取当前工作簿  2.2打开  QAxObject* workbook = workbooks->querySubObject("Open(const QString&)", ("C:/Users/lixc/Desktop/tt2.xlsx"));//Excel文件地址3: 打开sheetQAxObject* worksheet = workbook->querySubObject("WorkSheets(int)", 1); // 获取工作表集合的工作表1, 即sheet14: 获取行数,列数QAxObject* usedrange = worksheet->querySubObject("UsedRange"); // sheet范围    int intRowStart = usedrange->property("Row").toInt(); // 起始行数   为1    int intColStart = usedrange->property("Column").toInt();  // 起始列数 为1     QAxObject *rows, *columns;    rows = usedrange->querySubObject("Rows");  // 行    columns = usedrange->querySubObject("Columns");  // 列     int intRow = rows->property("Count").toInt(); // 行数    int intCol = columns->property("Count").toInt();  // 列数    qDebug()setProperty("Name", QStringLiteral("华文彩云"));  //设置单元格字体       font->setProperty("Bold", true);  //设置单元格字体加粗       font->setProperty("Size", 20);  //设置单元格字体大小       font->setProperty("Italic", true);  //设置单元格字体斜体       font->setProperty("Underline", 2);  //设置单元格下划线       font->setProperty("Color", QColor(255, 0, 0));  //设置单元格字体颜色(红色)6.3合并拆分单元格   QString merge_cell;       merge_cell.append(QChar(3 - 1 + 'A'));  //初始列       merge_cell.append(QString::number(5));  //初始行       merge_cell.append(":");       merge_cell.append(QChar(5 - 1 + 'A'));  //终止列       merge_cell.append(QString::number(8));  //终止行       QAxObject *merge_range = work_sheet->querySubObject("Range(const QString&)", merge_cell);   //merge_range 可以设置单元格属性   merge_range->setProperty("MergeCells", true);  //合并单元格       //merge_range->setProperty("MergeCells", false);  //拆分单元格7: 保存文件7.1保存当前文件(根据已经打开的工作簿,如果工作簿是新建的文件保存默认存储于Document文件夹中) workbook->dynamicCall("Save()");  //保存文件    7.2指定目录存储QString fileName = QFileDialog::getSaveFileName(NULL, QStringLiteral("保存文件"), QStringLiteral("excel名称"), QStringLiteral("EXCEL(*.xlsx)"));    //QString fileName=QStringLiteral("C:/Users/lixc/Desktop/excel名称.xlsx");    workbook->dynamicCall("SaveAs(const QString&)", QDir::toNativeSeparators(fileName)); //保存到filepath    // 注意一定要用QDir::toNativeSeparators, 将路径中的"/"转换为"\", 不然一定保存不了9:关闭文件 workbook->dynamicCall("Close (Boolean)", false);  //关闭文件 excel.dynamicCall("Quit(void)");  //退出 如果excel存在于堆上,注意手动释放 delete excel;注意:调试过程中出现异常:需要打开任务管理器,结束Excle进程//获得单元格对象QAxObject* cell = worksheet->querySubObject("Cells(int, int)", i, j);  

                        五、项目实战

                        在了解了大致的使用步骤后,我们可以通过实际项目来综合运用了。

                        实战项目1

                        项目代码如下:

                        //#include #include #include "mainwindow.h"#include #include #include #include int main(int argc, char *argv[]){    QApplication a(argc, argv);//    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB18030"));//    QTextCodec::setCodecForLocale(QTextCodec::codecForName("GB18030"));//    QTextCodec::setCodecForTr(QTextCodec::codecForName("GB18030"));    QAxWidget excel("Excel.Application");    excel.setProperty("Visible", true);    QAxObject * workbooks = excel.querySubObject("WorkBooks");    if (!workbooks)  return 1;    //错误返回,用 if(!excel)则不行    workbooks->dynamicCall("Open (const QString&)", QString("E:\wenjian\cs\code\QT\testExcel2\test.xlsx"));    QAxObject * workbook = excel.querySubObject("ActiveWorkBook");      //5) 获取活动工作簿:    QAxObject * worksheets = workbook->querySubObject("WorkSheets");    //获取所有的工作表:    int intCount = worksheets->property("Count").toInt();               //获取工作表数量:    qDebug() setProperty("Value", QVariant(intVal+1));       QAxObject * range2 = worksheet->querySubObject("Range(C1)");       intVal = range2->property("Value").toInt();       range2->setProperty("Value", QVariant(intVal+1));    }    QAxObject * worksheet = workbook->querySubObject("Worksheets(int)", 1);    QAxObject * usedrange = worksheet->querySubObject("UsedRange");    QAxObject * rows = usedrange->querySubObject("Rows");    QAxObject * columns = usedrange->querySubObject("Columns");    int intRowStart = usedrange->property("Row").toInt();    int intColStart = usedrange->property("Column").toInt();    int intCols = columns->property("Count").toInt();    int intRows = rows->property("Count").toInt();    qDebug() querySubObject(“Worksheets(int)”, 1);
                      • 获取cell的值:

                        QAxObject * range = worksheet->querySubObject(“Cells(int,int)”, 1, 1 );

                      • 项目代码如下:

                      #include #include #include //#include #include "mainwindow.h"#include int main(int argc, char **argv){    QApplication a(argc, argv);    QAxObject excel("Excel.Application");    excel.setProperty("Visible", false);    QAxObject * workbooks = excel.querySubObject("WorkBooks");    workbooks->dynamicCall("Open (const QString&)", QString("E:\wenjian\cs\code\QT\testExcel3\test.xlsx"));    QAxObject * workbook = excel.querySubObject("ActiveWorkBook");    QAxObject * worksheets = workbook->querySubObject("WorkSheets");    int intCount = worksheets->property("Count").toInt();    QAxObject * worksheet = workbook->querySubObject("Worksheets(int)", 1);    QAxObject * usedrange = worksheet->querySubObject("UsedRange");    QAxObject * rows = usedrange->querySubObject("Rows");    QAxObject * columns = usedrange->querySubObject("Columns");    int intRowStart = usedrange->property("Row").toInt();    int intColStart = usedrange->property("Column").toInt();    int intCols = columns->property("Count").toInt();    int intRows = rows->property("Count").toInt();    qDebug() property("Column").toInt();    // 注意: 这里的行和列都是从1开始计数的    qDebug() property("Count").toInt();    qDebug() querySubObject("Rows");    QAxObject* columns = usedrange->querySubObject("Columns");    qDebug() property("Count").toInt();    qDebug() setProperty("VerticalAlignment", -4108);// left:-4161 center:-4108 right:-4107    cell->setProperty("WrapText", true);// 单元格内容多时自动换行    // cell>dynamicCall("ClearContents()");// 清空单元格内容    // 设置颜色,字体    cell = worksheet->querySubObject("Cells(int, int)", 12, 12);// 获取单元格对象    cell->setProperty("Value", "Text");    QAxObject* interior = cell->querySubObject("Interior");    interior->setProperty("Color", QColor(0, 255, 0));// 背景颜色: Green    QAxObject* border = cell->querySubObject("Borders");    border->setProperty("Color", QColor(0, 0, 255));// 边框颜色: Blue    QAxObject* font = cell->querySubObject("Font");    font->setProperty("Name", QStringLiteral("华文彩云"));    font->setProperty("Bold", true);    font->setProperty("Size", 20);    font->setProperty("Italic", true);    font->setProperty("Underline", 3);// 下划线:2双下划线:3    font->setProperty("Color", QColor(255, 0, 0));// 字体颜色: Red    // 合并拆分单元格    QString merge_cell;    merge_cell.append(QChar('A'+20));// 从第(20+1)列开始,因为'A'表示第一列    merge_cell.append(QString::number(15));// 从第15行开始    merge_cell.append(":");    merge_cell.append(QChar('A'+21));// 到(21+1)列结束    merge_cell.append(QString::number(16));// 到第16列结束    QAxObject* merge_range = worksheet->querySubObject("Range(const QString&)", merge_cell);    merge_range->setProperty("MergeCells", true);// 合并单元格//    merge_range->setProperty("MergeCells", false);// 拆分单元格    // 文件保存    QString fileName = QFileDialog::getSaveFileName(NULL, QStringLiteral("Save File As"), QStringLiteral("Shadow3D"), QStringLiteral("EXCEL(*.xlsx | *.xls)"));    workbook->dynamicCall("SaveAs(conse QString&)", QDir::toNativeSeparators(fileName));    // 关闭文件    workbook->dynamicCall("Close(Boolean)", false);    // 退出excel    excel.dynamicCall("Quit(void)");    // delete excel;// 如果excel是通过new方式建立在堆上,要记得释放。    w.show();    return a.exec();}

                      实战项目4

                      widget.h

                      #ifndef WIDGET_H#define WIDGET_H#include #include QT_BEGIN_NAMESPACEnamespace Ui { class Widget; }QT_END_NAMESPACEclass Widget : public QWidget{    Q_OBJECTpublic:    Widget(QWidget *parent = nullptr);    ~Widget();    void OpenExcel();    void AddNewExcel();    void SaveAndClose();    int GetRowsCount();    QString GetCell(int row, int column);    QString GetCell(QString numer);    void SetCell(int row, int column, QString value);    void SetCell(QString number, QString value);    void SetCellColor(int row, int column, QColor color);private:    Ui::Widget *ui;    QAxObject *m_pExcel;    QAxObject *m_pWorkBooks;    QAxObject *m_pWorkBook;    QAxObject *m_pWorkSheets;    QAxObject *m_pWorkSheet;};#endif // WIDGET_H

                      widget.cpp

                      #include "widget.h"#include "ui_widget.h"#include #include Widget::Widget(QWidget *parent)    : QWidget(parent)    , ui(new Ui::Widget)    , m_pExcel(nullptr)    , m_pWorkBooks(nullptr)    , m_pWorkBook(nullptr)    , m_pWorkSheets(nullptr)    , m_pWorkSheet(nullptr){    ui->setupUi(this);    // 连接excel 控件    m_pExcel = new QAxObject("Excel.Application");    // m_pExcel->setControl("Excel.Applicatio");    // 设置操作excel时不打开excel窗体    m_pExcel->dynamicCall("SetVisible(bool Visible)",false);    // 设置不显示任何警告信息    m_pExcel->setProperty("DisplayAlert",false);}// 打开已有的excelvoid Widget::OpenExcel(){    QString strExcelPath = "C:\Users\Qcx\Desktop\test.xlsx";    // 获取当前工作簿    m_pWorkBooks = m_pExcel->querySubObject("WorkBooks");    // 打开指定工作簿    m_pWorkBook = m_pWorkBooks->querySubObject("Open(const QString&)",strExcelPath);    if(m_pWorkBook)    {        qDebug()querySubObject("Item(int)",1);}// 创建新的Excelvoid Widget::AddNewExcel(){    // 获取当前工作簿    m_pWorkBooks = m_pExcel->querySubObject("WorkBooks");    m_pWorkBooks->dynamicCall("Add");    m_pWorkBook = m_pExcel->querySubObject("ActiveWorkBook");    m_pWorkSheets = m_pWorkBook->querySubObject("Sheets");    m_pWorkSheet = m_pWorkSheets->querySubObject("Item(int)",1);}// 保存并关闭Excelvoid Widget::SaveAndClose(){    QString strSavePath = "C:\Users\Qcx\Desktop\temp.xlsx";    // 保存文件,一定要将路径中的'/'转为'\',前者只能被Qt识别    m_pWorkBook->dynamicCall("SaveAs(const QString&)", QDir::toNativeSeparators(strSavePath));    // 关闭文件    m_pWorkBook->dynamicCall("Close()");    // 关闭excel    m_pExcel->dynamicCall("Quit()");    delete m_pExcel;    m_pExcel = nullptr;}// 获取行数int Widget::GetRowsCount(){    int iRows = 0;    QAxObject *pRows = m_pWorkSheet->querySubObject("Rows");    iRows = pRows->property("Count").toInt();    return  iRows;}// 获取单元格内容,行号+列号QString Widget::GetCell(int row, int column){    QAxObject *pCell = m_pWorkSheet->querySubObject("Range(int, int)", row, column);    return  pCell->property("Value").toString();}// 获取单元格内容,单元格标号如: A1,C5QString Widget::GetCell(QString number){    QAxObject *pCell = m_pWorkSheet->querySubObject("Range(QString)", number);    return  pCell->property("Value").toString();}// 设置单元格内容,行号+列号void Widget::SetCell(int row, int column, QString value){    QAxObject *pCell = m_pWorkSheet->querySubObject("Range(int, int)", row, column);    pCell->setProperty("Value", value);    }// 设置单元格内容,单元格标号如: A1,C5void Widget::SetCell(QString number, QString value){    QAxObject *pCell = m_pWorkSheet->querySubObject("Range(QString)", number);    pCell->setProperty("Value", value);   }// 设置单元格颜色的方式与设置值的方式一样,都是先获取到单元格,再设置属性void Widget::SetCellColor(int row, int column, QColor color){    QAxObject *pCell = m_pWorkSheet->querySubObject("Range(int, int)", row, column);    QAxObject *pInterior = pCell->querySubObject("Interior");    pInterior->setProperty("Color", color);    }Widget::~Widget(){    delete ui;}

                      可能遇到的坑

                      在进行关闭操作时,明明执行没有任何错误,指针也没有异常,但就是Excel进程没有被杀***,我遇到的情况是电脑安装了福昕阅读器,会占用Excel的com接口。有两种解决方案:

                      1、暴力简单,直接卸载福昕阅读器;

                      2、打开Excel --> 选项 --> 加载项 --> 最下方的管理 --> 选中COM加载项 --> 转到 --> 取消FoxitReader PDF Creator COM Add-in。

                      实战项目5-封装好的库

                      简单封装代码

                      头文件 excelmanager.h
                      #ifndef EXCELMANGER_H#define EXCELMANGER_H#include #include #include #include class ExcelManger : public QWidget{    Q_OBJECTpublic:    explicit ExcelManger(QWidget *parent = nullptr);    ~ExcelManger();protected:    static QAxObject *excel;    static QAxObject *workbooks;    static QAxObject *workbook;    static int count;    void new_excel(const QString&);    void open_excel(const QString&);    QString get_cell_value(QAxObject*, int, int);    QVariant get_range(QAxObject*, const QString&);    void set_cell_value(QAxObject*, int, int, const QString&);    void merge_cells(QAxObject*, const QString&);    void set_cell_font_bold(QAxObject *sheet, const QString &cell, bool isBold = true);    void set_cell_font_center(QAxObject *sheet, const QString &cell);    void set_rows_autofit(QAxObject *sheet, const QString &rows);    void set_cols_autofit(QAxObject *sheet, const QString &cols);    void save_excel();    void save_excel_as(const QString&);    void close();    void free_excel();signals:};#endif // EXCELMANGER_H
                      实现文件 excelmanager.cpp
                      #include "excelmanger.h"#include #include #include #include #ifdef Q_OS_WIN#include #endifQAxObject* ExcelManger::excel = nullptr;QAxObject* ExcelManger::workbooks = nullptr;QAxObject* ExcelManger::workbook = nullptr;int ExcelManger::count = 0;ExcelManger::ExcelManger(QWidget *parent) : QWidget(parent){    CoInitializeEx(nullptr, COINIT_MULTITHREADED);    if ((count++) == 0)    {        excel = new QAxObject("Excel.Application", this->parent());        excel->dynamicCall("SetVisible(bool)", false);        workbooks = excel->querySubObject("WorkBooks");    }}ExcelManger::~ExcelManger(){    if ((--count) == 0)        free_excel();}void ExcelManger::new_excel(const QString &path){    workbooks->dynamicCall("Add");    workbook = excel->querySubObject("ActiveWorkBook");    save_excel_as(path);}void ExcelManger::open_excel(const QString &path){    close();    QFile file(path);    if (!file.exists())        new_excel(path);    else        workbook = workbooks->querySubObject("Open(QString&)", path);    file.close();}QString ExcelManger::get_cell_value(QAxObject *sheet, int row, int col){    QAxObject *range = sheet->querySubObject("Cells(int,int)", row, col);    return range->property("Value").toString();}QVariant ExcelManger::get_range(QAxObject *sheet, const QString &range){    return sheet->querySubObject("Range(const QString&)", range)->property("value");}void ExcelManger::set_cell_value(QAxObject *sheet, int row, int col, const QString& value){    QAxObject *range = sheet->querySubObject("Cells(int,int)", row, col);    range->dynamicCall("Value", value);}void ExcelManger::merge_cells(QAxObject *sheet, const QString &cell){    QAxObject *range = sheet->querySubObject("Range(const QString&)", cell);    range->setProperty("VerticalAlignment", -4108);    range->setProperty("WrapText", true);    range->setProperty("MergeCells", true);}void ExcelManger::set_cell_font_bold(QAxObject *sheet, const QString &cell, bool isBold){    QAxObject *range = sheet->querySubObject("Range(const QString&)", cell);    range = range->querySubObject("Font");    range->setProperty("Bold", isBold);}void ExcelManger::set_cell_font_center(QAxObject *sheet, const QString &cell){    QAxObject *range = sheet->querySubObject("Range(const QString&)", cell);    range->setProperty("HorizontalAlignment", -4108);    range->setProperty("VerticalAlignment", -4108);}void ExcelManger::set_rows_autofit(QAxObject *sheet, const QString &rows){    QAxObject *Rows = sheet->querySubObject("Rows(const QString &)", rows);    Rows->dynamicCall("AutoFit()");}void ExcelManger::set_cols_autofit(QAxObject *sheet, const QString &cols){    QAxObject *Cols = sheet->querySubObject("Columns(const QString &)", cols);    Cols->dynamicCall("AutoFit()");}void ExcelManger::save_excel_as(const QString &path){    if (workbook)        workbook->dynamicCall("SaveAs(const QString &)", QDir::toNativeSeparators(path));}void ExcelManger::save_excel(){    if (workbook)        workbook->dynamicCall("Save()");}void ExcelManger::close(){    if (workbook)        workbook->dynamicCall("Close()");}void ExcelManger::free_excel(){    if (excel != nullptr)    {        workbooks->dynamicCall("Close()");        excel->dynamicCall("Quit()");        delete workbook;        delete workbooks;        delete excel;        excel = nullptr;        workbooks = nullptr;        workbook = nullptr;    }}

                      其中现有的功能主要是:

                      • new_excel():按照给定目录创建新表格文件。
                      • open_excel():按照给定目录打开表格文件。
                      • get_cell_value():获取指定工作表中某行某列的单元格值(返回类型为 QString)。
                      • set_cell_value():设置指定工作表中某行某列的单元格值(设置类型为 QString)。
                      • save_excel() 和 save_excel_as():保存文件以及保存为路径。
                      • close() 和 free_excel():关闭文件和 Application。
                      • 以及一些基本的单元格样式设置,更多功能待补充。
                        其他
                        CoInitializeEx(nullptr, COINIT_MULTITHREADED);

                        需要在使用 COM 接口前使用此函数初始化。

                        程序中使用了静态成员,是希望在有多个工作表被操纵的时候,保证后台只有一个 Excel 应用在运行。

                        当然为了实现这一目标,程序也需要保证在使用 ExcelManger 时每个对象能够得到正确的析构。

                        项目实战6-封装好的库

                        exceloperator.h

                        #ifndef EXCELOPERATOR_H#define EXCELOPERATOR_H#include #include #include #include class ExcelOperator : public QObject{    Q_OBJECTpublic:    explicit ExcelOperator(QObject *parent = nullptr);    ~ExcelOperator();    //打开文件    bool open(QString path);    //关闭文件    bool close();    //获取工作表数量    int getSheetsCount();    //根据名称创建工作表    QAxObject* addSheet(QString name);    //根据名称删除工作表    bool delSheet(QString name);    //根据编号删除工作表    bool delSheet(int index);    //根据名称获取工作表    QAxObject* getSheet(QString name);    //根据编号获取工作表    QAxObject* getSheet(int index);    //获取行对象    QAxObject* getRows(QAxObject* pSheet);    //获取行数    int getRowsCount(QAxObject* pSheet);    //获取列对象    QAxObject* getColumns(QAxObject* pSheet);    //获取列数    int getColumnsCount(QAxObject* pSheet);    //根据行列值获取单元格值, 如: 3行,5列    QString getCell(QAxObject* pSheet, int row, int column);    //根据行列编号获取单元格值, 如: "F6"    QString getCell(QAxObject* pSheet, QString number);    //根据行列值设置单元格值    bool setCell(QAxObject* pSheet, int row, int column, QString value);    //根据行列编号设置单元格值    bool setCell(QAxObject* pSheet, QString number, QString value);signals:public slots:private:    QAxObject*      m_pExcel;    QAxObject*      m_pWorksheets;    QAxObject*      m_pWorkbook;    QString         m_strPath;};#endif // EXCELOPERATOR_H

                        exceloperator.c

                        #include "exceloperator.h"#include ExcelOperator::ExcelOperator(QObject *parent) : QObject(parent)  , m_pExcel(NULL)  , m_pWorksheets(NULL)  , m_pWorkbook(NULL){}ExcelOperator::~ExcelOperator(){    close();}bool ExcelOperator::open(QString path){    m_strPath = path;    QAxObject *pWorkbooks = NULL;    CoInitializeEx(NULL, COINIT_MULTITHREADED);    m_pExcel = new(std::nothrow) QAxObject();    if (NULL == m_pExcel) {        qCritical()dynamicCall("SetVisible(bool)", false); //true 表示操作文件时可见,false表示为不可见        m_pExcel->setProperty("DisplayAlerts", false);        pWorkbooks = m_pExcel->querySubObject("WorkBooks");        pWorkbooks->dynamicCall("Add");        m_pWorkbook = m_pExcel->querySubObject("ActiveWorkBook");        qDebug()dynamicCall("Move(QVariant)", pWorkSheet->asVariant());        pWorkSheet->setProperty("Name", name);  //设置工作表名称    } catch (...) {        qCritical()dynamicCall("delete");    } catch (...) {        qCritical()dynamicCall("delete");    } catch (...) {        qCritical()querySubObject("UsedRange");//获取表格中的数据范围    QVariant var = usedRange->dynamicCall("Value");//将所有的数据读取刀QVariant容器中保存    QList excel_list;//用于将QVariant转换为Qlist的二维数组    QVariantList varRows=var.toList();    if(varRows.isEmpty())     {         return;     }    const int row_count = varRows.size();    QVariantList rowData;    for(int i=0;i

上一篇:华为OD机试 - 学生重新排队(Java & JS & Python & C & C++)

下一篇:揭秘,手机轻松查看JSP源代码的方法揭秘!