Qt中使用QAxObject操作Excel

在Qt中使用ActiveX控件

 

        Qt的windows商业版本提供了ActiveQt这个framework,使用这个组件我们可以在Qt中使用ActiveX控件,并且也可以开发基于Qt的ActiveX控件。ActiveQt包含了两个组件QAxContainer和QAxServer。

        l  QAxContainer允许我们使用COM对象,并且可以将将ActiveX控件嵌入到Qt程序中去。

        l  QAxServer可以将我们写的Qt控件导出为COM对象或者是ActiveX控件。

这次由于只是操作Excel进行读取写入,故只用到了QAxContainer。

QAxContainer不包含在QtCore里面,所以要使用QAxContainer的话还必须要在.pro文件中添加CONFIG+=qaxcontainer。

操作Excel接口说明

         其实接口只有几个:

属性方面的:

boolsetProperty(const char *name, const QVariant &value);
QVariant property(const char *name) const;

对象方面的:

QAxObject*querySubObject(const char *name, const QVariant &v1 = QVariant(),……)

对象方法方面的:(函数)

QVariantdynamicCall(const char *name, const QVariant &v1 = QVariant(), ……)

常用的基本也就这几个了。

基本的操作流程都是:先是querySubObject() 获取某一个子对象,然后可以对其设置属性setProperty()或读取属性property(),进一步可以调用dynamicCall()来实现对其进行操作。

 来一段网上常见的代码:

_excelObject =new QAxObject("Excel.Application");
1) 显示当前窗口:
excel.setProperty("Visible",true);
2) 更改 Excel 标题栏:
excel.setProperty("Caption","Invoke Microsoft Excel");
3) 添加新工作簿:
QAxObject *workbooks = excel.querySubObject("WorkBooks");
workbooks->dynamicCall("Add");
4) 打开已存在的工作簿:
workbooks->dynamicCall("Open(const QString&)", QString("c:/test.xls"));
5) 获取活动工作簿:
QAxObject *workbook = excel.querySubObject("ActiveWorkBook");
6) 获取所有的工作表:
QAxObject *worksheets = workbook->querySubObject("WorkSheets");
7) 获取工作表数量:
int intCount =worksheets->property("Count").toInt();
8) 获取第一个工作表:
QAxObject *worksheet = workbook->querySubObject("Worksheets(int)", 1);
9) 获取cell的值:
QAxObject *range = worksheet->querySubObject("Cells(int,int)", 1, 1 );

再 贴一段示例代码:

Excel::Excel(constQString &fileName, QAxObject *excelServer)
    : _excelObject(excelServer),_sheetsCount(1)
{
    if (_excelObject == NULL)
    {
        _excelObject = newQAxObject("Excel.Application");
        if (!_excelObject)
        {
            throwruntime_error(string("Excel服务启动失败.\r\n [DETAILS] Excel::Excel(); \r\n newQAxObject(\"Excel.Application\");"));
        }
        _isSetExcelServer = false;          ///< 构造函数的excelServer是否初始化(如果没有,需要我们初始化,析构里需要我们删除)
    }
    else
    {
        _isSetExcelServer = true;          ///< 构造函数的excelServer是否初始化(如果没有,需要我们初始化,析构里需要我们删除)
    }
   _excelObject->setProperty("Visible", false);         ///< 不可见   true的话可以看到Excel窗口如何操作的,方便调试
    QAxObject * workbooks =_excelObject->querySubObject("WorkBooks");
    workbooks->dynamicCall("Open (constQString&)", fileName);
    // ToDo ...
    // 校验是否打开了
 
    _curWorkbook =_excelObject->querySubObject("ActiveWorkBook");       ///< 当前工作簿
    _worksheets =_curWorkbook->querySubObject("WorkSheets");    ///< 当前excel对应的所有sheet集合
    _sheetsCount =_worksheets->property("Count").toInt();       ///< 当前excel文件里包含的sheet个数
    _curWorkSheet =_curWorkbook->querySubObject("Worksheets(int)", 1);///< 当前sheet(实际就是第一个sheet)
    _usedRange = usedRange();
 
}

