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