Qt:Qt导出Excel表格

来源:互联网 发布:php资产管理系统源码 编辑:程序博客网 时间:2024/05/16 13:41

      借鉴参考文献中的内容,并将其封装成一个ExcelExporter类,除了实现一些基本的写数据的功能,还增加了设置单元格样式、合并单元格的功能。在Qt中使用QAxObject类访问Com组件对象,需要在pro文件中添加下面的内容:

QT       +=axcontainer


Excel对象的主要层次结构:



核心代码:  

/*! *新建一个excel表格 */bool ExcelExporter::newExcel(const QString &fileName){    pApplication = new QAxObject();    bool b = pApplication->setControl("Excel.Application");//连接Excel控件    if(!b)        return false;    pApplication->dynamicCall("SetVisible(bool)", false);//false不显示窗体    pApplication->setProperty("DisplayAlerts", false);//不显示任何警告信息。    pWorkBooks = pApplication->querySubObject("Workbooks");    QFile file(fileName);    if (file.exists())    {        pWorkBook = pWorkBooks->querySubObject("Open(const QString &)", fileName);    }    else    {        pWorkBooks->dynamicCall("Add");        pWorkBook = pApplication->querySubObject("ActiveWorkBook");    }    if(!pWorkBook)        return false;    pSheets = pWorkBook->querySubObject("Sheets");    if(!pSheets)        return false;    pSheet = pSheets->querySubObject("Item(int)", 1);    if(!pSheet)        return false;    return true;}/*! * 设置最后一个Sheet名字 */void ExcelExporter::setSheetName(const QString &sheetName){    if(pSheet)        pSheet->setProperty("Name", sheetName);}/*! *增加一个sheet表 */void ExcelExporter::appendSheet(const QString &sheetName){    int sheet_count = pSheets->property("Count").toInt();  //获取工作表数目    QAxObject *pLastSheet = pSheets->querySubObject("Item(int)", sheet_count);//获取最后一个工作表    pSheet = pSheets->querySubObject("Add(QVariant)", pLastSheet->asVariant());    pLastSheet->dynamicCall("Move(QVariant)", pSheet->asVariant());    pSheet->setProperty("Name", sheetName);}/*! *删除一个sheet表 */void ExcelExporter::deleteSheet(const int index){    QAxObject *sheet = pSheets->querySubObject("Item(int)", index);    if(sheet){        sheet->dynamicCall("delete");        delete sheet;    }}/*! *设置单元格的值 */void ExcelExporter::setCellValue(int row, int column, const QString &value){    QAxObject *pCell = pSheet->querySubObject("Cells(int,int)", row, column);    if(pCell){        pCell->dynamicCall("Value", value);        pCell->setProperty("WrapText", true);  //内容过多,自动换行        delete pCell;    }}/*! *设置单元格背景色 */void ExcelExporter::setCellBackground(int row, int column, const QColor &c){    QAxObject *pCell = pSheet->querySubObject("Cells(int,int)", row, column);    if(pCell){        QAxObject* interior = pCell->querySubObject("Interior");        interior->setProperty("Color",QVariant::fromValue(c));        delete pCell;    }}/*! * 设置单元边框颜色 */void ExcelExporter::setCellBorder(int row, int column, const QColor &c){    QAxObject *pCell = pSheet->querySubObject("Cells(int,int)", row, column);    if(pCell){        QAxObject* border = pCell->querySubObject("Borders");        border->setProperty("Color", QVariant::fromValue(c));        delete pCell;    }}/*! * 设置行高 */void ExcelExporter::setCellRowHeight(int row, int column, const int h){    QAxObject *pCell = pSheet->querySubObject("Cells(int,int)", row, column);    if(pCell){        pCell->setProperty("RowHeight", h);  //设置单元格行高        delete pCell;    }}/*! * 设置列宽 */void ExcelExporter::setCellColumnWidth(int row, int column, const int w){    QAxObject *pCell = pSheet->querySubObject("Cells(int,int)", row, column);    if(pCell){        pCell->setProperty("ColumnWidth", w);  //设置单元格列宽        delete pCell;    }}/*! * 合并单元格 * \param begRow 起始行 * \param begCol 起始列 * \param endRow 终止行 * \param endCol 终止列 */void ExcelExporter::mergeCell(int begRow, int begCol, int endRow, int endCol){    QString merge_cell;    convertToColName(begCol,merge_cell);         //初始列    merge_cell.append(QString::number(begRow));  //初始行    merge_cell.append(":");    convertToColName(endCol,merge_cell);         //终止列    merge_cell.append(QString::number(endRow));  //终止行    QAxObject *merge_range = pSheet->querySubObject("Range(const QString&)", merge_cell);    if(!merge_range)        return;    merge_range->setProperty("HorizontalAlignment", -4108);    merge_range->setProperty("VerticalAlignment", -4108);    merge_range->setProperty("WrapText", true);    merge_range->setProperty("MergeCells", true);  //合并单元格    delete merge_range;}/*! * \brief 把列数转换为excel的字母列号 * \param data 大于0的数 * \return 字母列号,如1->A 26->Z 27 AA */void ExcelExporter::convertToColName(int data, QString &res){    if(data <=0 || data >= 65535)        return;    int tempData = data / 26;    int mode = data % 26;    if(tempData > 0 && mode != 0)    {        convertToColName(tempData,res);        convertToColName(mode,res);    }    else if(tempData > 0 && mode == 0)    {        convertToColName(tempData - 1,res);        res += to26AlphabetString(26);    }    else    {        res += to26AlphabetString(data);    }}/*! * \brief 数字转换为26字母 *        1->A 26->Z * \param data * \return */QString ExcelExporter::to26AlphabetString(int data){    QChar ch = data + 0x40;//A对应0x41    return QString(ch);}/*! *保存 */void ExcelExporter::saveExcel(const QString &fileName){    pWorkBook->dynamicCall("SaveAs(const QString &)",                           QDir::toNativeSeparators(fileName));    pWorkBook->dynamicCall("Close(Boolean)", false);  //关闭文件    if (pApplication != NULL)    {        pApplication->dynamicCall("Quit()");        delete pApplication;        pApplication = NULL;    }}

本方法下,写入excel表格时间较长,可能会造成程序假死现象,可以重新开启一个线程来处理这个导出过程。

参考文献中给出了一种快速读写Excel表格的方法。文章分析了导致速度满的原因是当对单元格进行读写,每处理一个单元格都要调用一个Excel子对象,如果读写很多单元格时候,就会造成反复调用而不析构,就会导致处理速度慢。

读取慢的根源就在于sheet->querySubObject("Cells(int, int)", row, col)

试想有10000个单元就得调用10000次querySubObject,网络上90%的教程都没说这个querySubObject产生的QAxObject*最好进行手动删除,虽然在它的父级QAxObject会管理它的内存,但父级不析构,子对象也不会析构,若调用10000次,就会产生10000个QAxObject对象 



   参考文献:

     Qt导出excel

        COM组件开发

       Qt快速读写Excel


原创粉丝点击