|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
通过VC实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文主要研究通过OLE/COM实现对Excel表格的操作。* ~2 y3 F6 W! A5 J
! F, f; D5 X$ z本文源码的应用环境说明:/ n) f/ p2 `# a9 S
Windows XP SP3
& E7 [* Y" ~9 t) d1 ~) o& VMicrosoft Visual Studio 2010
6 T c- L% A8 K- o- m) IMicrosoft Office Excel 2007 l) K2 ~0 O% f: C @
s0 \5 N& B( k/ V+ }
1、添加OLE/COM支持。
, {3 h4 P# i$ f3 h! p9 |首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。$ A) x+ Y* W; {! Z* \
本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。
4 Z4 d$ K9 t/ _3 X" p0 A, G, g) z& r通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。! l- d0 R* \( k- v. B3 b
#include <afxdisp.h> // MFC 自动化类) N- [1 E( x0 K; \8 I# V$ h! d
同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:' @8 `& V0 O# L' m, s' c
// 初始化 OLE 库% ]$ x3 s/ _7 H6 j% A W) J
if (!AfxOleInit())! Y+ W4 W \ N8 q/ x( o( i
{
, t& Y' H! g* lAfxMessageBox(IDP_OLE_INIT_FAILED);
& v1 [) j% Y hreturn FALSE;* a; ]# v( O1 r1 M, @4 e
}
) c) ?/ t8 T! {& i( s3 l- X$ l
; y' o; C. J& `8 ~# g2 ^! B) Z( \2、导入并封装Excel中的接口
3 S0 q9 n1 L9 i& F* e/ M* \Excel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。
8 y$ G- T6 X( H6 v3 Y0 Q7 t+ F由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。; e3 N( F4 a/ @& B9 v# N
VS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择; K$ X3 ~- t+ G1 ~. r2 _" E
要导入的Excel类型库中的接口。% ^% w0 w9 B3 h5 r
在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。, u8 K- z) Q g1 k! q) |) o* [% P' C2 z) d
. l/ i+ G6 {$ e
本文所导入的接口对应的类和头文件的说明如下所示:
/ G. i5 g+ Q& P3 T k+ ~! X 4 A+ o4 _" S6 A
Excel接口
1 d$ w7 ]/ m& p* x导入类
9 G; n6 w9 q% Y: J9 s7 v0 c头文件: v& O& P( V* t( C7 n |
说明
5 v: n( ~8 J; R5 Y! O1 ?_Application% }* R5 Y' U7 D' V7 y& S% e$ x
CApplicaton
% r# D- S7 V" UApplication.h. ~* q& E' e3 O! h
Excel应用程序。% b, Y6 Y5 @9 c$ B, G2 ]0 M2 a3 d
Workbooks' O$ C# W. m0 K8 o% b' ~; K
CWorkbooks; T3 k; ], j: j9 x
Workbooks.h7 y7 k+ }) U% N, d8 j
工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。
4 w$ y3 n* x1 o& r( a# ~% @_Workbook* y% m5 `5 J. l4 d
CWorkbook
+ D9 E3 Q, g8 e6 AWorkbook.h
" g. G' b* z' r) j. F8 {单个工作簿。
) Y6 o- X& k, J, @Worksheets& P& Z% ?& ]9 J! C. f& ~
CWorksheets8 Y$ X, S4 B3 Q$ \4 s- F& n
Worksheets.h0 N0 ?; _8 b# v) h0 D W# W
单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。
: A8 U( r& o, W- Y% W& U_Worksheet
2 J5 F+ ]; j; ECWorksheet
4 T) R3 k5 T/ S) n7 v* V# j9 j a4 CWorksheet.h
9 E, f1 ^& A6 J' r( d7 z2 ?/ z0 @单个Sheet表格。& p5 C1 x* w9 m, I
Range
' ?/ D; s }/ ` N K, iCRange
7 _, s( V' f- U9 c' O* i# _Range.h
# p5 t4 Y8 V y! r1 u7 { R, l9 j一定数量的单元格,可对单元格进行单个或多个单元格进行操作。( i- Z, T0 Y$ N# \
+ C& q3 ?8 F( E3 [) `
3、导入Excel的整个类型库
% f" t# C- l# M$ o! G$ I接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。& R+ X0 p1 x4 ?( u) c; i P t& H) C
通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:) s/ |9 Y- L2 y5 t: E, w
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
0 j9 T: j# B) @; E: d" x+ p; k" F. z这行代码的作用是导入Excel整个类型库到工程中。
: c, `3 _1 x5 b" w+ E R* ]0 J由VS2010自动产生的导入代码存在以下几个问题:
% T- z6 E9 G5 E4 v(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。
5 l# a8 A7 ~! i( Q' V6 x- f* J: K* u(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。' K1 \0 d" [ x
(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。
5 [% x d; f0 B! ^0 U) }# t* t3 V以上三点问题的解决方法如下:" q5 O/ J: J" o5 t
(1)仅在_Application接口对应头文件中导入Excel类型库。
- j O% W' l9 U% Z3 h(2)对冲突的类型进行重命名。
4 `0 X1 Y* Y7 u, T2 x% u3 y8 S(3)在导入Excel类型库之前,先导入Office和VB的相关库。
6 I2 ^& V! W- a; L- C' j b更改后的导入类型库的代码如下:
) V# q: _8 {) l! A v % f* n" g" |- c( a2 k4 n4 S
/*导入Office的类型库*/
! Z* V% ^8 _& V; p; D#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \7 m1 G( A4 e3 j6 r
rename("RGB", "MSORGB") \
0 W+ z" [3 f+ R2 [% prename("DocumentProperties", "MSODocumentProperties")
5 H6 N- ]8 k# Rusing namespace Office;, n! i1 {3 i- D z1 K0 y/ U
9 w6 t4 C/ z9 W
/*导入VB的类型库*/4 K; o, H" `" K7 x& n8 ]
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"1 F0 K# t" L1 P4 G( s8 k3 t
using namespace VBIDE;
' |# l% c( O9 W3 x4 j " V/ x# G% O z8 e" m
/*导入Excel的类型库*/
2 `2 n, ]% j. j#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \
3 X+ h, D' G- y. d n- B9 B% w0 t* yrename("DialogBox", "ExcelDialogBox") \( h: W% [' Z4 V; p
rename("RGB", "ExcelRGB") \
2 R. w! _$ V- K$ arename("CopyFile", "ExcelCopyFile") \" K$ K/ {7 m* T; H4 w) M ~$ D& t0 B
rename("ReplaceText", "ExcelReplaceText") \/ [( c9 a) A1 ]5 O4 q
no_auto_exclude
$ |) ~) ` t+ z% I3 EUsing namespace Excel;$ P. y! k* v; H" a8 K
+ ?2 c) K# ?% ]" G, V编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。
, g! H: z2 s3 q, J# t- u
' ?. P, I @ c! B5 f* t1 h" ^$ B4、操作Excel步骤& K _6 B! u! P
操作Excel的主要步骤如下:0 ]$ {/ w. I1 V: M& v9 D' L7 Q
(1)创建一个Excel应用程序。
- W: K4 N U9 S# p8 l/ s$ W(2)得到Workbook的容器。! I5 v5 N: ]: Z
(3)打开一个Workbook或者创建一个Workbook。
4 l$ K2 u1 l L1 `) j! |5 H2 R0 N(4)得到Workbook中的Worksheet的容器。
% K% h) U& z# P(5)打开一个Worksheet或者创建一个WorkSheet。3 Y; s0 u7 k- a* p" Z; l
(6)通过Range对WorkSheet中的单元格进行读写操作。& d' W" d, L! T% U" f
(7)保存Excel。2 I, M$ q$ G9 O: e: j- j
(8)释放资源。
H* ~- f5 o6 u c8 S2 w% ~ - q. E& e' V) `9 D$ n0 I, d
5、批量处理Excel表格
( w! Y. v- X( z5 m5 @VC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。( U# U' R8 A" ^: w1 E5 E+ [- z
对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。
7 j6 d0 j8 d/ t6 `VARIANT get_Value2();
. H3 y" ?6 ]. O3 {! bvoid put_Value2(VARIANT& newValue);
/ _: D2 w+ x6 G d其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。; Q7 ~7 I7 R; u. I2 Y8 F3 B) R
其中,VARIANT中实现二维数据的方法可参考% |. d) b/ U8 G, a
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html; a* |9 a9 X* a" }3 c$ u0 |2 _
当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。' J6 y, n- n; R! z; M, {
0 j, R9 B2 @" i' O4 i6、Excel表格的保存
! \( D; D5 C* J+ Q(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。
" ~7 T7 \7 A* a# s2 v(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。, J0 P# Y6 x% e# \, f4 q: Z
SaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。
. T. I7 ]2 Y @" k! z/ I6 |& `
2 R! L/ X4 y) Y8 ]" z5 P" D z( E7、获取当前Excel的版本/ R L" K/ W7 @# X; y
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
+ k# y w* b, r7 R2 b
6 R+ K+ B+ r/ a) t0 F9 m8、示例源代码2 j8 D& H& ?# m& f% Z/ c; B
主要代码如下:* @. [; ]2 O) s5 r$ O7 u
. v, ]* p6 J9 H& K
- c ^- b. ~/ f( Q+ _ J; A/ l' M5 ]4 R' C( G% x
m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);
2 l* F0 r( g4 @! X& G& r0 h- b. A+ Y% E9 Q f, B
CApplication ExcelApp;9 \; ^% h) x8 A# U
CWorkbooks books;1 i2 a. c- ]- i
CWorkbook book;
) t2 X/ D& {1 U4 O. W) S; ` CWorksheets sheets;
( K3 n$ E( y% k: Q( p# } CWorksheet sheet;
* P0 }* @5 X+ ?& c+ x" f# B4 Q% V CRange range;( Q9 B3 m8 ~4 @6 o# t* a4 D/ C& Q
LPDISPATCH lpDisp = NULL;
7 \4 P. ~8 m. U* l' g* X+ w/ z1 A
1 {7 h S* v" ?6 g/ q; f2 m1 r% m //创建Excel 服务器(启动Excel)
% }% p V2 Q7 f% v! e if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))
# }* \1 J( F% t' j% s9 r" Z: V {) i: X. Z- U# w e5 ` q
AfxMessageBox(_T("启动Excel服务器失败!"));
, F9 W G' Q+ y5 D return -1;, {* {; ?( P6 q7 [' G
}# M3 ?. ?/ N" W
0 ]9 C: C! \8 n/ k$ u5 o% H% G
/*判断当前Excel的版本*/
5 n' \" g6 N6 I CString strExcelVersion = ExcelApp.get_Version();
, z4 m" Z$ U# G( F int iStart = 0;
- {5 k: L) a3 { strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);$ m: d$ _) u4 F) W. s( i8 Q' \
if (_T("11") == strExcelVersion)4 x& k9 p) Y% ?* r, ?! {
{* q9 Z+ x# R& O2 d+ d
AfxMessageBox(_T("当前Excel的版本是2003。"));
% `% a; d. x8 k* V }4 g; K6 @, H9 R. j
else if (_T("12") == strExcelVersion)
) F1 q7 \$ x# ^6 E* N& Q6 Z% ? {
2 b6 L$ P# d# e8 V3 S1 l0 C! C AfxMessageBox(_T("当前Excel的版本是2007。"));0 F6 ^: V5 \5 y- e, T
}
2 ]# y1 Q' a9 G0 ]% r: L else
' s8 F, i: R& e {: G7 a, s) }) C# H' `, ?3 o% h4 d
AfxMessageBox(_T("当前Excel的版本是其他版本。"));" U+ ~5 C/ }% ^4 u2 a
}" K, L2 x0 [9 _% D& J* m! L
& l3 I0 S) w# F0 J4 q, T ExcelApp.put_Visible(TRUE);/ @. Y. X( p% L9 J- Y, G
ExcelApp.put_UserControl(FALSE); B8 k2 M8 Z6 b- ^
8 m& L6 Z3 G/ s5 P7 n$ d5 g) ^ /*得到工作簿容器*/
7 Y: g/ T8 D* @ books.AttachDispatch(ExcelApp.get_Workbooks());
$ b/ G7 m# T3 [5 B o+ s; R
* b3 U8 @* V1 x1 O8 T9 ]9 M /*打开一个工作簿,如不存在,则新增一个工作簿*/
: {8 c' j) T8 O3 `5 h0 e CString strBookPath = _T("C:\\tmp.xls");3 r# K2 J/ y, o. J5 z" k I
try# T1 i6 x" I- W; e
{/ X0 c- t+ ]% n1 u9 x. q
/*打开一个工作簿*/
4 z, c+ D7 q' G lpDisp = books.Open(strBookPath, 7 S& g0 K" i9 w L2 q5 k, q- P
vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,* P; @$ A5 T' O# H1 J( ]! B
vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, ^2 f, f, A, `. E+ J+ e
vtMissing, vtMissing, vtMissing, vtMissing);
9 U' Z6 W7 A. N7 V9 Y$ l$ Z! ~ book.AttachDispatch(lpDisp);
1 W/ h3 T3 n3 Q5 S }
" T3 C" U- x" e2 L$ m+ Z catch(...)8 a( T! l% G4 \( a3 O
{
9 ^$ C( h# u( ]3 c9 e' n5 e /*增加一个新的工作簿*/
3 j- F' t k+ G' K+ ] Z; C' n! X" ^0 S lpDisp = books.Add(vtMissing);# }4 Y4 a9 B A1 o
book.AttachDispatch(lpDisp);
/ e9 I# y( \8 S) D }; _" [2 j) P1 U2 e- G
5 C1 n M; J( k6 v6 }; w1 E
3 p- M9 i, y- P1 j4 H /*得到工作簿中的Sheet的容器*/
8 j$ P9 m# T0 e: y9 T sheets.AttachDispatch(book.get_Sheets()); ]- V) J1 M4 |
2 R0 T# a1 s9 h! c5 u
/*打开一个Sheet,如不存在,就新增一个Sheet*/2 b7 T$ V) l; H3 n
CString strSheetName = _T("NewSheet");
* | }, E3 [, J9 c! S5 e try: ^7 c( t, f |- Z
{3 ?2 Z/ ]. {# c. i$ u6 }% e
/*打开一个已有的Sheet*/' ?6 e- ~5 \# e! Z8 o- k
lpDisp = sheets.get_Item(_variant_t(strSheetName));2 w2 C7 I- X8 A% y; J9 {/ j
sheet.AttachDispatch(lpDisp);
! e: z& {' P4 _1 R }, B/ E) L, }+ i& T) ?
catch(...)' @# Z e3 a) O+ e' ]8 p/ S
{) H7 U {( g" j- M
/*创建一个新的Sheet*/$ o% v% Y- E2 l* ~$ S
lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
2 g0 B$ u! A! y* _ sheet.AttachDispatch(lpDisp);
5 h, W4 [. R7 _7 s! M' } sheet.put_Name(strSheetName);
7 F s% `5 N c' G, {* \' f# k% j' Z }
# f4 j+ i% W. h! `+ r" e0 x5 A7 \' P( u
system("pause");2 m9 U4 b6 h4 h+ p i& m7 x; c
$ G5 Q5 y( ~1 D- l9 V
/*向Sheet中写入多个单元格,规模为10*10 */
5 l, i1 h4 I1 M& a9 H. [0 Y4 t lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));4 L& N7 ^ C6 B* P3 ?" N
range.AttachDispatch(lpDisp);
. q, z5 x+ g9 O" ]2 o
# T8 c& }" X, T" t) e$ \( C* k# N+ [ VARTYPE vt = VT_I4; /*数组元素的类型,long*/; |, m/ p) ?& n! T* g
SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/
3 h7 O; E! @7 t9 Z0 I sabWrite[0].cElements = 10;
8 ]3 i# V% |9 I+ s6 Y) V sabWrite[0].lLbound = 0;
. T) N- Z3 k$ t sabWrite[1].cElements = 10;
& h: g5 ]+ Y- l. u. j sabWrite[1].lLbound = 0;. q& @% Y1 F5 ]$ \, U2 W
. A9 L* W0 s5 n6 f0 {) n( U7 Y
COleSafeArray olesaWrite;4 k% n |+ h/ x0 Q
olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);
6 ^' J& H$ w' a7 |9 O$ u: E4 o. m* I) P$ j
/*通过指向数组的指针来对二维数组的元素进行间接赋值*/
! [# [) h; f. D/ `+ l) _ long (*pArray)[2] = NULL;
9 G2 X& v0 c, k. V1 T. L$ f olesaWrite.AccessData((void **)&pArray);
$ M: k( e( T" I. @. q& ~ memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));
6 N+ j. \* U9 b7 }9 h. c
4 I9 j& A5 k5 K. p9 n5 ~ /*释放指向数组的指针*/' z0 c7 ~0 w/ g9 @
olesaWrite.UnaccessData();
$ l/ `8 y- v3 @4 A, r- Y0 S; h pArray = NULL;
- w- ?- Y7 M( a6 F% N. z0 R/ N" H u9 G
/*对二维数组的元素进行逐个赋值*/0 i6 Q5 B3 y+ E$ k( S
long index[2] = {0, 0};
( r* {4 J- C$ [ long lFirstLBound = 0;
1 H9 k) F7 x7 p7 o* L( x9 A! P* t long lFirstUBound = 0;! a, H; o/ ?. F
long lSecondLBound = 0;
7 b0 H: t" S, P# D" D' }* F8 D long lSecondUBound = 0;
! b; K5 u. }+ F$ C# K5 o olesaWrite.GetLBound(1, &lFirstLBound);7 R" r. K2 x; R r9 J1 o% [
olesaWrite.GetUBound(1, &lFirstUBound);
" O' W+ v, n1 G& m, [# w* a. x! a olesaWrite.GetLBound(2, &lSecondLBound);8 s3 Z9 E5 o' @1 t
olesaWrite.GetUBound(2, &lSecondUBound);
, F _# I% e7 Z* P: g, j8 u$ @ for (long i = lFirstLBound; i <= lFirstUBound; i++)2 x' } c- }' X/ S0 d" Q, _+ m
{
$ c; f1 `/ N4 O- z index[0] = i;' H' ~5 | g' A s A1 b; `! _
for (long j = lSecondLBound; j <= lSecondUBound; j++), R1 ]3 U. ^9 G
{
7 q7 i6 W- x% u* I* p index[1] = j;% v ^ q. e, W- i4 L
long lElement = i * sabWrite[1].cElements + j; 0 B' u0 v. X8 `
olesaWrite.PutElement(index, &lElement);( |: q# K5 |. F, P0 M. y- ~
}
" ?5 C# H2 K# B1 k% [" C }) Y5 w6 K% R: V7 a6 S, Q. p$ Q
3 ?6 w" ~+ x9 F4 T, G) V& j3 m /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/ R, S9 Q6 s9 Q' }
VARIANT varWrite = (VARIANT)olesaWrite;
% H+ i( \6 p6 Z! R( Z. N3 G n range.put_Value2(varWrite);2 C! K! h- y, f6 v0 o
/ z5 t; c/ R( k* ~) t# y
system("pause");
4 a& a% g" x; h. {
& M& S* u1 p( x% X /*根据文件的后缀名选择保存文件的格式*/' l$ q1 s+ t1 O8 |1 t: O9 ]1 `! j
CString strSaveAsName = _T("C:\\new.xlsx");* L. V- b- G: O
CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));
/ `, u7 b. D% v: d5 i. s XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;2 B% Y) Y, W; j; @
if (0 == strSuffix.CompareNoCase(_T(".xls")))* X c& T2 H. u$ }* ]) y0 F) J
{
8 k( C9 d& P' c" n6 P" v& `: U+ p: e NewFileFormat = xlExcel8;0 g! q) B* [; a% L( L; _
}
, z' m a$ L O: v book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing,
- N3 q5 @9 h5 w0 v d vtMissing, 0, vtMissing, vtMissing, vtMissing,
/ `+ b \8 G$ e* T8 B0 c! ^# S6 R vtMissing, vtMissing); E" r" _. e* r, B, P+ m
+ P5 m: B( a5 X+ x system("pause");% V6 U8 @+ D% H7 l+ S
8 l2 [- A0 I! s) Q# n+ g
/*读取Excel表中的多个单元格的值,在listctrl中显示*/$ H. s( R- Y& C
VARIANT varRead = range.get_Value2();5 {3 Q0 s6 ^- G3 t1 E6 I4 @3 n
COleSafeArray olesaRead(varRead);2 X5 n, U2 E A/ H5 y
4 j; X# ]6 y; Q. \ \) ]# e+ j VARIANT varItem;. \* d, `$ p. _( @
CString strItem;1 E, G7 A6 b2 S! M
lFirstLBound = 0;% `( E% }- |* J$ d0 }
lFirstUBound = 0;
2 R/ f7 Q0 ]6 j1 }$ O6 T lSecondLBound = 0;6 i% h5 [0 _! F* U* X5 R
lSecondUBound = 0;, K+ y( J' u( R. j8 K# V* ^' ]
olesaRead.GetLBound(1, &lFirstLBound);
! a* R8 f$ _, r6 G* f olesaRead.GetUBound(1, &lFirstUBound);2 K: n( v# G) i0 t1 y
olesaRead.GetLBound(2, &lSecondLBound);
1 Y5 A/ `. e: l3 V* ^3 \- P) t2 T olesaRead.GetUBound(2, &lSecondUBound);( K+ z1 C, j7 _% q2 o& F- N$ J7 l' f
memset(index, 0, 2 * sizeof(long));
, h4 h$ P4 O, l" h m_ListCtrl.InsertColumn(0, _T(""), 0, 100);
& e u4 F6 V( H: X0 K0 L for (long j = lSecondLBound; j<= lSecondUBound; j++)1 [ y. ~/ b/ ]4 n0 y1 L- @& v0 z, w
{* R' Z u0 \9 y) v
CString strColName = _T("");
& u" x6 X) e$ N, L9 k# { strColName.Format(_T("%d"), j);
' n+ X3 b% j0 v+ V+ K4 w) |! i m_ListCtrl.InsertColumn(j, strColName, 0, 100);% b, E" N0 t4 l) A
}
2 |# j% }! E8 P" O- [' G+ ~) K for (long i = lFirstLBound; i <= lFirstUBound; i++)
+ Q6 Y0 ]8 w" k$ _7 {8 h/ Q* \: d {% y3 x8 m7 u' z" R9 k2 ]% v: @% x
CString strRowName = _T("");
# V) \' C3 Q( u O \2 M strRowName.Format(_T("%d"), i);: I# q( ?$ Z: S
m_ListCtrl.InsertItem(i-1, strRowName);0 R6 f) q/ d/ T! L( W! }
- x E p* @6 s
index[0] = i;! ~/ V: g) _$ D& a% `" |# M
for (long j = lSecondLBound; j <= lSecondUBound; j++)
9 b( F% X6 J' K0 R, ^ {% i( O# ?, c& Y9 y" o7 v* T% x( O- a9 r
index[1] = j;7 g) R$ }. R5 G% N
olesaRead.GetElement(index, &varItem);
\* c) I) Y* \7 ~( F- W2 U
: m6 S8 Q( O: ~ switch (varItem.vt)3 `8 X+ y( d; ]1 v2 a
{
; z! i# h8 M- {* ` case VT_R8:
' y; W3 }. }- b6 c( b- \* w' ? {
3 x. H+ P' r3 y3 K3 I6 e strItem.Format(_T("%d"), (int)varItem.dblVal);
! x( q6 Y/ f0 z7 t& V }
- U4 q: d2 i" C5 J5 W: p. J6 e
6 D2 s0 P+ m7 J, o7 I, m% _; } case VT_BSTR:4 ~8 z, Z: }* T5 O L
{' W1 L( L" ]+ O, Q; n1 X
strItem = varItem.bstrVal;
3 c$ t* l7 Q t9 b) T' l; c! G0 K0 P }
) L6 q$ |9 G. o, [7 f @$ B3 B* p0 O" v, Z( A
case VT_I4:) E5 S8 f0 @0 k8 l
{
7 K9 E& P# C+ ?9 P strItem.Format(_T("%ld"), (int)varItem.lVal);. I2 B- q3 L9 i* Q, ]$ ]
}
$ Q) t' _2 \6 r! p& V; ?9 p& z' X# r
" U* [4 b$ C: _; z: a1 {, G x/ q q* z default:
8 D4 b) V% Q7 A7 q8 r. I0 h {% P1 y6 U- H) `* }7 y% _
2 e" O" Z) l4 f8 E/ L3 x+ {) d y }- Z: j; n' R) T M& h
}& i3 n" l, U6 U) N$ |
. C, R: j2 l1 T' {; c m_ListCtrl.SetItemText(i-1, j, strItem);' I9 M/ N/ F! @2 l7 a
}% B9 ]3 h, p1 h2 o/ x
}/ E1 s, n. Z( G1 ]
9 K. g; m' s* ^! g- Y5 ]% x9 m
d! d9 }3 Y$ t: j6 H* j/ L i" H# Q. ~! Z6 P
/*释放资源*/
, k# q# q- K D6 v$ E sheet.ReleaseDispatch();2 A0 |5 z# Y2 S7 r) [; p4 q4 O
sheets.ReleaseDispatch();* J5 U- r3 ~- D4 @7 z$ y H
book.ReleaseDispatch();" F M: r6 j5 W/ o; o
books.ReleaseDispatch();
8 [5 k5 T, r% y7 A( S ExcelApp.Quit();
: [7 E. A/ G! y& Z% i0 H. X. p ExcelApp.ReleaseDispatch();! X5 r$ K# z2 L% v: V
: i5 F2 `4 l0 b- @1 l
|
|