这里,我们先是启动Excel服务程序,然后获取其子对象workbooks,调用打开文件函数打开一个Excel文件,再定位到其中的一个sheet:curWorkSheet。接下来都是对该curWorkSheet进行操作。

 

Qt操作Excel总结


         刚开始也不知道如何下手,又没有什么现成的例子,只知道那几个接口,所有的调用参数根本不知道怎么设置。后来进过慢慢摸索,发现了如下的方法:

 

1、 可以打开Excel文件,然后录制一段宏代码(Excel2010视图—宏—录制宏)。你可以先手动执行一遍你想要的操作,然后查看宏代码。宏代码类似下面一段:

Sub 宏1()
'
' 宏1 宏'
   Range("B11").Select
   ActiveCell.FormulaR1C1 = "=SUM(R[-9]C:R[-3]C)"
   Range("G11").Select
   ActiveSheet.Shapes.AddChart.Select
   ActiveChart.ChartType = xlXYScatter
   ActiveSheet.Shapes("图表 1").IncrementLeft -52.5
   ActiveSheet.Shapes("图表 1").IncrementTop 26.25
   ActiveSheet.Shapes("图表 1").ScaleWidth 1.3125, msoFalse, msoScaleFromTopLeft
   ActiveSheet.Shapes("图表 1").ScaleHeight 1.1840277778, msoFalse, _
       msoScaleFromTopLeft
   ChDir "F:\百度云\Temp"
   ActiveChart.SeriesCollection.NewSeries
   ActiveChart.SeriesCollection(1).Name = "=""系列名称1"""
   ActiveChart.SeriesCollection(1).XValues = "=小汽车!$B$1:$Q$1"
   ActiveChart.SeriesCollection(1).Values = "=小汽车!$B$6:$Q$6"
   ActiveChart.PlotArea.Select
   ActiveChart.ChartArea.Select
End Sub

代码含义看英文单词应该能猜出个大概意思了吧。。。插入一个散点图,设置数据。。。

这段宏跟我们的Qt有什么关系呢?

2、 别急,在宏代码窗口这边按下F1,祭出神器——Excel2010 开发人员参考帮助菜单

 

在Excel对象模型参考目录下,我们可以看到所有的操作对象(如图所示),点击某个对象,可以看到有“属性”“方法”,部分还有“事件”,这些就是我们在Qt里调用时函数参数的来源参考了。

譬如,WorkBook下面有个方法close,用于关闭当前工作簿:


这里说明这个close()函数有三个可选参数,这样在Qt里我们就可以这样调用了:

_curWorkbook->dynamicCall("Close(Boolean)", false);

dynamicCall()第一个参数指定函数名,后面紧接着一个或者多个该函数参数。这里表示我们直接关闭工作簿不保存。


好了,基本就是这样的方法了:

1、 先根据你想要执行的操作,手动操作一遍Excel并录制一段宏

2、 根据宏代码,结合Excel2010 开发人员参考帮助菜单,将宏代码翻译成Qt代码

3、 run.


下面插入一段Qt操作Excel,插入散点图,设置散点图数据,添加趋势线,并得到趋势线函数式。


Excel中插入图表并显示趋势曲线


