您的位置:首页 > 编程语言 > C语言/C++

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

2013-08-22 11:35 507 查看
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++ 来实现自动化,这个函数是可以复用的

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环境下运行良好。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: