纯 C++ 代码创建并保存 EXCEL 文件

最近发现很多人都在研究OFFICE方面的编程,当然,偶也是一个啦:)
可是这方面的资料却很难找,而且大部分(几乎全部)都是英文的。
于是,便有了写这篇文章的念头(好了,言归正传)。

本来OFFICE已经为大家提供了很好用的COM组件,但我发现我怎么用怎么不顺手(估计是本人太菜了)。
于是便绞尽脑汁想用纯 C++ 代码来实现,终于,哈哈,嘿嘿,嚯嚯……

好了,下面是我的步骤(偶用的VC++ 6.0):
1. 先新建一个 Win32 控制台应用/Win32 Console Application 工程,工程名不妨叫做 createXLS
2. 工程向导里选择 A "Hello,World!" application ,新建完毕(废话)。
3. 打开 createXLS.cpp 文件,添加代码(本不想贴代码的,想做个工程让大家下载,因为太简单,不好意思兴师动众了):
#include  < ole2.h >    //  这个头文件一定要包含,否则就不能自动化了
#include  < stdio.h >

//  接着修改我们添加一个函数,这个函数是整个程序的基础
//  若以后写别的程序而想用纯 C++ 来实现自动化,这个函数是可以复用的
HRESULT AutoWrap( int  autoType, VARIANT  * pvResult, IDispatch  * pDisp, LPOLESTR ptName,  int  cArgs...);

//  修改主函数
int  main( int  argc,  char *  argv[])
{
    
//  printf("Hello World! ");  //  注释掉这一句

    
//  初始化COM库
    CoInitialize(NULL);

    
//  获得EXCEL的CLSID
    CLSID clsid;
    HRESULT hr 
=  CLSIDFromProgID(L " Excel.Application " & clsid);

    
if (FAILED(hr)) {
        ::MessageBox(NULL, 
" CLSIDFromProgID() 函数调用失败! " " 错误 " 0x10010 );
        
return   - 1 ;
    }

    
//  创建实例
    IDispatch  * pXlApp;
    hr 
=  CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, ( void   ** ) & pXlApp);
    
if (FAILED(hr)) {
        ::MessageBox(NULL, 
" 请检查是否已经安装EXCEL! " " 错误 " 0x10010 );
        
return   - 2 ;
    }

    
//  显示,将Application.Visible属性置1
    VARIANT x;
    x.vt 
=  VT_I4;
    x.lVal 
=   1 ;
    AutoWrap(DISPATCH_PROPERTYPUT, NULL, pXlApp, L
" Visible " 1 , x);

    
//  获取Workbooks集合
    IDispatch  * pXlBooks;
    {
        VARIANT result;
        VariantInit(
& result);
        AutoWrap(DISPATCH_PROPERTYGET, 
& result, pXlApp, L " Workbooks " 0 );
        pXlBooks 
=  result.pdispVal;
    }

    
//  调用Workbooks.Add()方法,创建一个新的Workbook
    IDispatch  * pXlBook;
    {
        VARIANT result;
        VariantInit(
& result);
        AutoWrap(DISPATCH_PROPERTYGET, 
& result, pXlBooks, L " Add " 0 );
        pXlBook 
=  result.pdispVal;
    }

    
//  创建一个15x15的数组,用于填充表格
    VARIANT arr;
    WCHAR szTmp[
32 ];
    arr.vt 
=  VT_ARRAY  |  VT_VARIANT;
    SAFEARRAYBOUND sab[
2 ];
    sab[
0 ].lLbound  =   1 ; sab[ 0 ].cElements  =   15 ;
    sab[
1 ].lLbound  =   1 ; sab[ 1 ].cElements  =   15 ;
    arr.parray 
=  SafeArrayCreate(VT_VARIANT,  2 , sab);

    
//  初始化数组内容
     for ( int  i = 1 ; i <= 15 ; i ++ ) {
        
for ( int  j = 1 ; j <= 15 ; j ++ ) {
            VARIANT tmp;
            tmp.vt 
=  VT_BSTR;
            wsprintfW(szTmp,L
" %i,%i " ,i,j);
            tmp.bstrVal 
=  SysAllocString(szTmp);
            
//  添加数据到数组中
             long  indices[]  =  {i,j};
            SafeArrayPutElement(arr.parray, indices, (
void   * ) & tmp);
        }
    }

    
//  从Application.ActiveSheet属性获得Worksheet对象
    IDispatch  * pXlSheet;
    {
        VARIANT result;
        VariantInit(
& result);
        AutoWrap(DISPATCH_PROPERTYGET, 
& result, pXlApp, L " ActiveSheet " 0 );
        pXlSheet 
=  result.pdispVal;
    }

    
