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 [email protected] *@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();
*/
时间: 2024-10-05 04:58:49