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

Excel开发入门(C#和C++实例)

2012-03-09 00:00 387 查看

Excel 开发文档

这篇文章的例子采用 Office 2003 英文版。首先打开一个 Excel2003 程序,然后选择菜单 Help — Microsoft Excel Help, 如下图:

这样,右边会出现一个帮助子窗口,如下:



选择 Table of Contents ,会出现下图。



最后一行 Microsoft Excel Visual Basic Reference 就是我们要找的文档。该文档基本描述了 Excel 的主要对象的属性和方法。

如果你安装了 MSDN FOR VS.NET 2005 英文版 , 你可以在下面的地址找到 Excel 的例子程序:
ms-help://MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_fxsamples/l ocal/sampleexecutables/Technologies/Interop/Applications/Office/Excel.zip
MSND 也包含了一个专题: Office Solutions Development 。

Excel Application 对象

概念

Application 对象代表的是 Excel 程序。 为了更好的理解 Application 是什么,我们可以先启动一个 Excel 程序 ,然后选择菜单栏最右边的关闭按钮,这样就可以关掉默认创建的空文档对象。 现在出现在我们眼前的就是 Application 对象:



Excel 是一个 MDI 程序。 MDI ( Mutiple Document Interface — 多文档界面)怎么理解呢?
熟悉微软历史悠久的 MFC 开发知识的程序员就知道:每一个 MDI 窗口应用程序都有一个主框架窗口,主框架 窗口可以拥有多 个子框架窗口 ,每个子框架窗口管理一个 Document 对象 ( 文档对象负责管理数据 ) 和一个 View 对象(视图对象负责显示数据,接受用户事件)。 实际上后来 MDI 概念只是代表一种风格,即一个主框架窗口允许同时显示多个子窗口 ,是否有 Document 对象已经不重要。
现在我们可以清楚地知道 Excel 的 Application 对象就代表了 MDI 风格窗口的主框架。

示例

示例的目的是描述如何使用多种语言来创建一个 Excel 程序。 为了简化篇幅, 如何使用 IDE 的内容不作详细描述。

C# 代码

首先创建一个 C# 的 Console 工程。我这里使用的总是 Visual Studio.net 2005 英文版。 然后右键选择工程,选择 Add Reference ,在弹出的对话框中选择 COM 一栏,选中如下的组件:



请注意下面的代码:
using System.Reflection; // For Missing.Value and BindingFlags
using System.Runtime.InteropServices; // For COMException
using Microsoft.Office.Interop.Excel;

namespace ExcelApplicationSample
{
class Program
{
static void Main ( string [] args)
{
try
{
Application app = new Application ();
app.Visible = true ;
app.Quit();
app=null; // 这句话可以使垃圾回收器关闭Excel进程
}
catch ( COMException e)
{
Console .WriteLine(e.Message);
}
}
}
}
Application app = new Application (); 创建了一个Excel的Application对象。 app.Visible = true ; 设置窗口状态为显示。 app .Quit(); 关闭Application对象。注意,如果出错会抛出COMException异常。 如果我们将断点放在app.Quit()这一行,我们会看到程序会打开一个只有主框架的Excel程序。就像前面的图示一样。

C++ 代码

创建一个 Win32 Console 工程 ExcelApplicationSampleCPlus 。然后选择添加 ATL 支持,如下图:



源代码如下:

#include "stdafx.h"
#include
using namespace std;

#import "C:Program FilesCommon FilesMicrosoft SharedOFFICE11mso.dll" rename( "RGB" , "MSRGB" )

#import "C:Program FilesCommon FilesMicrosoft SharedVBAVBA6VBE6EXT.OLB"
rename( "Reference" , "ignorethis" ), rename( "VBE" , "JOEVBE" )

#import "C:Program FilesMicrosoft OfficeOFFICE11excel.exe" exclude( "IFont" , "IPicture" )
rename( "RGB" , "ignorethis" ), rename( "DialogBox" , "ignorethis" ), rename( "VBE" , "JOEVBE" ),
rename( "ReplaceText" , "JOEReplaceText" ), rename( "CopyFile" , "JOECopyFile" ),
rename( "FindText" , "JOEFindText" ), rename( "NoPrompt" , "JOENoPrompt" )

using namespace Office;
using namespace VBIDE;
using namespace Excel ;

#include "WindowsError.h"

class AppartmentWrapper
{
public :
AppartmentWrapper()
{
::CoInitialize(NULL);
}

~AppartmentWrapper()
{
::CoUninitialize();
}
};

int _tmain( int argc, _TCHAR* argv[])
{
try
{
AppartmentWrapper appartment;
_ApplicationPtr ptr=NULL;
HRESULT hr=ptr.CreateInstance( "Exce2l.Application" );
if (FAILED(hr))
{
cout<<
return 1;
}
ptr->PutVisible (0,VARIANT_TRUE);
hr=ptr->Quit();
if (FAILED(hr))
{
cout<<
return 1;
}
}
catch (_com_error const & e)
{
cout<<
return 1;
}
return 0;
}

VC++ 的代码要比 C# 复杂得多,主要在于:

引入组件库的时候需要重命名一些类,避免重名

错误信息的获取没有 C# 的 COMException 异常对象来支持,需要自己处理。 CWindowsError::getOfficeError 方法是我自己花了一个小时才编写好的。代码如下:

#pragma once

#include
#include

class CWindowsError
{
public :
static std::string getLastError()
{
char szBuf[80];
void * lpMsgBuf=NULL;
DWORD dw = GetLastError();

FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
( char *) &lpMsgBuf,
0,
NULL);

wsprintfA(szBuf, "error %d: %s" ,dw, lpMsgBuf);

LocalFree(lpMsgBuf);
return szBuf;
}

static std::string getOfficeError(HRESULT hr)
{
char buf[256]={0};
FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
hr,
MAKELANGID(LANG_ NEUTRAL, SUBLANG_DEFAULT),
&buf[0],
256,
NULL);
std::stringstream stream;
stream<< "error " <
<<
": "
<

return stream.str();
}
};

