Qt 操作Excel


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();
*/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM