|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
通过VC实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文主要研究通过OLE/COM实现对Excel表格的操作。
) O! b) Z1 m1 c+ ]& j; t% a
8 ~2 K# v7 h$ D9 p, j本文源码的应用环境说明:) T' C9 o, W+ y; W
Windows XP SP3) g0 E! U S5 G# N7 q4 a
Microsoft Visual Studio 2010' A5 A( c1 {" u6 N+ c
Microsoft Office Excel 2007: L: i; H4 l$ b) d0 k5 c
1 d) g- U1 x |! s" o k1、添加OLE/COM支持。' w1 i. F' v3 m8 z/ X) z
首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。
* z' R. W, _7 V本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。
0 w, L, D, N& o4 r0 C通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。 M, H' q" K8 b" r+ e* j
#include <afxdisp.h> // MFC 自动化类
7 D$ c9 ~$ v& M5 y" V同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:
3 t0 T9 m; E+ n9 ?# T! U6 U* |// 初始化 OLE 库" U2 z. J2 _' a- {/ t7 S
if (!AfxOleInit())# l4 Y6 x6 `- }
{
: w/ A3 b |( t3 ? @AfxMessageBox(IDP_OLE_INIT_FAILED);6 ~1 X9 L( c% f1 d) {$ w8 l
return FALSE;/ s9 y4 j1 `- a0 L. U4 I1 d
}6 g0 @7 U3 T" V( U( b" v
9 B# [1 n6 n6 W5 D; P2、导入并封装Excel中的接口6 `7 k, d# r$ T G) O% l5 i0 Y- q
Excel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。% q2 {5 {/ N% h5 x2 f/ Y& [
由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。
, W& O% `2 a2 X* f" K' AVS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择
- f. {0 f, C# Z6 Q* V/ M要导入的Excel类型库中的接口。
I" E) k& D+ V Z! Q. _8 z6 f在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。
; ]! Q' @ w) l( }% }( D
5 m+ x1 Y7 g) u5 N本文所导入的接口对应的类和头文件的说明如下所示:' W) @7 e# C2 h7 ~- ?+ X( G
3 j3 k* I/ E& q3 U% a/ T5 s7 o, IExcel接口
9 t4 c4 @( P& Y$ L2 E: M# ?+ |导入类
' }9 D& r9 x, P# ~2 D头文件1 O7 p+ M, M3 e: E7 w( C9 ?
说明7 b6 m# N# E/ P9 o! q
_Application
' o v# z2 s. iCApplicaton0 E8 [7 w% a4 l9 ?" n# D
Application.h
9 d/ k$ t" _& w" G. V, A& hExcel应用程序。
$ ?9 W5 X. s0 H; K0 EWorkbooks
- |# W2 M9 V0 UCWorkbooks
8 r$ f8 _' l$ p9 TWorkbooks.h+ O ~' p! f4 @6 Q& f
工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。
3 ` p# }$ M. b8 x5 h_Workbook5 w. C; e) }" d: }& v3 C
CWorkbook
7 E, M) z" o1 h( }) ?6 vWorkbook.h
2 J2 S$ L; A6 d @; a+ ^8 \单个工作簿。
6 c3 b8 y8 j. wWorksheets
: Q% c/ x7 I$ J/ nCWorksheets
- t W4 Z$ W* BWorksheets.h2 {/ H7 }. M" Q$ B) T
单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。* \0 C: k1 s# ` J0 E+ X- R5 T
_Worksheet
+ J" t! ` m. J- tCWorksheet
" ]1 Y4 b/ j; a0 ]. F& N% ]Worksheet.h
% E7 t5 S$ |- m) w单个Sheet表格。
9 i# e% e$ L6 y+ g( ]Range. [* b% u9 X' g/ R% g1 T4 A6 x
CRange
5 {1 R& _' R$ I; L eRange.h
; Q1 z% }6 i/ {' `9 I- Z+ s一定数量的单元格,可对单元格进行单个或多个单元格进行操作。; m5 m0 G+ Q, y* _: I) C% i$ I
# b0 E$ r: Q9 D1 Z
3、导入Excel的整个类型库: H% W3 @; j( O5 G, z
接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。( y' Y' K3 E( ^/ q K, ~
通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:3 m$ w( ?! N& y4 s: M$ |
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace. e" |0 V$ j/ F" T* n
这行代码的作用是导入Excel整个类型库到工程中。% e; Y$ [ t3 L! b" W
由VS2010自动产生的导入代码存在以下几个问题:9 w4 _* d7 u) _
(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。
- c1 d- j8 [( Q: e1 ^' ~: h9 L) w2 Q(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。
$ |4 U! N7 O2 o2 ?9 d" W5 X(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。+ I2 V- u) K% L1 C) K% v, c8 j
以上三点问题的解决方法如下:) k: E5 g) b. D4 Q4 Y0 [7 e9 x
(1)仅在_Application接口对应头文件中导入Excel类型库。* v/ Y/ a# l" Q) x& ?4 j
(2)对冲突的类型进行重命名。4 W) v p- z9 a7 _% C) S/ J
(3)在导入Excel类型库之前,先导入Office和VB的相关库。3 z$ O+ K: t. x9 |8 H. b7 t& z
更改后的导入类型库的代码如下:
5 y/ \+ u( G+ `8 i+ g" F3 n & q: T( e1 G: t& u
/*导入Office的类型库*/
7 N3 _ e. m; Y* ?#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \
. z K8 d- ? i- ]rename("RGB", "MSORGB") \
$ A D/ M5 u+ U! f+ d1 o* f: Hrename("DocumentProperties", "MSODocumentProperties")
* C6 L1 [/ x. [4 z4 Tusing namespace Office;
# |+ z6 p- o3 I$ N # _) B; B _2 Q6 S
/*导入VB的类型库*/
5 l; d) m8 Y- K5 \8 [#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
: \, C0 }7 N5 G5 b) E2 Susing namespace VBIDE;" J, N \; f/ {) ?& g+ w/ U- W
/ v7 B H2 T5 Q* B6 |
/*导入Excel的类型库*/
3 h8 ]3 t# C( U5 H" @- m% X( ]#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \
! N$ k, S! c* _) O( V5 y0 H! erename("DialogBox", "ExcelDialogBox") \- y9 f" e+ a! ~6 K4 V0 Z
rename("RGB", "ExcelRGB") \) ]' i. p' M: u F" v d6 \
rename("CopyFile", "ExcelCopyFile") \
0 n! a& C+ \) W3 f. nrename("ReplaceText", "ExcelReplaceText") \
2 n5 f" D! G, c) O Qno_auto_exclude
$ x! |1 d6 m* _2 i" H/ D7 UUsing namespace Excel;, B) E7 p8 {; u3 G" n7 S# R, {' ]8 I
1 o. q: @2 H$ r) H" P! @# F. [编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。
9 h( M* }2 m1 S2 @$ t6 U % b) A8 N& U3 p+ U& @
4、操作Excel步骤
# [. i9 ?" {! Q! d9 ~4 y& g操作Excel的主要步骤如下:) m0 x; y7 e# r, \5 h- |. b
(1)创建一个Excel应用程序。
* w- {' w# H+ s/ y, X" Z" _(2)得到Workbook的容器。, d7 ^, N( P- A) T9 w' r
(3)打开一个Workbook或者创建一个Workbook。- Z7 U/ c2 v5 Z: G
(4)得到Workbook中的Worksheet的容器。
+ ?: u/ D8 \ `' }$ o* q3 k3 D(5)打开一个Worksheet或者创建一个WorkSheet。
+ W. N+ i) U9 a(6)通过Range对WorkSheet中的单元格进行读写操作。: m/ z* D5 ]2 e, P8 M. z
(7)保存Excel。
/ b$ K! i+ U& [' P9 u# k, l8 K9 a4 e(8)释放资源。- |7 V2 y+ {1 r
! A9 ?, O) D/ P9 P# ^- J
5、批量处理Excel表格
f! b1 |5 o8 k9 pVC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。4 h) C$ B# i4 f# O; c& c! C+ x
对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。
1 X. I; w4 s; w4 h; L: f7 ]VARIANT get_Value2();
0 w9 _) h& `4 |- J/ ]# ivoid put_Value2(VARIANT& newValue); G1 ^* v: R! `* o
其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。+ _8 o+ {% w( ?5 f
其中,VARIANT中实现二维数据的方法可参考, D1 L* l2 _9 p
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html6 U* t* _( ?$ I/ `
当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。 n% K( Z6 U0 G) Y8 x
; P4 m# E# R7 _, l2 h' e/ K6、Excel表格的保存. g- [+ S2 `2 S+ P
(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。0 d( G/ a" C' k8 C# B/ D% E
(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。
0 ` O7 ?8 |6 ?. U1 Q) T6 k1 ESaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。
- I5 p' b' X' r1 p& ^# O % G. I7 R/ @8 w& _% Y
7、获取当前Excel的版本" U' @) Z ~( _9 [: a- }* u
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
k6 u2 ]7 n: t' W& z: j 4 ^- u: g3 G7 r" e: S
8、示例源代码$ q& y* u l& _
主要代码如下:7 @ {! V9 I0 \ Y% V, E7 D+ [
& G/ N$ z5 Q9 x) o8 i0 A
7 I, Q3 `' F" g7 X
9 Y" ^7 c" U( n c5 n
m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);, o$ s2 U3 q/ X7 q/ O/ `
! `; D; K. p* m" Z0 X/ Y+ m
CApplication ExcelApp;
. X" B' u3 H. }+ A' j! ~/ Y& j: J CWorkbooks books;# K2 E0 I/ O, f6 A2 ?; _ H3 ]- i) J1 Q( z1 \
CWorkbook book;0 L) S/ g2 p) w3 ^; C3 D
CWorksheets sheets;; K' Y$ U* R6 }! t/ h# ?
CWorksheet sheet;
% i) r% F! H$ g CRange range;
& q, e V0 ]; \- V1 V; S: V LPDISPATCH lpDisp = NULL;
2 \- d3 j$ v5 v7 o T2 `7 l2 {) l0 t! o5 O4 a) k
//创建Excel 服务器(启动Excel)
' [' H* j5 W# t b/ a& j if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))8 v8 L2 N+ E, {- p
{
; s) r( {" V9 d2 W* |9 q AfxMessageBox(_T("启动Excel服务器失败!"));
4 L+ E A0 `* ~8 u" {: x return -1;! R) i1 o/ V9 d U3 M1 v/ ?( |
}
+ m) r8 _& h$ N& I" f' N- S/ t! o; c" t# e t
/*判断当前Excel的版本*/7 k7 _% {) {7 L9 @
CString strExcelVersion = ExcelApp.get_Version();$ F- y! Z2 A9 M- Y/ \& t
int iStart = 0;" t) M) l# }- r5 w( W; z7 |& ^
strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);& m6 Q9 e. B0 B3 t; L, ^3 |: v5 b Q/ w
if (_T("11") == strExcelVersion)
4 g/ a' G5 S' j {
+ `& S" V5 Z; l2 _ AfxMessageBox(_T("当前Excel的版本是2003。"));8 A3 P+ E1 _/ n: p$ @
}# b9 ^" P( S0 M! M& h' G9 d
else if (_T("12") == strExcelVersion): e G; A1 `+ ^9 V$ A7 N
{
& K1 I' y2 x) Z) ?' n( o AfxMessageBox(_T("当前Excel的版本是2007。"));5 X( O0 k; ?( S) \" k6 k
}
. @) U( ?: v+ m# e) }5 z else
# _2 R1 G# \# e5 V) s7 n {0 ]2 u( Z! Q9 \" D3 z) o. c! \- `+ ?- O0 e
AfxMessageBox(_T("当前Excel的版本是其他版本。"));
) ~6 K0 u- }2 q) n }
& \5 ^. A9 h' y I) G4 v) i( H7 T8 r, N( [, R6 h
ExcelApp.put_Visible(TRUE);
5 c1 X! ^: m5 A% @* D2 U6 L ExcelApp.put_UserControl(FALSE);
" `: @) Z7 `' l5 b& U7 T" J& m4 R. T
/*得到工作簿容器*/6 `, {0 ?. x2 A; F* Y: M7 r9 ~# b
books.AttachDispatch(ExcelApp.get_Workbooks());
8 f. J a$ @% @: a8 z7 \( z
( z! R# }' d5 j( S* G8 u! V) s /*打开一个工作簿,如不存在,则新增一个工作簿*/; Q* `+ ^) d: a0 b8 I) Z+ I
CString strBookPath = _T("C:\\tmp.xls");$ K( G2 }# u6 D4 \% d
try
- K% \! W5 X: S. }/ n! H {8 l/ ]( k$ P$ _ f+ N; F. T
/*打开一个工作簿*/# U6 V2 G g, R" ~/ z/ {5 r
lpDisp = books.Open(strBookPath,
' Z; G9 O8 ~# Q( ] n: @/ R vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,2 B! D; H1 X" J1 m! S
vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, : A) y+ k1 k5 O; s/ O+ F0 I; S
vtMissing, vtMissing, vtMissing, vtMissing);
; s* A* l9 ?3 a/ [4 t/ P book.AttachDispatch(lpDisp);, w3 P8 Y& C) R/ D' {3 E0 S. m+ V
}/ i1 B% D! |% @7 A8 W( q
catch(...)
; w+ m9 i4 T0 p; y% ~ {1 I( y# ]0 x$ H* ` J5 m
/*增加一个新的工作簿*/
* t, d1 Z% |/ X' K; v5 a9 ^ lpDisp = books.Add(vtMissing);% Z m: I C9 B! ]
book.AttachDispatch(lpDisp);" Q7 K# Z H: M/ M
}
5 G( M/ q" D7 p1 B( \6 ?1 U; b 4 J/ j% [5 ]# A+ ~4 ]4 ]4 V
4 }' }6 _5 d/ q4 v7 K# y+ ]% h$ R /*得到工作簿中的Sheet的容器*/4 i4 i' G& K1 x% I
sheets.AttachDispatch(book.get_Sheets());
0 ]7 L z# y8 g4 H! M
+ p [2 N X+ k/ l/ j. i /*打开一个Sheet,如不存在,就新增一个Sheet*/
# b, I, m1 F; j& ? @ CString strSheetName = _T("NewSheet");
4 k- ^* ]) V1 m+ x. A try0 Z5 }, R9 Z6 ?) }& T2 {) {: h$ P
{
8 e, X% L) o* U2 k& y. [# r /*打开一个已有的Sheet*/2 R) C2 o2 _7 H$ I
lpDisp = sheets.get_Item(_variant_t(strSheetName));
$ p6 s n5 e' v) _/ L sheet.AttachDispatch(lpDisp);
! {) K7 U/ O5 m$ W) L) E3 M* e% M }
* ]; R- K" f1 n' B/ Y/ S3 k catch(...)
; b9 A8 j% i' t' H5 n {5 ^ |: g, T0 p, t) O
/*创建一个新的Sheet*/
' n0 j- A1 I- P1 w+ x7 E lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);! y. l. ?8 H0 ~" e8 R
sheet.AttachDispatch(lpDisp);
' y5 k6 w( l; e' M# ]& ^* e* X/ c sheet.put_Name(strSheetName);
& H/ p# d K1 b, D }4 r L% ^, B4 }9 g5 x; `! e9 ^
* T- Q ?& Y0 ]7 V/ W
system("pause");. f' a+ e* R$ {2 C7 `( z! P7 D- b
+ k( R2 `: s; i( ]/ r /*向Sheet中写入多个单元格,规模为10*10 */
+ \4 I) t! [! ?' o9 S& q, J3 p lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));
4 O! |7 [- U2 w* l7 Z% Z/ ]! b range.AttachDispatch(lpDisp);
8 k! I& ^/ i" p; B# S6 `, y
) `1 f% X3 K, w% P5 W VARTYPE vt = VT_I4; /*数组元素的类型,long*/
9 m( g& ?' b5 W* J# U0 U1 t SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/9 V$ Z0 r. G* q# q+ I
sabWrite[0].cElements = 10;4 N* |* C f! g4 S+ t! `
sabWrite[0].lLbound = 0;; F1 H6 D4 r5 ]+ N
sabWrite[1].cElements = 10;# T. b: m6 p6 Z' G1 o% H
sabWrite[1].lLbound = 0;
- o4 R# f8 h3 N& I) K4 R P
: A$ S( E5 q: K2 v9 ]7 U COleSafeArray olesaWrite;
5 O: O. H& N: R* b1 @ olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);
. S! @# ~1 J- i8 X- `6 i3 _* L G# h U1 M% y
/*通过指向数组的指针来对二维数组的元素进行间接赋值*/! R2 g" `' P! X
long (*pArray)[2] = NULL;
; l1 z% L& m @4 x7 | olesaWrite.AccessData((void **)&pArray);; v" @" ^: R" u9 k7 B
memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));9 @0 B* {% O( Q4 B3 @
; S7 a( Y( H. n! b. g% M" d
/*释放指向数组的指针*/
3 B- d( M% G/ I0 y" J olesaWrite.UnaccessData();
: f. C8 ?2 `- F2 w) L pArray = NULL;
, U* G* c B; [4 j9 I) Q! w" W- k, A8 N; Z9 E3 f9 G+ R! S" Z
/*对二维数组的元素进行逐个赋值*/
$ |/ J9 D" f- W+ D long index[2] = {0, 0};* Y m3 r; k! _% E1 i+ `6 t0 \
long lFirstLBound = 0;$ u' _/ }" i6 n8 |5 @* K
long lFirstUBound = 0;: U2 T: l Q: E! y
long lSecondLBound = 0;
* [$ I( M) x( Z0 N* B# D) M long lSecondUBound = 0;
# k. X; V& {, ]$ d& j2 f0 K olesaWrite.GetLBound(1, &lFirstLBound);
+ y @1 v* w$ [9 F olesaWrite.GetUBound(1, &lFirstUBound);
! K! W) t2 @- k% _$ ^ olesaWrite.GetLBound(2, &lSecondLBound);
% R" I2 a% ]1 _' t olesaWrite.GetUBound(2, &lSecondUBound);& l2 ?5 m- t) z) B; \, W* f9 L% ^
for (long i = lFirstLBound; i <= lFirstUBound; i++)
6 P. I E( S+ v$ ~& z) ] {
( U9 V3 f( M9 b- K index[0] = i;
% P. g$ c+ x+ }/ T+ S for (long j = lSecondLBound; j <= lSecondUBound; j++)
8 D; Z# A4 O6 @) H: J" U, C$ O {: s4 a. b, w- {% m1 \
index[1] = j;
' ?4 A6 S; B: _4 _: k, o- Q$ U$ w long lElement = i * sabWrite[1].cElements + j;
" g6 H9 R) ?2 d* _ olesaWrite.PutElement(index, &lElement);" I. S, }) D4 p _! |. V
}( ~- J' k( J# q5 M: O; v( z6 K: q
}
; W- G) u7 y* T5 P- |+ v: A
7 u0 _! `( J7 V) e8 z /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/% s! D/ E7 |5 A, x/ o: c( y
VARIANT varWrite = (VARIANT)olesaWrite;
1 A: P' u I: S' g range.put_Value2(varWrite);
& x( J* ~4 [- a$ P' ]3 o) y) L t6 n) Z6 F
system("pause");& c- L- K3 E: @: M! b" C u
) K3 {0 }9 e$ _, K /*根据文件的后缀名选择保存文件的格式*/
+ \3 U4 L; A. W) } CString strSaveAsName = _T("C:\\new.xlsx"); q* h5 v7 b% i+ w
CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));% X7 O& A! |: f% x3 a2 D0 Z( \$ R
XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;
; i& P- F0 p4 p' a if (0 == strSuffix.CompareNoCase(_T(".xls")))
% r! ~9 ^, i9 n. x* s* g7 _7 E m {9 ~2 X) R; H6 {* x) x2 Q
NewFileFormat = xlExcel8;; Y: s/ B6 I0 v
}
' i C2 Z! {. V: M+ u9 I; V book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, ' f) \6 }( i' X+ G* Y: I- B
vtMissing, 0, vtMissing, vtMissing, vtMissing,
# O$ W! u6 R6 t$ z. ^ vtMissing, vtMissing);& ^* U, l- R' k5 J! F4 e$ ^! t4 b
1 j' \( s, |$ A- s system("pause");
5 k- U' F9 z: A* D: s% f
* n7 [% s& w# r /*读取Excel表中的多个单元格的值,在listctrl中显示*/
6 P% Q6 I! e/ p% l VARIANT varRead = range.get_Value2();
6 Z$ W! `& p* n! N! E COleSafeArray olesaRead(varRead);
5 t) k+ J' a7 X& W* g
: H! y. G% T3 {; S9 u. N* x VARIANT varItem;
# W! U6 Q1 k7 u& u CString strItem;- D* I! D0 _/ j# Q) t1 a+ Y
lFirstLBound = 0;
! X. @/ a4 ^6 p7 ]8 o3 G lFirstUBound = 0;
4 O# j/ [9 X; G5 m lSecondLBound = 0;
_7 F8 M) o; D. s3 i# E+ H- ? lSecondUBound = 0;, D# h' }; F2 V; R
olesaRead.GetLBound(1, &lFirstLBound);# C7 g# h/ J5 h6 t: g5 Z
olesaRead.GetUBound(1, &lFirstUBound);2 Q% {* s! X" D8 _
olesaRead.GetLBound(2, &lSecondLBound);
9 G3 G& `5 m# |1 |/ I' N% F, w. h7 k olesaRead.GetUBound(2, &lSecondUBound);
" j: h# O8 l. q' D$ J% \* X memset(index, 0, 2 * sizeof(long));9 h6 X6 f' L" l3 ^( ~+ r7 ?7 w
m_ListCtrl.InsertColumn(0, _T(""), 0, 100);
; a: o* I, x1 |- t6 } for (long j = lSecondLBound; j<= lSecondUBound; j++)
' F7 a3 H4 @0 g0 B/ J2 t {
, M- g: m1 S1 M t1 j CString strColName = _T("");. _5 f) c( i/ J) l: f9 H- ^, U
strColName.Format(_T("%d"), j);
% w1 @# _7 R. [! s9 i m_ListCtrl.InsertColumn(j, strColName, 0, 100);
) x8 a4 V3 t8 e, ?# b4 b# L" s3 e }
& S4 _6 Q# j5 T for (long i = lFirstLBound; i <= lFirstUBound; i++)! j0 z, H S7 m" A# |7 |
{% {8 Z4 g) J5 j% |. @- d
CString strRowName = _T("");
. C0 Z( V$ G K2 u3 S+ a$ Y strRowName.Format(_T("%d"), i); y+ p" H: ~/ x: } D# i
m_ListCtrl.InsertItem(i-1, strRowName);9 M9 u( ?4 M2 Y4 h4 G
' Q4 V9 {& m$ r2 e5 ]3 t index[0] = i;) R+ J* S* ~; s
for (long j = lSecondLBound; j <= lSecondUBound; j++)" j$ u1 i$ ], H( B# L
{
4 ?# W/ d$ c* Y3 o; s8 X r index[1] = j;
* Q( p" R9 |' S* p olesaRead.GetElement(index, &varItem);9 j3 O* d& ?6 \6 X
6 F' z* f3 k3 u: j$ B1 x! I- y switch (varItem.vt)
: Z3 U7 N1 F3 l0 {0 h {8 l1 ]( h! r6 L4 c% A& M: W5 [
case VT_R8:3 S; l' k& Y- X6 q( ~
{( A. Q' p7 [, y0 f5 r G3 s
strItem.Format(_T("%d"), (int)varItem.dblVal);3 ?/ T3 j' \" A: l! p! v2 I
}
2 g% z- j1 C' G: ?- U: \3 f) k& I. o# S5 \+ z3 \( z' Q
case VT_BSTR:2 _" m) j3 j) g
{! Q w4 T$ G( \ {/ p9 O0 e
strItem = varItem.bstrVal;+ V: r" ?# v$ E9 q8 |
}
( h, x: e! x6 Z, ]" [, ^9 z' H+ u) e' M% ]) J
case VT_I4:
2 X7 n: Y7 O/ `4 b- d ~1 ` {; p" N. P+ A9 {8 M5 q/ R
strItem.Format(_T("%ld"), (int)varItem.lVal);: N1 q2 z% \3 C7 C# e
}
( j9 g, [# r- x; R0 C0 w
: b* T$ U" ?7 w default:& s1 Q7 B1 ]: N8 I0 A" p4 R
{
! Z5 B! }6 [; G2 N
. v$ x: Q- P1 K/ e }
( l, }" x2 ]1 _0 y6 v; ]5 @$ v( X }
' G$ R" {: }9 B+ d @7 n
3 L; F' y# |/ ~; N3 M8 m m_ListCtrl.SetItemText(i-1, j, strItem);
) f$ G M I; Y7 Y }
& s& l X7 t& f, @0 m# C }
s# L9 Y7 ?; @2 d6 k
f. A& W& I2 N, A* F- b' O0 i% N( d- U" H9 |3 R* |8 A
7 l' s |* X6 a4 }% J v /*释放资源*/8 h/ t E2 O9 X" n% l% u: {
sheet.ReleaseDispatch();
6 r; h/ p- C- ?2 J3 v1 y( j sheets.ReleaseDispatch();* M8 y; G3 }! S
book.ReleaseDispatch();& o* f* N: s [1 }4 o" A* e+ t" e
books.ReleaseDispatch();6 K( v4 x$ {/ A' J3 k5 y0 l7 C
ExcelApp.Quit();+ f" L1 s( D4 ]5 h* T
ExcelApp.ReleaseDispatch();7 L- \9 j! O7 V/ y
5 w/ {3 G" i3 ~( X5 {2 B7 u
|
|