|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
通过VC实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文主要研究通过OLE/COM实现对Excel表格的操作。" _! G4 h5 Y' y; E4 `7 ]2 o v. ^
& x0 p- @; w! |1 |5 D
本文源码的应用环境说明:
! M$ x) [! p: wWindows XP SP33 R* v0 ?+ i N! H/ _' M$ T
Microsoft Visual Studio 2010+ ^( j* g0 B9 q$ ^- w: O6 l) g* V
Microsoft Office Excel 20078 N) g8 J4 a9 a
2 P+ f! x( y+ |/ f
1、添加OLE/COM支持。
6 S8 N1 R2 @" U! O首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。
, J3 |; i" ]( B2 a1 Z6 b本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。
4 a( y. |" s3 L: M" s$ M通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。+ I# C# K. |3 Z$ ?$ Z/ V. C: c
#include <afxdisp.h> // MFC 自动化类- O0 J2 m$ V3 y: _- [
同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:9 c& H- d; a* J6 X1 s E
// 初始化 OLE 库7 g" z7 v# E& E
if (!AfxOleInit())
+ V4 ^8 B A1 W3 D5 A{
8 v4 Y9 H o4 @2 wAfxMessageBox(IDP_OLE_INIT_FAILED);
6 [" q. ]( Y9 l% o, Preturn FALSE;4 n$ y* a* @! W# a$ ~. x% j
}
1 Y6 G/ V' u- |4 X ; [( p8 G+ n8 u2 N: x
2、导入并封装Excel中的接口
# P7 t O% {* [" tExcel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。
( X! |$ ^& k- q. c( s, P+ ^6 h/ i由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。
$ q8 u% W, o/ CVS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择! a4 K4 u: U" _: f6 Z+ I
要导入的Excel类型库中的接口。
1 Q0 W* N' y5 |: C# ~1 m在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。; x* _8 j! J' \0 Z4 P
4 E A w0 B1 m( Y0 a! k" z
本文所导入的接口对应的类和头文件的说明如下所示:5 }3 b& K4 l( g$ D# ^" J" _9 C9 i @
5 ?- w! j' a" P& C0 f' r+ HExcel接口
8 f) @: z/ m% [/ E导入类
* U* e9 C% d; A& c) G- M头文件
w3 A' b5 k! m# a& m- S% L说明
) S j2 k; m5 b3 d/ x* x" {6 ]_Application
e4 H$ y) C0 b ^2 U- }+ R9 }. DCApplicaton% H% ~7 R" `+ W" Q4 z! g
Application.h! V0 E" n$ j' a. U
Excel应用程序。
' l( E: r N& \Workbooks1 h% Y0 g, [( _' }) Z4 a. z9 o: p
CWorkbooks
1 V! R8 @ Q5 _, H( N8 D$ _Workbooks.h
5 Z3 Z; d4 }3 H! U- E9 n5 k0 i' _工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。3 N8 J0 C4 Q! D8 D
_Workbook& H+ V8 v0 P. T
CWorkbook+ z6 a V0 E9 W) Q7 q) J: [
Workbook.h1 ~' V: a/ s( f0 H1 ]0 ]2 e$ f+ d
单个工作簿。
* J6 ^/ X) Z0 Q( I& F% VWorksheets
! K. f# @4 U/ ^7 Y. l# T! LCWorksheets
6 o0 d' P+ U! H9 }Worksheets.h* h" x7 l( y" _7 j5 c% U8 q
单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。
% q: e+ |. \; a* ?- o8 _; p" x_Worksheet1 h- x) H( q& k: Z; x7 S, k" H
CWorksheet3 W1 ?3 ], Y# c1 w( ^+ i
Worksheet.h
7 _! l) a! X& f$ \单个Sheet表格。
/ m2 S' }& u0 vRange, b& J y u- Z
CRange9 z! Q1 H7 h2 S, d
Range.h3 h9 r4 R d# j1 T! F. I
一定数量的单元格,可对单元格进行单个或多个单元格进行操作。
4 b, _ E5 r u$ E B- T
" [) G. a$ Y0 X3、导入Excel的整个类型库6 S# S, A8 ]1 k) L# |0 `
接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
7 n6 }! ~8 ?$ o8 w. N! z% B$ \3 t( B% O, q通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:
* L2 o+ {7 w) t ?4 B1 \#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
- L6 l: f0 J/ D2 I这行代码的作用是导入Excel整个类型库到工程中。
- Z Z6 v" [# i! \( W! \由VS2010自动产生的导入代码存在以下几个问题:- d# B6 P" Q; U! B3 I$ O5 M
(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。4 d( c0 ^# U) p0 P# P
(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。
) v* g1 V1 t, p5 d" d, O5 r6 A& r(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。6 \2 Y$ H) n- t. f/ v
以上三点问题的解决方法如下:
/ r o% w; n- N0 [' o6 v(1)仅在_Application接口对应头文件中导入Excel类型库。* H( u& e) }! F
(2)对冲突的类型进行重命名。
: a8 v8 t- ~! q(3)在导入Excel类型库之前,先导入Office和VB的相关库。
" O8 H: p$ q0 M& k/ v更改后的导入类型库的代码如下:
( D2 W6 P# F: O( r7 G2 @4 j
4 u- S8 Z, s& I4 {9 e3 t/*导入Office的类型库*/4 @ X% F U, t. S, z- p
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \4 ]/ u' |' p' K* f, e2 O$ w
rename("RGB", "MSORGB") \
" t- N3 y' n) F' x0 S6 Urename("DocumentProperties", "MSODocumentProperties")- n5 A" i+ ?: r
using namespace Office;! I8 t/ @& W# f8 J- o! D5 }
! N9 ]( v: `) n# g, l& ^. a
/*导入VB的类型库*/
; _7 R; C4 R, R& j#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
$ \- v6 k" f5 }! Susing namespace VBIDE;
1 T; w# p. s m , l6 K% U2 k/ p" S9 s g1 H
/*导入Excel的类型库*/6 ]; J) F( n( y: @( E& g3 l! ^
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \ y, s, G: E+ j$ r ^
rename("DialogBox", "ExcelDialogBox") \, M! w2 y: X! w8 [
rename("RGB", "ExcelRGB") \: o) S \) p0 G% f5 I7 ^
rename("CopyFile", "ExcelCopyFile") \* g# e# u! T+ I5 |* X& h
rename("ReplaceText", "ExcelReplaceText") \
; E8 h( J0 p3 g$ t; }# h+ l2 Wno_auto_exclude4 n2 P# x" _5 P+ ?
Using namespace Excel;
' P8 ]4 H0 a7 f5 i( B
1 v4 U5 H0 x* }( ~5 Q# D5 X编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。1 o* i, g% M Z4 g
2 d9 \1 D) P7 O8 L4 A4、操作Excel步骤4 r# M! r, e$ I: X) E, t
操作Excel的主要步骤如下:# V9 L1 U$ G; H1 ]
(1)创建一个Excel应用程序。# d6 q& z, b, T
(2)得到Workbook的容器。& ^! x# \1 S. J) w
(3)打开一个Workbook或者创建一个Workbook。
5 D) B& b5 ?- \ l(4)得到Workbook中的Worksheet的容器。
: F2 o. |6 e; l# t" _(5)打开一个Worksheet或者创建一个WorkSheet。) N# G9 c1 K. G# b# P& C2 y g
(6)通过Range对WorkSheet中的单元格进行读写操作。
i8 j; K i( H" X+ N5 c(7)保存Excel。
! K* [) r5 Z6 v; b(8)释放资源。
; X( m$ h; W B+ ~" n; d, U# ? 2 ~# d2 u' M; ~% J2 j
5、批量处理Excel表格
R W' y9 U0 V% h. WVC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。3 H6 N' H1 q2 x2 _, j, n0 l
对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。! e' q* {5 B1 ]; l
VARIANT get_Value2();
" V/ P X6 {8 ~2 t, Vvoid put_Value2(VARIANT& newValue);
; p+ K. ^$ S; v% z) F8 X其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。6 M7 g* @& S6 Z; F9 d
其中,VARIANT中实现二维数据的方法可参考+ q; {5 r0 w8 o; K4 F3 C `
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html' t' L! D, Q, T% z& w$ P
当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。
/ m! o! v3 @0 H6 I
c" x$ p U6 T4 J* X. I! Q6、Excel表格的保存
" F5 C/ ^; k o6 L/ A(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。7 F1 U: @6 c8 z9 w! Q4 R: j. j
(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。
/ x. u) p* J9 v8 KSaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。% H# ^: M) b0 }% [) i
4 f; N$ Z* Q; u4 T; J7、获取当前Excel的版本% R( w, B$ _6 l9 n4 W5 ]
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
. z+ i; K2 z' p* W9 m5 m ^+ R( c& r 4 o, ^3 |: G% X; @$ C7 [
8、示例源代码
: I5 G) d" y: u1 }4 A8 V主要代码如下:, T* C; Y, d" N; }+ b4 X+ R% {
' ?1 ^! X& r1 o% j
" B7 C1 r3 ~' w5 O" i0 z* W& `9 A" f' ~% g
m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);
) D) a* N! y8 z" j, {) t1 m/ l2 Q- E# m9 C5 [1 M
CApplication ExcelApp;
* o u' c6 O% j7 j( b CWorkbooks books;
& o4 U$ J) d# `9 F5 o( N1 M CWorkbook book;+ I: d( \" U; F
CWorksheets sheets;
; v5 G3 V: r$ H& U( X. C8 K- ` CWorksheet sheet;) K. [& \% l% M4 t
CRange range;
1 `$ _8 J# r0 i3 \3 z* H LPDISPATCH lpDisp = NULL;4 x! {4 \. o/ g: c! e2 h5 ^
0 t k2 Z, h$ B+ J( w L: ? //创建Excel 服务器(启动Excel)5 s' ^5 b9 j+ r6 K5 s4 d
if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))
+ y4 M/ |2 X; v {
+ T6 e+ q5 C5 Q! k! P% M AfxMessageBox(_T("启动Excel服务器失败!"));
% C; J3 a- X5 ]+ I U6 y) g return -1;
" V+ s) O5 m/ W2 D3 j. J( I }# K0 d( @$ B) K6 P
) O8 N- Q/ Z0 D$ v3 ], {) M /*判断当前Excel的版本*/9 F0 J( [/ q6 A3 y# B
CString strExcelVersion = ExcelApp.get_Version();
4 Y' M6 ~/ f h. |: {9 Y" r int iStart = 0;
2 ?; p! X y1 ^0 \3 Y strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);
; l8 N. I$ G: Z2 N if (_T("11") == strExcelVersion)7 L" S# n5 B6 f5 v' U C! [
{
5 `/ |6 l9 C4 r. p AfxMessageBox(_T("当前Excel的版本是2003。"));% k4 W0 S% B! R/ P/ a
}
1 d6 ^# I7 i! p- B( L( [9 @ else if (_T("12") == strExcelVersion)3 ]( c& `! I: _5 A! E
{1 o1 K$ B1 F( l" R9 J& j
AfxMessageBox(_T("当前Excel的版本是2007。"));# X( u& l1 F6 I8 R O/ R/ T
}
0 R( s, u. U9 V, X( F2 M( ~ else1 Y7 R- A9 ^: {) O
{
' ~% f7 A, T* r* `( z AfxMessageBox(_T("当前Excel的版本是其他版本。"));7 n! V0 d% ~, L, d, c7 M+ G
}7 T! O1 N+ M6 w7 N1 w
0 x9 w/ }/ `) ^: ^ ExcelApp.put_Visible(TRUE);
& P1 r S) B) K ExcelApp.put_UserControl(FALSE);2 O9 p( ?. |: E4 X8 V: P; v4 F/ a
; h9 Y$ o9 z- R5 M /*得到工作簿容器*/. a9 M% q7 g" ?0 l6 |
books.AttachDispatch(ExcelApp.get_Workbooks());
1 c# \6 K) j/ k. s8 j0 Y3 A
( C' K/ J3 e; H( G1 A /*打开一个工作簿,如不存在,则新增一个工作簿*/
+ n5 j! k8 l/ A) B+ d8 I! I CString strBookPath = _T("C:\\tmp.xls");
; Z: A v7 o9 r) q3 M try
5 u6 N3 z( b% X v {' K; ]3 @; \0 D
/*打开一个工作簿*/6 w' x* R' y3 c# \( m, Q. J; e
lpDisp = books.Open(strBookPath,
/ Q, l2 e2 q. ^/ @2 H vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
$ w& ^; _$ ]9 R( }7 I vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, & O9 a- V3 y, {) b( U
vtMissing, vtMissing, vtMissing, vtMissing);
1 s3 ?& v3 ], L) g2 [3 m book.AttachDispatch(lpDisp);6 ?- {9 K5 j3 W3 O# s" L
}
, ^4 s; q: K6 e' w A9 c; v* b& i catch(...)
/ {5 ?4 d, @3 l! i, Q {: U9 T$ E3 V J. u0 R
/*增加一个新的工作簿*/
% U6 ]$ i* H7 u/ W! j lpDisp = books.Add(vtMissing);
, }2 `. v; _' B* F$ m% y! K. ` book.AttachDispatch(lpDisp);9 D n. i$ k' Y2 Y
}! O0 G7 i T) v1 y7 K9 t
9 m7 q3 s% y5 H) s# Q1 k; {" J1 ?3 h1 Q4 U, k3 z; B% x
/*得到工作簿中的Sheet的容器*/
- e# a) V, l/ J- W* O5 U3 F sheets.AttachDispatch(book.get_Sheets());8 d( t& p& V$ ?: l9 V4 {
+ p5 x( t+ ]4 R _, @* U7 w' O /*打开一个Sheet,如不存在,就新增一个Sheet*/3 F! w$ D* K& G- X* [
CString strSheetName = _T("NewSheet");
- [" o: C) ?) [/ u c$ } try3 x5 b2 ~$ D/ A; M( L, m' A
{
# o* k: T9 z6 `6 i, G /*打开一个已有的Sheet*/5 }$ o1 p C2 k
lpDisp = sheets.get_Item(_variant_t(strSheetName));
9 l2 O. `/ r7 v+ a& i sheet.AttachDispatch(lpDisp);
6 g' e# u5 c; Z7 p3 L, a! R }
7 B# z Z- D: K W( H catch(...)
; G$ o8 \7 G j- @& I {
k# }1 b1 L) c& ~& N: y /*创建一个新的Sheet*/% _. u9 v* {& u: |+ s& g. R
lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
# T5 J. V4 i9 ?: N3 x" Z sheet.AttachDispatch(lpDisp);* r. a' a6 Z% f D4 E" Y7 | [. r
sheet.put_Name(strSheetName);
6 T7 T% L+ N; u2 F9 G" k }
" U6 A( q$ J/ I0 [5 B
6 D7 X: F4 J7 A3 {/ F system("pause");
) p: s0 U, @" _/ |) C$ T2 O, {) ^* H1 c
/*向Sheet中写入多个单元格,规模为10*10 */
- Q/ V. r8 |1 E' r3 f/ s) X lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));
+ q; \, T3 q7 \3 G6 }, I' d) w range.AttachDispatch(lpDisp);# s" x4 `9 w: n# E
9 }6 ^% p: j' L VARTYPE vt = VT_I4; /*数组元素的类型,long*/1 C0 P7 }0 d6 s+ b" z' c" G
SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/
6 g8 |- a3 v% k4 ^! a sabWrite[0].cElements = 10;
" U2 b2 M t: d: r9 z' S1 S7 C sabWrite[0].lLbound = 0;& a' V2 X# R; k
sabWrite[1].cElements = 10;
/ D! H4 n: q3 M$ z# _. E# U; ^ sabWrite[1].lLbound = 0;
$ |# | x$ a7 O3 }
( H9 L# b3 O1 A7 b8 l W COleSafeArray olesaWrite;& k) {# v3 ~$ e4 `# c
olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);- R) B( r! D/ D
5 ^, u T" }, Z& s /*通过指向数组的指针来对二维数组的元素进行间接赋值*/
( T& a1 [: n1 I& u$ R long (*pArray)[2] = NULL;5 K% r- ?4 H$ d6 e
olesaWrite.AccessData((void **)&pArray);! Q( {% k+ Z' m2 ~& A
memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));# x0 O; G: U1 u2 ~5 ~2 h
' E! B! D0 L2 v6 r /*释放指向数组的指针*/
: G( q) U( I& I6 j- \ olesaWrite.UnaccessData();
& l W* e3 l5 J5 K, ` pArray = NULL;
% J0 T% A! V5 A9 u: u- c- I# f9 K u
: @* t/ F7 N! F$ {1 C /*对二维数组的元素进行逐个赋值*/
" x* v. t/ \$ c long index[2] = {0, 0};
, k0 p8 _; @4 w9 d6 F long lFirstLBound = 0;/ U( c7 g7 m0 h! O. J: X6 o
long lFirstUBound = 0;
! F6 d; i9 V( }& T3 N2 o7 ^ long lSecondLBound = 0;
0 h# i/ ?" u; }( s* R long lSecondUBound = 0;* S( p1 U% f5 K3 V7 C
olesaWrite.GetLBound(1, &lFirstLBound);
3 Y5 V7 w- w; ~0 g. t/ c! W olesaWrite.GetUBound(1, &lFirstUBound);
# R; N: ]5 ^* [' n9 D olesaWrite.GetLBound(2, &lSecondLBound);7 \6 Y* J( ?% l2 m! X6 ]
olesaWrite.GetUBound(2, &lSecondUBound);6 ^3 _ r) T* ~8 [6 Q, q1 `% s
for (long i = lFirstLBound; i <= lFirstUBound; i++)
9 H* N; |$ O5 j8 B3 ?5 c9 j9 B {0 R7 _1 ~4 d, G0 x1 [
index[0] = i;
( p: f0 o4 K# ~, o A, X! b+ k' K for (long j = lSecondLBound; j <= lSecondUBound; j++)
, {2 @. S: H) q* A {
6 i& \3 ]" O1 V' w# Z; f2 T index[1] = j;
/ y* y2 V- g5 ~4 c' u& T3 _) x- V( d long lElement = i * sabWrite[1].cElements + j;
6 {- w A! s( i- B" ?7 S olesaWrite.PutElement(index, &lElement);, [6 I4 n0 S0 _: _ O
}
% H3 `/ x1 q3 J! w5 ]0 T }
6 h7 x2 ^0 N1 o: f( ~+ r
k6 ?3 `$ N. {; M /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/, ~1 B L0 b8 H( l4 B3 r! x
VARIANT varWrite = (VARIANT)olesaWrite;
: U# _3 P& [# z3 c8 g9 R2 H0 |& y range.put_Value2(varWrite);$ w% w1 M# a, O* a0 Z+ k0 ]
H6 W% [- P+ l2 f6 f0 N
system("pause");
& c& h$ G3 p1 G4 i# W! [2 ~! n9 d# z, C* R. H% W; E, H
/*根据文件的后缀名选择保存文件的格式*/9 c# r) C/ q; c- ^! S' @
CString strSaveAsName = _T("C:\\new.xlsx");
! A2 M5 G9 H8 \$ g CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));
$ a, L. B) ]2 J. L- t# n5 V& C XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;
1 Z. F7 z' K7 H, F if (0 == strSuffix.CompareNoCase(_T(".xls")))
9 f" e, Q& o3 L$ |0 ] {
# K! p- x. r5 ?1 r( I NewFileFormat = xlExcel8;$ Y. ?. G* O1 b9 D
}
4 ^. o K5 V: S: ]4 j book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, * o. {) u% D+ k8 F$ A' B
vtMissing, 0, vtMissing, vtMissing, vtMissing,
% v1 z7 ^ b& c; J7 a- j4 A( z vtMissing, vtMissing);* B, n, y4 m1 {5 b- Y- U. `$ K
$ b; [8 V: S+ ~6 f6 ~
system("pause");
1 r' M p# A3 i6 U
. i1 I: L5 C, [; H /*读取Excel表中的多个单元格的值,在listctrl中显示*/
6 s! h, l$ [6 K VARIANT varRead = range.get_Value2();
" X( L( Z4 g. [. J COleSafeArray olesaRead(varRead);
9 E, s1 K6 `' \/ b: Y, ]
( E' ]4 l, h5 e. b6 d+ R VARIANT varItem;
! C+ \3 B5 c8 _, q& {3 e) i4 _& n" N7 f CString strItem;
8 @( j* N. _) p, _4 c' p3 L& E lFirstLBound = 0;, [- P* K7 W& u' Y B
lFirstUBound = 0;+ u6 B% d( z" M R9 G
lSecondLBound = 0;* G. ~( A9 M9 K! Z* |
lSecondUBound = 0;
% \! C: g, o( p; f6 f5 Z0 `4 j olesaRead.GetLBound(1, &lFirstLBound);9 X0 D0 l9 y: U# h7 P
olesaRead.GetUBound(1, &lFirstUBound);
" Z; f6 H7 p( Z- ?1 V olesaRead.GetLBound(2, &lSecondLBound);
# {6 f& t* N8 F: A, a olesaRead.GetUBound(2, &lSecondUBound);
. A r# V/ J* N% s' u* R9 Q memset(index, 0, 2 * sizeof(long));, z, L' X# c; U; F7 m# {+ U) p0 M
m_ListCtrl.InsertColumn(0, _T(""), 0, 100);- H: A4 ~. T6 w: X( M: _% q! ^+ \
for (long j = lSecondLBound; j<= lSecondUBound; j++)9 f5 w- [' l/ p% n( g
{
* q- ~& [9 Z6 C$ F% K) @ ` CString strColName = _T("");' f+ @, |: T% N. K/ p9 F- {7 C9 b
strColName.Format(_T("%d"), j);
0 x; y4 P4 }# c8 u& I- I y3 e m_ListCtrl.InsertColumn(j, strColName, 0, 100);( H# V/ ?0 j" W. ~4 L& K! g. W. ]: N
}! P; o" m4 N" M7 c& s
for (long i = lFirstLBound; i <= lFirstUBound; i++)
8 T8 H' P' R9 q" d1 q) z {
, y3 V/ s) _) ]& M' f CString strRowName = _T("");( {# d2 i" d+ ?: [, [$ ?( I
strRowName.Format(_T("%d"), i);
8 Y- Z( u' Q' J& C; r m_ListCtrl.InsertItem(i-1, strRowName);4 v% Z1 L% ~% ^8 h! O
5 d" r+ v. C$ D `) P/ @* D
index[0] = i;
; f" Z7 h$ J$ e for (long j = lSecondLBound; j <= lSecondUBound; j++)
- H( r2 Z& f/ }/ h, o {
8 U; L! [4 R# c0 z index[1] = j;
6 N+ g4 ~ D) f# S) H olesaRead.GetElement(index, &varItem);
) S0 g4 r* Y/ b( n) f& V1 t
: W2 j$ W; j5 ] switch (varItem.vt) W; {1 `" g8 x, ?
{
, g, ^; W m; {! p% p4 d case VT_R8:# m% v, n K5 a( s3 V' y* D
{7 M. ~# Y9 o* R' V& N# Q* @) T
strItem.Format(_T("%d"), (int)varItem.dblVal);; j A$ \9 n+ I; W1 s
}8 p/ y0 W/ E, e, U) z$ u4 A+ d. c
! k$ ^& Z. F/ u case VT_BSTR:
: `; \3 r$ D& l {. j) G* s' T$ \1 K7 |
strItem = varItem.bstrVal;
/ u( I9 h, _: @6 V5 P7 i+ [$ q } Q0 T! t3 H0 X. a6 z! v* G( w" B
% a6 |+ ^" z) s# s$ O6 }
case VT_I4:) L& d) M4 F/ m0 Y
{
3 ~4 d/ f/ y+ o strItem.Format(_T("%ld"), (int)varItem.lVal);. T& c( P, G5 @6 P
}& c, R7 X4 j! G$ C% A
, Z- Q6 v4 |0 K$ h5 b5 J7 z+ u default:
; p. m$ A& O6 o& j7 ]6 _ {
3 E$ P; {& o5 k/ ]9 @ D0 H0 y4 ?# k
}
/ r3 w7 a4 X2 @% v( q }
: v" c3 X. x/ m1 i* A( ?
: T9 x4 h$ t4 L) ~ m_ListCtrl.SetItemText(i-1, j, strItem);, ?8 q% X* l0 F6 I" ~# G- w# U
}
* R& ?6 o7 D6 J3 F }( U# l6 \5 a( N
# I: l3 c/ s& E7 [
( E3 ^8 U5 p3 x, z0 R6 D; c& @. j( d4 O, v8 O" g: P
/*释放资源*/
! ]) y A7 \: b" H1 ~ sheet.ReleaseDispatch();- i7 X% Q5 |. Z+ S% L% i
sheets.ReleaseDispatch();
$ |! y! O# F$ R5 V% J X book.ReleaseDispatch();
& G0 {; R! h# m books.ReleaseDispatch();
) O. j/ W3 }, h4 q" S ExcelApp.Quit();
, e! q5 c$ L$ ^" c ExcelApp.ReleaseDispatch();0 D, y& q {7 V1 I: K5 f L9 c
7 @' A9 v2 b- f, ^' @1 c
|
|