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