|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
通过VC实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文主要研究通过OLE/COM实现对Excel表格的操作。
5 F, w3 y4 G* ^1 X' F
3 w" k, G+ j; [* ]本文源码的应用环境说明:
4 P9 f3 m' Q) q IWindows XP SP38 ? \1 U8 ?5 m
Microsoft Visual Studio 2010/ n" v( F! G* M: N5 X
Microsoft Office Excel 2007+ z" Z; z9 V9 F/ @' y
$ }9 c! c8 N# T7 f/ G1、添加OLE/COM支持。
) }! w N0 l# Y2 f- K- n, U& l首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。
2 a& T, o0 j* c M3 t! V本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。
4 O) R' O# `+ Q6 C9 v% N通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。
0 b, {2 f& O7 v4 C. P2 r! H8 W- V#include <afxdisp.h> // MFC 自动化类4 g: j2 j' s) A. q$ V# M
同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:
; F9 L& w: d2 ^4 m& U& S// 初始化 OLE 库
( m9 n; U% w7 q2 U N) Mif (!AfxOleInit())0 z4 A, Y. U K5 z
{
: e7 b& e8 a5 Y4 R( V# b3 _AfxMessageBox(IDP_OLE_INIT_FAILED);
+ E' b5 [/ y" o0 V& c$ e4 ureturn FALSE;
# w; o* P; C$ j0 y) e}5 P4 \. g/ d( I. @
/ M5 V' P. m* U% n2、导入并封装Excel中的接口1 i/ R! f, r. `: w
Excel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。
0 K+ b E! @8 N' G M由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。
! T- }4 V K9 V0 s- A8 VVS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择- l& d1 A5 {' Z0 r! d- H# Y, Z
要导入的Excel类型库中的接口。
: K" A6 S/ h3 ?, M% M+ ?7 s在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。8 L. M( N/ h7 L. p/ P9 H0 q
+ y, f0 K p) _4 l& k: D
本文所导入的接口对应的类和头文件的说明如下所示:% ~6 k. P# m) X# B6 Y9 D d n9 P
6 C0 c& V' W8 o8 ?7 z2 I8 [( c7 j8 Q
Excel接口! ~+ P) a* I4 l* y& |+ l/ U
导入类7 h0 H" d1 w/ C
头文件6 i; Z) l. L7 i- O, S, W
说明" r9 J W1 Q% G/ ?, T4 {5 V
_Application2 x I9 }& S( O
CApplicaton
- q3 w0 I6 @: g. }4 {% T: N: A) iApplication.h
- z0 D* B2 z3 ]( b- hExcel应用程序。% F( I8 W+ h, B9 e( B$ a' G
Workbooks
# p2 y v( J! w( Z9 m. e! DCWorkbooks
" }5 Y( s6 {+ y. n7 s8 _Workbooks.h
3 x; `4 u/ u) ?' z6 P3 `; s4 r工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。
* W9 \8 m$ h# Y. Q_Workbook% s! [( f5 C4 |3 y4 K# j7 C
CWorkbook
* U; y+ U I( i$ w q& H1 FWorkbook.h0 v" }7 H/ r. p' o
单个工作簿。
# r9 b+ r% p. c! P8 G# G+ `/ z1 jWorksheets
$ j4 s) \; s: b4 @. PCWorksheets
0 {3 R F/ R4 f$ QWorksheets.h
6 C: B+ ^% u5 e单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。
0 I3 R2 M, J( n# _3 U6 p_Worksheet* j! @! h1 g1 `, F" b
CWorksheet, Q& n3 X9 U- m/ B- b9 H$ X# n s; {
Worksheet.h. j! p$ p+ k) X0 l L
单个Sheet表格。. Z( n ^& R4 L! I
Range
4 E& |# _' E# b' J) n1 {CRange
. g" K) ^4 X5 z M7 \1 g7 ~; V. K% rRange.h
3 i3 e+ v0 P9 I J; ^$ B" k一定数量的单元格,可对单元格进行单个或多个单元格进行操作。
; R4 N) R6 H1 D6 s9 L# | 8 s- `2 z: X+ m9 n: Y
3、导入Excel的整个类型库5 o: x# A) l& }4 V+ K- o
接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
" [' h% c+ L9 {0 [/ E通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:" i1 |+ t& u2 P$ x) B
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
6 |- g3 B4 H( X& g0 Z; f. N这行代码的作用是导入Excel整个类型库到工程中。
! E& R/ a8 D; Y由VS2010自动产生的导入代码存在以下几个问题:
" a# X7 X$ {/ ?& l' @(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。( A4 }0 c/ ~$ a3 I
(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。5 I Z/ m9 G" F$ Z& T' _. ^
(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。# _4 q# i6 J6 q
以上三点问题的解决方法如下:
# [) r4 E3 u0 M; k: F1 G(1)仅在_Application接口对应头文件中导入Excel类型库。. A0 ~! i7 S; C+ N0 f
(2)对冲突的类型进行重命名。+ U$ \ t' D6 |0 u5 R8 J& [& F$ A
(3)在导入Excel类型库之前,先导入Office和VB的相关库。
3 l: K8 ` i' o+ E更改后的导入类型库的代码如下:
) N! |0 A& L- Y: F6 F5 {! ~0 _ + W* j9 W) x0 R
/*导入Office的类型库*/
3 A3 H$ t* I: R; \; n# x" E& n#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \# L' p. [% b2 ]. x! M
rename("RGB", "MSORGB") \
6 ?" _4 g* z5 y8 S5 ]& H/ prename("DocumentProperties", "MSODocumentProperties")
P6 {# |# ?% U- B5 `: e- {using namespace Office;$ @' w0 F6 Q5 {' k# r) D2 E
e1 f/ l& J2 w% R
/*导入VB的类型库*/
& o3 G1 h" }* ?- O* k" G#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
^, K' H, {2 h% V- r- ousing namespace VBIDE;
# e, e( J1 n* V n2 h& ]* c 3 i8 [( j6 R' y3 F) Q* e7 y$ c d
/*导入Excel的类型库*/
- I9 i" f# G( e7 h& z+ J( h#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \" w1 D5 U/ ~' x; L* V
rename("DialogBox", "ExcelDialogBox") \( I8 g9 ]' _" ]/ N
rename("RGB", "ExcelRGB") \
. k5 d5 s! P% p/ @rename("CopyFile", "ExcelCopyFile") \5 x" K3 H8 q3 r$ E, I
rename("ReplaceText", "ExcelReplaceText") \! \* @- ]$ ?5 F3 x4 V
no_auto_exclude% W* }( G# Q6 G
Using namespace Excel;
5 Z, u8 r$ O( H
& e& C2 x3 B% }- x3 U) G编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。0 N6 F) n3 Z3 Y1 X
! j! {: r. _6 X0 J; T, b4、操作Excel步骤
0 A4 {; N `0 d$ T, S. s操作Excel的主要步骤如下:
0 x9 c5 a( S: C- z" `(1)创建一个Excel应用程序。
# |1 f5 T- ?/ @4 p! \(2)得到Workbook的容器。 D5 W2 t5 Q. H7 Z; Y' \
(3)打开一个Workbook或者创建一个Workbook。% Z4 O: A- i; R" P5 E$ G
(4)得到Workbook中的Worksheet的容器。3 K, f& N' y4 D
(5)打开一个Worksheet或者创建一个WorkSheet。0 w# q# j0 k! Q
(6)通过Range对WorkSheet中的单元格进行读写操作。
: Q. ^# s$ K5 P9 c) @+ R: u& R% s0 e(7)保存Excel。' l; }& {! k! |- b9 |* j
(8)释放资源。
4 F' G' i/ W- Z# \: i0 q5 ]
' i1 \! l# s6 B; h6 I7 j+ g8 j# o5、批量处理Excel表格% Q( G$ M( Q9 F l
VC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。
. a% [1 e/ v& v; y, M, c3 ^对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。
5 a/ s; w1 R6 V4 z5 v. C1 I1 R/ qVARIANT get_Value2();0 o3 z. d' Z. f E. z
void put_Value2(VARIANT& newValue); y- m* L- W7 s, u
其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。
7 D1 B9 A) i O0 `其中,VARIANT中实现二维数据的方法可参考
6 ^: W; ?# q, {' ehttp://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html S0 u! Z9 `4 C
当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。, ]0 w. f7 ]2 C) Y5 b. q
9 J, A% h* D2 x7 o' Z+ t
6、Excel表格的保存! ?5 {8 E3 E2 t9 B& b
(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。& B+ e& [3 l$ Y5 M, W
(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。. @: o) ^. v3 f! N5 f, H# N
SaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。8 \( Z3 F9 h5 U" \ F8 N3 O: \
5 W( y: k# @ b4 ^, V: U7、获取当前Excel的版本 {8 g# G3 U: @3 `
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
7 H- O6 N+ j: D $ h4 |& ?& Q, S1 u, F
8、示例源代码
1 K1 b! p7 _: u. N5 N# J b主要代码如下:9 a# V. X5 b4 F$ n
& r6 g, `8 J* L' }' t6 @! P# a- I1 v
' m8 o1 e8 N* a, k' Y& b5 k- k* x& _6 t( F. r
m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);4 T! R; W2 S) Q0 }" o! ?; D5 l
" F- s* }! }8 y e3 h0 n% }# m
CApplication ExcelApp;( D2 Y* w* B- q
CWorkbooks books;
: a8 [/ {, ^- Q0 e5 @# U6 R- u6 ? CWorkbook book;& L' Q# Y- e0 a" v% i
CWorksheets sheets;
$ R5 ?3 C+ ?( L8 b CWorksheet sheet;8 s- | ]/ S# t6 W
CRange range; l% g) c$ o- I2 _6 c
LPDISPATCH lpDisp = NULL;! a. [* p- |: K$ H8 m
2 ^% Y9 h3 h2 a7 ]7 ^
//创建Excel 服务器(启动Excel)
: a, f/ T3 j+ I/ K S5 D: `+ J if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))
+ q9 y# G7 X2 h& O' O {) Y- x4 Q1 o& R
AfxMessageBox(_T("启动Excel服务器失败!"));+ ?/ N4 C2 [% I7 Y
return -1;8 ~, E. Y: u. |5 O" D8 _ V0 ?
}- j3 ?9 O$ V5 \& ~. B+ x D
) v* X+ l9 Z* V- K* {& W /*判断当前Excel的版本*/: d8 n4 U0 d! j }! W" D
CString strExcelVersion = ExcelApp.get_Version();
' h* q+ N B8 X' S* s6 V& q int iStart = 0;6 I6 d8 W% N9 b
strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);
7 M% p5 o `: n if (_T("11") == strExcelVersion)- t& b. |9 U1 f" ] i
{5 @' Y; ]9 z. b2 r. O0 m
AfxMessageBox(_T("当前Excel的版本是2003。"));! \/ S* V- X, W0 n/ t3 I% l: O
}) ?2 O/ o+ h( r; B- }, K' m( T. P
else if (_T("12") == strExcelVersion)
6 ~/ T4 g$ W+ B* n2 x9 j; V' T {& W$ a1 U% z# A! e
AfxMessageBox(_T("当前Excel的版本是2007。"));
8 {9 V7 a0 L/ D4 x }2 c# |, X4 a P& q
else q% k$ r- T. l
{
+ U! u0 V- J& y0 Z c9 _ AfxMessageBox(_T("当前Excel的版本是其他版本。"));
8 T4 F! Z5 L2 v% H }
1 b+ e; w; J( q: @0 H$ O y6 O$ w0 o( O. w6 k7 r7 N* [
ExcelApp.put_Visible(TRUE);5 Y" [7 S7 K* M& I# G
ExcelApp.put_UserControl(FALSE);* |% i" A. W X" y0 G: k) h
$ z* V$ D# ?1 K5 t- N
/*得到工作簿容器*/
% J( h& r4 j0 Q$ l! y books.AttachDispatch(ExcelApp.get_Workbooks());, o P# |2 T4 n8 n2 B
' U5 g& C! l" m$ B
/*打开一个工作簿,如不存在,则新增一个工作簿*/3 }8 p, Z! O. f8 v7 a9 d$ R
CString strBookPath = _T("C:\\tmp.xls");; [; G2 ]/ e, W1 B% S- I4 l% V1 W
try
, j9 c1 n1 X3 u$ u0 h2 A {
# H0 K' O1 _# I& o3 w1 H4 ~ /*打开一个工作簿*/4 i0 @$ E/ I$ z; v- d t- g( ~
lpDisp = books.Open(strBookPath, 4 g: r+ p; H4 r7 I; \# o) c
vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
$ J; ^$ U: K4 j. _9 A vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, 4 p( b) ^" v7 Z R6 Y) f1 d! O9 d
vtMissing, vtMissing, vtMissing, vtMissing);
c, p/ w, {$ A! _. D7 J u) a book.AttachDispatch(lpDisp);* H0 Y; f2 C. M8 T, X: Z; r% g
}
, U3 q" a: v) t0 \2 M catch(...)) s+ v0 @$ q) [% |. O, h1 b9 M7 ?
{, @; q: ?3 `- N" z! m
/*增加一个新的工作簿*/5 m) X, I0 r5 u8 ^0 ~; F0 S
lpDisp = books.Add(vtMissing);
8 P3 A- o6 c; y% Y2 P book.AttachDispatch(lpDisp);( [! {: U. A4 V# ]/ g
}
& I- s+ S& h2 W2 M3 F
8 I: ]. |5 _2 e8 u, M
, G# H( G* l- x9 l5 S /*得到工作簿中的Sheet的容器*/$ c' O) L2 I! m
sheets.AttachDispatch(book.get_Sheets());
2 Q, A, [ i' m
+ G% U7 l X; F5 |3 h+ B, V4 X: {9 [ /*打开一个Sheet,如不存在,就新增一个Sheet*/" W8 e' f! ]. }- q& H
CString strSheetName = _T("NewSheet");
- G2 z! q9 V6 _/ ?& S/ ?4 m try
( @6 ~2 l% |+ H3 c4 d) o9 X {4 O0 U, _ \, N; c( z8 o
/*打开一个已有的Sheet*/
' h7 C) G1 @& F5 O lpDisp = sheets.get_Item(_variant_t(strSheetName));
P2 d# w& M# v. N$ I' {. j sheet.AttachDispatch(lpDisp);: D3 N2 y5 F; j, ? r* x" m
}% C, Y8 W* b: `! v
catch(...), f: c7 d; V' @0 h0 b
{( q+ r# L, f, X( ~ O
/*创建一个新的Sheet*/, ^9 ?8 L/ P* H( Z3 C) L
lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);' K+ i2 ~ e9 P; f
sheet.AttachDispatch(lpDisp);
2 E U( }3 i! M, y8 V sheet.put_Name(strSheetName);3 S0 c3 Q3 V2 M
} M" G. Q' v' r8 S- X3 b) p
+ x6 r- O3 P* M8 `1 @4 o6 [ system("pause");
7 p& S2 N3 u/ o- J l8 h8 T% a6 e1 X: Y4 ?( m9 z3 a. d7 q4 Q
/*向Sheet中写入多个单元格,规模为10*10 */2 G' z- B+ F1 A! P! d2 H
lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));
/ g4 a) B2 @8 e8 r' g0 O; t6 D range.AttachDispatch(lpDisp); `& A5 P, n, y% I( N9 Y& N& E1 f
; r+ w- k$ u+ F$ I7 x: b
VARTYPE vt = VT_I4; /*数组元素的类型,long*/
8 X0 {; P/ W4 y3 ~ SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/ M8 d% @* ]+ y" f
sabWrite[0].cElements = 10;
. i: Q- W8 [. _ sabWrite[0].lLbound = 0;
3 t( T" i: ~2 v$ _ sabWrite[1].cElements = 10;# {+ n( k+ H- u! N: Y( A
sabWrite[1].lLbound = 0;
8 \6 k9 ?2 E: w' Q! D3 [- o( m0 H% F! x* F& K/ k0 l5 s1 u* i
COleSafeArray olesaWrite; I _. [! P7 F' n& @0 I
olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);+ x6 S' x" Y' h) o/ a5 b
6 w; q3 K3 x* c- |8 B4 Z" I /*通过指向数组的指针来对二维数组的元素进行间接赋值*/
- B! B2 x& S( X6 z long (*pArray)[2] = NULL;/ X8 L q- c) J" q
olesaWrite.AccessData((void **)&pArray);% l: d! K- W6 O# z8 r2 c
memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));3 i9 n: e- ]4 G9 [2 F, A% X V
$ x1 |. s4 P% ^
/*释放指向数组的指针*/
, p. K- k/ W, G! M5 e olesaWrite.UnaccessData();9 M$ r2 A. d& h9 u+ z1 k
pArray = NULL;+ t4 a; h- B+ t# o
. W, l5 x" m6 N7 m: H- o3 J* o
/*对二维数组的元素进行逐个赋值*// G6 D/ o% k* ]/ z+ u! p
long index[2] = {0, 0};
' L- ]2 g4 T+ d long lFirstLBound = 0;) V& G% A. E. @3 ~9 l4 b9 [
long lFirstUBound = 0;
: Q& W* p: b9 }6 e0 g0 y" ^$ w long lSecondLBound = 0;$ W2 C9 @2 m! ]: w& o& l
long lSecondUBound = 0;$ }6 W+ @, c& E7 A b" I
olesaWrite.GetLBound(1, &lFirstLBound);5 ~3 |+ k7 [/ c
olesaWrite.GetUBound(1, &lFirstUBound);
8 t& j ], Z5 X0 G6 f5 C* F olesaWrite.GetLBound(2, &lSecondLBound);
8 A0 E L, b3 u olesaWrite.GetUBound(2, &lSecondUBound);! |+ M/ j+ q5 {/ y1 C
for (long i = lFirstLBound; i <= lFirstUBound; i++)
8 K& p8 y9 T+ Z3 l {
4 D( a7 u2 f Y" B. D3 F8 T index[0] = i;& m8 r: l5 B2 n R3 j
for (long j = lSecondLBound; j <= lSecondUBound; j++)( ]3 Y% |9 c1 V0 o5 o9 G
{! B+ [# V! b& B( `5 Q( C1 a4 q
index[1] = j;
, f6 B7 j& _! Q2 h0 M9 u1 K { long lElement = i * sabWrite[1].cElements + j; 7 U/ ^% A* M7 m" S( g6 s* ?' ^
olesaWrite.PutElement(index, &lElement);6 J. M% i: Z0 W
}! A7 \' c, S. g" C5 R
}
# \) T7 d3 [8 b' C
9 f" f: L. C0 O0 t* _ /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/7 f/ E p9 N/ j e
VARIANT varWrite = (VARIANT)olesaWrite;, Y4 B. d t9 a; X; m% j9 ]
range.put_Value2(varWrite); t1 h; P0 u* E" \
0 i: ]9 X/ i) ~0 \ system("pause");
6 o4 C7 D: j! c) n* X' m
- i& {% [) W& u* h7 b/ c; k* Y5 N /*根据文件的后缀名选择保存文件的格式*/
+ {' D) e6 v! `1 g; p! ? CString strSaveAsName = _T("C:\\new.xlsx");
' r) E/ E! _, o g CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));6 h$ e) O H8 _0 Y; G/ w
XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;
% J( n# r3 _5 T2 Z0 Z/ @ if (0 == strSuffix.CompareNoCase(_T(".xls")))
3 ~. b- F: h K) i$ e3 {/ B0 k {8 p) `3 X/ R( G2 b9 Q
NewFileFormat = xlExcel8;
3 t6 o8 O9 ` R% ]) K }) I" @+ [/ j f$ r
book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, 0 ]2 j4 m6 w2 d
vtMissing, 0, vtMissing, vtMissing, vtMissing,
4 i8 n. c% ~! X+ t vtMissing, vtMissing);
8 x* p7 u: Q. f6 I
7 o w8 w. ~5 T" ]( N' G$ s system("pause");8 R' `! W! n# ^3 w5 p/ C7 N9 C
# _1 G. N! r3 }5 q2 D5 \ /*读取Excel表中的多个单元格的值,在listctrl中显示*/
! G& O# W b& E5 L; ]8 @* v0 z4 { VARIANT varRead = range.get_Value2();1 ~6 g9 i( ^" F5 H# |
COleSafeArray olesaRead(varRead);: H3 J, i9 P2 G$ }9 R' T8 l
, X2 }8 X, T/ N" _ VARIANT varItem;
, p, T+ Z% a4 p8 ? A8 C CString strItem;2 t' e0 X3 ~# d1 Y
lFirstLBound = 0;' X! K8 h% u" H3 F. z7 ]' p9 t8 `
lFirstUBound = 0;
( J$ r" n4 v! u$ K' u! n. ? lSecondLBound = 0;7 {7 x' R, {% k+ k# e/ p" |
lSecondUBound = 0; G0 _" n {/ ^
olesaRead.GetLBound(1, &lFirstLBound);
# L6 ^$ i; V, K" k7 y6 [. j olesaRead.GetUBound(1, &lFirstUBound);
6 v7 w7 V" `& D' A2 B" A$ \( | olesaRead.GetLBound(2, &lSecondLBound);! ~0 z' q6 J4 A% J! X& m8 J
olesaRead.GetUBound(2, &lSecondUBound);
8 G) ]5 X( W/ d: M6 U memset(index, 0, 2 * sizeof(long));! j) E+ }" q0 X- l, ^8 q% u
m_ListCtrl.InsertColumn(0, _T(""), 0, 100);( ~ V* ]; y- N) L6 ^5 j. D7 I" u
for (long j = lSecondLBound; j<= lSecondUBound; j++)
/ d& r' _+ ]( @7 B% T {
& F# W& F% H1 `; ]! S. t CString strColName = _T("");
6 Y( E9 \4 O7 D' s# p- u2 O strColName.Format(_T("%d"), j);; d+ ]* E& x3 q- l
m_ListCtrl.InsertColumn(j, strColName, 0, 100);
# N$ \ {8 s8 H3 s. _ }4 Y4 k) T f. ]# e2 o- O0 n# W& o
for (long i = lFirstLBound; i <= lFirstUBound; i++)4 D" e; W% S2 G/ O
{# S& E$ z" ?% K7 Q# q a/ e
CString strRowName = _T("");) t9 m$ T- c- X* O' c* }
strRowName.Format(_T("%d"), i);
) T% o6 H$ v7 ^: A7 e* K5 u$ [ m_ListCtrl.InsertItem(i-1, strRowName);
/ B7 B P( z! ?( i5 l$ h7 T% [5 F; n9 f5 N3 i7 k6 I' G
index[0] = i;* e; Z# X% a9 k1 ~
for (long j = lSecondLBound; j <= lSecondUBound; j++)
+ E! n. z9 ^6 K9 D1 O {
' r, }! a3 E0 l c% Y4 f4 X index[1] = j;. Z' ~# _' E' p
olesaRead.GetElement(index, &varItem);2 V) k) J2 R; y6 }2 R
/ V+ g' z) E) _" n0 J; E( n: [
switch (varItem.vt)
( w; g2 E4 f0 M) i: G {1 v) H, R' c8 [) Q) K
case VT_R8:5 L( c# j% i- { K; {# _( l2 W1 [! l1 m
{) w# F$ Z7 O5 M5 g/ X1 Q4 t
strItem.Format(_T("%d"), (int)varItem.dblVal);
& P4 m5 Y% Z2 }1 C }
0 J: A1 C" p1 x8 m4 I
- h: W% j" }, v% c case VT_BSTR:; W$ Q- ?) l1 ^* B
{
z9 X" X2 v# \8 [, x9 h! x strItem = varItem.bstrVal;' V3 D8 U1 |, O: U9 }! n4 f
}0 l# Y) V$ X0 P
8 F$ _( h0 \7 B, P- R case VT_I4:- J7 Z- q0 s( q0 U
{/ V% S/ U5 W8 Y1 q
strItem.Format(_T("%ld"), (int)varItem.lVal);4 G3 A& f+ D; ~3 ~% v
}
" g: o$ D: v$ F; K& y7 O6 v/ z p. W7 d$ r2 A& ^
default:3 V; h5 Q2 ?9 ~* {, @' w5 T
{
: L" [- @$ W8 ]0 [' i' w# _! q9 a/ b& M d4 B( T7 s" I
}5 z9 t! c6 J, a
}
* d! m5 ~7 R W5 l# O. c* J
9 m% W W5 E3 s4 q m_ListCtrl.SetItemText(i-1, j, strItem);8 ]7 j! T0 U; ~% w0 T& _9 y' P
}, v; x; q0 N) k8 H- }5 V8 y; G
}$ u* E# R4 _" \1 N; R9 g
$ l& h' L% T% Z- n' U: i( @! r
( o4 ?4 e+ ?! f9 i
/ U& u# a% {9 i7 u5 K- k: ^ r w
/*释放资源*/
& E6 ~1 x/ ~6 ~6 q6 | sheet.ReleaseDispatch();
5 v( [' `8 O3 a7 r: H3 {& a9 Z5 ` sheets.ReleaseDispatch();
$ A+ l) L' F/ W( h book.ReleaseDispatch();9 h: |2 `# P% }0 w8 p5 a
books.ReleaseDispatch();
3 y, C+ z5 I6 V" m" k ExcelApp.Quit();# D* v$ I0 M4 o. ~0 X
ExcelApp.ReleaseDispatch();
# k2 n6 R! I4 W, S+ F) D8 M# h) \- x2 `2 P/ Z9 ], ^; V7 A6 Z
|
|