QT uses QAxObject to read Excel tutorial - the most complete network

1. Background

There is no official library for operating Excel in QT. This article introduces the ActiveX object (QAxObject) of the Windows system to operate Excel.

Of course, there are some open source libraries that can be used to operate Excel. For details, see: Some libraries for Qt processing Excel

This article only explains how QAxObject reads Excel.

2. Introduction

First of all, let's explain some concepts first, so that we can understand the basic process of Qt operating excel.
In Qt, QAxObject encapsulates COM objects, QAObject is derived from QAxBase, and QAxBase provides a set of APIs to directly access COM objects through IUnknown pointers. The specific structure is shown in the figure below.

Write picture description here

The Excel we want to operate is also a COM object, so the operation on Excel can be realized in the above-mentioned way.

Before the specific operation, let's take a look at the hierarchical structure of excel, as shown in the figure, Application object –> Workbook object –> Worksheet object –> Range object.
An excel has an Application object, and an Application object consists of multiple workbook objects. These workbook objects are managed by the workbooks object. The workbook object contains several worksheets. These worksheet objects are managed by the worksheets object. The range object under the worksheet , corresponding to the table unit in this worksheet.

Write picture description here

Basic operation method

get object

The above objects generally obtain a sub-object through QAxObjectthe querySubObject()method, for example:

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);

The objects obtained in turn are:

  • An Excel Applicationobject.
  • An object that manages Workbookobjects Workbooks.
  • pathThe object corresponding to the Excel file whose path is Workbook.
  • The object that manages the worksheets within Sheetit Sheets.
  • The object corresponding to the first worksheet Sheet.
  • The object of the table cell at row rowand column .colrange

call dynamic method

You can also dynamicCall()call some actions through the method, such as:

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

This is the call to save as pathpath.

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

This is called save.

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

This sets the value of the cell.

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

This is set to be invisible when Excel is opened (that is, in the background).

workbooks->dynamicCall("Add");

This is to create a new Excel file.

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

This is closing the Excel application.

In addition, there are many similar methods.

Set and get properties

Generally setProperty()set properties through the method, such as:

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

Set up the cells respectively:

  • Center vertically.
  • Centered horizontally.
  • Text wraps automatically.
  • Cells are merged.
  • The font is bold.

And if you want to get attributes, you can use property()the method, which will return an QVariantobject, which can be converted to the basic type of Qt through methods such as toString(), toInt()etc. according to your needs.

More related

In addition to the above mentioned, more methods can go directly to Microsoft's official website to view documents .

3. Requirements for use

add module

To use QAxObject in Qt Creator, you need to add in pro first:
QT += axcontainer

Include the header file ActiveQt/QAxObject

#include <QAxObject>

How to connect with 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文件

Basic operation of Excel

Only simple read and write operations are introduced, and operations such as modifying the cell format are required, please refer to "Excel VBA Reference Manual.chm"

Excel file operation

Get the collection of the current workbook. It should be noted here that the workbook is an Excel file.

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

Create a new workbook , create a new workbook is to create a new Excel file

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

To open an existing workbook is to open an Excel file

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

save workbook

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

save as workbook

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

Sheet worksheet operation

get all worksheets

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

Get a certain worksheet according to the serial number , the serial number order is the sorting at the bottom after excel is opened

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

Get the number of rows and columns in the table

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();  //!  列数

content manipulation

Data Content Manipulation – Get Cell – Based on Coordinates

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

Data content operation – get cell – based on row and column names

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

Data content manipulation – read cell content

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

Data content operation -- write cell content

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

Large amount of data read

Read all cell content - the amount of data is large, only one operation is required to read all the content, avoiding repeated QAxObect operations on each cell

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

At this time, the result is saved in QVariant, which needs to be converted into QList<QList> by itself

QList<QList<QVariant>> excel_list;
auto rows = var.toList();

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

big data writing

Stored in QList<QList>, need to limit the range

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

data input

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

4. Specific instructions for use

Generally, we use QAxObject to operate Excel into the following steps:

  1. Connect ControlExcel
  2. Open workbook (new or open Excel file)
  3. open sheet
  4. Get the number of rows and columns
  5. read and write
  6. set style
  7. save document
  8. Save as
  9. close file

Next, we will explain in detail how to complete the above operation.

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()<<"intRowStart:"<<intRowStart<<"\t intColStart"<<intColStart;
    qDebug()<<"intRow"<<intRow<<"\t intCol"<<intCol;

5: 读和写
	5.1读取单元格方式1
	for(int i=intRowStart;i<intRow+intRowStart;i++)
    {
        for(int j=intColStart;j<intCol+intColStart;j++)
        {
            QAxObject* cell = worksheet->querySubObject("Cells(int, int)", i, j);  //获单元格值
            qDebug() << i << j << cell->dynamicCall("Value2()").toString();
        }
    }

	5.2读取单元格方式2
	QString X = "A2"; //设置要操作的单元格,A1
    QAxObject* cellX = worksheet->querySubObject("Range(QVariant, QVariant)", X); //获取单元格
    qDebug() << cellX->dynamicCall("Value2()").toString();

	5.3写单元格方式1
	cellX->dynamicCall("SetValue(conts QVariant&)", 100); // 设置单元格的值

	5.4写单元格方式2
	QAxObject *cell_5_6 = worksheet->querySubObject("Cells(int,int)", 5, 6);
    cell_5_6->setProperty("Value2", "Java");

6:设置样式(未测试)
	//获得单元格对象
	QAxObject* cell = worksheet->querySubObject("Cells(int, int)", i, j);  
	6.1设置单元格内容的显示setProperty()
	   cell->setProperty("Value", "Java C++ C# PHP Perl Python Delphi Ruby");  //设置单元格值
	   cell->setProperty("RowHeight", 50);  //设置单元格行高
	   cell->setProperty("ColumnWidth", 30);  //设置单元格列宽
	   cell->setProperty("HorizontalAlignment", -4108); //左对齐(xlLeft):-4131  居中(xlCenter):-4108  右对齐(xlRight):-4152
	   cell->setProperty("VerticalAlignment", -4108);  //上对齐(xlTop)-4160 居中(xlCenter):-4108  下对齐(xlBottom):-4107
	   cell->setProperty("WrapText", true);  //内容过多,自动换行
	   cell->dynamicCall("ClearContents()");  //清空单元格内容

	6.2设置单元格的样式	QAxObject* interior = cell->querySubObject("Interior");
	   QAxObject* interior = cell->querySubObject("Interior");
	   interior->setProperty("Color", QColor(0, 255, 0));   //设置单元格背景色(绿色)
       QAxObject* border = cell->querySubObject("Borders");
       border->setProperty("Color", QColor(0, 0, 255));   //设置单元格边框色(蓝色)
       QAxObject *font = cell->querySubObject("Font");  //获取单元格字体
       font->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);  

5. Project actual combat

After understanding the general steps of use, we can use it comprehensively through actual projects.

Practical project 1

The project code is as follows:

//#include <QtGui/QApplication>
#include <QApplication>
#include "mainwindow.h"
#include <QAxObject>
#include <QAxWidget>
#include <QTextCodec>
#include <QtDebug>

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() << "工作表数量" << intCount;
    for (int i = 1; i <= intCount; i++)
    {
       int intVal;
       QAxObject * worksheet = workbook->querySubObject("Worksheets(int)", i);     //获取第i个工作表:
       qDebug() << i << worksheet->property("Name").toString();
       QAxObject * range = worksheet->querySubObject("Cells(1,1)");    //获取cell的值:
       intVal = range->property("Value").toInt();
       range->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() << "表格行数" << intRows;
    qDebug() << "表格列数" << intCols;
//    for (int i = intRowStart; i < intRowStart + intRows; i++)
//    {
//       for (int j = intColStart; j <= intColStart + intCols; j++)
//       {
//           QAxObject * range = worksheet->querySubObject("Cells(int,int)", i, j );
//           qDebug() << i << j << range->dynamicCall("Value2()").toString();  //property("Value");不行
//       }
//    }

    for (int i = intRowStart; i < intRows; i++)
    {
       for (int j = intColStart; j < intCols; j++)
       {
           QAxObject * range = worksheet->querySubObject("Cells(int,int)", i, j );
           qDebug() << i << j << range->dynamicCall("Value2()").toString();  //property("Value");不行
       }
    }

    excel.setProperty("DisplayAlerts", 0);
    //qDebug("here?");
    workbook->dynamicCall("SaveAs (const QString&)", QString("E:\\wenjian\\cs\\code\\QT\\testExcel2\\temp.xls"));//这里只能用相对路径!!!用绝对路径就报下面的错误。
    excel.setProperty("DisplayAlerts", 1);
    workbook->dynamicCall("Close (Boolean)", false);
    excel.dynamicCall("Quit (void)");

    MainWindow w;
    w.show();
    return a.exec();
}

