|
|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
通过VC实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文主要研究通过OLE/COM实现对Excel表格的操作。
5 n1 S, y, Q$ `$ u: n
/ e" t g& u( S: D本文源码的应用环境说明:' q. J; B+ w! S* V2 E7 o
Windows XP SP3
4 ^' F" p! O. o6 mMicrosoft Visual Studio 2010& n; W' p% D/ H! ]
Microsoft Office Excel 2007/ k8 ?' x7 `: e9 ]. o, l/ @
( z. {1 R5 y% a5 _$ J' k k& `1、添加OLE/COM支持。
6 P7 f" Y% L6 N# f# M0 h; b% _; E首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。
1 y1 a2 C3 D0 Q! K8 R; I+ ~本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。6 ~' Y. O1 Y. W! j/ i' i( R5 Y
通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。
) q% W3 n5 p" h5 A#include <afxdisp.h> // MFC 自动化类
1 {- b6 {: A+ }* a3 c$ h1 \同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:
9 l( B6 Y6 y* J% k% P4 K! O// 初始化 OLE 库
9 P; J6 z5 t& Q& L( Vif (!AfxOleInit())/ H7 T/ b" a/ u
{
* o2 o; l: K% M# d& nAfxMessageBox(IDP_OLE_INIT_FAILED);
+ `6 Q) j1 R+ G4 X* o( xreturn FALSE;1 z5 V1 Y+ g% d2 e# f
}9 {$ ~( d8 N: n$ N
; x& ] A( b& Y- X- P( G
2、导入并封装Excel中的接口" Z0 U7 w4 O# f* S% D
Excel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。
# x5 m4 t% b) Y6 @9 ^5 u4 Y由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。9 t$ a9 m$ l% n, D |# U
VS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择
: n$ K7 [0 P3 H, d1 S+ {$ I要导入的Excel类型库中的接口。
. w2 n; U' [; `0 J, S在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。1 z. f9 L2 g0 {6 ~4 H: r
! l F3 p, r4 }本文所导入的接口对应的类和头文件的说明如下所示:
' m& }1 S- W* e1 J3 J+ |
7 @9 `/ b+ b# c4 RExcel接口% ~: Y% @2 g$ q# L g8 K
导入类- _. b& ?) n9 m* I
头文件
1 `5 A( a6 g, \$ ^" R$ s- z说明+ O, `4 P* P) y; w
_Application0 v: j) O% l$ U' r- O# h
CApplicaton
) K0 s( E+ x, X3 H% C+ iApplication.h
+ t- u5 {% ]) a4 Y1 | hExcel应用程序。
1 O) e! L* Z: NWorkbooks/ r, e. ^4 p" p0 l1 z1 j) A+ u" Q
CWorkbooks' Y$ s9 d$ P) x! m" C0 `
Workbooks.h
2 n @7 j7 J& u& s! ^/ c1 v工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。1 {3 g& N) Z0 M& Z5 k
_Workbook
% }0 Q/ V% q- [' h3 JCWorkbook$ L* m9 [% b- y- h7 ^9 A
Workbook.h
2 y" O" T& p. n5 G- _ T- e单个工作簿。
0 p! I/ r9 k+ h- o# B0 YWorksheets F2 b1 e! {4 ]% p, G
CWorksheets, ]0 ]$ Q4 \ r* }1 s8 i4 g; s
Worksheets.h- y8 }" p* g+ e5 `
单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。
: R) ^$ ?% m( Y% ^. E/ l_Worksheet( ~' U5 Y/ A; b' X3 [$ P
CWorksheet( D8 Q4 j" Q; z( v; e8 s
Worksheet.h7 ]0 J; Q) j# Y" S" A q ^1 I
单个Sheet表格。
8 i* D) D; ~" G5 W1 B" ~0 ZRange
2 X' M& v7 C! O. D2 _2 K0 B; a0 dCRange
9 R2 w2 m+ O& s1 N" M; [5 V( rRange.h" c( j5 a' \* x- Y' Z
一定数量的单元格,可对单元格进行单个或多个单元格进行操作。( ]' ?3 r/ ? U! f
0 n5 s' C2 a8 y/ m5 ]! Y3 p
3、导入Excel的整个类型库* ~+ T6 b7 G- B2 d) F
接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
! ]! @% x; a6 A通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:
0 a) d5 w" h5 w9 j8 Z4 Z#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace+ Y3 n- Y& V+ k: p, y" M5 o
这行代码的作用是导入Excel整个类型库到工程中。
( F; n; \& D- |7 _) Y4 C0 [由VS2010自动产生的导入代码存在以下几个问题:
) l |8 v* r9 B(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。2 o3 I9 c# z) l8 B9 ^5 q/ e
(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。$ ^8 c5 k3 ~. ]5 O( f' W
(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。
/ `! o7 `! U$ t' T以上三点问题的解决方法如下: }% `+ A" d+ p# r( V
(1)仅在_Application接口对应头文件中导入Excel类型库。
6 M% v7 O: T* G" z" \(2)对冲突的类型进行重命名。2 |1 [' B4 P3 O6 Z W& i, |
(3)在导入Excel类型库之前,先导入Office和VB的相关库。
: e" I* Z% g8 T) c更改后的导入类型库的代码如下:
1 z) a! J) [" N$ W, z5 d8 B$ a8 x
+ I" T5 B8 M& H" f' d0 w+ X2 K/*导入Office的类型库*/
' X! F6 W2 K$ \/ U% N; {#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \
& F7 c. b& @) t. B E2 orename("RGB", "MSORGB") \7 T% _# C* Y& F. k B. u+ E
rename("DocumentProperties", "MSODocumentProperties")
q5 l8 j8 U+ B# Rusing namespace Office; J8 V7 n, j/ S) } |
- Q; N' \) y6 R. x. c+ H
/*导入VB的类型库*/. B* } u( Y4 }4 ]& m& X) |* u* @. n
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"! X E% f4 Y& @) t4 p6 O8 b
using namespace VBIDE;
2 Q/ N) E$ Y4 C& V + w/ S4 a' D9 q
/*导入Excel的类型库*/
" f l6 ]; n" z3 Q3 L#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \
6 A( ?6 V4 V- W4 F9 `rename("DialogBox", "ExcelDialogBox") \
9 V2 v5 d' K! p7 l" q' erename("RGB", "ExcelRGB") \8 p; A: [$ C* t. h5 u
rename("CopyFile", "ExcelCopyFile") \, f8 a \; v+ {2 V1 l; r
rename("ReplaceText", "ExcelReplaceText") \
5 [1 }* p3 c. _no_auto_exclude7 E5 U. ]7 o+ M8 C$ }) M# W
Using namespace Excel;
1 h. m2 [6 w7 e) M0 C! n
$ K1 E( D, l% C0 u: x8 e编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。
% s; z" L) m# [' ]' ]& i& K
) d& n' g' v; l) }/ J" @4 N' ^* ]' \' _! u4、操作Excel步骤$ N( i) R1 V' _0 O
操作Excel的主要步骤如下:* r+ \; H- P0 x4 x
(1)创建一个Excel应用程序。
! \$ O6 R4 @8 @: i, y/ Y3 \(2)得到Workbook的容器。: s. [; C/ _! x$ }0 Z2 ~, u/ ?
(3)打开一个Workbook或者创建一个Workbook。
! I/ U9 W9 z: U, \3 S/ T/ I(4)得到Workbook中的Worksheet的容器。) e4 k% R' Q5 D4 b& u7 u
(5)打开一个Worksheet或者创建一个WorkSheet。
* n9 E4 n" }7 D2 f(6)通过Range对WorkSheet中的单元格进行读写操作。
+ z! U, _- F" z! Q(7)保存Excel。$ c* ?- ~1 S, H9 M$ F
(8)释放资源。5 k# S; k( x# V( F% n9 F, _
% m6 r1 [0 m3 q+ p, O5 G2 U+ y. H( B5、批量处理Excel表格& S5 Q& G h& h- x# B& V- b, K
VC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。
# y5 X9 }# }& h对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。% U7 O9 I! Q0 |5 ~
VARIANT get_Value2();* _& `, r% @# p& V# r$ c
void put_Value2(VARIANT& newValue);+ l- M8 d4 \$ R( k" q( I, J2 A0 b# N
其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。
; A4 y. V' ]0 S! ~其中,VARIANT中实现二维数据的方法可参考
5 u5 X6 S$ B! C" p3 T2 q9 Ihttp://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html
$ t( U0 _0 q9 r H5 f4 q& I当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。
* p6 ~5 A5 O( f/ m- y+ d+ n, e3 D 1 R m+ u2 J: M; t6 ?3 B, G
6、Excel表格的保存0 `7 ~( F. r7 A8 d- m* K' G
(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。
* |3 [2 g7 F; E: h(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。
. \! y( F# O1 I( Q. I( rSaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。& o4 X, o0 c9 c5 w1 Y" O. c+ K2 S
) Y- N: G! S1 L n7、获取当前Excel的版本, G0 U; t2 \5 _+ Q/ h3 _3 `, p
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
' p. E/ X2 d4 Q7 u - ]+ m6 B0 i6 ^, W& g4 m6 V$ V
8、示例源代码
! Y7 A# V7 [. R( I' F/ [主要代码如下:
. J2 h4 J8 E, x7 l$ U 4 G5 K2 r* e- R9 N6 R
/ X: O, h- E, K3 N/ O0 y/ Y
$ l$ u8 }& v, v7 T/ u4 b! l1 } m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);
) @/ A! k9 ^1 d# @6 W6 p% O
# ?3 Z* K( c* c# S CApplication ExcelApp;2 d$ M6 E3 h- ^! s) T
CWorkbooks books;+ J+ Q8 C& b( Q) e
CWorkbook book;, p0 Z( }& J" m- ?3 b6 ^
CWorksheets sheets;
9 c7 P' k3 W. s" r CWorksheet sheet;% C9 G3 y8 l8 D( M
CRange range;
8 Q: q2 I5 f" \: [$ m- A/ F LPDISPATCH lpDisp = NULL;
; W; b0 y5 ^( S6 H8 k
k0 L9 a; e5 q8 o1 ? //创建Excel 服务器(启动Excel)
" D" G0 R: k& s- F8 L! h) l2 n0 A if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))
" \# d0 q! f5 T" D {
G K2 {8 O# X AfxMessageBox(_T("启动Excel服务器失败!"));5 b6 @- c# y) H! a7 O1 N' C
return -1;, O% s$ e( X8 ? G* }
}: |4 w/ j2 d5 ^4 m2 R8 n% v5 N
4 o7 \! C0 a! P
/*判断当前Excel的版本*/
; h) U. J! ^+ f4 {5 Q CString strExcelVersion = ExcelApp.get_Version();
6 d( T. z& C; ^! v1 K1 F. g int iStart = 0;5 V' ?% ]1 [: n2 B( h: {0 d8 x
strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);# h( ?1 {9 I* D9 }
if (_T("11") == strExcelVersion)
; s# F' c: x$ s9 ?* v {* ~: D+ E: A* }; x4 L" G
AfxMessageBox(_T("当前Excel的版本是2003。"));3 W4 U7 k) g0 h
}
5 \% p( W- b1 m3 f% x) Y else if (_T("12") == strExcelVersion)
; C1 W; Z8 N; j {( b, R, ]/ }, ?, {8 I
AfxMessageBox(_T("当前Excel的版本是2007。"));
|% L+ J! I4 O1 y }/ x# O- y6 [" o2 u! @
else# b$ v" C6 l# e; R/ V
{
, O" f' ^* j+ s/ `2 S AfxMessageBox(_T("当前Excel的版本是其他版本。"));
5 x: [9 I- ]6 p+ u6 E3 W }. S5 G, `: i) Y' _) h7 p
8 K6 E" }. f5 Q2 h0 y9 w
ExcelApp.put_Visible(TRUE);
- {! `) B! b, O9 z5 q ExcelApp.put_UserControl(FALSE); D1 [; r# [; c0 @ U
3 u% k; H# l2 N g# T' E. Z2 O l
/*得到工作簿容器*/9 p T5 }7 R2 o" K4 U; o$ R. |
books.AttachDispatch(ExcelApp.get_Workbooks());7 E: V2 y' U8 d+ r% n: ]
9 L& D2 j! N& E+ l$ M& H5 R /*打开一个工作簿,如不存在,则新增一个工作簿*/4 b! h. A! N+ ^! f0 S4 p
CString strBookPath = _T("C:\\tmp.xls");/ K1 t! S6 z9 t: a2 N. ?, t
try) h, d+ o& ]- Z8 S" X
{1 a/ [& r6 T, c
/*打开一个工作簿*/3 e+ o. H( a. y, t% G
lpDisp = books.Open(strBookPath,
! \4 ~& L$ k/ L4 F- b vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
$ E2 g# k, n X/ \: q! B6 U: r: H vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, ) [* @) j% a9 J/ z! P" `9 y
vtMissing, vtMissing, vtMissing, vtMissing);
' Q% H" j9 I$ I, S- G! ~ book.AttachDispatch(lpDisp);
D+ J/ @ W' @ }' ~" _. b0 S0 e+ }
catch(...)
, Q9 g& p" H5 z! }$ c {
" K& B6 w/ l+ t /*增加一个新的工作簿*/5 X2 B) D- }: f% u1 C+ ~
lpDisp = books.Add(vtMissing);
: S5 P* ^6 D! |$ m* E7 ^1 Q7 c; D book.AttachDispatch(lpDisp);0 J3 A) ~4 f( T4 p5 @' Z. h+ p; z
}" r+ S/ T8 v1 }2 q- t1 g: W* Q+ ^
' G6 W' q* P/ ^2 W. v6 n( R" b
$ J( l" y; Y" e( h# w( M% G5 \, o /*得到工作簿中的Sheet的容器*/
# g5 C- Y/ o1 d3 \* S3 L: W+ A sheets.AttachDispatch(book.get_Sheets());% Q8 b! T3 m+ N$ w% q2 h' P! I
2 ?* I4 s$ L7 v& h( d/ s% n1 |
/*打开一个Sheet,如不存在,就新增一个Sheet*/
% `; C6 F& H" g5 C) ~ CString strSheetName = _T("NewSheet");
' I6 i! k: `$ R$ g6 I/ T; D! D try" g4 Y2 p8 E: b0 R5 n
{( E: |& t, u9 F- x' b1 p
/*打开一个已有的Sheet*/
1 d; @( \, A6 n4 P lpDisp = sheets.get_Item(_variant_t(strSheetName));
( I9 p- T T+ I4 _* L sheet.AttachDispatch(lpDisp);- K9 h0 t! |8 H t8 g
}1 v8 k% @3 ~. s) A
catch(...)
5 u! m& z+ m B2 x" l& [# d {) U: W6 v1 _* B6 ^! X# u
/*创建一个新的Sheet*/1 N `9 C+ ?. a4 x& E; e
lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
: R, q1 x. Q4 }7 H- T sheet.AttachDispatch(lpDisp);' x4 k7 z8 w/ ?- @8 a+ n" R1 F& ~
sheet.put_Name(strSheetName);* F) S4 |" n r7 U7 {6 o" I, P( H! R
}
6 Q* b/ V) K, B5 v. v( g7 f
/ ~) P9 R% J% B system("pause");
# i. e5 g1 N- b3 D' Q5 c' ?4 a8 w& z5 ?* e N
/*向Sheet中写入多个单元格,规模为10*10 */
6 K) @6 H4 X. |0 @" T Z, g lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));
+ Q# t ]" F2 Z! [9 t range.AttachDispatch(lpDisp);
; q* ^: B0 z; d7 T; c
7 b- ~ C6 F6 g VARTYPE vt = VT_I4; /*数组元素的类型,long*/
* d, S1 P6 ^. @% B7 b/ C, h SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/: G* a7 W& G5 ~& ~
sabWrite[0].cElements = 10;
! z8 t2 I, {$ q7 T+ ?$ s6 D7 B! {; q sabWrite[0].lLbound = 0;% _6 h% m* \1 ^
sabWrite[1].cElements = 10;
+ G9 h5 n' P1 ]" S* e* _ sabWrite[1].lLbound = 0;# q/ {- v! ^# Z) Q/ o% T
" N; m" w; A$ a8 c
COleSafeArray olesaWrite;: U# A6 R+ N: P/ Q
olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);3 X. O7 L0 B! q4 m4 W7 @
( y1 h4 l& e0 e9 _
/*通过指向数组的指针来对二维数组的元素进行间接赋值*/
! n0 }3 L" D6 R8 j. b5 f: L4 S long (*pArray)[2] = NULL;6 b: W& t, x5 M$ _- a8 N! I
olesaWrite.AccessData((void **)&pArray);4 Z9 E% t) `! \
memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));4 j' v- D" G0 x/ I x6 I
8 x2 Y9 H- U9 |* E- m
/*释放指向数组的指针*/7 h& _0 K+ t& R _. x' m
olesaWrite.UnaccessData();- g* C$ Y1 i1 S! {9 K; l
pArray = NULL;1 K5 X% t. z ^3 x4 Z/ [
& r: a! q- c; ^' s5 d, M
/*对二维数组的元素进行逐个赋值*/* c0 T0 i# Y( E N' W3 Z% y! H
long index[2] = {0, 0};: K. l$ @$ [: S! E {
long lFirstLBound = 0;- P4 X% g+ ]7 b% T ]/ o9 `6 ?
long lFirstUBound = 0; C3 i" y; f& [2 H/ h7 @
long lSecondLBound = 0;) G& n7 m* ?: L
long lSecondUBound = 0;
& ]3 }: U9 e: ~) G- S% m u! x olesaWrite.GetLBound(1, &lFirstLBound);% q8 `" s" {" S' r6 ?, K
olesaWrite.GetUBound(1, &lFirstUBound);# `$ ] k* B8 v3 l
olesaWrite.GetLBound(2, &lSecondLBound);. w" m+ G. I% N$ a9 Z0 I+ _
olesaWrite.GetUBound(2, &lSecondUBound); S6 V7 i0 ^8 l7 o
for (long i = lFirstLBound; i <= lFirstUBound; i++)
# o1 x& j/ q0 L9 H8 @/ e. u {/ j& K3 o1 E, N7 c+ ~( A
index[0] = i;: @* P& X G3 u) z, F' f
for (long j = lSecondLBound; j <= lSecondUBound; j++) n |, S8 n/ d* B" m
{
- u* G3 n6 y' d/ X5 o4 t9 o index[1] = j;
* G U& A# P% v9 W long lElement = i * sabWrite[1].cElements + j; & O+ D5 h9 \' Q2 u; w
olesaWrite.PutElement(index, &lElement);: |7 g& z8 F a' _. z
}3 ` t9 W) t, k0 U% I, @* ]
}8 c! e g1 \, l" H- S. H. [: C2 `
! S" X% f7 X+ s+ p* N2 V# P /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/
, U9 \. u8 V' }' } i2 O P$ O VARIANT varWrite = (VARIANT)olesaWrite;8 A4 u( u5 `" s+ i5 W
range.put_Value2(varWrite);
% x M$ W8 e3 Q) \ m
$ E8 i% H/ }( y: z system("pause");+ K. }0 T/ S. z- Z
% {, ?6 ^# C- _% O, { /*根据文件的后缀名选择保存文件的格式*/
0 m- T( E1 ]6 A5 O! ]: J) O0 _ CString strSaveAsName = _T("C:\\new.xlsx");4 O- r% n) z6 H* ~6 x, H
CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));3 |1 F: Q; m0 z: H
XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;
7 j! A$ r s+ o. }9 [ if (0 == strSuffix.CompareNoCase(_T(".xls")))
5 P! H# c( p( B8 | {" f% q5 }8 V# D- _' w
NewFileFormat = xlExcel8;
) T' c& ]2 P J' I5 Z }4 d1 B6 _% P6 s @/ O
book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, " H' P4 h& y4 \" _8 L) A
vtMissing, 0, vtMissing, vtMissing, vtMissing, p+ m. L! N* ]) L: d: L8 W; u
vtMissing, vtMissing);) r+ r$ W( H* l' f8 ]- e9 Z
) U. n$ r' R8 r system("pause");( i$ L! a% h7 j& B# Y5 X
3 `, X6 D* z) L4 y
/*读取Excel表中的多个单元格的值,在listctrl中显示*/
5 l$ a1 P9 @- b VARIANT varRead = range.get_Value2();
: M5 i* u( o) U/ C COleSafeArray olesaRead(varRead);& S- s, \ r$ ?: w. r/ R
# g5 L7 Z7 Z) ~ g) L" c/ V' y+ ]
VARIANT varItem;
/ p6 a# C- n) ~% q2 A ^+ s CString strItem;+ j3 _$ {6 V/ S& V) g* d5 c
lFirstLBound = 0;
?2 k S# T) ~8 ^ lFirstUBound = 0;. U7 ?+ Y0 [* t7 O1 R: ?7 {
lSecondLBound = 0;8 o& x5 M% n7 k9 ?- h
lSecondUBound = 0;
; `4 U! G" G. Y6 O olesaRead.GetLBound(1, &lFirstLBound);
) w: H/ d1 C) ~+ d% Y olesaRead.GetUBound(1, &lFirstUBound);
7 K, Q m3 b1 s3 [4 U5 l# X olesaRead.GetLBound(2, &lSecondLBound);
: y9 g; w" v! k# ~/ z olesaRead.GetUBound(2, &lSecondUBound);
1 h: w& X3 s: ? memset(index, 0, 2 * sizeof(long));% _# }8 `; |+ R, B1 h1 \# r8 Z0 m
m_ListCtrl.InsertColumn(0, _T(""), 0, 100);. W$ W2 a `7 X, g
for (long j = lSecondLBound; j<= lSecondUBound; j++)
$ f- o9 K4 z* q {
7 @/ j' V) R) _5 Y CString strColName = _T("");
9 c; r; m) T' `/ q8 h8 a; q strColName.Format(_T("%d"), j);$ H+ M% z# @. L2 w* t
m_ListCtrl.InsertColumn(j, strColName, 0, 100);4 y% Y$ ^3 l8 d7 @
}
* P2 x* y! Z- V( S2 j6 H$ h for (long i = lFirstLBound; i <= lFirstUBound; i++)
' n2 W% m2 U3 I% ^# D {
+ a; k& u+ l4 {- p6 T CString strRowName = _T("");. r8 b8 \7 ~/ Y9 N6 e; q
strRowName.Format(_T("%d"), i);
6 ~* |) Y+ o7 K( S m_ListCtrl.InsertItem(i-1, strRowName);
5 }7 I+ x1 F; Z' V/ y) K2 {& J( v2 J$ n, K+ ]( R8 O
index[0] = i;
! N3 t7 `, ]) q" q2 W for (long j = lSecondLBound; j <= lSecondUBound; j++)7 D; T' X- p2 l# ^; D ~
{! l* w+ c1 J3 l, O8 m- o0 ~8 L3 ]
index[1] = j;8 k, F H/ b$ |# Q2 C3 m. o5 q9 [
olesaRead.GetElement(index, &varItem);2 G( V9 E+ \3 q1 A1 ?; U
- r* J/ v, b! w7 c! ]" }0 B# O
switch (varItem.vt)
) x- |$ {+ Z: E9 c+ g/ N8 K {
6 q& B1 N1 h V* h; x# } case VT_R8:
: W! i3 v- @. _ {
# Z0 z1 O" A( N2 L strItem.Format(_T("%d"), (int)varItem.dblVal);, Q9 X& _5 i5 X: C
}$ {+ u, U$ \8 ]8 w8 W
0 Y0 L% H/ J0 u4 p2 W' C case VT_BSTR:
6 C" O; U; I+ N" T% p$ e# ? {
" I- x+ J& K& x7 z# z3 R8 q strItem = varItem.bstrVal;
3 \+ e% ~1 {# e$ v% m. T }+ `2 C3 i7 j3 F% I
( K) x* ~/ m& N
case VT_I4:
5 k+ r# }" q5 z: j+ j9 \4 B, ] {- I( F) } T& ^8 f- S! z( ^( p% ?
strItem.Format(_T("%ld"), (int)varItem.lVal);; s' p. [2 Y% i: P. J: H
}0 z2 K: G- F1 f3 }9 f+ i/ o
; P( b$ v; {& v; }# X8 k default:
- z* n* P( i1 V7 E; o+ {" t7 z* Q& |5 w {
( d1 { S- c. e- @5 S; Z1 b
+ c9 R9 z: [2 @ \+ S6 X }
6 J2 @8 K+ `! q& b9 } }
# S j0 I4 Q9 W) v* ~, k% q, n" h$ X# s9 D$ c! s
m_ListCtrl.SetItemText(i-1, j, strItem);5 g0 m6 l) U# P" l5 ` r
}
; N) r$ o- A# V7 ^ } P5 A& l0 `( h" D6 a4 F3 H
- q5 B5 g& e- @7 T9 w5 A
" W3 D* n( K) c3 }" _$ K: a
# {0 i* T/ R; U6 j2 W4 z /*释放资源*/1 r4 W$ t- X. H) ?
sheet.ReleaseDispatch();3 d1 G5 F( Y; C! x- K+ N
sheets.ReleaseDispatch();8 {- o9 c S- l
book.ReleaseDispatch();
- H& B; L) R' a/ ? books.ReleaseDispatch();$ D* j% Z+ w/ W" t& ], q( b; R% S6 q
ExcelApp.Quit();6 N8 Q* Y. a3 A( X
ExcelApp.ReleaseDispatch();5 E5 w7 X, `! {$ n. \' P' ~ G
T* f7 B( W; O; b0 p |
|