另外你需要对 COM 有所了解,这点对很多 VC 程序员难度都不小。

由于 .Net 是通过 Interop 方式间接调用 Office 组件(整个 Office 程序都是由 COM 组件编写的),因此比起 C++ 直接调用 IDispatch 接口方式要慢得多。不过一般情况下,使用 Office 的程序性能要求不会很苛刻, .Net 技术可以让我们的生活更加轻松许多。

Work b ooks Work b ook 对象

WorkBook 对象代表了一个 Excel 程序可以打开的一个 工作簿。如下图中标题为 Book1 的子窗口就是一个 Workbook 对象。



由于 Excel 是 MDI 程序,所以可以同时打开多个 WorkBook 对象作为子窗口。如下图中的 Book1 和 Book2 窗口。



代表框架窗口的 Application 对象管理着 WorkBooks 对象, WorkBooks 对象是 WorkBook 对象的集合。

创建一个空 Work b ook 对象

C# 代码

我们对前面的 C# 代码进行了 一些修改,代码如下:
class Program
{
static void Main ( string [] args)
{
Application app= null ;
try
{
app = new Application ();
Workbook book=CreateDocument(app);
app.Visible = true ;
}
catch ( COMException e)
{
Console .WriteLine(e.Message);
}
finally
{
app.Quit();
}
}

static Workbook CreateDocument( Application app)
{
return app.Workbooks.Add( XlWBATemplate .xlWBATWorksheet);
}
}
注意CreateDocument方法的实现代码 , XlWBATemplate 枚举类型 的值 指定了 要创建的 Workb ook的类型。
xlWBATChart 代表 Chart.
xlWBATExcel IntlMacroSheet 代表 Excel version 4 macro.
xlWBATExcel4MacroSheet 代表 Excel version 4 international macro.
xlWBATWorksheet 代表 Worksheet.
Worksheet 的概念下面一个章节会讲到,这里需要知道的是当创建一个 WorkBook 对象的时候 , 总是会 自动 创建一个 Worksheet 对象。

