Qt之读Excel

原创
2015/11/09 14:45
阅读数 345

项目需要从Excel里读取数据,从网上找到有个qtxlsx包可以脱离windows平台,但是有些情况不适用,就是我们公司Excel被加密了,只有打开解密软件的同时使用office excel才能打开excel,所以我必须使用微软的excel接口进行操作,这里只能使用以下方法了:

1、pro文件加入axcontainer

image

2、如果读写Excel是在子线程里,在使用QAxObject操作时需要先添加如下结构

CoInitialize(0);
….//你的各种读写Excel操作
CoUninitialize();

这里可以看出是对相关功能的初始化和释放,不添加的话会报错,如果不是在子线程里操作不需要这些。

至于这些具体做了什么,我没有研究。。。

3、在以上结构内部读写Excel

这里要介绍的一个文档就是Excel自带的开发者文档,我们所有操作几乎都是基于开发者文档里的API,也就是VBA的API了。

如下图所示,打开excel,打开vba,按F1获得帮助文档

image

打开Excel 2010开发人员参考---Excel对象模型参考:

image

可以看到很多对象。。。这些对象就是我们要操作的东西

如何操作看如下代码,相信多看看就知道如何使用了,就不详细介绍原理了,我也不知道:

    QAxObject excel("Excel.Application");    
    excel.setProperty("DisplayAlerts",false);
    workBooks=excel.querySubObject("Workbooks");
    workBooks->dynamicCall("Open(const QString&)",excelFileFullName);
    QVariant titleValue=excel.property("Caption");
    qDebug()<<QString("Excel title:")<<titleValue.toString();
    workBook=excel.querySubObject("ActiveWorkBook");
    QVariant path=workBook->property("Path");
    qDebug()<<QString("Path:")<<path.toString();
    workSheets=workBook->querySubObject("Worksheets");
    int workSheetsCount=workSheets->property("Count").toInt();
    qDebug()<<QString("WorkSheetsCount:")<<workSheetsCount;
    for(int i=1; i<=workSheetsCount; i++)
    {
        workSheets = workBook->querySubObject("Worksheets(int)", i);  //Sheets(int)也可换用Worksheets(int)
        QString workSheetName = workSheets->property("Name").toString();  //获取工作表名称
        QString message = QString("sheet ")+QString::number(i, 10)+ QString(" name");
        qDebug()<<message<<workSheetName;
        //get report template version to decide how to read excel
        if(workSheetName=="appendix-TireInf"){
            sheetNumOfAp_TireInf=i;
            qDebug()<<"sheetNumOfAp_TireInf:"+QString::number(sheetNumOfAp_TireInf);
            ExcelRead(sheetNumOfAp_TireInf,"G3",reportTemplateVersion);
        }
    }

 

读写完毕,关闭excel,否则系统会有excel进程残留: 
workBook->dynamicCall("Close(boolean)",false);   
excel.dynamicCall("Quit(void)");
以上可以看出:
操作一个对象分为三种操作:
1、获得该对象的子对象,如获得workBook下的workSheets,就使用querySubObject函数;
2、获得该对象的某个属性,使用property函数;
3、使用该对象的某个函数,使用dynamicCall函数;
 一些特殊方法:
导出图片函数:
/** *  函数名:ExcelSavePicture
 *  使用条件:通过QAxObject方法已取得workBook对象
 *  功能描述: 从第sheetNum表里取出所有picture,放在savePath里
 *  @sheetNum 第几张表
 *  @savePath 取得的图片放在这里,指路径如"D:\\FEADB"
 *
 *  @ return 成功返回true;失败返回false。
 */
bool Report::ExcelSavePicture(int sheetNum,QString savePath)
{
    workSheet=workBook->querySubObject("WorkSheets(int)",sheetNum);
    if(!workSheet) {qDebug()<<"Error:querySubObject(WorkSheets(int))";return false;}
    QAxObject *shapes=workSheet->querySubObject("Shapes");
    int shapesCount=shapes->property("Count").toInt();
    qDebug()<<"shapesCount:"+QString::number(shapesCount);
    for(int i=1;i<shapesCount+1;i++) {
        QAxObject *shape=shapes->querySubObject("Item(int)",i);
        qDebug()<<"shapeNum:"+QString::number(i);
        QString shapeName=shape->property("Name").toString();
        qDebug()<<"shapeName:"+shapeName;
        QString shapeType=shapeName.split(" ")[0];
        qDebug()<<"shapeType:"+shapeType;
        //qRegisterMetaType<Office::MsoShapeType>("Office::MsoShapeType");
        //int shapeType=shape->property("Type").toInt();
        //qDebug()<<"shapeType:"+QString::number(shapeType);
         if(shapeType==QString("Picture"))
         {
             QString shapeName=shape->property("Name").toString();
             qDebug()<<"shapeName:"+shapeName;
             QString sheetName;
             if(!getSheetName(sheetNum,sheetName))
                 return false;
             QString exportPath=savePath+"/"+taskName+"/Pictures/"+sheetName;
             QDir exportDir;
             exportDir.mkpath(exportPath);
   
             QString exportPathName=exportPath+"/"+shapeName+".jpg";
             qDebug()<<"exportPathName:"+exportPathName;
             double shapeLeft=shape->property("Left").toDouble();
             double shapeTop=shape->property("Top").toDouble();
             double shapeWidth=shape->property("Width").toDouble();
             double shapeHeight=shape->property("Height").toDouble();
             qDebug()<<"shapeLeft:shapeTop:shapeWidth:shapeHeight="+QString::number(shapeLeft)+":"+QString::number(shapeTop)+":"+QString::number(shapeWidth)+":"+QString::number(shapeHeight);
             shape->dynamicCall("Copy(void)");
             QAxObject *chartObjects=workSheet->querySubObject("ChartObjects(void)");
             QAxObject *chartObject=chartObjects->querySubObject("Add(Double,Double,Double,Double)",shapeLeft,shapeTop,shapeWidth,shapeHeight);
             QAxObject *pasteChart=chartObject->querySubObject("Chart");
             pasteChart->dynamicCall("Paste(int)",XLPASTEALL);
             pasteChart->dynamicCall("Export(QString,QVariant,QVariant)",exportPathName,"JPG","False");
             QAxObject *parentChart=pasteChart->querySubObject("Parent");
             parentChart->dynamicCall("Delete(void)");
    return true;
}

展开阅读全文
打赏
1
0 收藏
分享
加载中
推荐一个功能丰富、兼容性好、高性能的 Excel 文档基础库 #Excelize#https://github.com/xuri/excelize
2020/11/27 10:21
回复
举报
更多评论
打赏
1 评论
0 收藏
1
分享
返回顶部
顶部