The contents of test.xlsx are as follows:

[External link image transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the image and upload it directly (img-VWR6lCEv-1677385787835) (C:\Users\10521\AppData\Roaming\Typora\typora-user-images\ image-20230226101051423.png)]

Executing the code will print the following information:

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-ZMXaMuYv-1677385787836) (C:\Users\10521\AppData\Roaming\Typora\typora-user-images\ image-20230226101140437.png)]

Explain that the code reads and prints the contents of the Excel table.

Practical project 2

The specific operation process is as follows:

QAxWidget excel(“Excel.Application”);

  1. Show current window:
    excel.setProperty(“Visible”, true);
  2. Change the Excel title bar:
    excel.setProperty(“Caption”, “Invoke Microsoft Excel”);
  3. Add new workbook:
    QAxObject * workbooks = excel.querySubObject(“WorkBooks”);
    workbooks->dynamicCall(“Add”);
  4. Open an existing workbook:
    workbooks->dynamicCall(“Open (const QString&)”, QString(“c:/test.xls”));
  5. Get the active workbook:
    QAxObject * workbook = excel.querySubObject(“ActiveWorkBook”);
  6. Get all worksheets:
    QAxObject * worksheets = workbook->querySubObject(“WorkSheets”);
  7. Get the number of worksheets:
    int intCount = worksheets->property(“Count”).toInt();
  8. Get the first worksheet:
    QAxObject * worksheet = workbook->querySubObject(“Worksheets(int)”, 1);
  9. Get the value of the cell:
    QAxObject * range = worksheet->querySubObject(“Cells(int,int)”, 1, 1 );

The project code is as follows:

#include <QApplication>
#include <QDir>
#include <QDebug>
//#include <QAxBase>
#include "mainwindow.h"
#include <QAxObject>

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() << "开始行数" << intRowStart;
    qDebug() << "开始列数" << intColStart;
    qDebug() << "总行数" << intRows;
    qDebug() << "总列数" << intCols;

    for (int i = intRowStart; i < intRowStart + intRows; i++)
    {
        for (int j = intColStart; j < intColStart + intCols; j++)
        {
            QAxObject * range = worksheet->querySubObject("Cells(int,int)", i, j );
            qDebug() << i << j << range->property("Value");
        }
    }
    excel.setProperty("DisplayAlerts", 0);
    workbook->dynamicCall("SaveAs (const QString&)", QDir::toNativeSeparators("E:\\wenjian\\cs\\code\\QT\\testExcel3\\temp.xlsx"));
    excel.setProperty("DisplayAlerts", 1);
    workbook->dynamicCall("Close (Boolean)", false);
    excel.dynamicCall("Quit (void)");
    return a.exec();
}

The Excel file to be operated is consistent with that in the actual combat project 1.

Execute the code to print information as follows:

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-OIat4Y1r-1677385787836) (C:\Users\10521\AppData\Roaming\Typora\typora-user-images\ image-20230226102643579.png)]

Practical project 3

code show as below:

// 参考内容: 	https://blog.csdn.net/qq319923400/article/details/80149367
//			    https://www.cnblogs.com/lifexy/p/10743316.html
//			    https://www.cnblogs.com/lifexy/p/10743352.html

#include "widget.h"