C++ 代码

_WorkbookPtr createWorkbook(_ApplicationPtr app)
{
WorkbooksPtr books=app->GetWorkbooks();
_variant_t v(xlWorksheet);
return books->Add(v);
}

int _tmain( int argc, _TCHAR* argv[])
{
try
{
AppartmentWrapper appartment;
_ApplicationPtr ptr=NULL;
HRESULT hr=ptr.CreateInstance( "Excel.Application" );
if (FAILED(hr))
{
cout<<
CWindowsError::getOfficeError(hr)<<endl;
return 1;
}
_WorkbookPtr workbook=createWorkbook(ptr);
ptr->PutVisible (0,VARIANT_TRUE);
hr=ptr->Quit();
if (FAILED(hr))
{

cout<<CWindowsError::getOfficeError(hr)<<endl;

return 1;
}
}
catch (_com_error const & e)
{
cout<<CWindowsError::getOfficeError(hr)<<endl;
return 1;
}
return 0;
}

C++ 中的 Workbook 类型的枚举定义为:
enum XlSheetType
{
xlChart = -4109,
xlDialogSheet = -4116,
xlExcel4IntlMacroSheet = 4,
xlExcel4MacroSheet = 3,
xlWorksheet = -4167
};

打开一个已经存在的 WorkBook 对象

C# 代码

static Workbook OpenDocument( Application app, String fileName)
{
return app.Workbooks.Open(fileName, Type .Missing, Type .Missing, Type .Missing, Type .Missing, Type .Missing, Type .Missing, Type .Missing,
Type .Missing, Type .Missing, Type .Missing, Type .Missing, Type .Missing, Type .Missing, Type .Missing);
}

C++ 代码

_WorkbookPtr openWorkbook(_ApplicationPtr app,string const & fileName)
{
WorkbooksPtr books=app->GetWorkbooks();
return books->Open(_bstr_t(fileName.c_str()));
}

WorkSheets WorkSheet 对象

每一个 Workbook 对象都拥有一个或者多个 Worksheet 对象。每个 Worksheet 对象代表了一张表格。如下图:



这里有 Sheet1,Sheet2,Sheet3 三张表格, 他们都是 Worksheet 对象。 当前的 Workbook 对象代表了这个子窗口,并且用有成员 Worksheets 对象。 Worksheets 对象是三个 Worksheet 对象的集合。

读取某表格实际使用的行数和列数

Worksheet sheet = ( Worksheet )book.Sheets[ "Sheet1" ];
int rowCount=sheet.UsedRange.Rows.Count;
int colCount = sheet.UsedRange.Columns.Count;

读取某 表格指定位置的数据

static String G etValue( Worksheet sheet, int row, int col)
{
Range cell=( Range )sheet.UsedRange.Cells[row, col];
return cell.Text.ToString();
}
注意,行和列的索引总是从1开始。

改写某 表格指定位置的数据

static void S etValue( Worksheet sheet, int row, int col, String value)
{
Range cell = ( Range )sheet.UsedRange.Cells[row, col];
cell.Value2 = value; ;
}

插入 行到某 表格中

// 插行(在指定 WorkSheet 指定行上面插入指定数量行)
static void InsertRows(Excel. Worksheet wst, int rowIndex, int count)
{
Excel. Range range = (Excel. Range )wst.Rows[rowIndex, Type .Missing];

for ( int i = 0; i < count; i++)
{
range.Insert(Excel. XlDirection .xlDown, Type .Missing);
}
}

5

$(document).ready(function(){dp.SyntaxHighlighter.HighlightAll('code');});

原文链接:
http://blog.csdn.net/sheismylife/article/details/4618961
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: