VARIANT变量是COM组件之间互相通信的重要的参数变量之一,它可以容纳多种不同的类型,如short、long、double等,包括各类指针和数组。组件之间的互相调用是比较耗时的,尤其带当组件位于不同进程中时,因此,减少传递次数是提高效率的一种有效方法。其中,Excel表格的操作就可能涉及到大量数据,一次传递一个二维数组是提高对Excel表的操作效率。下面以两种不同方式来实现VARIANT二维数组的操作。

1、使用SAFEARRAY实现二维数组

SAFEARRAY安全数组可以实现多维数组,SAFEARRAY实现的步骤可以大致分为三步。

(1)创建SAFEARRAY安全数组,包括设置数组元素的类型、数据的维数,大小等。

(2)对SAFEARRAY数组赋值,既可通过SafeArrayPutElement函数逐个元素进行负责,也可通过指针来获得SAFEARRAY的数据地址,然后对指针指向的值进行赋值操作。其中,如果SAFEARRAY中的数组时多维数组,即可以把多维数组转换为一维数组,也可以通过获得指向数组的指针方式来操作数组中的元素。

(3)使用VARIANT变量把SAFEARRAY进行包装。

使用SAFEARRAR实现二维数组的源代码如下:

  VARTYPE vt = VT_I4; /*数组元素的类型,long*/
  SAFEARRAYBOUND sab[2]; /*用于定义数组的维数和下标的起始值*/
  sab[0].cElements =2;
  sab[0].lLbound =0;
  sab[1].cElements =2;
  sab[1].lLbound =0;
  /*创建一个2*2的类型为long的二维数组*/
  SAFEARRAY* psa = SafeArrayCreate(vt, sizeof(sab)/sizeof(SAFEARRAYBOUND), sab);
  if (NULL == psa)
  {
  throw;
  }

  /*通过指向数组的指针来对二维数组的元素进行间接赋值*/
  long (*pArray)[2] = NULL;
  HRESULT hRet = SafeArrayAccessData(psa, (void **)&pArray);
  if (FAILED(hRet))
  {
    throw;
  }
  memset(pArray, 0, 2*2*sizeof(long));
  /*释放指向数组的指针*/
  SafeArrayUnaccessData(psa);
  pArray = NULL;

  /*对二维数组的元素进行逐个赋值*/
  long index[2] = {0, 0};
  long lFirstLBound = 0;
  long lFirstUBound = 0;
  long lSecondLBound = 0;
  long lSecondUBound = 0;
  SafeArrayGetLBound(psa, 1, &lFirstLBound);
  SafeArrayGetUBound(psa, 1, &lFirstUBound);
  SafeArrayGetLBound(psa, 2, &lSecondLBound);
  SafeArrayGetUBound(psa, 2, &lSecondUBound);
  for (long i = lFirstLBound; i <= lFirstUBound; i++)
  {
    index[0] = i;
    for (long j = lSecondLBound; j <= lSecondUBound; j++)
    {
      index[1] = j;
      long lElement = i * sab[1].cElements + j; 
      HRESULT hRet = SafeArrayPutElement(psa, index, &lElement);
      if (FAILED(hRet))
      {
         throw;
      }
     }
  }

  /*把SAFEARRAY转换为VARIANT*/
  VARIANT var;
  var.vt = VT_ARRAY | vt; /*vt必须和psa的数据类型保持一致*/
  var.parray = psa;
  SafeArrayDestroy(psa);
  psa = NULL;

2、使用COleSafeArray实现二维数组

COleSafeArray继承于VARIANT,是MFC的自动化类,因此,只有在使用MFC类库时才能使用该类。COleSafeArray封装操作相关的函数,可通过MSDN查询该类的成员函数来了解与安全数组相关的函数。COleSafeArray还可以直接转换为VARIANT。因此,相对于SAFEARRAY,COleSafeArray的使用更方便。COleSafeArray和SAFEARRAY之间的关系就是MFC类库和Win32 SDK的关系,使用步骤类似。

使用COleSafeArray实现二维数组的源代码如下所示:

    VARTYPE vt = VT_I4; /*数组元素的类型,long*/
SAFEARRAYBOUND sab[2]; /*用于定义数组的维数和下标的起始值*/
sab[0].cElements =2;
sab[0].lLbound =0;
sab[1].cElements =2;
sab[1].lLbound =0; COleSafeArray olesa;
olesa.Create(vt, sizeof(sab)/sizeof(SAFEARRAYBOUND), sab);

  /*通过指向数组的指针来对二维数组的元素进行间接赋值*/
  long (*pArray)[2] = NULL;
  olesa.AccessData((void **)&pArray);
  memset(pArray, 0, 2*2*sizeof(long));
  /*释放指向数组的指针*/
  olesa.UnaccessData();
  pArray = NULL;

  /*对二维数组的元素进行逐个赋值*/
  long index[2] = {0, 0};
  long lFirstLBound = 0;
  long lFirstUBound = 0;
  long lSecondLBound = 0;
  long lSecondUBound = 0;
  olesa.GetLBound(1, &lFirstLBound);
  olesa.GetUBound(1, &lFirstUBound);
  olesa.GetLBound(2, &lSecondLBound);
  olesa.GetUBound(2, &lSecondUBound);
  for (long i = lFirstLBound; i <= lFirstUBound; i++)
  {
    index[0] = i;
    for (long j = lSecondLBound; j <= lSecondUBound; j++)
    {
      index[1] = j;
      long lElement = i * sab[1].cElements + j; 
      olesa.PutElement(index, &lElement);
    }
  }


    /*把COleSafeArray变量转换为VARIANT*/
