C++使用VARIANT实现二维数组的操作、怎么使用COleSafeArray实现二维数组将字符串写入excel

65 篇文章 2 订阅
8 篇文章 0 订阅
配合OLED_V2的excel操作

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/

如何使用COleSafeArray实现二维数组将字符串写入excel

// VARTYPE vt = VT_BSTR  ; /*数组元素的类型,string*/
        VARTYPE vt = VT_I4; /*数组元素的类型,long*/

    SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/

    sabWrite[0].cElements = 1;

    sabWrite[0].lLbound = 0;

    sabWrite[1].cElements = 3;

    sabWrite[1].lLbound = 0;

    COleSafeArray olesaWrite;

    olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);

    /*通过指向数组的指针来对二维数组的元素进行间接赋值*/

    long (*pArray)[2] = NULL;

    olesaWrite.AccessData((void **)&pArray);

    memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));

    /*释放指向数组的指针*/

    olesaWrite.UnaccessData();

    pArray = NULL;

    /*对二维数组的元素进行逐个赋值*/

    long index[2] = {0, 0};

    long lFirstLBound = 0;

    long lFirstUBound = 0;

    long lSecondLBound = 0;

    long lSecondUBound = 0;

    olesaWrite.GetLBound(1, &lFirstLBound);

    olesaWrite.GetUBound(1, &lFirstUBound);

    olesaWrite.GetLBound(2, &lSecondLBound);

    olesaWrite.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 = str[j];

            //CString lElement = ch;

            olesaWrite.PutElement(index, &lElement);

}

    }

    /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/

    VARIANT varWrite = (VARIANT)olesaWrite;

    range.put_Value2(varWrite);    
这样能将输入的整形写入excel,当变成VT_BSTR报内存不足,求指导如何修改
------解决方案--------------------
可以通过另外一种写法,
CRange write_range = start_range.get_Offset(COleVariant((long)7),COleVariant((long)j)) ;
  write_range.put_Value2((COleVariant)(str[j]));

C++中,可以使用Windows API来操作Excel,以下是一个示例代码,可以将二维数组写入Excel中: ```c++ #include <Windows.h> #include <string> void writeToExcel(int** data, int rows, int cols, std::string fileName) { // 初始化COM库 CoInitialize(NULL); // 创建Excel应用程序对象 IDispatch* pExcelApp; CLSID clsid; CLSIDFromProgID(L"Excel.Application", &clsid); CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void**)&pExcelApp); // 设置Visible属性为true,即可看到Excel打开的界面 VARIANT var; var.vt = VT_BOOL; var.boolVal = TRUE; IDispatch* pExcelAppDisp; pExcelApp->QueryInterface(IID_IDispatch, (void**)&pExcelAppDisp); DISPID dispid; LPOLESTR szMember = L"Visible"; pExcelAppDisp->GetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_SYSTEM_DEFAULT, &dispid); pExcelAppDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &var, NULL, NULL, NULL); // 获取Workbooks集合对象 IDispatch* pWorkbooks; szMember = L"Workbooks"; pExcelAppDisp->GetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_SYSTEM_DEFAULT, &dispid); VARIANT result; pExcelAppDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &result, NULL, NULL, NULL); pWorkbooks = result.pdispVal; // 打开Excel文件或创建一个新文件 IDispatch* pWorkbook; VARIANT vFileName; vFileName.vt = VT_BSTR; vFileName.bstrVal = SysAllocStringLen(NULL, fileName.size()); MultiByteToWideChar(CP_ACP, 0, fileName.c_str(), fileName.size(), vFileName.bstrVal, fileName.size()); szMember = L"Open"; pWorkbooks->GetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_SYSTEM_DEFAULT, &dispid); pWorkbooks->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &result, NULL, NULL, NULL); pWorkbook = result.pdispVal; // 获取Worksheets集合对象 IDispatch* pWorksheets; szMember = L"Worksheets"; pWorkbook->GetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_SYSTEM_DEFAULT, &dispid); pWorkbook->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &result, NULL, NULL, NULL); pWorksheets = result.pdispVal; // 获取第一个Worksheet对象 IDispatch* pWorksheet; szMember = L"Item"; VARIANT index; index.vt = VT_I4; index.lVal = 1; pWorksheets->GetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_SYSTEM_DEFAULT, &dispid); pWorksheets->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &result, 1, &index, NULL); pWorksheet = result.pdispVal; // 将数据写入Worksheet中 for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { VARIANT value; value.vt = VT_I4; value.lVal = data[i][j]; szMember = L"Cells"; pWorksheet->GetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_SYSTEM_DEFAULT, &dispid); VARIANT xIndex; xIndex.vt = VT_I4; xIndex.lVal = i + 1; VARIANT yIndex; yIndex.vt = VT_I4; yIndex.lVal = j + 1; VARIANT cell; VARIANT params[2] = { xIndex, yIndex }; pWorksheet->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &cell, 2, params, NULL); szMember = L"Value"; cell.pdispVal->GetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_SYSTEM_DEFAULT, &dispid); cell.pdispVal->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &value, NULL, NULL, NULL); } } // 保存并关闭Excel文件 szMember = L"Save"; pWorkbook->GetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_SYSTEM_DEFAULT, &dispid); pWorkbook->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, NULL, NULL, NULL, NULL); szMember = L"Close"; pWorkbook->GetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_SYSTEM_DEFAULT, &dispid); pWorkbook->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, NULL, NULL, NULL, NULL); // 释放COM资源 pExcelAppDisp->Release(); pExcelApp->Release(); CoUninitialize(); } ``` 调用示例: ```c++ int data[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; writeToExcel((int**)data, 3, 4, "test.xlsx"); ``` 该示例代码中,使用了Windows API的COM接口来操作Excel实现了将二维数组写入Excel的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值