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