VARIANT var = (VARIANT)olesa;

参考资料

http://blog.sina.com.cn/s/blog_74f586a50100rv6t.html
http://hfp0601.blog.163.com/blog/static/228483522011031104718762/

C++使用VARIANT实现二维数组的操作的更多相关文章

  1. C++程序设计实践指导1.2二维数组的操作运算改写要求实现

    改写要求1:改写为以单链表表示二维数组 #include <cstdlib> #include <iostream> using namespace std; struct L ...

  2. nRF51800 蓝牙学习 进程记录 2:关于二维数组 执念执战

    前天在玩OLED时想完成一直想弄得一个东西,就是简单的单片机游戏.因为STM32和nRF51822的内存足够,所以就用缓存数组的方法来显示图像(我也不知道术语是啥,反正就是在内存中建立一个128X64 ...

  3. 对二维数组使用指针进行操作的探索(C语言)

    /* Name: 对二维数组使用指针进行操作的探索 Copyright: Author: lingr7 Date: 01/12/18 11:55 Description: */ #include< ...

  4. 二维数组是二级指针pointer to pointer!

    二维数组居然是个类似于二级指针(pointer to pointer)的东西,十分震惊! #include <stdio.h> int main() { ][]={{,,,},{,,,}, ...

  5. VueX中直接修改数据报错,修改一维数组,二维数组,报错的原因

    直接修改state中的的数据是不被允许的,会报错 这个时候可以使用三种种方式处理 第一种:使用拓展运算符,深拷贝一维数组或对象var arrA = [1,2,3,4]var a = [...arr]| ...

  6. PHP 二维数组根据某个字段排序

    二维数组根据某个字段排序有两种办法,一种是通过sort自己写代码,一种是直接用array_multisort排序函数 一. 手写arraysort PHP的一维数组排序函数: sort  对数组的值按 ...

  7. 剑指Offer-【面试题03:二维数组中的查找】

    package com.cxz.question3; /* * 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序. * 请完成一个函数,输入这样的一个二维数组和 ...

  8. PHP开发笔记:二维数组根据某一项来进行排序

    比如说我们现在有一个二维数组: $arr = array( ‘d' => array(‘id' => 5, ‘name' => 1, ‘age' => 7), ‘b' => ...

  9. 剑指Offer面试题:2.二维数组中的查找

    一.题目:二维数组中的查找 题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. ...

随机推荐

  1. SharePoint\O365 CSOM操作"请求访问设置"功能

    博客地址:http://blog.csdn.net/FoxDave 请求访问设置是在SharePoint网站权限菜单中的一个功能,如下图: 它用来设置成员是否可以共享网站以及个别文件和文件夹,是否允许 ...

  2. Python开发入门与实战10-事务

    1. 事务 本章我们将通过一个例子来简要的说明“事务”,这个开发实战里经常遇到的名词.事务是如何体现在一个具体的业务和系统的实现里. 事务是通过将一组相关操作组合为一个,要么全部成功要么全部失败的单元 ...

  3. hive的基本操作

    1.创建表 First, create a table with tab-delimited text file format: (1)CREATE TABLE u_data ( userid INT ...

  4. MapReducer程序调试技巧

    写过程序分布式代码的人都知道,分布式的程序是比较难以调试的,但是也不是不可以调试,对于Hadoop分布式集群来说,在其上面运行的是mapreduce程序,因此,有时候写好了mapreduce程序之后, ...

  5. GCD下的几种实现同步的方式

    GCD多线程下,实现线程同步的方式有如下几种: 1.串行队列 2.并行队列 3.分组 4.信号量 实例: 去网上获取一张图片并展示在视图上. 实现这个需求,可以拆分成两个任务,一个是去网上获取图片,一 ...

  6. 2016年12月11日 php面向对象

    面向对象 1.类(由众多对象中抽象出来的) 2.对象(一切皆对象,由类实例化出来的). 类: 求圆的面积 面向过程的方式 1.将圆抽象为一个类 2.实例化对象 class Qiu { var $ban ...

  7. 根据地图上的两个点各自的x,y坐标,计算出2点之间的直线距离。显示为公里、米

    /** * calc_map_distance() , 根据地图上的两个点各自的x,y坐标,计算出2点之间的直线距离 * @param array $point_1 第1个点的x,y坐标 array( ...

  8. html+css图片下弹出蒙版

    鼠标移入时弹出蒙版!!! html<!DOCTYPE html<html lang="en"<head> <meta charset="UT ...

  9. 一些上流的CSS3图片样式

    直接在图片元素上直接应用CSS3 inset box-shadow 或 border-radius时,浏览器并不能完美的渲染它们.不过,如果把这个图片用作背景图,你就可以可以给它添加任何样式了,浏览器 ...

  10. maven项目修改java编译版本的方式

    背景 使用 maven 3.x 安装到本地后,创建的项目一般都是基于JDK1.5版本.而目前大多数的项目已经升级到1.6或以上,尤其是Servlet3.0 已经要求Java6或以上版本的环境,往往需要 ...