Qt对Excel的数据读/写操作没有现存的类,需要使用QAxObject,下面是从网上下载下来的一个封装好的类,感觉还可以,一般情况下够用,拿来给大家分享。

头文件:

#ifndef EXCELENGINE_H
#define EXCELENGINE_H #include <QObject>
#include <QFile>
#include <QString>
#include <QStringList>
#include <QVariant>
#include <QAxBase>
#include <QAxObject>
#include <QTableWidget>
#include <QTableView>
#include <QTableWidgetItem>
#include <QDebug>
typedef unsigned int UINT;
/**
*@brief 这是一个便于Qt读写excel封装的类,同时,便于把excel中的数据
*显示到界面上,或者把界面上的数据写入excel中,同GUI进行交互,关系如下:
*Qt tableWidget <--> ExcelEngine <--> xls file.
*
*@note ExcelEngine类只负责读/写数据,不负责解析,做中间层
*@author yaoboyuan 254200341@qq.com
*@date 2012-4-12
*/
class ExcelEngine : protected QObject
{
public:
ExcelEngine();
ExcelEngine(QString xlsFile);
~ExcelEngine();
public:
bool Open(UINT nSheet = 1,bool visible = false); //打开xls文件
bool Open(QString xlsFile,UINT nSheet = 1,bool visible = false);
void Save(); //保存xls报表
void Close(); //关闭xls报表
bool SaveDataFrTable(QTableWidget* tableWidget); //保存数据到xls
bool ReadDataToTable(QTableWidget* tableWidget); //从xls读取数据到ui
QVariant GetCellData(UINT row,UINT column); //获取指定单元数据
bool SetCellData(UINT row,UINT column,QVariant data); //修改指定单元数据
    UINT GetRowCount()const;
UINT GetColumnCount()const;
    bool IsOpen();
bool IsValid();
protected:
void Clear();
private:
QAxObject *pExcel; //指向整个excel应用程序
QAxObject *pWorkbooks; //指向工作簿集,excel有很多工作簿
QAxObject *pWorkbook; //指向sXlsFile对应的工作簿
QAxObject *pWorksheet; //指向工作簿中的某个sheet表单
    QString   sXlsFile;      //xls文件路径
UINT nCurrSheet; //当前打开的第几个sheet
bool bIsVisible; //excel是否可见
int nRowCount; //行数
int nColumnCount; //列数
    int       nStartRow;     //开始有数据的行下标值
int nStartColumn; //开始有数据的列下标值
    bool      bIsOpen;       //是否已打开
bool bIsValid; //是否有效
    bool      bIsANewFile;   //是否是一个新建xls文件,用来区分打开的excel是已存在文件还是有本类新建的
bool bIsSaveAlready;//防止重复保存
};
#endif // EXCELENGINE_H

