在VC中使用智能指针操作Excel
2008-10-10 12:02
211 查看
在
VC
中使用智能指针操作
Excel
最近的一个工程中,需要将数据导入
Excel
表格中,项目经理知道我以前没有接触过操作
Excel
的经验,于是给了一段小程序给我,让我参考着做。
这段程序是使用智能指针操作
Excel
,在网络上找了一个星期,居然没有一片关于智能指针操作
Excel
的文章,只有
Automation
技术,而且所有介绍
Automation
技术的文章都是大同小异,并且代码多,说明少。没有任何帮助,光有一堆代码,对于理解和使用没有太大的帮助。在这样一个艰苦的条件下,我决定利用手中仅有的工具:
Microsoft Excel Visual Basic
参考
和
Microsoft Visual Studio 2005
的提示功能,摸索出一些利用智能指针操作
Excel
的心得,写出来,既是一次总结,也是一种分享,并且摸索还在继续,心得也还陆续会有。
一、背景说明
1
.
Microsoft Excel Visual Basic
参考是提供给
VB
程序员的一个操作
Excel
的帮助,帮助中的对象、集合、方法、常量都已经在
COM
中实现,在
VC
中可以找到对应的实体。
2
.既然是智能指针,那么绝大多数的操作都是“
->
”,然而,如果安装了
Visual Assist X
,使用“
->
”操作符的时候,是得不到任何提示的。这个时候,如果需要查看提示,则可以先使用“
.
”操作符,编译时再将“
.
”改成“
->
”。
二、
Excel
概念介绍
从
MFC
工程结构的角度来看,
Excel
属于多文档视图结构,一个应用程序包含若干个文档,称作工作簿,每个文档中包含若干个工作表。从智能指针对象模型来看可以做如下划分:
1
.
_ApplicationPtr
:该对象即表示一个
Excel
应用程序。
2
.
WorkbooksPtr
:在一个
_ApplicationPtr
对象中,包含一个工作簿集合。
3
.
_WorkbookPtr
:在工作簿集合中包含若干的工作簿对象。一个工作簿对象对应一个
xls
文件。
4
.
WorksheetsPtr
:在一个工作簿对象中,包含一个工作表集合。
5
.
_WorksheetPtr
:在工作表集合中包含若干个工作表对象,工作表对象是操作
Excel
的基本单位。
6
.
Range
:这是一个集合,工作表中单元格的集合,控制对单元格的操作。
三、准备工作
1
.
加载动态库。
#define
OFFICEXP
1
#define
OFFICE2000
2
//
如果使用OFFICE2000
的内核,手动将此处改为#define OFFICE_VER OFFICE2000
#define
OFFICE_VER
OFFICEXP
#define
USE_PROGID
1
#define
USE_LIBID
0
#define
_M2STR
(
x
) #
x
#define
M2STR
(
x
)
_M2STR
(
x
)
#ifndef
MSDLL_PATH
#if
OFFICE_VER
==
OFFICEXP
#define
_MSDLL_PATH
"C:/Program Files/Common Files/Microsoft Shared/Office11/MSO.DLL"
#elif
OFFICE_VER
==
OFFICE2000
#define
_MSDLL_PATH "C:/Program Files/Microsoft Office/Office/MSO9.dll"
#endif
#else
#define _MSDLL_PATH M2STR(MSDLL_PATH)
#endif
#import
_MSDLL_PATH
rename
(
"RGB"
,
"MSRGB"
)
#ifdef
VBE6EXT_PATH
#import M2STR(VBE6EXT_PATH)
#else
#import
"C:/Program Files/Common Files/Microsoft Shared/VBA/VBA6/VBE6EXT.OLB"
#endif
#if
USE_PROGID
#import
"progid:Excel.Sheet"
auto_search
auto_rename
rename_search_namespace
(
"Office10"
)
#elif
USE_LIBID
#import "libid:{00020813-0000-0000-C000-000000000046}" auto_search auto_rename version(1.3) lcid(0) no_search_namespace
#else
#ifndef MSEXCEL_PATH
#if
OFFICE_VER == OFFICEXP
#define
_MSEXCEL_PATH "C:/Program Files/Microsoft Office/Office11/excel.exe"
#elif
OFFICE_VER == OFFICE2000
#define
_MSEXCEL_PATH "C:/Program Files/Microsoft Office/Office/excel.exe"
#endif
#else
#define _MSEXCEL_PATH
M2STR(MSEXCEL_PATH)
#endif
#import _MSEXCEL_PATH auto_search auto_rename dual_interfaces
#endif
using
namespace
Excel
;
2
.初始化
COM
组件。
CoInitialize
(
NULL
);
程序结束时记得释放资源
CoUninitialize
();
四、正式开始
1
.操作
Excel
,首先要初始化一个应用程序实例,代码如下:
_ApplicationPtr
pApp
;
pApp
.
CreateInstance
(
L
"Excel.Application"
);
pApp
->
PutVisible
(0,
VARIANT_TRUE
);
使用
ADO
操作过数据库的人对代码的前两句不会感到陌生,初始化的实例不同而已,而第三句,则是使
Excel
应用程序显示出来,就像在“开始”菜单中运行
Excel
一样,可以看到一个打开的
Excel
程序,如果赋值
VARIANT_FALSE
则看不到应用程序,但是在任务管理器中已经创建了一个
EXCEL
进程,这是前两句的功劳。
程序结束前退出应用程序:
pBook
.
PutSaved
(0,
VARIANT_TRUE
);
pApp
->
Quit
();
2
.在这个空白的应用实例中,需要创建一个工作簿(即文档)。代码如下:
WorkbooksPtr
pBooks
=
pApp
->
GetWorkbooks
();
_WorkbookPtr
pBook
=
pBooks
->
Add
((
long
)
xlWorkbook
);
前面讲过,在应用实例中有一个工作簿集合,就算初始时集合是空的,它也是存在的,要创建一个工作簿,实际就是在这个集合中添加一个工作簿而已,第一句代码获得工作簿集合,第二句添加一个工作簿,并返回新创建工作簿的指针。由于一个工作簿对应一个“
xls
”文件,所以,大部分情况下我们在一个应用实例中都只会创建一个工作簿,这和习惯有关,但不是绝对,如果添加了多个,可以使用
_WorkbookPtr
Workbooks
::
GetItem
(
const
_variant_t
&
Index
)
这个函数来获得每个工作簿的指针。
通过
Studio
的提示功能,我们看到
Add
函数的原型:
Excel
::
_WorkbookPtr
Excel
::
Workbooks
::
Add
(
const
_variant_t
&
Template
,
long
lcid
= 0)
在
Microsoft Excel
帮助中,从“方法”,“
A
”,“
Add
”找到“应用于
Workbooks
对象的
Add
方法”,我们可以看到对第一个参数的说明(前面说过,由于
VC
缺少这类函数的说明,我们只能借助
VB
了),这个说明对
VC
同样适用。小弟水平有限,没有弄清第二个参数的所以然,姑且使用默认值,在这里不影响对
Excel
的操作,这个参数大概是与
COM
机制有关的某个东西吧。
3
.上一步使用
xlWorkbook
参数添加了一个工作簿,因此,这个工作簿中默认有一个工作表,同样的道理,在工作簿中有一个工作表集合,要操作工作表,首先得到工作表集合。
SheetsPtr
pSheets
=
pBook
->
GetWorksheets
();
可以这样
_WorksheetPtr pSheet
=
pSheets
->
GetItem
(1);
也可以这样
_WorksheetPtr
pSheet
=
pBook
->
GetActiveSheet
();
来得到默认创建的那个工作表。这是因为当前只有一个工组表,所以这个工组表就默认为激活的工作表(在工作簿中只会有一个工作表处于激活状态,就是当前操作的这个工作簿)。如果工作簿中有多个工组表,还是需要通过
pSheets
->
GetItem
函数获得工作表对象。补充,有些操作可以在工作表处于非激活状态下进行,这样,使用
pSheets
->
GetItem
获得工作表对象即可对工作表操作,但是有些操作必须是工作表处于激活状态下进行,因此,获得工作表对象后,还需要
pSheet
->
Activate
();
激活它。
给工作表重命名吧:
pSheet
->
PutName
(
"Exp One Sheet"
);//
如果运行有错,可以
pSheet
->
PutName
(L
"Exp One Sheet"
)
插入一个工作表,函数原型:
_WorksheetPtr
Worksheets
::
Add
(
const
_variant_t
&
Before
=
vtMissing
,
//
在哪个工作表前插入
const
_variant_t
&
After
=
vtMissing
,
//
在哪个工作表后插入
const
_variant_t
&
Count
=
vtMissing
,
//
插入工组表个数
const
_variant_t
&
Type
=
vtMissing
)
//
插入工作表类型
有意思的是,不光这个函数,其他的有默认值的参数的默认值都是
vtMissing
。遗憾的是我没能找到
vtMissing
的具体说明,姑且先用着。
看下面的代码:
_WorksheetPtr pSheet
=
pSheets
->
GetItem
(2);
VARIANT
var
;
var
.
vt
=
VT_DISPATCH
;
var
.
pdispVal
=
pSheet
;
pSheets
->
Add
();
//
在第一个工作表之前插入一个空白工作表
pSheets
->
Add
(
var
);
//
在pSheet
工作表之前插入一个空白工作表
pSheets
->
Add
(
vtMissing
,
var
);
//
在pSheet
工作表之后插入一个空白工作表
pSheets
->
Add
(
vtMissing
,
var
,2);
//
在pSheet
工作表之后插入两个空白工作表
这里仅仅涉及到
_variant_t
类型的使用,将不做说明。注意前两个参数的使用即可,其他类型的参数将报错。
4
.下面将让你看到不同于
C
风格的代码操作工作表中的单元格。
pSheet
->
Range
[
"A1"
][
vtMissing
]->
Value2
=
"EXP A1"
;
pSheet
->
Range
[
"A1"
][
vtMissing
]->
Interior
->
Color
=
RGB
(255,0,0);
pSheet
->
Range
[
"A1"
][
vtMissing
]->
Font
->
Name
=
L
"
隶书"
;
pSheet
->
Range
[
"A1"
][
vtMissing
]->
Font
->
FontStyle
=
L
"Bold Italic"
;
pSheet
->
Range
[
"A1"
][
vtMissing
]->
Font
->
Size
= 10;
如何?是不是有点像
VB
?只需要赋值就能改变对象的属性,以上代码等价于:
RangePtr
range
=
pSheet
->
GetRange
(
"A3"
,
vtMissing
);
range
->
PutValue2
(
"EXP A3"
);
InteriorPtr
interior
=
range
->
GetInterior
();
interior
->
PutColor
(
RGB
(255,0,0));
Excel
::
FontPtr
font
=
range
->
GetFont
();
font
->
PutName
(
L
"
隶书"
);
font
->
PutFontStyle
(
L
"Bold Italic"
);
font
->
PutSize
(10);
VC
的程序员看到这段代码是不是就觉得亲切了,这是
COM
技术的魔力,要想知道为何,自己研究
COM
技术吧。
对上面的代码只做两点说明:
(
1
)
Range
[
"A1"
][
vtMissing
]
和
GetRange
(
"A3"
,
vtMissing
)
表示获得
A3
表示的单元格(用过
Excel
的人都知道
A3
表示什么),通过集合的形式表现出来,该集合只有一个单元格。如果把
vtMissing
换成
B5
,那么将获得一个由
A3
和
B5
之间左右单元组成的集合。
(
2
)
FontPtr
之前的
Excel::
是必须的,缺少
Excel::
编译器会报错,提示不能确定是哪一个
FontPtr
,因为在不同的命名空间中存在若干个
FontPtr
。也许还存在其他的类型会有这样的情况,因此,要特别留意命名空间的限制。
五、小经验
1
.基于
COM
技术,一般的,
I = A->GetP()
可以等价成
I = A->P
;
A->PutP(I)
可以等价成
A->P = I
。
2
.在
Microsoft Excel Visual Basic
参考中查找对象,方法和属性的时候,可以基于第一点将
VB
转换成
VC
。根据
VB
提供的参数类型,在
VC
中使用
VARIANT
类型承载。
如果有讲的不对的地方,欢迎加
MSN
和我交流:
bwmwm@live.cn
。
VC
中使用智能指针操作
Excel
最近的一个工程中,需要将数据导入
Excel
表格中,项目经理知道我以前没有接触过操作
Excel
的经验,于是给了一段小程序给我,让我参考着做。
这段程序是使用智能指针操作
Excel
,在网络上找了一个星期,居然没有一片关于智能指针操作
Excel
的文章,只有
Automation
技术,而且所有介绍
Automation
技术的文章都是大同小异,并且代码多,说明少。没有任何帮助,光有一堆代码,对于理解和使用没有太大的帮助。在这样一个艰苦的条件下,我决定利用手中仅有的工具:
Microsoft Excel Visual Basic
参考
和
Microsoft Visual Studio 2005
的提示功能,摸索出一些利用智能指针操作
Excel
的心得,写出来,既是一次总结,也是一种分享,并且摸索还在继续,心得也还陆续会有。
一、背景说明
1
.
Microsoft Excel Visual Basic
参考是提供给
VB
程序员的一个操作
Excel
的帮助,帮助中的对象、集合、方法、常量都已经在
COM
中实现,在
VC
中可以找到对应的实体。
2
.既然是智能指针,那么绝大多数的操作都是“
->
”,然而,如果安装了
Visual Assist X
,使用“
->
”操作符的时候,是得不到任何提示的。这个时候,如果需要查看提示,则可以先使用“
.
”操作符,编译时再将“
.
”改成“
->
”。
二、
Excel
概念介绍
从
MFC
工程结构的角度来看,
Excel
属于多文档视图结构,一个应用程序包含若干个文档,称作工作簿,每个文档中包含若干个工作表。从智能指针对象模型来看可以做如下划分:
1
.
_ApplicationPtr
:该对象即表示一个
Excel
应用程序。
2
.
WorkbooksPtr
:在一个
_ApplicationPtr
对象中,包含一个工作簿集合。
3
.
_WorkbookPtr
:在工作簿集合中包含若干的工作簿对象。一个工作簿对象对应一个
xls
文件。
4
.
WorksheetsPtr
:在一个工作簿对象中,包含一个工作表集合。
5
.
_WorksheetPtr
:在工作表集合中包含若干个工作表对象,工作表对象是操作
Excel
的基本单位。
6
.
Range
:这是一个集合,工作表中单元格的集合,控制对单元格的操作。
三、准备工作
1
.
加载动态库。
#define
OFFICEXP
1
#define
OFFICE2000
2
//
如果使用OFFICE2000
的内核,手动将此处改为#define OFFICE_VER OFFICE2000
#define
OFFICE_VER
OFFICEXP
#define
USE_PROGID
1
#define
USE_LIBID
0
#define
_M2STR
(
x
) #
x
#define
M2STR
(
x
)
_M2STR
(
x
)
#ifndef
MSDLL_PATH
#if
OFFICE_VER
==
OFFICEXP
#define
_MSDLL_PATH
"C:/Program Files/Common Files/Microsoft Shared/Office11/MSO.DLL"
#elif
OFFICE_VER
==
OFFICE2000
#define
_MSDLL_PATH "C:/Program Files/Microsoft Office/Office/MSO9.dll"
#endif
#else
#define _MSDLL_PATH M2STR(MSDLL_PATH)
#endif
#import
_MSDLL_PATH
rename
(
"RGB"
,
"MSRGB"
)
#ifdef
VBE6EXT_PATH
#import M2STR(VBE6EXT_PATH)
#else
#import
"C:/Program Files/Common Files/Microsoft Shared/VBA/VBA6/VBE6EXT.OLB"
#endif
#if
USE_PROGID
#import
"progid:Excel.Sheet"
auto_search
auto_rename
rename_search_namespace
(
"Office10"
)
#elif
USE_LIBID
#import "libid:{00020813-0000-0000-C000-000000000046}" auto_search auto_rename version(1.3) lcid(0) no_search_namespace
#else
#ifndef MSEXCEL_PATH
#if
OFFICE_VER == OFFICEXP
#define
_MSEXCEL_PATH "C:/Program Files/Microsoft Office/Office11/excel.exe"
#elif
OFFICE_VER == OFFICE2000
#define
_MSEXCEL_PATH "C:/Program Files/Microsoft Office/Office/excel.exe"
#endif
#else
#define _MSEXCEL_PATH
M2STR(MSEXCEL_PATH)
#endif
#import _MSEXCEL_PATH auto_search auto_rename dual_interfaces
#endif
using
namespace
Excel
;
2
.初始化
COM
组件。
CoInitialize
(
NULL
);
程序结束时记得释放资源
CoUninitialize
();
四、正式开始
1
.操作
Excel
,首先要初始化一个应用程序实例,代码如下:
_ApplicationPtr
pApp
;
pApp
.
CreateInstance
(
L
"Excel.Application"
);
pApp
->
PutVisible
(0,
VARIANT_TRUE
);
使用
ADO
操作过数据库的人对代码的前两句不会感到陌生,初始化的实例不同而已,而第三句,则是使
Excel
应用程序显示出来,就像在“开始”菜单中运行
Excel
一样,可以看到一个打开的
Excel
程序,如果赋值
VARIANT_FALSE
则看不到应用程序,但是在任务管理器中已经创建了一个
EXCEL
进程,这是前两句的功劳。
程序结束前退出应用程序:
pBook
.
PutSaved
(0,
VARIANT_TRUE
);
pApp
->
Quit
();
2
.在这个空白的应用实例中,需要创建一个工作簿(即文档)。代码如下:
WorkbooksPtr
pBooks
=
pApp
->
GetWorkbooks
();
_WorkbookPtr
pBook
=
pBooks
->
Add
((
long
)
xlWorkbook
);
前面讲过,在应用实例中有一个工作簿集合,就算初始时集合是空的,它也是存在的,要创建一个工作簿,实际就是在这个集合中添加一个工作簿而已,第一句代码获得工作簿集合,第二句添加一个工作簿,并返回新创建工作簿的指针。由于一个工作簿对应一个“
xls
”文件,所以,大部分情况下我们在一个应用实例中都只会创建一个工作簿,这和习惯有关,但不是绝对,如果添加了多个,可以使用
_WorkbookPtr
Workbooks
::
GetItem
(
const
_variant_t
&
Index
)
这个函数来获得每个工作簿的指针。
通过
Studio
的提示功能,我们看到
Add
函数的原型:
Excel
::
_WorkbookPtr
Excel
::
Workbooks
::
Add
(
const
_variant_t
&
Template
,
long
lcid
= 0)
在
Microsoft Excel
帮助中,从“方法”,“
A
”,“
Add
”找到“应用于
Workbooks
对象的
Add
方法”,我们可以看到对第一个参数的说明(前面说过,由于
VC
缺少这类函数的说明,我们只能借助
VB
了),这个说明对
VC
同样适用。小弟水平有限,没有弄清第二个参数的所以然,姑且使用默认值,在这里不影响对
Excel
的操作,这个参数大概是与
COM
机制有关的某个东西吧。
3
.上一步使用
xlWorkbook
参数添加了一个工作簿,因此,这个工作簿中默认有一个工作表,同样的道理,在工作簿中有一个工作表集合,要操作工作表,首先得到工作表集合。
SheetsPtr
pSheets
=
pBook
->
GetWorksheets
();
可以这样
_WorksheetPtr pSheet
=
pSheets
->
GetItem
(1);
也可以这样
_WorksheetPtr
pSheet
=
pBook
->
GetActiveSheet
();
来得到默认创建的那个工作表。这是因为当前只有一个工组表,所以这个工组表就默认为激活的工作表(在工作簿中只会有一个工作表处于激活状态,就是当前操作的这个工作簿)。如果工作簿中有多个工组表,还是需要通过
pSheets
->
GetItem
函数获得工作表对象。补充,有些操作可以在工作表处于非激活状态下进行,这样,使用
pSheets
->
GetItem
获得工作表对象即可对工作表操作,但是有些操作必须是工作表处于激活状态下进行,因此,获得工作表对象后,还需要
pSheet
->
Activate
();
激活它。
给工作表重命名吧:
pSheet
->
PutName
(
"Exp One Sheet"
);//
如果运行有错,可以
pSheet
->
PutName
(L
"Exp One Sheet"
)
插入一个工作表,函数原型:
_WorksheetPtr
Worksheets
::
Add
(
const
_variant_t
&
Before
=
vtMissing
,
//
在哪个工作表前插入
const
_variant_t
&
After
=
vtMissing
,
//
在哪个工作表后插入
const
_variant_t
&
Count
=
vtMissing
,
//
插入工组表个数
const
_variant_t
&
Type
=
vtMissing
)
//
插入工作表类型
有意思的是,不光这个函数,其他的有默认值的参数的默认值都是
vtMissing
。遗憾的是我没能找到
vtMissing
的具体说明,姑且先用着。
看下面的代码:
_WorksheetPtr pSheet
=
pSheets
->
GetItem
(2);
VARIANT
var
;
var
.
vt
=
VT_DISPATCH
;
var
.
pdispVal
=
pSheet
;
pSheets
->
Add
();
//
在第一个工作表之前插入一个空白工作表
pSheets
->
Add
(
var
);
//
在pSheet
工作表之前插入一个空白工作表
pSheets
->
Add
(
vtMissing
,
var
);
//
在pSheet
工作表之后插入一个空白工作表
pSheets
->
Add
(
vtMissing
,
var
,2);
//
在pSheet
工作表之后插入两个空白工作表
这里仅仅涉及到
_variant_t
类型的使用,将不做说明。注意前两个参数的使用即可,其他类型的参数将报错。
4
.下面将让你看到不同于
C
风格的代码操作工作表中的单元格。
pSheet
->
Range
[
"A1"
][
vtMissing
]->
Value2
=
"EXP A1"
;
pSheet
->
Range
[
"A1"
][
vtMissing
]->
Interior
->
Color
=
RGB
(255,0,0);
pSheet
->
Range
[
"A1"
][
vtMissing
]->
Font
->
Name
=
L
"
隶书"
;
pSheet
->
Range
[
"A1"
][
vtMissing
]->
Font
->
FontStyle
=
L
"Bold Italic"
;
pSheet
->
Range
[
"A1"
][
vtMissing
]->
Font
->
Size
= 10;
如何?是不是有点像
VB
?只需要赋值就能改变对象的属性,以上代码等价于:
RangePtr
range
=
pSheet
->
GetRange
(
"A3"
,
vtMissing
);
range
->
PutValue2
(
"EXP A3"
);
InteriorPtr
interior
=
range
->
GetInterior
();
interior
->
PutColor
(
RGB
(255,0,0));
Excel
::
FontPtr
font
=
range
->
GetFont
();
font
->
PutName
(
L
"
隶书"
);
font
->
PutFontStyle
(
L
"Bold Italic"
);
font
->
PutSize
(10);
VC
的程序员看到这段代码是不是就觉得亲切了,这是
COM
技术的魔力,要想知道为何,自己研究
COM
技术吧。
对上面的代码只做两点说明:
(
1
)
Range
[
"A1"
][
vtMissing
]
和
GetRange
(
"A3"
,
vtMissing
)
表示获得
A3
表示的单元格(用过
Excel
的人都知道
A3
表示什么),通过集合的形式表现出来,该集合只有一个单元格。如果把
vtMissing
换成
B5
,那么将获得一个由
A3
和
B5
之间左右单元组成的集合。
(
2
)
FontPtr
之前的
Excel::
是必须的,缺少
Excel::
编译器会报错,提示不能确定是哪一个
FontPtr
,因为在不同的命名空间中存在若干个
FontPtr
。也许还存在其他的类型会有这样的情况,因此,要特别留意命名空间的限制。
五、小经验
1
.基于
COM
技术,一般的,
I = A->GetP()
可以等价成
I = A->P
;
A->PutP(I)
可以等价成
A->P = I
。
2
.在
Microsoft Excel Visual Basic
参考中查找对象,方法和属性的时候,可以基于第一点将
VB
转换成
VC
。根据
VB
提供的参数类型,在
VC
中使用
VARIANT
类型承载。
如果有讲的不对的地方,欢迎加
MSN
和我交流:
bwmwm@live.cn
。
相关文章推荐
- [转]在VC中使用智能指针操作Excel
- 在VC中使用智能指针操作Excel
- 在VC中使用智能指针操作Excel(转载)
- 使用VC++操作Excel文件
- 使用VC++操作Excel文件
- VC/MFC使用OLE操作 EXCEL
- 使用VB或VC操作Excel 2003
- 使用VB或VC操作Excel 2003
- 使用VB或VC操作Excel 2003(例程)
- VC操作Excel,使用Worksheet的get_Range发生异常
- (转)使用VC操作Excel 2003(例程)
- VC操作Excel(总结)
- 使用EPPLUS操作EXcel
- VC中操作excel和word冲突的解决方案
- VC使用SQLDMO操作SQL Server
- 使用C#和Excel进行报表开发(五)-操作单元格边框和颜色
- java使用poi操作Excel
- 使用NPIO操作Excel
- [原]用c#做了一个桌面程序用来分离excel文件里的数据时出现“操作必须使用一个可更新的查询”错误的解决
- c#操作excel方式三:使用Microsoft.Office.Interop.Excel.dll读取Excel文件