|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
通过VC实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文主要研究通过OLE/COM实现对Excel表格的操作。2 g4 T7 x% i3 P" a+ d# s/ o
% [6 _; |1 P6 ^! ^) G+ W8 M本文源码的应用环境说明:6 V% f+ u) e& S3 i1 ]
Windows XP SP3/ S' e, r, f" A
Microsoft Visual Studio 20104 ^9 \: W' m9 Y* x1 ~/ c% p
Microsoft Office Excel 2007& J; r9 r/ t8 P0 J
! c7 v5 m5 Q! }3 Q) E) G$ F7 C }1、添加OLE/COM支持。
@/ ?9 r; e$ {0 O( Z! | N首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。
3 ]0 I6 v4 v. s2 b' S8 _) H$ R本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。: v! x: Y+ @' U) T. i
通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。$ c: r8 J& x) X8 o5 I2 j
#include <afxdisp.h> // MFC 自动化类/ X% O6 {8 W# ~* k3 ~2 @0 y1 M7 Z
同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:0 |! O# j9 g; e; N/ z
// 初始化 OLE 库) y" D2 O q9 `; A; a
if (!AfxOleInit())3 E" o2 C1 f0 A: p
{
( J) g& n0 A+ C. ^1 K4 MAfxMessageBox(IDP_OLE_INIT_FAILED);, m; u7 {( r. g+ s3 Y2 b' S+ [
return FALSE;& w7 j' t) O. c( I2 B5 c
}0 |$ [: i" x w0 K( i
F( Y) k& l" f8 S% L* d2、导入并封装Excel中的接口# p# ~5 @3 ^; `# }
Excel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。
) k0 _- l3 o# m由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。7 `2 P; X) O8 H5 P" z4 {
VS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择) ~7 r4 n0 F3 K% V8 g
要导入的Excel类型库中的接口。/ P8 k7 Z/ x; r- v: W# n" \% E
在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。# i/ q* R% v0 m/ P; G
6 D* u0 D& V4 A6 N( {( r) [本文所导入的接口对应的类和头文件的说明如下所示:
* ~7 s) N' ]- ^! p x) n / ]( ^7 a8 b4 l
Excel接口3 P# ?* V% t, X3 W- V1 ?- I
导入类- g' M" S; M- W: S% l2 @
头文件: k' C( x! G% }4 ^8 K
说明( e; Q1 [. B. l' E$ m* Y% H) y/ u
_Application5 U- S/ A8 _. D$ E i
CApplicaton1 |* S; o* R/ [/ f9 e; o
Application.h
0 d' Q. \) ?6 V {2 }Excel应用程序。
9 @. u& b+ |6 ^8 w; r$ H- HWorkbooks
' N1 `! h& K0 I3 f* |CWorkbooks
. X6 c. A9 V, u. S/ { ~1 t& ?( ]Workbooks.h8 k# S. p2 G# m) M% b# y
工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。
% u ^/ |1 J8 p% T/ Y_Workbook; G1 S' G& N* U4 j* `
CWorkbook! u, t+ ~1 K8 f
Workbook.h
# l6 d! t [2 c9 L1 Z1 ^单个工作簿。$ M1 S5 v- f" s" ^
Worksheets9 r8 H: P! ]" c1 {" y" ^
CWorksheets) i4 J( b& l5 @) J+ J
Worksheets.h u: v8 N: Z8 }$ [
单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。
# M- B3 P" q8 W( y/ j. x# C4 R7 t_Worksheet
+ [6 c! A8 r, C( W- p7 c( Z1 X1 {# ~CWorksheet
1 r, s# j% M* _' aWorksheet.h
! R4 @' Q8 T, i0 X' m单个Sheet表格。
; U& t$ q* |2 i+ r) h, \! X) b; QRange
- C' P- O7 E1 u0 u$ iCRange# W$ {; Q( B# r; t
Range.h: B2 n5 ~0 u$ y. R6 k
一定数量的单元格,可对单元格进行单个或多个单元格进行操作。/ Q' @1 U4 [* T
# v# r# H% t, |- j
3、导入Excel的整个类型库
- Q3 }) v4 I7 r7 i2 H) ^* U接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。; f1 ^4 o% x$ h1 F9 Q! I1 i
通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行: T- N. P9 g( M' z* \/ J6 l
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
# H( J6 V; E0 L# }这行代码的作用是导入Excel整个类型库到工程中。2 C0 t- ?- t l) ] q- l5 A
由VS2010自动产生的导入代码存在以下几个问题:* [4 `% d! L" I' N' s. u# H: V
(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。7 R( j6 ]# X4 ]! c
(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。: O2 V: Q4 x$ s+ I5 U
(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。( Q& |/ m$ r/ f
以上三点问题的解决方法如下:
/ G$ P/ @+ E! C% |$ v: c' H9 i" i(1)仅在_Application接口对应头文件中导入Excel类型库。* z9 D/ p9 ?5 t3 s& J6 B+ ]
(2)对冲突的类型进行重命名。* _& S" A, M' @& z
(3)在导入Excel类型库之前,先导入Office和VB的相关库。
1 n' P# E: t5 e2 x) x5 r更改后的导入类型库的代码如下:
& v/ A; q: N9 T. M4 N% n
( F+ j6 |" a4 Q" {3 \4 b/*导入Office的类型库*/
# a. X- z, U* I) j5 U& [#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \
) ^4 I+ F8 J, E# H6 j0 l9 wrename("RGB", "MSORGB") \
- x& U! O. s9 K1 x6 k9 |" }rename("DocumentProperties", "MSODocumentProperties"). e- F. Y) g6 u: N5 T, _; g- d5 q
using namespace Office;! u) n2 ?4 Q( w- Q0 |
N8 j2 B+ x5 f: i/*导入VB的类型库*/" H4 ~+ f" I8 a/ [
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB", y8 X% d5 l, }# J7 U% s; D7 u$ U
using namespace VBIDE;
. i2 ]3 N" L. c9 b o! s5 I; ]
% |( b) S( Q, `& n8 y8 r/*导入Excel的类型库*/
/ D6 J- b$ \+ ~) E5 V& d#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \8 `& q5 G, B! l- {" O4 ^
rename("DialogBox", "ExcelDialogBox") \ X- ?) b) L; L# K1 m% Z- v
rename("RGB", "ExcelRGB") \+ c" H5 u5 v% z
rename("CopyFile", "ExcelCopyFile") \
; T8 [! Z1 M$ W. Y2 F/ trename("ReplaceText", "ExcelReplaceText") \$ z6 e- I9 p# ?) Z$ f7 `* G+ K5 a
no_auto_exclude) o5 m4 C7 Q, j3 y7 Q7 b1 O$ |6 H
Using namespace Excel;
3 w3 B: x8 `. S
4 @0 o/ O q A+ Z: X编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。3 J' E+ C/ Y2 X& S3 `
/ H4 d3 x8 H/ Y
4、操作Excel步骤
5 c7 x; k& D7 o5 f8 \操作Excel的主要步骤如下:3 Q9 r% Z1 ?( Z' Q, i6 e0 R
(1)创建一个Excel应用程序。6 z, i5 p' U9 X( [/ I
(2)得到Workbook的容器。. z6 v: x* X' L, Q. G1 n. N: y) R
(3)打开一个Workbook或者创建一个Workbook。
?# e+ d# ~$ {2 Q; I' G# i(4)得到Workbook中的Worksheet的容器。
1 v5 H8 \2 C4 W8 \% g1 T(5)打开一个Worksheet或者创建一个WorkSheet。
( \( y8 D% u) i(6)通过Range对WorkSheet中的单元格进行读写操作。
. z" x1 o' J) h' m# W+ O(7)保存Excel。
: V7 ~; N# n: K; K(8)释放资源。
& v; J& c5 {. d) s
5 i/ I5 V! C* Y) i5、批量处理Excel表格) n9 R5 n: Q G5 [4 ?+ c
VC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。! |- _1 o: D( f
对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。6 ~5 K1 S: k# N1 K: d* A* `1 j# d8 `
VARIANT get_Value2();
$ q5 |) X8 o0 S8 [7 n/ avoid put_Value2(VARIANT& newValue);; b7 H4 @7 R' b; j, J y0 I
其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。 T3 ~! J/ Y; @0 _
其中,VARIANT中实现二维数据的方法可参考( ]) G- O! V1 P+ i! }* ^
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html
$ W% X( x# h/ \# f! v当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。
7 @( G7 w! F e3 } 0 n- R( M3 S0 R s1 j) _7 J
6、Excel表格的保存 i2 l; Z2 A6 x" i& g$ l
(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。8 @" |/ h' e+ J+ b' a! Z
(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。) E2 [$ b# S" F
SaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。, [# O. ~1 T9 {' S2 S" u
5 {! P+ X0 @- Z
7、获取当前Excel的版本* G/ x* c/ Q+ |+ f- t
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
2 f* [+ @8 }- Q
6 b* M0 Z4 x9 R7 G# u7 t8、示例源代码4 e% z/ b; q- N, S0 I0 E0 R9 j5 c2 N) `
主要代码如下:
$ J; v$ r+ ^ T1 {1 |( N
. y& w3 _+ `$ ?7 G" f5 L) Z4 z* f- D6 t- ?+ ^& d4 }
& Y; u: S0 E+ E# j2 k m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);. f5 F0 y6 Z( n- L* }
, l7 g$ Y0 t R8 V7 k2 z7 ` CApplication ExcelApp;
1 D) p5 j/ H& }) l$ `; y CWorkbooks books;* N$ C8 N( t; G
CWorkbook book;. T" q& |' b( v
CWorksheets sheets;$ G* }# S9 H5 H1 V3 c) @
CWorksheet sheet;1 t1 a. ?4 I; ?
CRange range;* x9 O( T; `0 _" z/ v' w% [, P, }
LPDISPATCH lpDisp = NULL;
" c0 |* A/ g# u/ P* x- ?5 [
" _; Q: s2 T( `8 C0 O5 Y //创建Excel 服务器(启动Excel)+ ?1 N( D4 X2 {. g/ C
if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))
1 L% ~- O/ m6 l, r2 h3 E% J. p- W {
+ J$ O4 L* J& U* R4 E AfxMessageBox(_T("启动Excel服务器失败!"));( U3 [4 t g( c8 M) S6 G
return -1; x! H" Y$ _! u( F0 `1 b
}
0 {) x' i; p* X7 _9 t% E4 d
5 M- h! m9 z' [1 b- `9 u! V /*判断当前Excel的版本*/$ v9 n7 G% j6 z$ D8 f
CString strExcelVersion = ExcelApp.get_Version();* f8 |8 h# ]# R" Z
int iStart = 0;# D. C) a; x: d+ `9 m5 @$ r- X
strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);% \! f. [9 K5 {9 R" s
if (_T("11") == strExcelVersion)
b; J6 M. r! J0 r4 D {9 |6 O6 g: x% }9 J
AfxMessageBox(_T("当前Excel的版本是2003。"));
# ]9 y9 G, L4 s6 }3 }4 A }, B8 W5 v; M5 a$ H, [, o: a! Q
else if (_T("12") == strExcelVersion). X7 S6 V8 k# b W3 o
{- d3 H" A' l7 H* {$ p: v6 U
AfxMessageBox(_T("当前Excel的版本是2007。"));
3 h( `4 x Q% `8 [% j! _ }
# x( d7 u/ m! t$ p4 _2 _ else5 \9 B m( G! ? e. P9 E7 I% ~
{5 w1 S; I$ K+ ]* s/ A
AfxMessageBox(_T("当前Excel的版本是其他版本。"));
2 l2 }( C# e' X5 z }. a$ H& V3 h# B) Q b0 _
I& s& m, V3 D! W$ z$ P ExcelApp.put_Visible(TRUE);1 \! ?+ C9 r% \6 E H
ExcelApp.put_UserControl(FALSE);4 Z* w8 ~/ u1 ^- J/ B/ I
: p6 {- ?; J- d' Z /*得到工作簿容器*/& d8 c4 K5 `! g; x4 |2 E; z/ L$ v) C
books.AttachDispatch(ExcelApp.get_Workbooks());
1 }6 \5 B4 T6 l4 X* Z
# L3 Q; S$ |; m+ [9 L /*打开一个工作簿,如不存在,则新增一个工作簿*/
3 M, b5 S' _5 ^9 V% n; ? CString strBookPath = _T("C:\\tmp.xls");: f8 S9 ]- }! D
try
. `# D# L7 U7 k- X! v! G7 A2 r {/ @/ W) K0 S( P' G! R
/*打开一个工作簿*/
) _. i) @! A' f# @) Y0 t lpDisp = books.Open(strBookPath, - r& K) R) b" U6 o p
vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,) ], Y& q5 p4 S( r( l( ?( d
vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
; h7 y" U. d) k( j, h vtMissing, vtMissing, vtMissing, vtMissing);) Y V$ l! [1 |9 ]: u9 ?
book.AttachDispatch(lpDisp);
: r* b) }- F' r8 i. k$ C }
; J$ \* p' f8 J7 P7 H4 R: T catch(...)* I$ m2 [3 y2 Z ~
{ ~# _8 I+ B3 r7 l$ ^2 Z' E: F/ A* T
/*增加一个新的工作簿*/
! q5 K# m6 E0 ~2 k0 f lpDisp = books.Add(vtMissing);
1 \: Q3 Z& a! U& d$ E9 ~9 r book.AttachDispatch(lpDisp);: D% ^: ?# y$ Z
}( Q6 d: u, S% R% d
5 S, P& x: d! y$ d% e, @2 K# B7 G
, C4 K- R9 `: n& J; E% F/ t2 A
/*得到工作簿中的Sheet的容器*/& L$ F' P* A8 [% v; g) E
sheets.AttachDispatch(book.get_Sheets());
* z! Q! b- V" L( }4 r9 W8 U. _4 g" | H* ]3 _: H/ ^ `
/*打开一个Sheet,如不存在,就新增一个Sheet*/
" |0 p+ v$ q' c/ S CString strSheetName = _T("NewSheet");
% x- i$ l4 R" l) b, n0 w try
" h3 ?8 m: ^8 m+ t& c9 |# \- D {6 i% ~+ C! [) i$ l3 z/ W, D9 T
/*打开一个已有的Sheet*/
$ h( Q: i/ e2 _: _ lpDisp = sheets.get_Item(_variant_t(strSheetName));4 ]- y- P; Q; X
sheet.AttachDispatch(lpDisp);! v8 A/ u% n- C1 ^" {. l j
}+ k% ^" v7 m" Q7 r2 \; C
catch(...)
& r8 x! @0 E% u! R6 j {
, D) F" ~- D9 H, ~9 k/ | /*创建一个新的Sheet*/ D8 K: E$ a5 T% u& e5 `
lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
/ N- U( z$ c4 c. q+ a sheet.AttachDispatch(lpDisp);' u! r% U9 |% g, t
sheet.put_Name(strSheetName);
# k) |/ t, Y i/ X! B0 J/ l) k$ y, k* t }
+ u, B7 o$ q: S/ D# e; R
) i6 T$ u6 J9 {7 R0 K, H1 R system("pause");
5 P+ L2 |$ B, {8 B7 ^
8 \- |' o, d* C ^ `% M( U /*向Sheet中写入多个单元格,规模为10*10 */
2 P/ b; A# }0 I4 P: f9 c0 X$ G lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));
8 Q3 K- h$ C) g- o; ? range.AttachDispatch(lpDisp);
; s6 X& q2 W3 I7 z" l- X& F. g4 c, h& [! c4 f% @
VARTYPE vt = VT_I4; /*数组元素的类型,long*/! h; A% W3 q, x- j7 s
SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/
0 f/ V9 I, Y3 w1 }; A( Y sabWrite[0].cElements = 10;
) g0 m$ [# _. Z+ Z$ B7 [$ l sabWrite[0].lLbound = 0;5 w3 ~; C1 o$ U, F3 U- ]3 A( h* Y
sabWrite[1].cElements = 10;
9 N- T/ Z4 { x! R- G sabWrite[1].lLbound = 0;
1 V+ i/ N+ k/ {0 b
" l5 m- X3 z/ F COleSafeArray olesaWrite;
, e. ?8 z: k1 T0 a7 [1 ^# `! U olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);
4 }) |& t& s1 \# A
8 k4 }8 @5 _. D5 n A7 H /*通过指向数组的指针来对二维数组的元素进行间接赋值*/3 O% R; o3 s6 z* ~$ Y/ Q6 _
long (*pArray)[2] = NULL;
# g9 I$ F/ b# J- ] p# P olesaWrite.AccessData((void **)&pArray);, n$ {7 x. u, S/ u( ^
memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));0 p5 i- x3 a$ x9 Y! }
. a. V& A9 R6 K
/*释放指向数组的指针*/
# G+ q# q/ N( P" j( C olesaWrite.UnaccessData();: o" B- r' c1 c
pArray = NULL;! r. ~' A- ?0 n9 \1 n
$ W5 @1 k# V( M' n2 ]3 k /*对二维数组的元素进行逐个赋值*/( \ s' d. B' J$ d4 l# F9 [
long index[2] = {0, 0};
9 E) [$ j# v6 w4 x, J long lFirstLBound = 0;
: l3 \8 x5 G, i: A6 D8 b/ }" R. ]) X long lFirstUBound = 0;0 N* {# w. o- f' V# a2 N/ `4 m
long lSecondLBound = 0;, I: R% T/ Z) p
long lSecondUBound = 0;
0 T1 J/ a* J/ T) z9 P olesaWrite.GetLBound(1, &lFirstLBound);* \% s( J( t, G- T; T1 t
olesaWrite.GetUBound(1, &lFirstUBound);% o. G% ^+ C+ P# S+ \# F. L* g
olesaWrite.GetLBound(2, &lSecondLBound);
7 z4 x1 e0 t* u' ` olesaWrite.GetUBound(2, &lSecondUBound);
7 B m1 n/ m1 F% s% { for (long i = lFirstLBound; i <= lFirstUBound; i++)4 G; E5 C- {5 K! e. T
{: F0 v8 w) W) O, J; R. ?) s
index[0] = i;0 W' _7 ]$ N/ s9 o) G) U
for (long j = lSecondLBound; j <= lSecondUBound; j++)8 u0 A9 @7 e" I- H( N
{
6 S2 T- E- t! ~" u; S1 r index[1] = j;
6 o, e9 r" t- ? long lElement = i * sabWrite[1].cElements + j; ! P- ~ b" o% z- e2 G2 ^2 b
olesaWrite.PutElement(index, &lElement);; k5 x% w& i, Q* H
}
2 s6 a- ]1 x7 B/ _% O1 U0 l }
* n4 G) A# l& K3 }5 I9 `- x
4 p1 `2 ?& q: e /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/0 B0 h# i: r$ t0 v. V
VARIANT varWrite = (VARIANT)olesaWrite;2 _4 E0 a& o6 B% Y0 k
range.put_Value2(varWrite);
' x, J6 B; l5 v1 C! H
& ?* W: y: A/ a I3 a9 ^' Q system("pause");
' p6 E! n6 ~* y8 ]( D/ j+ A# ]8 B$ B! _, V
/*根据文件的后缀名选择保存文件的格式*/! s' M3 B& @1 Z. q7 |5 a4 `
CString strSaveAsName = _T("C:\\new.xlsx");
1 ?5 Z2 }5 C* S! i7 [/ } CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));
; M) Q h+ w' |; C XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;
0 X& X- k! R0 {4 ~ if (0 == strSuffix.CompareNoCase(_T(".xls")))
+ B% e4 g, K$ l, c9 Q2 ]( n {4 r/ Y6 ~9 F5 r* G2 F( e) K. D
NewFileFormat = xlExcel8;) x, u7 u+ n+ O5 z+ F3 b* }
}. H# N0 M! ]1 e
book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, 5 D4 \4 E+ D: m1 m: g9 r8 I
vtMissing, 0, vtMissing, vtMissing, vtMissing, ! H( p! L/ Y" Q& s8 c `4 }
vtMissing, vtMissing);
$ u4 a: |! j6 M/ [0 V: e
9 B' R: {8 C2 F, _. K system("pause");
1 C" O( E: g3 r8 J4 h5 n5 J
! T' P. h+ U4 }3 j" j+ W /*读取Excel表中的多个单元格的值,在listctrl中显示*/' x1 C1 ~- ^( t0 C/ O9 h
VARIANT varRead = range.get_Value2();
# }5 Q# C4 ~' q+ J5 ^# O7 i COleSafeArray olesaRead(varRead);3 |) F `" e+ k( q" X" R* q
2 s' ~* d" a8 {
VARIANT varItem; K: C$ w8 b% D
CString strItem;
! F6 M: B7 M+ Y3 o# W6 l" M* K lFirstLBound = 0;6 c# M/ c. S. w2 r; V& \, s
lFirstUBound = 0;- b4 D) \/ ~7 b
lSecondLBound = 0;
2 ^! j! _0 ]# M2 C; e lSecondUBound = 0;
2 n6 b9 G$ u7 Z olesaRead.GetLBound(1, &lFirstLBound);' P9 l3 {% D; t, j, ]& m& C* W
olesaRead.GetUBound(1, &lFirstUBound);0 j( M/ |1 E$ l' q
olesaRead.GetLBound(2, &lSecondLBound);
7 R, }# U' O! U. _- g olesaRead.GetUBound(2, &lSecondUBound);, p/ D& z* C2 N2 w+ n
memset(index, 0, 2 * sizeof(long));. o( O. R4 r% W7 _; Y
m_ListCtrl.InsertColumn(0, _T(""), 0, 100);
- A) }6 b! Y3 x! k" V& C for (long j = lSecondLBound; j<= lSecondUBound; j++)
: S# T) e& c: W/ G7 u* C. @ {
& x8 @1 J" _' w, n2 g CString strColName = _T("");) [ D: S- D! a! z2 N# ^
strColName.Format(_T("%d"), j);+ f3 q3 Y5 A/ T9 m
m_ListCtrl.InsertColumn(j, strColName, 0, 100);' p/ `5 j1 q5 _& ^
}
8 z% i4 B: r5 w% q1 d for (long i = lFirstLBound; i <= lFirstUBound; i++)
5 g% j$ a$ U3 R5 z3 F' W {
. \8 w; |- r: f- B0 b/ v) m9 _ CString strRowName = _T("");
2 O" s' L9 z; E. \, Q strRowName.Format(_T("%d"), i);# [8 d6 z7 l4 f) x+ w2 s
m_ListCtrl.InsertItem(i-1, strRowName);
- _9 o5 r) I2 W3 w m5 o
! [# [2 v1 a7 t; f$ b9 p; c index[0] = i;
; ~0 Q" I4 {* l$ o# M; X( v for (long j = lSecondLBound; j <= lSecondUBound; j++)
% {# m' u7 x$ f2 \* n- w) z {( F. G# L# ]4 Y% ~8 e% |7 y6 w2 x
index[1] = j;
9 o- l2 G, H& ?9 M3 ~ X olesaRead.GetElement(index, &varItem);$ `: y/ G' v5 \+ [; k2 w7 _
9 M# U/ f$ m6 h6 O2 f4 T+ e( Y switch (varItem.vt)
9 y8 R2 S; i$ e' e. | {
$ B9 H. g+ k( @ case VT_R8:- c1 a& ^8 ]; h% ~
{( O$ d% H! }& y9 m
strItem.Format(_T("%d"), (int)varItem.dblVal);6 e& u) K5 ]( |/ p
}
3 `% G f0 k6 L* ^/ A& m/ a" a( W1 z" u/ z1 I0 i+ P; b
case VT_BSTR:* l9 R8 m; _+ I/ d
{
8 \$ q# P7 M7 n# G4 n2 Z- ]& o$ I strItem = varItem.bstrVal;
: j; z! _0 p( w. h/ k5 p }
; ?, [2 R5 `- t' b# X
* K7 n& N0 F- W& s case VT_I4:
& t0 m- U: X# ] {! s4 P4 h e7 i& f% ^* W* X
strItem.Format(_T("%ld"), (int)varItem.lVal);
$ f1 {6 @ ^: ^+ ~ }
M8 }3 U1 [! @
( c x: i& [1 \+ W$ H& L( m default:- H8 W6 N! H. X' {
{
4 Z2 I& v- F$ p$ [& s( f% M' R) D$ a( @1 I' F, I
}. o' J' Q- V; N% c
}# J: r- Y- Q' y, l/ \
2 V# L) W, g; C8 x5 n m_ListCtrl.SetItemText(i-1, j, strItem);- D. b9 z( ^6 }3 a( y8 A% }$ ~3 n& _
}6 S# y0 y' J# G+ `- n9 O
}" S/ P9 a4 O6 n+ F5 X
& Y0 ?! C5 O/ n6 m) b5 \" w
g9 Y- q: B! z7 w
* {* [6 @# d$ m, X /*释放资源*/
( l: Q7 R% |# v+ X0 M sheet.ReleaseDispatch();# P" }% [* T% @1 \
sheets.ReleaseDispatch();
! U9 Q) I/ v7 p, h book.ReleaseDispatch();' C1 z$ ?( S; ?2 L- ~( K" x
books.ReleaseDispatch();
# s: W0 S2 s! f6 \% o& Q& @8 Z1 _1 V# U2 L ExcelApp.Quit();
) K! q* H$ O s1 P! e2 h# Z0 n2 R ExcelApp.ReleaseDispatch();; Y) u4 m) m$ N
9 J, v7 {+ ?2 V" [! k |
|