void TFVExcelFileProcess::formula(double percentage)
{
    //getColFenwei(percentage);
    ///
    QAxObject *shapes = _curWorkSheet->querySubObject("Shapes");

    QAxObject *emptyCell = _curWorkSheet->querySubObject("Cells(int,int)", 1, usedColsCount()+3 );
    // 先选中一个空白的地方,不然后面的SeriesCollection会先将所有行都做个散点图。。。
    emptyCell->dynamicCall("Select(void)");
    shapes->dynamicCall("AddChart(int)",-4169,100,100,500,800); // height width
    // 再将视野拖回到左上角区域
    QAxObject *range = _curWorkSheet->querySubObject("Range(QVariant)","$B$1:$D$1");
    range->dynamicCall("Select(void)");

    int nbChart = shapes->property("Count").toInt();
    qDebug() << "chart size :" <<nbChart;
    QAxObject *shape = shapes->querySubObject("Range(int)",nbChart);
    qDebug() << "Name" <<shape->property("Name").toString();        // 获取Name属性
    qDebug() << "Title" <<shape->property("Title").toString();      // 获取Title属性
    //shape->dynamicCall("ScaleWidth(QVariant,QVariant)",2,0);
    shape->dynamicCall("Select(void)");

    QAxObject *chart = _curWorkbook->querySubObject("ActiveChart");
    QAxObject *seriesCollection = chart->querySubObject("SeriesCollection()");
    seriesCollection->dynamicCall("NewSeries (void)");
    int nb = seriesCollection->property("Count").toInt();
    QAxObject *series = chart->querySubObject("SeriesCollection(int)",nb);
    series->setProperty("Name","SeriesNo1");

    // 选中部分单元格
    //QAxObject *range = _curWorkSheet->querySubObject("Range(QVariant,QVariant)",coordInt2String(1,2),coordInt2String(1,9));
    //QAxObject *range = _curWorkSheet->querySubObject("Range(QVariant)","$B$1:$Q$1");
    //range->dynamicCall("Select(void)");
    //QAxObject * xvalues = worksheet->querySubObject("Range(A2:A9)");
    //QAxObject * yvalues = worksheet->querySubObject("Range(B2:B9)");
    //serie->setProperty("XValues", xvalues->asVariant());
    //serie->setProperty("Values", yvalues->asVariant());

    // 给该系列添加源数据
    // 这里我的数据来自其他部分,非Excel文件,
    // 想使用Excel文件数据可采用上面的方法,先选中数据单元格,然后传递过去
    QList<QVariant> listXValues, listValues;
    for (int i=1; i<_colFenwei.size(); i++)
    {
        listXValues.push_back(i+1);
        listValues.push_back(_colFenwei.at(i));
    }
    series->setProperty("XValues",listXValues);
    series->setProperty("Values",listValues);
    series->dynamicCall("Select(void)");

    // 添加趋势线
    QAxObject *trendLines = series->querySubObject("Trendlines()");
    if (trendLines) {
        trendLines->dynamicCall("Add()");
        int nbTrendLines = trendLines->property("Count").toInt();
        QAxObject *trendLine = series->querySubObject("Trendlines(int)",nbTrendLines);
        // 设定图标格式为 “散点图”,数字-4133来自 枚举变量 XlTrendlineType  : xlLogarithmic
        trendLine->setProperty("Type",-4133);       // XlTrendlineType  : xlLogarithmic
        trendLine->setProperty("Name","TrendLineName");
        trendLine->setProperty("DisplayEquation",true);
        //trendLine->setProperty("DisplayRSquared",true);

        QAxObject *dataLabel = trendLine->querySubObject("DataLabel");
        QString strFormula = dataLabel->property("Formula").toString();
        qDebug() << strFormula;         // "y = -9.113ln(x) + 78.016"

        getFormulaCoeffcient(strFormula,_cofA, _cofB);
        qDebug() << _cofA;
        qDebug() << _cofB;
    }
    // 保存文件
    /*
    QString qstrFileName = QCoreApplication::applicationDirPath().append("/FCQ_");
    qstrFileName.append(QDateTime::currentDateTime().toString("yyyyMMddHHmmss"));
    qstrFileName.replace("/", "\\");
    //qDebug() << qstrFileName;
    //保存文件并退出
    //_curWorkbook->dynamicCall("SaveCopyAs(QString)",qstrFileName);
    _curWorkbook->dynamicCall("SaveAs(QString)",qstrFileName);
    */
}


 代码请戳这里 : http://download.csdn.net/detail/seumonkey/6811425

 

  • 34
    点赞
  • 216
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值