//  选择一个15x15大小的Range
    IDispatch  * pXlRange;
    {
        VARIANT parm;
        parm.vt 
=  VT_BSTR;
        parm.bstrVal 
=  ::SysAllocString(L " A1:O15 " );

        VARIANT result;
        VariantInit(
& result);
        AutoWrap(DISPATCH_PROPERTYGET, 
& result, pXlSheet, L " Range " 1 , parm);
        VariantClear(
& parm);

        pXlRange 
=  result.pdispVal;
    }

    ::MessageBox(NULL, 
" 我要填充数据了哈! " " 通知 " 0x10000 );

    
//  用我们的数组填充这个Range
    AutoWrap(DISPATCH_PROPERTYPUT, NULL, pXlRange, L " Value " 1 , arr);
    pXlRange
-> Release();

    
//  另外再选择一个Range
    {
        VARIANT parm;
        parm.vt 
=  VT_BSTR;
        parm.bstrVal 
=  ::SysAllocString(L " A11:O25 " );

        VARIANT result;
        VariantInit(
& result);
        AutoWrap(DISPATCH_PROPERTYGET, 
& result, pXlSheet, L " Range " 1 , parm);
        VariantClear(
& parm);

        pXlRange 
=  result.pdispVal;
    }

    ::MessageBox(NULL, 
" 我还要填充一次哈! " " 通知 " 0x10000 );

    
//  用我们的数组再次填充这个Range
    AutoWrap(DISPATCH_PROPERTYPUT, NULL, pXlRange, L " Value " 1 , arr);

    ::MessageBox(NULL, 
" 好了,我们该保存文件了! " " 通知 " 0x10000 );

    
//  接下来我们该保存文件了,利用Worksheet.SaveAs()方法(我这里忽略了其他所有参数,除了文件名)
    {
        VARIANT filename;
        filename.vt 
=  VT_BSTR;
        filename.bstrVal 
=  SysAllocString(L " c:/test.xls " );
        AutoWrap(DISPATCH_METHOD, NULL, pXlSheet, L
" SaveAs " 1 , filename);
    }

    ::MessageBox(NULL, 
" 哈哈,收工了! " " 通知 " 0x10000 );

    
//  退出,调用Application.Quit()方法
    AutoWrap(DISPATCH_METHOD, NULL, pXlApp, L " Quit " 0 );

    
//  释放所有的接口以及变量
    pXlRange -> Release();
    pXlSheet
-> Release();
    pXlBook
-> Release();
    pXlBooks
-> Release();
    pXlApp
-> Release();
    VariantClear(
& arr);

    
//  注销COM库
    CoUninitialize();

    
return   0 ;
}

//  AutoWrap 函数的正体(真身,哈哈)
//  先声明:这个函数不是偶写的哈(别问是谁写的,偶也不知道)
//  AutoWrap() - Automation helper function...
HRESULT AutoWrap( int  autoType, VARIANT  * pvResult, IDispatch  * pDisp, LPOLESTR ptName,  int  cArgs...) {
    
//  Begin variable-argument list...
    va_list marker;
    va_start(marker, cArgs);

    
if ( ! pDisp) {
        MessageBox(NULL, 
" NULL IDispatch passed to AutoWrap() " " Error " 0x10010 );
        _exit(
0 );
    }

    
//  Variables used...
    DISPPARAMS dp  =  { NULL, NULL,  0 0  };
    DISPID dispidNamed 
=  DISPID_PROPERTYPUT;
    DISPID dispID;
    HRESULT hr;
    
char  buf[ 200 ];
    
char  szName[ 200 ];

    
//  Convert down to ANSI
    WideCharToMultiByte(CP_ACP,  0 , ptName,  - 1 , szName,  256 , NULL, NULL);

    
//  Get DISPID for name passed...
    hr  =  pDisp -> GetIDsOfNames(IID_NULL,  & ptName,  1 , LOCALE_USER_DEFAULT,  & dispID);
    
if (FAILED(hr)) {
        sprintf(buf, 
" IDispatch::GetIDsOfNames("%s") failed w/err 0x%08lx " , szName, hr);
        MessageBox(NULL, buf, 
" AutoWrap() " 0x10010 );
        _exit(
0 );
        
return  hr;
    }

    
//  Allocate memory for arguments...
    VARIANT  * pArgs  =   new  VARIANT[cArgs + 1 ];
    
//  Extract arguments...
     for ( int  i = 0 ; i < cArgs; i ++ ) {
        pArgs[i] 
=  va_arg(marker, VARIANT);
    }

    
//  Build DISPPARAMS
    dp.cArgs  =  cArgs;
    dp.rgvarg 
=  pArgs;

    
//  Handle special-case for property-puts!
     if (autoType  &  DISPATCH_PROPERTYPUT) {
        dp.cNamedArgs 
=   1 ;
        dp.rgdispidNamedArgs 
=   & dispidNamed;
    }

    
//  Make the call!
    hr  =  pDisp -> Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, autoType,  & dp, pvResult, NULL, NULL);
    
if (FAILED(hr)) {
        sprintf(buf, 
" IDispatch::Invoke("%s"=%08lx) failed w/err 0x%08lx " , szName, dispID, hr);
        MessageBox(NULL, buf, 
" AutoWrap() " 0x10010 );
        _exit(
0 );
        
return  hr;
    }
    
//  End variable-argument section...
    va_end(marker);

    delete [] pArgs;

    
return  hr;
}

 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值