#include <QApplication>
#include <QAxObject>		// .pro需要添加: QT += axcontainer
#include <QFileDialog>
#include <QDebug>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;

    QAxObject excel("Excel.Application");		// 关联excel
    excel.setProperty("Visible", true);			// 运行程序时要不要通过excel打开当前编辑的表格
    excel.setProperty("DisplayAlerts", false);		// excel关闭时是否询问要不要保存
    //excel.setProperty("Caption", "Qt Excel");		// 类似于文件类型吧,感觉这个名称意义不大

    QAxObject* workbooks = excel.querySubObject("WorkBooks");
    workbooks->dynamicCall("Add");			// 增加一个excel表格,写两遍会打开两个不同的excel表格
    QAxObject* workbook = excel.querySubObject("ActiveWorkBook");
    QAxObject* worksheet = workbook->querySubObject("WorkSheets(QString)", "Sheet1");  	// 通过sheet名获取sheet1
    // QAxObject* worksheet = workbook->querySubObject("WorkSheets(int)", "1");  	// 通过编号获取sheet1, 结果和上面一样
    worksheet->setProperty("Name", "Shadow3D_1");			// 修改sheet名

    // 行列相关查询
    QAxObject* usedrange = worksheet->querySubObject("UsedRange");
    int intRowStart = usedrange->property("Row").toInt();
    int intColStart = usedrange->property("Column").toInt();
    // 注意: 这里的行和列都是从1开始计数的
    qDebug() << "intRowStart: " << intRowStart << "\tintColStart: " << intColStart;

    // 查看已经使用的最大行数和最大列数
    int intRow = usedrange->querySubObject("Rows")->property("Count").toInt();
    int intCol = usedrange->querySubObject("Columns")->property("Count").toInt();
    qDebug() << "Rows: " << intRow << "\tColumns: " << intCol;

    // 写单元格
    for(int i = 1; i < 10; i++)
        for(int j = 1; j < 10; j++)
            worksheet->querySubObject("Cells(int, int)", i, j)->setProperty("Value2", i+j);

    // 查看已经使用的最大行数和最大列数
    usedrange = worksheet->querySubObject("UsedRange");			// 当重新修改sheet后,必须重新获取UsedRange值才能得到最新的行数和列数。
    QAxObject* rows = usedrange->querySubObject("Rows");
    QAxObject* columns = usedrange->querySubObject("Columns");
    qDebug() << rows << columns;				// 不知道这个rows和columns的值表示什么意义,每次运行都不一样。。。
    intRow = rows->property("Count").toInt();
    intCol = columns->property("Count").toInt();
    qDebug() << "Rows: " << intRow << "\tColumns: " << intCol;

    // 读单元格
    QAxObject* cell = worksheet->querySubObject("Cells(int, int)", 5, 5);	// 获取单元格对象
    QString cellStr = cell->dynamicCall("Value2()").toString();
    qDebug() << "cell: " << cellStr;					// "10"
    qDebug() << "cell: " << cellStr.toUtf8().data();	// 10	( QString 类型转换为 QByteArray,再转换成Char* )

    // 单元格格式
    cell = worksheet->querySubObject("Cells(int, int)", 11, 11);
    cell->setProperty("Value", "bool setProperty(const char *name, const QVariant &value");
    cell->setProperty("RowHeight", 50);
    cell->setProperty("ColumnWidth", 30);
    cell->setProperty("HorizontalAlignment", -4108);	// left:-4131 center:-4108 right:-4152
    cell->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();
}

Combat Item 4

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <ActiveQt/QAxObject>

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 <QDebug>
#include <QDir>

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()<<"Open Excel Success!";
    }

    // 获取sheets
    m_pWorkSheets = m_pWorkBook->querySubObject("Sheets");
    // 获取某个sheet
    m_pWorkSheet = m_pWorkSheets->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;
}

pits that may be encountered

When the shutdown operation was performed, there was obviously no error in the execution, and the pointer was not abnormal, but the Excel process was not killed. The situation I encountered was that the computer installed Foxit Reader, which would occupy the COM interface of Excel. There are two solutions:
1. Violent and simple, uninstall Foxit Reader directly;
2. Open Excel --> Options --> Add-Ins --> Management at the bottom --> Select COM Add-Ins --> Go to --> Uncheck FoxitReader PDF Creator COM Add-in.

Practical project 5-encapsulated library

Simple package code

head Fileexcelmanager.h

#ifndef EXCELMANGER_H
#define EXCELMANGER_H

#include <QWidget>
#include <QString>
#include <QAxObject>
#include <QDialog>

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

implementation fileexcelmanager.cpp

#include "excelmanger.h"
#include <QDebug>
#include <QVariant>
#include <QFile>
#include <QDir>
#ifdef Q_OS_WIN
#include <windows.h>
#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;
    }
}

Among the existing functions are mainly:

  • new_excel(): Create a new table file according to the given directory.
  • open_excel(): Open the table file according to the given directory.
  • get_cell_value(): Get the cell value of a row and a column in the specified worksheet (the return type is QString).
  • set_cell_value(): Set the cell value of a row and a column in the specified worksheet (the setting type is QString).
  • save_excel()and save_excel_as(): save the file and save as path.
  • close()and free_excel(): close the file and Application.
  • And some basic cell style settings, more functions to be added.

other

CoInitializeEx(nullptr, COINIT_MULTITHREADED);

It needs to COMbe initialized with this function before using the interface .

Static members are used in the program to ensure that only one Excel application is running in the background when multiple worksheets are manipulated.

Of course, in order to achieve this goal, the program also needs to ensure that each object can be correctly destructedExcelManger when it is used .

Project combat 6-encapsulated library