源文件:
#include "excelengine.h"
#include "qt_windows.h" ExcelEngine::ExcelEngine()
{
pExcel = NULL;
pWorkbooks = NULL;
pWorkbook = NULL;
pWorksheet = NULL;
sXlsFile = "";
nRowCount = 0;
nColumnCount = 0;
nStartRow = 0;
nStartColumn = 0;
bIsOpen = false;
bIsValid = false;
bIsANewFile = false;
bIsSaveAlready = false;
HRESULT r = OleInitialize(0);
    if (r != S_OK && r != S_FALSE)
{
qDebug("Qt: Could not initialize OLE (error %x)", (unsigned int)r);
}
} ExcelEngine::ExcelEngine(QString xlsFile)
{
pExcel = NULL;
pWorkbooks = NULL;
pWorkbook = NULL;
pWorksheet = NULL;
sXlsFile = xlsFile;
nRowCount = 0;
nColumnCount = 0;
nStartRow = 0;
nStartColumn = 0;
bIsOpen = false;
bIsValid = false;
bIsANewFile = false;
bIsSaveAlready = false;
    HRESULT r = OleInitialize(0);
if (r != S_OK && r != S_FALSE)
{
qDebug("Qt: Could not initialize OLE (error %x)", (unsigned int)r);
}
}
ExcelEngine::~ExcelEngine()
{
if ( bIsOpen )
{
//析构前,先保存数据,然后关闭workbook
Close();
}
OleUninitialize();
}
/**
*@brief 打开sXlsFile指定的excel报表
*@return true : 打开成功
* false: 打开失败
*/
bool ExcelEngine::Open(UINT nSheet, bool visible)
{
if(bIsOpen)
{
Close();
}
nCurrSheet = nSheet;
bIsVisible = visible;
    if(NULL == pExcel)
{
pExcel = new QAxObject("Excel.Application");
if(pExcel)
{
bIsValid = true;
}
else
{
bIsValid = false;
bIsOpen = false;
return bIsOpen;
}
pExcel->dynamicCall("SetVisible(bool)", bIsVisible);
}
    if(!bIsValid)
{
bIsOpen = false;
return bIsOpen;
} if(sXlsFile.isEmpty())
{
bIsOpen = false;
return bIsOpen;
}
    /*如果指向的文件不存在,则需要新建一个*/
QFile f(sXlsFile);
if(!f.exists())
{
bIsANewFile = true;
}
else
{
bIsANewFile = false;
} if(!bIsANewFile)
{
pWorkbooks = pExcel->querySubObject("WorkBooks"); //获取工作簿
pWorkbook = pWorkbooks->querySubObject("Open(QString, QVariant)",sXlsFile,QVariant(0)); //打开xls对应的工作簿
}
else
{
pWorkbooks = pExcel->querySubObject("WorkBooks"); //获取工作簿
pWorkbooks->dynamicCall("Add"); //添加一个新的工作薄
pWorkbook = pExcel->querySubObject("ActiveWorkBook"); //新建一个xls
}
pWorksheet = pWorkbook->querySubObject("WorkSheets(int)", nCurrSheet);//打开第一个sheet
    //至此已打开,开始获取相应属性
QAxObject *usedrange = pWorksheet->querySubObject("UsedRange"); //获取该sheet的使用范围对象
QAxObject *rows = usedrange->querySubObject("Rows");
QAxObject *columns = usedrange->querySubObject("Columns"); //因为excel可以从任意行列填数据而不一定是从0,0开始,因此要获取首行列下标
nStartRow = usedrange->property("Row").toInt(); //第一行的起始位置
nStartColumn = usedrange->property("Column").toInt(); //第一列的起始位置
nRowCount = rows->property("Count").toInt(); //获取行数
nColumnCount = columns->property("Count").toInt(); //获取列数
    bIsOpen  = true;
return bIsOpen;
}
/**
*@brief Open()的重载函数
*/
bool ExcelEngine::Open(QString xlsFile, UINT nSheet, bool visible)
{
sXlsFile = xlsFile;
nCurrSheet = nSheet;
bIsVisible = visible;
return Open(nCurrSheet,bIsVisible);
} /**
*@brief 保存表格数据,把数据写入文件
*/
void ExcelEngine::Save()
{
if(pWorkbook)
{
if(bIsSaveAlready)
{
return ;
}
        if(!bIsANewFile)
{
pWorkbook->dynamicCall("Save()");
}
else /*如果该文档是新建出来的,则使用另存为COM接口*/
{
pWorkbook->dynamicCall("SaveAs (const QString&,int,const QString&,const QString&,bool,bool)",
sXlsFile,56,QString(""),QString(""),false,false);
}
bIsSaveAlready = true;
}
}
/**
*@brief 关闭前先保存数据,然后关闭当前Excel COM对象,并释放内存
*/
void ExcelEngine::Close()
{
Save();//关闭前先保存数据
if(pExcel && pWorkbook)
{
pWorkbook->dynamicCall("Close(bool)", true);
pExcel->dynamicCall("Quit()");
delete pExcel;
pExcel = NULL;
        bIsOpen        = false;
bIsValid = false;
bIsANewFile = false;
bIsSaveAlready = true;
}
} /**
*@brief 把tableWidget中的数据保存到excel中
*@param tableWidget : 指向GUI中的tablewidget指针
*@return 保存成功与否 true : 成功
* false: 失败
*/
bool ExcelEngine::SaveDataFrTable(QTableWidget *tableWidget)
{
if(NULL == tableWidget)
{
return false;
}
    if(!bIsOpen)
{
return false;
}
    int tableR = tableWidget->rowCount();
int tableC = tableWidget->columnCount(); //获取表头写做第一行
for(int i=0;i<tableC;i++)
{
if(tableWidget->horizontalHeaderItem(i) != NULL)
{
this->SetCellData(1,i+1,tableWidget->horizontalHeaderItem(i)->text());
}
}
    //写数据
for(int i=0;i<tableR;i++)
{
for(int j=0;j<tableC;j++)
{
if(tableWidget->item(i,j) != NULL)
{
this->SetCellData(i+2,j+1,tableWidget->item(i,j)->text());
}
}
}
    //保存
Save();
return true;
}
/**
*@brief 从指定的xls文件中把数据导入到tableWidget中
*@param tableWidget : 执行要导入到的tablewidget指针
*@return 导入成功与否 true : 成功
* false: 失败
*/
bool ExcelEngine::ReadDataToTable(QTableWidget *tableWidget)
{
if(NULL == tableWidget)
{
return false;
} //先把table的内容清空
int tableColumn = tableWidget->columnCount();
tableWidget->clear();
for(int n=0;n<tableColumn;n++)
{
tableWidget->removeColumn(0);
}
    int rowcnt    = nStartRow + nRowCount;
int columncnt = nStartColumn + nColumnCount; //获取excel中的第一行数据作为表头
QStringList headerList;
for(int n = nStartColumn;n<columncnt;n++)
{
QAxObject* cell = pWorksheet->querySubObject("Cells(int,int)",nStartRow, n);
if(cell)
{
headerList<<cell->dynamicCall("Value2()").toString();
}
} //重新创建表头
tableWidget->setColumnCount(nColumnCount);
tableWidget->setHorizontalHeaderLabels(headerList); //插入新数据
for(int i=nStartRow+1,r=0;i<rowcnt;i++,r++)//行
{
tableWidget->insertRow(r); //插入新行
for(int j=nStartColumn,c=0;j<columncnt;j++,c++)//列
{
QAxObject * cell = pWorksheet->querySubObject("Cells(int,int)",i,j);//获取单元格        //在r新行中添加子项数据
if(cell)
{
tableWidget->setItem(r,c,new QTableWidgetItem(cell->dynamicCall("Value2()").toString()));
}
}
} return true;
}
/**
*@brief 获取指定单元格的数据
*@param row : 单元格的行号
*@param column : 单元格的列号
*@return [row,column]单元格对应的数据
*/
QVariant ExcelEngine::GetCellData(UINT row, UINT column)
{
QVariant data;
QAxObject *cell = pWorksheet->querySubObject("Cells(int,int)",row,column);//获取单元格对象
    if(cell)
{
data = cell->dynamicCall("Value2()");
}
return data;
}
/**
*@brief 修改指定单元格的数据
*@param row : 单元格的行号
*@param column : 单元格指定的列号
*@param data : 单元格要修改为的新数据
*@return 修改是否成功 true : 成功
* false: 失败
*/
bool ExcelEngine::SetCellData(UINT row,UINT column,QVariant data)
{
bool op = false;
QAxObject *cell = pWorksheet->querySubObject("Cells(int,int)",row,column);//获取单元格对象
    if ( cell )
{
QString strData = data.toString(); //excel 居然只能插入字符串和整型,浮点型无法插入
cell->dynamicCall("SetValue(const QVariant&)",strData); //修改单元格的数据
op = true;
}
else
{
op = false;
} return op;
}
/**
*@brief 清空除报表之外的数据
*/
void ExcelEngine::Clear()
{
sXlsFile = "";
nRowCount = 0;
nColumnCount = 0;
nStartRow = 0;
nStartColumn = 0;
}
/**
*@brief 判断excel是否已被打开
*@return true : 已打开
* false: 未打开
*/
bool ExcelEngine::IsOpen()
{
return bIsOpen;
}
/**
*@brief 判断excel COM对象是否调用成功,excel是否可用
*@return true : 可用
* false: 不可用
*/
bool ExcelEngine::IsValid()
{
return bIsValid;
} /**
*@brief 获取excel的行数
*/
UINT ExcelEngine::GetRowCount()const
{
return nRowCount;
}
/**
*@brief 获取excel的列数
*/
UINT ExcelEngine::GetColumnCount()const
{
return nColumnCount;
} 简单使用:

