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

来源:互联网 发布:rc522 stc源码 编辑:程序博客网 时间:2024/06/05 13:43
本文转载于http://blog.sina.com.cn/s/blog_4c79cc450100ll43.html
最近发现很多人都在研究OFFICE方面的编程,当然,偶也是一个啦:)可是这方面的资料却很难找,而且大部分(几乎全部)都是英文的。于是,便有了写这篇文章的念头(好了,言归正传)。本来OFFICE已经为大家提供了很好用的COM组件,但我发现我怎么用怎么不顺手(估计是本人太菜了)。于是便绞尽脑汁想用纯 C++ 代码来实现,终于,哈哈,嘿嘿,嚯嚯……好了,下面是我的步骤(偶用的VC++ 6.0):1. 先新建一个“Win32 控制台应用/Win32 Console Application”工程,工程名不妨叫做“createXLS”。2. 工程向导里选择“A "Hello,World!" application”,新建完毕(废话)。3. 打开“createXLS.cpp”文件,添加代码(本不想贴代码的,想做个工程让大家下载,因为太简单,不好意思兴师动众了):#include <ole2.h>  // 这个头文件一定要包含,否则就不能自动化了// 接着修改我们添加一个函数,这个函数是整个程序的基础// 若以后写别的程序而想用纯 C++ 来实现自动化,这个函数是可以复用的</span>HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp, LPOLESTR ptName, int cArgs...);// 修改主函数int main(int argc, char* argv[]){ // printf("Hello World!\n"); // 注释掉这一句 // 初始化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 0xlx", 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\"=lx) failed w/err 0xlx", szName, dispID, hr);        MessageBox(NULL, buf, "AutoWrap()", 0x10010);        _exit(0);        return hr;    }    // End variable-argument section...    va_end(marker);    delete [] pArgs;    return hr;}程序在WINDOWS2000+EXCEL2000环境下运行良好,呵呵

0 0
原创粉丝点击