exceloperator.h

#ifndef EXCELOPERATOR_H
#define EXCELOPERATOR_H

#include <QObject>
#include <ActiveQt/QAxObject>
#include <QDebug>
#include <QDir>

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 <objbase.h>

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()<<"创建Excel对象失败...";
        return false;
    }
    try {
        m_pExcel->setControl("Excel.Application");
        m_pExcel->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()<<"excel path: "<<m_strPath;

        // 获取打开的excel文件中所有的工作sheet
        m_pWorksheets = m_pWorkbook->querySubObject("WorkSheets");
    } catch (...) {
        qCritical()<<"打开文件失败...";
        return false;
    }

    return true;
}

bool ExcelOperator::close()
{
    qDebug()<<"excel close...";
    if (m_pExcel)
    {
        qDebug()<<"closing...";
        m_pWorkbook->dynamicCall("SaveAs(const QString&)", QDir::toNativeSeparators(m_strPath));
        m_pWorkbook->dynamicCall("Close()");
        m_pExcel->dynamicCall("Quit()");
        delete m_pExcel;
        m_pExcel = NULL;
    }
    return true;
}

int ExcelOperator::getSheetsCount()
{
    int count =  0;
    count = m_pWorksheets->property("Count").toInt();
    return count;
}


QAxObject* ExcelOperator::addSheet(QString name)
{
    QAxObject *pWorkSheet = NULL;
    try {
        int count = m_pWorksheets->property("Count").toInt();  //获取工作表数目
        QAxObject *pLastSheet = m_pWorksheets->querySubObject("Item(int)", count);
        pWorkSheet = m_pWorksheets->querySubObject("Add(QVariant)", pLastSheet->asVariant());
        pLastSheet->dynamicCall("Move(QVariant)", pWorkSheet->asVariant());
        pWorkSheet->setProperty("Name", name);  //设置工作表名称
    } catch (...) {
        qCritical()<<"创建sheet失败...";
    }
    return pWorkSheet;
}

bool ExcelOperator::delSheet(QString name)
{
    try {
        QAxObject *pFirstSheet = m_pWorksheets->querySubObject("Item(QString)", name);
        pFirstSheet->dynamicCall("delete");
    } catch (...) {
        qCritical()<<"删除sheet失败...";
        return false;
    }
    return true;
}

bool ExcelOperator::delSheet(int index)
{
    try {
        QAxObject *pFirstSheet = m_pWorksheets->querySubObject("Item(int)", index);
        pFirstSheet->dynamicCall("delete");
    } catch (...) {
        qCritical()<<"删除sheet失败...";
        return false;
    }
    return true;
}

QAxObject* ExcelOperator::getSheet(QString name)
{
    QAxObject* pWorkSheet = NULL;
    try {
        pWorkSheet = m_pWorksheets->querySubObject("Item(QString)", name);
    } catch (...) {
        qCritical()<<"获取sheet失败...";
    }
    return pWorkSheet;
}

QAxObject* ExcelOperator::getSheet(int index)
{
    QAxObject* pWorkSheet = NULL;
    try {
        pWorkSheet = m_pWorksheets->querySubObject("Item(int)", index);
    } catch (...) {
        qCritical()<<"获取sheet失败...";
    }
    return pWorkSheet;
}

QAxObject* ExcelOperator::getRows(QAxObject* pSheet)
{
    QAxObject* pRows = NULL;
    try {
        pRows = pSheet->querySubObject("Rows");
    } catch (...) {
        qCritical()<<"获取行失败...";
    }
    return pRows;
}

int ExcelOperator::getRowsCount(QAxObject* pSheet)
{
    int rows = 0;
    try {
        QAxObject* pRows = getRows(pSheet);
        rows = pRows->property("Count").toInt();
    } catch (...) {
        qCritical()<<"获取行数失败...";
    }
    return rows;
}

QAxObject* ExcelOperator::getColumns(QAxObject* pSheet)
{
    QAxObject* pColumns = NULL;
    try {
        pColumns = pSheet->querySubObject("Columns");
    } catch (...) {
        qCritical()<<"获取列失败...";
    }
    return pColumns;
}

int ExcelOperator::getColumnsCount(QAxObject* pSheet)
{
    int columns = 0;
    try {
        QAxObject* pColumns = getColumns(pSheet);
        columns = pColumns->property("Count").toInt();
    } catch (...) {
        qCritical()<<"获取列数失败...";
    }
    return columns;
}

QString ExcelOperator::getCell(QAxObject* pSheet, int row, int column)
{
    QString strCell = "";
    try {
        QAxObject* pCell = pSheet->querySubObject("Cells(int, int)", row, column);
        strCell = pCell->property("Value").toString();
    } catch (...) {
        qCritical()<<"获取单元格信息失败...";
    }

    return strCell;
}

QString ExcelOperator::getCell(QAxObject* pSheet, QString number)
{
    QString strCell = "";
    try {
        QAxObject* pCell = pSheet->querySubObject("Range(QString)", number);
        strCell = pCell->property("Value").toString();
    } catch (...) {
        qCritical()<<"获取单元格信息失败...";
    }

    return strCell;
}

bool ExcelOperator::setCell(QAxObject* pSheet, int row, int column, QString value)
{
    try {
        QAxObject* pCell = pSheet->querySubObject("Cells(int, int)", row, column);
        pCell->setProperty("Value", value);
    } catch (...) {
        qCritical()<<"写入单元格信息失败...";
        return false;
    }
    return true;
}

bool ExcelOperator::setCell(QAxObject* pSheet, QString number, QString value)
{
    try {
        QAxObject* pCell = pSheet->querySubObject("Range(QString)", number);
        pCell->setProperty("Value", value);
    } catch (...) {
        qCritical()<<"写入单元格信息失败...";
        return false;
    }
    return true;
}

Six, some tips

read data in excel

I said before how to save the data in Qt to excel, now let’s talk about how to read the data in excel to Qt (whether it is read into a table or saved into a data model, the core point is to convert excel The data in the container is read into the Qt container, and then as long as the data in the container can be read, it is very simple to save it to the table or the model later).

Suppose we already have such an excel sheet saved by Qt, and now we want to read the data in it

img

code show as below:

void Widget::on_readbtn_clicked()
{
    QAxObject *excel = new QAxObject(this);//建立excel操作对象
    excel->setControl("Excel.Application");//连接Excel控件
    excel->setProperty("Visible", false);//显示窗体看效果,选择ture将会看到excel表格被打开
    excel->setProperty("DisplayAlerts", true);//显示警告看效果
    QAxObject *workbooks = excel->querySubObject("WorkBooks");//获取工作簿(excel文件)集合
    QString str = QFileDialog::getOpenFileName(this,"打开",
                                                    QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation),"Excel 文件(*.xls *.xlsx)");
    workbooks->dynamicCall("Open(const QString&)", str);//打开刚才选定的excel
    QAxObject *workbook = excel->querySubObject("ActiveWorkBook");
    QAxObject *worksheet = workbook->querySubObject("WorkSheets(int)",1);
    QAxObject *usedRange = worksheet->querySubObject("UsedRange");//获取表格中的数据范围

    QVariant var = usedRange->dynamicCall("Value");//将所有的数据读取刀QVariant容器中保存
    QList<QList<QVariant>> 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<row_count;++i)
    {
        rowData = varRows[i].toList();
        excel_list.push_back(rowData);
    }//转换完毕
    qDebug()<<excel_list.at(3).at(1).toInt();
 
    //然后将二维数组Qlist<Qlist<QVariant>>中的数据读取出来,到表格或者数据模型中,具体在这里过程省略
    
    workbook->dynamicCall( "Close(Boolean)", false );
    excel->dynamicCall( "Quit(void)" );
    delete excel;//因为前面选择了不显示excel窗口,如果这里不删除excel的话,excel依然是打开的,只是我们看不见(因为被隐藏起来了)
}

The line of code marked in red can be used to test whether the data in the two-dimensional array can be successfully read.

When qDebug()<<excel_list.at(3); is entered, the printed result isimg

Because there are a total of 24 columns in excel, but only 6 rows have data, so you can see that this is actually the data in the 4th row of the table (because it starts from zero 0, 1, 2, 3) all read out .

When qDebug()<<excel_list.at(3).at(3); is input, the printed result is

img

img

That is, the data in row 4 and column 4 is printed out.

When entering qDebug()<<excel_list.at(3).at(3).toInt();, the printed result is the number 3.

As a result, the work of reading excel is basically completed. As for how to save it in the form or model, it depends on your preference.

*Tips: Since the data saved in excel is read into the Qlist array, it is not necessarily a regular two-dimensional array, so if necessary, the first and second rows of excel can be reserved for saving information, these The information can be used to judge what rules to read when reading.

Guess you like

Origin blog.csdn.net/qq_41854911/article/details/129225457