/*
ExcelEngine excel(QObject::tr("c:\\Test.xls")); //创建
excel.Open(); //打开

int num = 0;
for (int i=1; i<=10; i++)
{
for (int j=1; j<=10; j++)
{
excel.SetCellData(i,j,++num); //修改指定单元数据
}
}

QVarient data = excel.GetCellData(1,1); //访问指定单元格数据
excel.GetCellData(2,2);
excel.GetCellData(3,3);
excel.Save(); //保存
excel.Close();
*/

//导入数据到tablewidget中
/*
ExcelEngine excel(QObject::tr("c:\\Import.xls"));
excel.Open();
excel.ReadDataToTable(ui->tableWidget); //导入到widget中
excel.Close();
*/

//把tablewidget中的数据导出到excel中
/*
ExcelEngine excel(QObject::tr("c:\\Export.xls"));
excel.Open();
excel.SaveDataFrTable(ui->tableWidget); //导出报表
excel.Close();
*/

Qt 操作Excel的更多相关文章

  1. QT操作EXCEL

    介绍一下最基本的QT对EXCEL的读写操作. 声明:转载于:http://blog.csdn.net/czyt1988/article/details/52121360 在使用QT的操作数据库的时候, ...

  2. qt 操作excel表格

     自己编写的一个Qt C++类,用于操作excel表格,在Qt中操作excel需在.pro中增加CONFIG+=qaxcontainer配置. 1.打开Excel:objExcel = new QAx ...

  3. QT操作Excel(通过QAxObject使用了OLE,前提是本地安装了Excel)

    新建QT GUI项目,在选择选项中勾选ActiveQT Container. #include <qaxobject.h> QAxObject *obj = new QAxObject(& ...

  4. QT 操作 excel 教程

    前言:环境 win7 64位,QT4.8.5,QT Creator 在 .pro 文件中加入语句"CONFIG+=qaxcontainer"; 源码如下: //main.cpp # ...

  5. qt操作excel報錯解決

    如果電腦上沒有office,需要判斷,否则,会报错 onecore\com\combase\catalog\catalog.cxx()\combase.dll!00007FFF1DF823CB: (c ...

  6. Qt 操作excel报错

    onecore\com\combase\catalog\catalog.cxx(2376)\combase.dll!00007FFF1DF823CB: (caller: 00007FFF1DED3A1 ...

  7. Qt之操作Excel

    Visual Basic for Applications(VBA)是一种Visual Basic的一种宏语言,主要能用来扩展Windows的应用程式功能,特别是Microsoft Office软件. ...

  8. Qt QAxObject操作excel文件过程总结(转):

    正好同事问道Qt下操作excel. 转自:http://blog.csdn.net/a156392343/article/details/48092515 配制方面: 1.确保Excel软件在本地服务 ...

  9. Qt读写excel

    今天在利用Qt进行excel操作时,代码总是走到打开excel这一步是总是出现程序崩溃.在网上查找了各种帖子  说法不一,尝试都没有解决.后来猜想是不是excel没有激活影响的.发现自己的excel没 ...

随机推荐

  1. 小波变换和motion信号处理(三)(转)

    这篇文章算太监了,去作者blog提问去吧:http://www.kunli.info/2012/04/08/fourier-wavelet-motion-signal-3/ 从前两篇发布到现在,过去一 ...

  2. mmsql查看最近操作日志

    SELECT TOP 2000 query_stats.query_hash AS "Query Hash", Sum(Query_Stats.total_logical_Read ...

  3. SIGGRAPH

    这两天看了一些文章,今天来说说SIGGRAPH. 对于搞图形学的人来说,SIGGRAPH绝对是如雷贯耳.SIGGRAPH是计算机图形界(也包含图像)最顶级的会议,没有之中的一个,是全世界的图形学者公认 ...

  4. linux ssh 中在window 传文件 下载文件 工具

    centos 安装工具 yum install lrzsz

  5. 多项式逼近remes算法

    http://wenku.baidu.com/link?url=gpaBIucx0ov0ez3QHrO4FooBtNz2i80s4LKsh-LV3NnPYNjTUu7e1V7bT_jMHwOUZk4X ...

  6. Hdu 2473(并查集删除操作) Junk-Mail Filter

    有木有非常吊 加强 加强版   啊  ,看了都不敢做了   .后来先做了食物链这个我还是看过的.但还是A不掉,没明确神魔意思 .总而言之.大牛的博客是个好东西.我就那么看了一下,还是不懂怎莫办啊,哎, ...

  7. careercup-树与图 4.9

    4.9 给定一颗二叉树,其中每个结点都含有一个数值.设计一个算法,打印结点数值总和等于某个给定值的所有路径.注意,路径不一定非得从二叉树的根节点或叶子节点开始或结束. 类似于leetcode:Path ...

  8. Android(java)学习笔记210:采用post请求提交数据到服务器(qq登录案例)

    1.POST请求:  数据是以流的方式写给服务器 优点:(1)比较安全 (2)长度不限制 缺点:编写代码比较麻烦   2.我们首先在电脑模拟下POST请求访问服务器的场景: 我们修改之前编写的logi ...

  9. Mac安装Mysql过程

    1.Mysql官网下载安装包 http://dev.mysql.com/downloads/mysql/ 选择Mac OS X 10.10 (x86, 64-bit), DMG Archive版本下载 ...

  10. ReadWriteLock与ReentrantReadWriteLock

    JAVA的JUC包中的锁包括"独占锁"和"共享锁".JUC中的共享锁有:CountDownLatch.CyclicBarrier.Semaphore.Reent ...