|
|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
通过VC实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文主要研究通过OLE/COM实现对Excel表格的操作。
+ a( [# o: x& L# k 0 ?0 ^9 A+ T9 D* m1 h$ G
本文源码的应用环境说明:
# L! b4 S& u0 Y, H6 EWindows XP SP3; J' s, u; N/ V6 K. @* O( ~8 `
Microsoft Visual Studio 2010 j0 J3 O$ X6 k+ g1 o+ [' [8 W* x
Microsoft Office Excel 2007$ [0 H# Z+ h3 F0 l7 k6 l
4 A0 q' ^3 E, J9 K& M1、添加OLE/COM支持。" U; |$ w$ | ~/ S
首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。5 t8 O) Y, d! q L5 L
本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。
0 s/ [% S! Z+ x" y: ~2 ? E3 f通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。* L/ W& J' l9 z7 U& s# h
#include <afxdisp.h> // MFC 自动化类4 C! o( ?6 M# R
同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:& q# [( `7 w }* c( O. Z" d& |
// 初始化 OLE 库3 C# Z) M: a$ Y( n8 u
if (!AfxOleInit())
7 O- |0 V6 h3 q9 s+ B) ~+ `0 _7 p+ r, {/ y{3 |( [$ Z3 p6 K F" z
AfxMessageBox(IDP_OLE_INIT_FAILED);4 d* }* t$ f9 }1 Q& X
return FALSE;
4 g9 I* B7 j9 l2 }0 z6 Q. U) x}
3 Q* D o! B0 t5 P6 s
4 q" o) F/ K& ]8 o6 R/ d2、导入并封装Excel中的接口- f8 k3 W* i4 Y& D/ ~
Excel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。
9 v; ^; v5 O! j由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。 {" C: ]5 A7 p
VS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择
1 B6 u& Y9 X9 [0 Y E, i要导入的Excel类型库中的接口。. U9 P6 p) l& [7 p# b( b5 G! h
在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。' n0 J7 c0 B0 V: z3 u/ a; I
8 U2 h h! s# z% g; h本文所导入的接口对应的类和头文件的说明如下所示:3 n8 s3 P6 D, @9 @; V& T7 t
& h& V% X, a8 F+ ^6 C% fExcel接口3 x5 `2 U3 d7 m- m9 C& p
导入类2 n- M/ U! F4 ^: p: z% I" Q; q+ o
头文件% L) R7 J5 A0 o) c! N
说明
; C. r8 J, M+ P1 I_Application
' O& K. ~. E4 dCApplicaton, }" Q3 V6 {* Z
Application.h
/ k" S$ U) E3 o/ s; aExcel应用程序。
T& p: q. N3 n4 `) LWorkbooks
: v8 p! Q, h& F6 ]: CCWorkbooks
. S2 l1 M$ n' f8 D: R/ h; L6 y% _; XWorkbooks.h
( v4 r! |( _4 _& Q) `+ E ]2 x工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。# r4 m5 ^5 U4 D5 f% n" q6 k
_Workbook, c, r8 ^2 {" N. e) U7 \
CWorkbook
" F6 R' K% Z) A+ f2 D5 Q4 C% sWorkbook.h" k1 l1 c$ w) x2 l
单个工作簿。
9 X+ ~0 i- ]% g3 V8 D4 MWorksheets! p/ ?1 n, I6 M) ?
CWorksheets
2 R( G. v0 R6 t; k& fWorksheets.h8 v3 Y& Q4 }; k# M
单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。
; Y$ t& Q7 _2 c" \_Worksheet
9 H5 A6 A! _' I# A3 R; E5 R& fCWorksheet/ p' E& O6 F. ~& i3 m% w3 n7 w
Worksheet.h
+ _* q! Z% t1 l% d1 d- O" N* ]6 H0 E单个Sheet表格。; T: `7 l: @ s* L8 ?. ], ~ [
Range
; X5 ]3 G4 i- q" fCRange! w# ]5 L4 [* m7 e. p2 O
Range.h
" s* ?- L5 F( n6 \9 c% w* ]一定数量的单元格,可对单元格进行单个或多个单元格进行操作。
6 N2 _, z D4 Y! S+ G/ I" J* q* N1 R * f+ ~. g' J' T3 r
3、导入Excel的整个类型库! j4 H5 R* j, Y- `
接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
' g+ o# m" X) J2 O2 N通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:
2 V( z0 l1 n Z) V1 ?#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
4 k3 }$ }* r6 Z( Z, h C这行代码的作用是导入Excel整个类型库到工程中。
3 ^/ @. \0 N% j. r6 e由VS2010自动产生的导入代码存在以下几个问题:
$ C6 T! E. h3 G) m(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。
0 X) ]" Y/ G' a/ o(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。
' i) j" b2 [! Q( r; i9 j8 B0 l(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。
& z2 \9 M+ q4 K! l以上三点问题的解决方法如下:
% z4 I- X( R4 j8 }, f(1)仅在_Application接口对应头文件中导入Excel类型库。/ e2 H# s9 ^1 L
(2)对冲突的类型进行重命名。
5 u: n2 b! ~0 b1 |, e, v n(3)在导入Excel类型库之前,先导入Office和VB的相关库。* C& }& Q9 ?" Z8 y+ a6 X
更改后的导入类型库的代码如下:
8 T6 H. a6 A9 E! _# {5 C: B # h; C6 d j( a S; w2 A
/*导入Office的类型库*/
6 b9 D8 d8 I J5 R4 V$ X/ c#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \
: }0 z" }9 R$ d5 g9 g. _# brename("RGB", "MSORGB") \
& a5 p M: E3 A7 m% I1 r; ~2 w% K' Rrename("DocumentProperties", "MSODocumentProperties")
7 d4 ^& Z* {+ T4 x( susing namespace Office;, A/ `; r2 _$ S8 q$ _" a
% ]% }9 _: f) K. {* ~/*导入VB的类型库*/# N- Z5 B5 t w* N) ~3 N7 x; c
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
5 o; O+ X. B: Dusing namespace VBIDE; G) z8 n( s' l1 G# }, B7 m. C& Y( l
1 i7 Z# r; p& C! W- w/*导入Excel的类型库*/
! d7 q0 ~$ {6 ~- v0 E1 g8 ]#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \! U d! d: m; E7 c( Y6 q' h
rename("DialogBox", "ExcelDialogBox") \
* c4 R, f# w0 ?7 E& xrename("RGB", "ExcelRGB") \/ n6 N0 d! u1 x
rename("CopyFile", "ExcelCopyFile") \' T3 M1 J3 ^' N9 o/ J; g# P' F
rename("ReplaceText", "ExcelReplaceText") \: Q: L3 Y! d; c, j( H
no_auto_exclude
" U d8 f& s0 a" MUsing namespace Excel;
) A, U2 s$ h, z! y7 M1 ^
0 s! }7 J- G7 x& s6 _0 {% k7 S; M1 m编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。
% Y! } {* \& Q1 v
6 u n/ O. B% W# Y! z, E4、操作Excel步骤
% B+ p. d5 X; T操作Excel的主要步骤如下:6 z/ F0 a% t* L( \
(1)创建一个Excel应用程序。; U) R" G, _. Y+ ~& `/ M
(2)得到Workbook的容器。
0 ^* c9 Y# J7 h9 g5 o(3)打开一个Workbook或者创建一个Workbook。( Y/ h; g7 ]0 Y2 t
(4)得到Workbook中的Worksheet的容器。! q- w+ r+ r9 j6 f
(5)打开一个Worksheet或者创建一个WorkSheet。
6 l# I/ a; [) T! g(6)通过Range对WorkSheet中的单元格进行读写操作。
) n D% A) O" ^/ r. s6 M(7)保存Excel。0 p8 C d2 s. \+ ]
(8)释放资源。
9 ?3 s) X1 c8 F + O. R$ D7 u# R& h% F
5、批量处理Excel表格; H w8 S; h3 L" [7 G2 X1 H7 C5 L' N f
VC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。
- i9 S) E: p7 Z对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。) U) r( T+ L+ n* k$ K+ g6 d
VARIANT get_Value2();
# c8 s$ X! E. Cvoid put_Value2(VARIANT& newValue);& s& \6 h. {0 ?" v
其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。
2 O' ^$ `& L3 s1 O/ G' c' i其中,VARIANT中实现二维数据的方法可参考% A. Q6 R' u3 L+ I$ ~7 Q
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html. U0 |0 J" | y' q
当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。
/ E; Q) F- ^' m: `
+ [3 E, F1 g) F/ G: r7 D' |6、Excel表格的保存. ]9 r! \" K0 d. J; d
(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。( w c+ w; B' _* j! H0 x& k" I
(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。7 t7 V5 ?' O) |: Q/ V
SaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。
9 [% L' p q8 F: M, F6 K! [
/ ~5 [5 x; m+ H5 T7、获取当前Excel的版本3 _# ^9 e+ s1 ~7 W# G9 r
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。1 L* d d. y: r" q1 g" C
. @5 G; i2 `+ K3 N. Y6 w2 J8、示例源代码
2 V. {) F% X) J; ]5 b主要代码如下:9 m; L1 g' A$ }% A. _! s
6 M4 l- a' q. i- J2 ~) R: n& I
( }4 s+ R! `- I
) q0 [ v; A- G( |; ?
m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);5 l/ v" Q* m. E1 O! ?
v8 W5 V: n+ a* [ CApplication ExcelApp;
7 T6 `- l. n6 N9 n" [3 y' ?( e CWorkbooks books;
" [/ Z) ]$ z' o0 N* B0 I0 ?1 T CWorkbook book;
) ~& S5 a; I2 N CWorksheets sheets;- n$ a$ B x- B
CWorksheet sheet;
8 j" y9 N. O& h! J. c$ e CRange range;
- P" j/ z% x" @) N* D. x* I' M LPDISPATCH lpDisp = NULL;
* C' m% _/ x& W! i7 C! x$ i1 g' N6 a3 j4 Z
//创建Excel 服务器(启动Excel) h: K3 A1 ^, l
if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))
9 g, C! g5 I) d0 R {
& T' [% k8 {; |# I0 I; v a5 }! M9 z AfxMessageBox(_T("启动Excel服务器失败!"));
5 l- x6 |( m1 u8 n$ b return -1;
' u' M* {2 v( l: D% f }' A7 b Y. u; ?. m
# @; Y5 \( F7 ]
/*判断当前Excel的版本*/* R" ?0 N# G( w( U0 ^! \* d# {2 ~
CString strExcelVersion = ExcelApp.get_Version();0 f p) f' f* s8 ~& L) O
int iStart = 0;7 x! R& u8 N: k: U5 }8 E
strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);
2 D1 ^' E( P8 H+ j$ l7 G7 B7 ] S if (_T("11") == strExcelVersion)
5 x# u# X8 n# G+ @5 k% Z/ m/ f; I {
, c3 `& x$ P( B4 F AfxMessageBox(_T("当前Excel的版本是2003。"));
) r" u1 ]# I: w2 f }* j/ A5 ^/ ?' ]7 n
else if (_T("12") == strExcelVersion), _1 B( J- L0 K+ f
{9 V$ H+ j; r- f
AfxMessageBox(_T("当前Excel的版本是2007。"));
. L: _7 |+ L2 g }
) e! F# M* `' Q else
, ~9 U: I3 v' z0 w9 E0 W {; C& y. K0 L1 S/ s2 l1 N0 r, |
AfxMessageBox(_T("当前Excel的版本是其他版本。"));1 Z& h; U P. R& o
}- J0 C' d0 m5 p& x7 W: {6 a
& n- }- K/ i# P/ |! N
ExcelApp.put_Visible(TRUE);; w( A, D( d, @0 l) a7 ]
ExcelApp.put_UserControl(FALSE);8 k r- ^1 d4 u- J; d& B9 v Q
' |+ j1 S9 V. K9 Y, @
/*得到工作簿容器*/
5 u1 T( Q3 o8 k- K& l w7 r books.AttachDispatch(ExcelApp.get_Workbooks());
9 K: @0 P/ @2 B l- V
2 `3 [# s: Z* x /*打开一个工作簿,如不存在,则新增一个工作簿*/
3 q1 f. V( h% f CString strBookPath = _T("C:\\tmp.xls");, `9 W2 o, m) K" M) N
try
/ ^5 p* e$ I' p) P {' w! c! e, X# b
/*打开一个工作簿*/
: F t; D: ]( p. A, I5 m lpDisp = books.Open(strBookPath,
* Y) W0 b/ b6 ^, X" K8 N vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
- K8 ^7 w( a9 b6 ^' Z! C6 t vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
+ w2 R* d* T3 ?+ c4 O/ `8 [ vtMissing, vtMissing, vtMissing, vtMissing);# x( m7 v7 }2 s6 H* M- [
book.AttachDispatch(lpDisp);6 A) w# u( v6 N6 h
}
. ~/ [( L7 Z9 u catch(...)
+ e* b1 }- x! J3 _2 g8 @" {6 E {
* ~0 [: B2 `7 \* R /*增加一个新的工作簿*// ^) P6 |. V4 P5 }! m
lpDisp = books.Add(vtMissing);
0 B7 n& t, f5 E1 o3 Y5 ^0 R0 O. s book.AttachDispatch(lpDisp);
7 V. t& q5 H$ b# H% x }
$ ?9 y9 M9 u1 G0 p6 U/ g
. i# b3 |! T: s( ^4 l3 |5 C
( c( a. X0 @ @, {# Q /*得到工作簿中的Sheet的容器*/ k$ j, M* v7 ?1 B' G8 K# Z* V7 X
sheets.AttachDispatch(book.get_Sheets());$ Y. i; O( G% ?. q# G4 ~ c9 h
; I! f+ J3 ?. `( n: J. F# b' ?, Z7 |
/*打开一个Sheet,如不存在,就新增一个Sheet*/7 v/ c+ z) v- N( z* D" Y8 c6 s
CString strSheetName = _T("NewSheet");
+ ~$ y2 _8 L3 |& x: t: m try; R, g6 H H& W5 r9 D
{: H( p' G$ Z2 |, h" e+ n
/*打开一个已有的Sheet*/8 {% c. Q1 E# y# l( s
lpDisp = sheets.get_Item(_variant_t(strSheetName));
, H1 s1 A* E2 S sheet.AttachDispatch(lpDisp);
" @$ k0 p. N& ~7 k* z }
3 f; _9 D; d, L catch(...)
3 @( K7 m: h' t) G) Q) } {
8 @8 {9 |) r% e( w: A6 W* W /*创建一个新的Sheet*/
+ o# o6 w' |1 \! R lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
2 i0 I: r/ n. f) I' d: R1 { sheet.AttachDispatch(lpDisp);. ^& s+ f& I* |9 ]6 W8 S; E
sheet.put_Name(strSheetName);
8 G, j" d$ R) }6 I8 Z$ {% s }( v* p7 Z. o* {6 {6 f
& Z1 b% }1 d& U7 D
system("pause");, B% l( O& @( v( ]
* v# N1 B( D# x+ ^2 t
/*向Sheet中写入多个单元格,规模为10*10 */9 ~3 {3 \4 Y" C, V
lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));7 X2 [4 n8 C9 J) p; z
range.AttachDispatch(lpDisp);
( l- H% Y, x% `! R) `, X
8 U# k/ `" d) N) V% C VARTYPE vt = VT_I4; /*数组元素的类型,long*/
8 s* l" u# q7 Q v6 w SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/! W; T* `9 v' s7 \$ I" E) c
sabWrite[0].cElements = 10;0 W5 e0 T; Q2 R4 e
sabWrite[0].lLbound = 0;
( \7 @$ P5 w' ?5 @ sabWrite[1].cElements = 10;
. v+ R1 U; i% m+ S% d& \6 d' {! ^" w sabWrite[1].lLbound = 0;# U- ]. D3 ~- J8 c+ D1 M# J; O
- I/ O+ G% ?7 X( k& E7 B; n
COleSafeArray olesaWrite;
X* J" h' N% p# U t, p- ]/ e olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);
! }: D g9 X% f. p( f$ X* p& n8 ~# u+ w. \
/*通过指向数组的指针来对二维数组的元素进行间接赋值*/
; M, h, N4 i% z+ ]$ W long (*pArray)[2] = NULL;
$ }: c0 ^! T! N; P' @ olesaWrite.AccessData((void **)&pArray);; ]7 z" P7 u. v& n7 c) h
memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));9 G* b+ H# i. v. \9 x1 ?" `) z! S
! z9 x1 j5 \( m* q$ F% t. L /*释放指向数组的指针*/
! I/ z& ^% i3 _* p olesaWrite.UnaccessData();; {; A% g; \! m! z' V4 p5 S- u
pArray = NULL;
% j# k, N2 Z& D( N" S% [- X2 y/ r, d3 u E# f- E' e+ a
/*对二维数组的元素进行逐个赋值*/2 S$ i0 e' i N6 O z* z) i0 ] V
long index[2] = {0, 0};$ K" P, P; F% b
long lFirstLBound = 0;& n( o. I F/ o
long lFirstUBound = 0;+ H' k0 D% x* m1 s0 Q& V7 ?, g
long lSecondLBound = 0;$ w) x8 r. ~" f6 m- e7 V
long lSecondUBound = 0;- q$ P; d9 u. V& y
olesaWrite.GetLBound(1, &lFirstLBound);
- s1 Q( R& U `$ c olesaWrite.GetUBound(1, &lFirstUBound);$ K3 ~2 k+ Q- }' \" y
olesaWrite.GetLBound(2, &lSecondLBound);
2 T3 k9 {0 R! V! K0 ^$ s k# X olesaWrite.GetUBound(2, &lSecondUBound);' | E" n V2 m2 m% D" b
for (long i = lFirstLBound; i <= lFirstUBound; i++)$ L: E d0 m: F1 n9 U1 D7 o
{
7 x" B- T* G1 e! ~) ~ m! q7 g index[0] = i;
- Z9 Q4 s5 v% P( Q4 O7 ? for (long j = lSecondLBound; j <= lSecondUBound; j++)
. j! T# _1 L6 Q6 V' i3 G {
7 Z/ o4 V- |! F! a) S+ v) z index[1] = j;
* N1 W/ b- Q9 O, p3 Q long lElement = i * sabWrite[1].cElements + j; # Q0 o' a, ]) Z: c/ B" o; k/ D
olesaWrite.PutElement(index, &lElement);! u; P; k- [9 A; l
}
, o% I' V, b' Z }
, i8 o1 A# w" v1 ~$ Q
8 E) M; i. @& ?1 ^0 L" ~# H; x$ Q /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/
. u# s+ r' c3 g; N# R' T VARIANT varWrite = (VARIANT)olesaWrite;$ g n9 f( c, g. i2 u, |/ M2 J
range.put_Value2(varWrite);9 R5 C: a& @, U& Z$ L' h, _& G8 {% n
1 j* H9 o: f5 C% `
system("pause");4 H7 W+ ~. w9 @
6 T- n5 X# C0 z! z9 K7 c- v" S4 k
/*根据文件的后缀名选择保存文件的格式*/( l( O- i# h- D$ J6 }; ~+ `
CString strSaveAsName = _T("C:\\new.xlsx");
- n6 W: c0 Q0 i$ Y2 J CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));) ]! i1 j: I4 Q4 g8 E5 I: G+ z
XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;4 n# `( g, q0 E8 Y) O- p
if (0 == strSuffix.CompareNoCase(_T(".xls")))6 I$ U4 D1 z' T* ?' D0 r' e
{
! o1 @2 }! Z! Y- J; r NewFileFormat = xlExcel8; m' ]9 n; @, o
}# m1 h8 V+ |7 A9 n9 [8 c( p
book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, 8 m* S# x* Y; Y4 X8 F
vtMissing, 0, vtMissing, vtMissing, vtMissing, # _/ { {( E* w3 g9 i8 {, Z9 Z
vtMissing, vtMissing);
: s9 N2 u1 h$ D7 ]0 ^; [& @. ?* _+ j! }! s) p5 K
system("pause");; h8 m5 ^0 Y* D; R* d2 @
R+ m, O9 ` h" P6 T4 o1 ~ /*读取Excel表中的多个单元格的值,在listctrl中显示*/
! U( G b& {+ U* n# D5 ^- ]( `8 S" o VARIANT varRead = range.get_Value2();4 p1 l5 L: ~' W' S3 A
COleSafeArray olesaRead(varRead);
* o/ j7 `( s, d% ^0 `' n. i8 n' I9 q" L; k0 P2 `, B: | ]/ k
VARIANT varItem;( Y, t' _# x6 g+ F/ y% f$ A) l ~
CString strItem;
# [ I' y+ i; }! ` lFirstLBound = 0;$ m( B( Q+ c9 j# ^. Y
lFirstUBound = 0;- \2 k% m3 z" {2 r
lSecondLBound = 0;
( M& H, C* @9 q$ m' \ lSecondUBound = 0;
5 u# _4 b% ^, A' G" z olesaRead.GetLBound(1, &lFirstLBound);
- ]8 M/ z4 v) O( n S# _ olesaRead.GetUBound(1, &lFirstUBound);
3 {1 H- x1 `, t" W olesaRead.GetLBound(2, &lSecondLBound);5 ]0 _; n! V0 E7 G1 v
olesaRead.GetUBound(2, &lSecondUBound);6 x3 L. W7 r1 \
memset(index, 0, 2 * sizeof(long));
* V, J } H) s1 f! e3 l5 h8 S m_ListCtrl.InsertColumn(0, _T(""), 0, 100);# f- B; T D% z. j4 [
for (long j = lSecondLBound; j<= lSecondUBound; j++)- q9 r8 e+ b6 I& c" o
{" K/ c2 g U! }/ i R- T7 Y5 u
CString strColName = _T("");
! V$ u: q# } _ M2 q: O strColName.Format(_T("%d"), j);, }( H# L' N1 _: |
m_ListCtrl.InsertColumn(j, strColName, 0, 100);9 b4 `" S+ B0 h9 @5 ]& C! w* E
}
# d, r# F" C4 g4 y% {4 |3 F for (long i = lFirstLBound; i <= lFirstUBound; i++)6 m: W' T8 s! k4 m6 J& |: q+ f/ D5 C6 {
{
, M- s& {. \5 Y& K% G+ P, B' w, k CString strRowName = _T("");" z$ S* I' e* y: n8 [2 w
strRowName.Format(_T("%d"), i);0 d V0 y7 l9 Q h2 h
m_ListCtrl.InsertItem(i-1, strRowName);
4 z( G) y3 R6 b5 V/ X2 U; T9 t0 b, G! `0 R& N- p% B
index[0] = i;
, u4 w$ q4 f# J2 J6 } for (long j = lSecondLBound; j <= lSecondUBound; j++)6 \6 Q* f( K" l7 i7 O" H
{. I- J& R& Y# M7 _5 h
index[1] = j;
7 Q: c, J0 B1 Q8 @- A. R) F olesaRead.GetElement(index, &varItem);
5 Q* N. @3 [; p: S2 x+ w# n4 b0 _( g5 d
switch (varItem.vt)7 H/ p$ P" I) l% \9 n3 g* u+ |) j; ~
{0 J. n% k5 S; |! U& ]3 J
case VT_R8:
# S, P$ T0 H5 T& o$ | {% Q8 a4 I: f, U( J+ Y5 H6 M
strItem.Format(_T("%d"), (int)varItem.dblVal);
. e+ p1 g2 d3 E4 I }
% N2 a/ x& ~1 [ B* M! p) w5 T; t; ^1 g6 d6 C# w0 j& d' b, g7 j
case VT_BSTR:
( J, M( l) F9 ?: v. h {: \" L K. \3 V2 p; p
strItem = varItem.bstrVal; n4 w9 T$ ]5 x3 s
}
% w1 ]: F) P( w4 q* X0 z( R3 s; M6 i f$ t6 L3 x
case VT_I4:8 ^. o, p( `6 B! j J3 }, E
{, S" q3 J+ J3 {! V s0 s: M3 T9 b9 b& V
strItem.Format(_T("%ld"), (int)varItem.lVal);. p: d+ J- n8 T' v
}
# I7 X+ G; T1 J' h' S
2 B: S( i- B5 y% f# S) F default:) G( V/ H* f$ i1 M% z% M
{# T! R# T( M* {9 ^4 W
7 L/ d" d) t9 R4 k- z" j }
/ o4 L( S9 P1 _& J: Q }+ J% h' ]4 o9 y3 G5 s) G
- l# g0 h5 e8 J6 |' } m_ListCtrl.SetItemText(i-1, j, strItem);
4 d) A9 A5 |" _1 F2 x) r% F }
) I, `9 a* w& U% |9 I }$ q i6 h+ m9 l- t7 M3 J
8 y0 F! h% ]7 O1 O7 B; C
& T1 U4 u. p; m; n% |" i
2 \' f1 b2 `4 W: b/ t+ z, s
/*释放资源*/! s* O+ _# `" C4 ~, ~$ ?
sheet.ReleaseDispatch();! Y3 j* H1 q* F) U2 Z# s1 T7 l
sheets.ReleaseDispatch();! {( Y2 b9 T( V: g5 W# x9 ~
book.ReleaseDispatch();8 g3 p E: e, b
books.ReleaseDispatch();
8 o, f4 D# a$ N: n ExcelApp.Quit();
( ?) E* v3 o; J" ? b ExcelApp.ReleaseDispatch();
% K6 V$ O5 k/ J% D# e# {$ ~! n. S" l$ T7 X& `
|
|