1.使用QAxObject读写Excel
QAxObject类提供了一个包裹COM对象的QObject。
 QAxObject可以被实例化为一个空的对象,用它应该包裹的COM对象的名字,或者用一个指向代表现有COM对象的IUnknown的指针。如果COM对象实现了IDispatch接口,该对象的属性、方法和事件就可以作为Qt属性、槽和信号使用。基类,QAxBase,提供了一个API,可以通过IUnknown指针直接访问COM对象。
 QAxObject是一个QObject,并可以作为QObject使用,例如,它可以被组织在一个对象的层次结构中,接收事件并连接到信号和槽。
 QAxObject也从QAxBase继承了大部分与ActiveX相关的功能,特别是dynamicCall()和querySubObject()。
 警告。你可以对QAxObject进行子类化,但是你不能在子类中使用Q_OBJECT宏(生成的moc-file将不会被编译),所以你不能进一步添加信号、槽或属性。这个限制是由于在运行时生成的元对象信息造成的。为了解决这个问题,将QAxObject聚合为QObject子类的一个成员。
 也请参见QAxBase、QAxWidget、QAxScript和ActiveQt Framework。
下面是示例代码:
excelopt.h
#ifndef EXCELOPT_H
#define EXCELOPT_H
#include <QObject>
#include <QAxObject>
#include <Windows.h>
class ExcelOpt : public QObject
{
    Q_OBJECT
public:
    explicit ExcelOpt(QObject *parent = nullptr);
    ~ExcelOpt();
    bool open(const QString &fileName);
    bool save();
    bool saveAs(const QString &fileName);
    void close();
    QVariant read(int row, int column);
    bool write(int row, int column, const QVariant &value);
signals:
public slots:
    void slots_exception(int code, const QString &source, const QString &desc, const QString &help);
private:
    QAxObject *m_excel;
    QAxObject *m_workbooks;
    QAxObject *m_workbook;
    QAxObject *m_worksheets;
    QAxObject *m_worksheet;
};
#endif // EXCELOPT_H
excelopt.cpp
#include "excelopt.h"
#include <QDebug>
ExcelOpt::ExcelOpt(QObject *parent) : QObject(parent)
{
    m_excel = NULL;
    m_workbooks = NULL;
    m_workbook = NULL;
    m_worksheets = NULL;
    m_worksheet = NULL;
    CoInitializeEx(NULL, COINIT_MULTITHREADED);
    //HRESULT result = OleInitialize(nullptr);   //换成CoInitialize似乎也是一样的
    //if (result != S_OK && result != S_FALSE)
    //{
    //    qDebug()<<QString("Could not initialize OLE (error %x)").arg(static_cast<unsigned int>(result));
    //}
    // 创建一个新的Excel应用程序
    //m_excel = new QAxObject("Excel.Application");
    
    m_excel = new QAxObject(this);    //连接Excel控件
	if (m_excel->setControl("Excel.Application"))
	{
	}
	else
	{
        m_excel->setControl("ket.Application");  //连接Excel控件
	}
    m_excel->setProperty("Visible", false);  //不显示窗体
    
    
    connect(m_excel, SIGNAL(exception(int, const QString &, const QString &, const QString &)), this, SLOT(slots_exception(int, const QString &, const QString &, const QString &)));
    // 获取所有工作簿
    m_workbooks = m_excel->querySubObject("Workbooks");
}
ExcelOpt::~ExcelOpt()
{
    // 关闭所有工作簿
    m_workbooks->dynamicCall("Close()");
    // 关闭Excel应用程序
    m_excel->dynamicCall("Quit()");
    delete m_worksheet;
    delete m_worksheets;
    delete m_workbook;
    delete m_workbooks;
    delete m_excel;
    OleUninitialize();
}
bool ExcelOpt::open(const QString &fileName)
{
    // 如果工作簿已打开,则先关闭它
    if (m_workbook) {
        m_workbook->dynamicCall("Close()");
        delete m_worksheet;
        delete m_worksheets;
        delete m_workbook;
    }
    // 打开指定的工作簿
    m_workbook = m_workbooks->querySubObject("Open(const QString&)", fileName);
    if (!m_workbook)
        return false;
    // 获取所有工作表
    m_worksheets = m_workbook->querySubObject("Worksheets");
    if (!m_worksheets)
        return false;
    // 获取第一个工作表
    m_worksheet = m_worksheets->querySubObject("Item(int)", 1);
    if (!m_worksheet)
        return false;
    return true;
}
bool ExcelOpt::save()
{
    if (!m_workbook)
        return false;
    // 保存工作簿
    return m_workbook->dynamicCall("Save()").toBool();
}
bool ExcelOpt::saveAs(const QString &fileName)
{
    if (!m_workbook)
        return false;
    // 将工作簿另存为指定的文件
    return m_workbook->dynamicCall("SaveAs(const QString&)", fileName).toBool();
}
void ExcelOpt::close()
{
    if (m_workbook) {
        // 关闭工作簿
        m_workbook->dynamicCall("Close()");
        delete m_worksheet;
        delete m_worksheets;
        delete m_workbook;
        m_worksheet = nullptr;
        m_worksheets = nullptr;
        m_workbook = nullptr;
    }
}
QVariant ExcelOpt::read(int row, int column)
{
    if (!m_worksheet)
        return QVariant();
    // 读取指定单元格的值
    return m_worksheet->querySubObject("Cells(int,int)", row, column)->dynamicCall("Value()");
}
bool ExcelOpt::write(int row, int column, const QVariant &value)
{
    if (!m_worksheet)
        return false;
    // 写入指定单元格的值
    m_worksheet->querySubObject("Cells(int,int)", row, column)->setProperty("Value2", value);
    return true;
}
void ExcelOpt::slots_exception(int code, const QString &source, const QString &desc, const QString &help)
{
}
main.cpp
#include "QtWidgetsApplication1.h"
#include <QtWidgets/QApplication>
#include "excelopt.h"
#include <QDebug>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
	ExcelOpt objExcel;
	objExcel.open("C:\\Users\\roson\\Desktop\\test.xlsx");
	qDebug() << objExcel.read(1, 1).toString();
	objExcel.write(5, 2, QString("roson"));
	qDebug() << "write finish";
	objExcel.save();
    QtWidgetsApplication1 w;
    w.show();
    return a.exec();
}

1.1 注意事项(非常重要)
(1)
运行上面的代码的时候,很可能会出现运行异常,错误信息的格式如下:
QAxBase: Error calling IDispatch member SaveAs: Exception thrown by server
 Code : -2146827284
  Source : Microsoft Excel
  Description: Microsoft Excel ???D://24ED7000?? ???:
  Help : xlmain11.chm
  
其中“Code”的值会因为错误类型的不同而不同,可以去网上查阅这个错误代码所指代的含义。
上面这个错误代码“-2146827284”一般是因为Excel表格文件的路径不对造成的,我们在传参时,一定要用文件的绝对路径,这样就可以有效的避免上面的错误,切记!!!
(2)
如果在程序运行时,报错QAxBase: Error calling IDispatch member ActiveSheet: Unknown error,或者Excel表格突然弹出激活、许可协议等界面,则说明你的office没有激活,用激活工具激活office后就好了
(3)
有的人会出现读取Excel内容可以成功,但是在写入数据的时候遇到了问题,写进去的东西为空。经过排查是因为office和wps的原因,主要是property的Value值的问题。
office支持的是
setProperty("Value", value)
 然而要在装有wps中写入成功就需要把value属性改为Value2
setProperty("Value2", value)    Value2 wps 和 office中都可以使用。
  
(4)
使用QtCreator时,我们要使用QAxObject,是需要在.pro文件中添加: QT += axcontainer,使用VS开发时,也需要添加这个模块,否则编译不过的。
2.Qt Xlsx插件
QtXlsx是一个可以读取和写入Excel文件的第三方库。它不需要Microsoft Excel,可以在Qt5支持的任何平台上使用。该库可以用来:
 (1)创建一个新的.xlsx文件
 (2)读取.xlsx文件内容
 (3)往.xlsx文件写入内容
官网:http://qtxlsx.debao.me/

















![[附源码]Nodejs计算机毕业设计基于JAVA快递配送平台Express(程序+LW)](https://img-blog.csdnimg.cn/e0bfad53589c4646a9ed508f9ad3206f.png)


