QT使用QAxObject读取Excel教程

您所在的位置:网站首页 excel对象用法 QT使用QAxObject读取Excel教程

QT使用QAxObject读取Excel教程

2023-03-03 00:14| 来源: 网络整理| 查看: 265

文章目录 一、背景二、介绍基本操作方法获取对象调用动态方法设置和获取属性更多相关 三、使用要求添加模块与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分为以下的步骤:

连接控件Excel打开工作簿(新建或打开Excel文件)打开sheet获取行数,列数读和写设置样式保存文件另存为关闭文件

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

1:连接控件Excel 2: 打开工作簿(新建或打开Excel文件) 3: 打开sheet 4: 获取行数,列数 5: 读和写 6:设置样式 7: 保存文件 8:另存为 9:关闭文件 1:连接控件Excel QAxObject 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: 打开sheet QAxObject* worksheet = workbook->querySubObject("WorkSheets(int)", 1); // 获取工作表集合的工作表1, 即sheet1 4: 获取行数,列数 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_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE class Widget : public QWidget { Q_OBJECT public: 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); } // 打开已有的excel void 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); } // 创建新的Excel void 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); } // 保存并关闭Excel void 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,C5 QString 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,C5 void 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_OBJECT public: 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 #endif QAxObject* 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_OBJECT public: 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


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3