|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
通过VC实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文主要研究通过OLE/COM实现对Excel表格的操作。
: M* H3 h+ j/ r" x+ k - [/ d M- k" l$ f# i$ j4 f
本文源码的应用环境说明:
! a% }* m' \4 [/ g& |8 x% EWindows XP SP39 U) w7 {, ]0 j
Microsoft Visual Studio 2010
\& \( ?! k% lMicrosoft Office Excel 2007
! F, @) g4 L2 G, J0 G- z) u5 V
: a1 b+ S( ?% h3 s9 K6 Q: b1、添加OLE/COM支持。8 U! l8 \, n! m; Y4 _. h9 b/ D
首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。
8 z2 p6 S$ g/ I# P本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。
4 ^' |. S- F. t: U! z0 V通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。1 J: u8 v0 w* O" z; s) U. ^
#include <afxdisp.h> // MFC 自动化类6 L2 p) m& f* r6 c; g1 S, p
同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:4 S1 p1 q' o5 ]$ }: c. ~! R& i
// 初始化 OLE 库
- _/ E' Q( P' L5 cif (!AfxOleInit())- L# s( D0 u+ ]( k6 y. C( ?- W6 `. x
{
5 I1 T9 ]* A3 k( O: \3 \AfxMessageBox(IDP_OLE_INIT_FAILED);9 j( x% Y7 n' |4 B" N. ?
return FALSE;
8 C4 Y, J+ p8 _2 ~' W3 L}4 s9 _& H- X, A4 J' {. }
4 Z) _* V# _9 v1 W& z2、导入并封装Excel中的接口1 s1 c3 }; a2 h+ A
Excel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。1 s- p+ F1 U" k# f- V5 w
由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。+ i9 A6 _9 e* P+ a) k
VS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择
1 z. t% p# C, N! l' R- G2 {要导入的Excel类型库中的接口。
0 I$ p0 @$ A' F7 a/ |/ K' U在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。& U' O: ?; x& X; L4 @* o
, D2 U3 {7 v5 e- L
本文所导入的接口对应的类和头文件的说明如下所示:
i& E* m# U' ^3 V+ F
9 l2 P, `+ k5 ^& b' eExcel接口, `8 w$ ^4 V8 d* {
导入类
, E7 g0 h9 Z5 c头文件* E! [" F) M& X: M
说明
; E- J7 m4 e. E3 R, R, ]$ __Application
9 b H! z' B% {' Y, mCApplicaton. e% x. Y8 B; r
Application.h
% Y( u. `7 s: {* y8 d/ X& }3 vExcel应用程序。, r( q( N7 ]8 j5 F4 }+ v6 P
Workbooks0 @; }& o# Q9 d. h% H
CWorkbooks; n8 I# |4 i1 Q
Workbooks.h
5 C9 h x0 X9 r% U工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。; q- y! Q1 A; t
_Workbook8 l% E& h% _: t7 n$ W
CWorkbook3 P3 E4 L# w% z! ?+ p: h( s0 m. P) o
Workbook.h' W. a6 G+ T# t- O: c) W* t
单个工作簿。# W5 D9 \% N' n9 ~7 @8 c
Worksheets0 _0 [/ R! z9 ?3 Y" S" t
CWorksheets% ]/ E) \' ~; y
Worksheets.h
5 `7 x8 w* L( e9 E单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。
# `7 Z2 ^3 M! g2 p# Z' N3 ?; X_Worksheet
% F9 l+ b, {! S/ k+ Z$ ^! I. o, GCWorksheet
3 m, n4 z+ o8 r' \Worksheet.h
; e; |; G6 z2 O- o$ `$ V单个Sheet表格。- ]8 j* s: P& [
Range
: y4 t' b3 k" ^+ h, n. DCRange
; W, [4 `, e) D6 |; `1 lRange.h
" p4 t V6 Y) n* B ?+ K- X一定数量的单元格,可对单元格进行单个或多个单元格进行操作。
9 ^8 O0 m! j" ]; U, ] 4 C2 F3 o* @( ]3 w4 H7 f" s" |7 E
3、导入Excel的整个类型库, w4 D4 L- ?4 f5 A0 ?! U" Z) {0 |( i
接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
V# u$ C s) c/ c! e4 I4 u5 j通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:* l' W/ p5 K: `
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
) x H+ W) O( F$ T这行代码的作用是导入Excel整个类型库到工程中。
; z2 X5 E0 P1 f由VS2010自动产生的导入代码存在以下几个问题:, J! ]' |/ F6 w5 C
(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。
, [4 Q6 \" R5 A0 a, U3 P4 ^+ Q& H(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。
- U+ Q$ I9 P0 D0 M* K Q(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。. Q7 y4 K, [& U; _, O3 E
以上三点问题的解决方法如下:
) j( Y) E; H/ p; Y: w0 n(1)仅在_Application接口对应头文件中导入Excel类型库。8 z/ y M- C! K) U. S6 K, l
(2)对冲突的类型进行重命名。$ |& h8 O% s. b: s; v& y9 t
(3)在导入Excel类型库之前,先导入Office和VB的相关库。, I4 R5 o- g7 y: I$ P8 T
更改后的导入类型库的代码如下:
+ h9 a- _3 w! k7 z - |+ k' m9 r1 N
/*导入Office的类型库*/: o( T6 f7 r+ P C* G, X7 H1 \
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \4 v: |& _ D; ~- r
rename("RGB", "MSORGB") \$ }/ u5 G5 Z# e) w! D# @
rename("DocumentProperties", "MSODocumentProperties")3 S0 M0 ]: r+ B7 ~ g* [
using namespace Office;
" D3 G m$ H. e' Y 0 w O+ B7 h6 D6 p$ f$ k
/*导入VB的类型库*/$ j1 U+ x$ p' P
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"* I& ~! h$ L- f1 F* M) a9 c
using namespace VBIDE;9 Q3 X( h1 _/ f5 V
3 K! y1 j" ]; o5 X. ]+ q) Z2 v/*导入Excel的类型库*/
' u4 r( Z! ]. q, f+ C# J1 v+ t9 y#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \3 V, K O7 Q' d8 k2 x% Z1 f
rename("DialogBox", "ExcelDialogBox") \
& h: ]' r+ w4 A7 K. Prename("RGB", "ExcelRGB") \; @" J" b$ K) B! V" {9 E1 o
rename("CopyFile", "ExcelCopyFile") \
$ i7 e5 G9 g: Z4 b0 J/ w. A0 xrename("ReplaceText", "ExcelReplaceText") \
3 `; P/ p4 I4 f5 E5 wno_auto_exclude# ^: B: u+ u9 m2 Y4 b
Using namespace Excel;$ V, ?; \; m4 {/ E5 K
$ Z* L% n5 Q/ @" ^4 f编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。
$ k" l+ g4 u0 |; V! y6 } $ ]- L1 x( O* ]6 r$ ?; p: ]3 N
4、操作Excel步骤5 P# s) k# K2 G% C v8 e' D
操作Excel的主要步骤如下:
- p, h/ J+ C7 j9 k1 s1 g(1)创建一个Excel应用程序。9 t# J2 S: X1 N2 d- ~+ r, l5 ]& L( U% |
(2)得到Workbook的容器。
" V s/ x( M+ ~: I(3)打开一个Workbook或者创建一个Workbook。# V+ o; J S/ c% L! Q
(4)得到Workbook中的Worksheet的容器。
$ d* }2 b2 U# i& u6 n' ]& a- ~(5)打开一个Worksheet或者创建一个WorkSheet。& B6 p9 B, p6 ~0 l2 ]2 D* h
(6)通过Range对WorkSheet中的单元格进行读写操作。
, _/ a: B7 `6 {+ l' V(7)保存Excel。; Z$ X8 u3 d5 F8 Y0 T1 D+ x6 C
(8)释放资源。" w0 X8 H/ t" p7 Z( ^' q
4 M+ s! S2 `6 B9 B6 @+ E& H
5、批量处理Excel表格0 e5 [* g& U% e3 R' Z
VC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。$ _. U; m. D5 a6 Q0 `
对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。
" V/ L' g& F$ x- c0 fVARIANT get_Value2();2 V5 W: j$ W) C8 R# X
void put_Value2(VARIANT& newValue);
+ V- Q6 y* r6 P$ t" W其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。, X- @- z+ V" J/ P9 \ G
其中,VARIANT中实现二维数据的方法可参考
3 `% A* |) R+ y8 Uhttp://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html# N% K# Q1 z! B! Z( W
当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。* |2 J( }- X/ E
$ x" m6 M3 j. D+ p; A8 Y6、Excel表格的保存# s* s) d7 w2 U( G. ]$ e, w; Y+ C
(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。+ u) G2 D: A+ a4 L, z2 [
(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。+ r" d" {6 E( g9 J& q
SaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。: Q" M: f* N2 a5 c, f7 z6 k# v8 B! d
9 a; z0 r5 {, a$ k* W7、获取当前Excel的版本
7 L0 ?: c8 M" Z) Q* O" k5 s1 r& o+ o可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
" F/ h( @ m8 X$ H 6 I: N5 k3 C& y# I
8、示例源代码2 `2 [% Y7 T) f& \7 ?
主要代码如下:
/ r5 ?+ m9 s0 c! f5 y7 B2 Q $ u3 A9 ~& Q2 d
+ ?1 A" k( h5 O( t" [% X% ^ f; l) J0 e; N$ g
m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);
8 V8 ?4 a5 ^% b0 m% T5 U4 p1 p) i8 q$ G3 Y8 P( d# R: I
CApplication ExcelApp;
% l3 E1 C5 a) S6 x+ t& b* Z CWorkbooks books;3 w8 R. L1 d3 V2 Y: j: I9 i& p
CWorkbook book;2 b C, X+ Z' ]6 Q$ ]9 y: E
CWorksheets sheets;5 O$ i) r; `1 w# }/ |
CWorksheet sheet;
: a0 A$ R3 j) S CRange range;
5 _% j) u) ?7 `) K' I. x( l+ N LPDISPATCH lpDisp = NULL;$ m* U- X# r+ O9 h3 b
$ J$ `2 t$ w, ~! M4 g //创建Excel 服务器(启动Excel)/ o) r2 i; F; ?! h
if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))& g! v L8 g" \. p9 |- @4 e
{( u( H3 c8 I/ f z
AfxMessageBox(_T("启动Excel服务器失败!"));* J1 R: m$ v- O, F+ c9 `% ~/ F# P* h
return -1;6 n5 G: |% n2 W, X0 E: Z. x
}. ?+ ^6 H3 L# K) u/ k/ S" ?$ P' j
0 ]+ ~* d, j' A7 R; J8 x /*判断当前Excel的版本*/
- f4 @/ f+ s. u- g, u; C CString strExcelVersion = ExcelApp.get_Version();, S: u5 z7 \* Y2 S; \
int iStart = 0;7 |. g" {0 N- K( T
strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);- }5 }" M4 y5 x* w8 V; z4 Z6 D
if (_T("11") == strExcelVersion)% G& e' w( p- {8 R( D% L$ B
{
1 R! m! d) ^ F/ y! F5 A u& S- h8 u AfxMessageBox(_T("当前Excel的版本是2003。"));4 ^* _. f6 [* O' x* D" U, h8 F5 c- m
}
) A, n6 Q- L2 ]3 {2 T8 | else if (_T("12") == strExcelVersion)" M5 c Z* d0 k/ M1 C; M+ Z; o
{1 e# t' N" l, C0 W. n0 @
AfxMessageBox(_T("当前Excel的版本是2007。"));
1 \* G5 L4 O4 y+ |% P5 g }
- ?3 b- G e- i3 o else6 \% Y9 M& @; Q! z) o! D2 ?- H9 r
{
7 @$ B1 h% |$ i, T. \5 X: d8 D AfxMessageBox(_T("当前Excel的版本是其他版本。"));2 D8 s. I& x+ o L; w
}
1 j }$ t8 h/ c0 W& h7 s8 D9 W( p( I- W/ N! e5 G
ExcelApp.put_Visible(TRUE);; ] f& u. \# Y
ExcelApp.put_UserControl(FALSE);2 \3 }0 X1 u$ C
1 v! |) T- V; G+ Q5 A- u! r /*得到工作簿容器*/
; m G! a1 S6 Y" w0 a9 X' B, S books.AttachDispatch(ExcelApp.get_Workbooks());
+ l' ^# s* A$ W3 Z# n( r5 L( i! M
% C; F! P( P4 j9 o: j- Z$ Q1 L /*打开一个工作簿,如不存在,则新增一个工作簿*/ g+ |7 P, ^2 ? O" A/ ^( Y- n
CString strBookPath = _T("C:\\tmp.xls");. o+ e. @6 P7 @
try/ d- a) s) ?' A# W# }4 {0 _7 S
{
8 X% L! P, r9 D2 N' | d4 ~ /*打开一个工作簿*/2 r8 E' g5 A3 ], X0 q: n. b% X
lpDisp = books.Open(strBookPath,
/ x- j7 k) _: U4 d9 l vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
4 H. _2 @1 L3 d2 @- V vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, % ~: a; s' A; s/ s0 m. p
vtMissing, vtMissing, vtMissing, vtMissing);- g/ C0 {! P; s# z! O2 f
book.AttachDispatch(lpDisp);
$ D' r+ W6 y0 H" D3 u0 i }
, |6 J! I2 ~. K4 W$ `- p catch(...)
, E" S/ M" [: T& | {
- Z q& ~/ B) d# f /*增加一个新的工作簿*/* Y6 m0 I$ b5 E; K* U
lpDisp = books.Add(vtMissing);
) x- l6 T+ S3 x# P( R% h book.AttachDispatch(lpDisp); P$ L( ~! P; B1 b4 a
}
' t S2 f& T0 Z! h; i / _* }- y( Y9 K+ \# q4 ]
' d/ i* }$ {) p) ]: } I/ M! J; ~
/*得到工作簿中的Sheet的容器*/
$ M& |7 I- Q% Q( m sheets.AttachDispatch(book.get_Sheets());
# H' j# C" x- H5 F5 k# S) F
& d$ p8 D. N% I( g$ N$ Y, H /*打开一个Sheet,如不存在,就新增一个Sheet*/, n W7 r. c# P( j
CString strSheetName = _T("NewSheet");
" D2 z3 R( W$ R" t5 }' X; ^7 b" Q9 r try
* m! G% n6 l* r7 l# p7 ~1 v/ Y {
* n4 z. I3 \9 } /*打开一个已有的Sheet*/
( Z3 U. F8 z; S1 u lpDisp = sheets.get_Item(_variant_t(strSheetName));
$ S: ?) V, `6 h- \# ] sheet.AttachDispatch(lpDisp);; _0 ?* o$ O1 T2 O! ]& y- Q, Z; U* U
}
. ~% P, `0 T6 z5 t( \, g catch(...)
2 H' f- \' m7 r: L {
: t. r! j# j4 N /*创建一个新的Sheet*/
% G2 A1 z8 C) \9 K- u" z lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);- U5 f3 d$ X8 A0 L4 i+ m! B
sheet.AttachDispatch(lpDisp);
6 y5 W; m6 U6 Y3 _2 O8 m% x! S sheet.put_Name(strSheetName);6 }4 t- |8 }4 f3 S& q8 {8 D' c4 n6 p
}
: l8 X, Z U( Z& B$ L1 D+ g& s4 F! e% h
system("pause");
% @$ s# r. y5 J( V7 k
- B+ }2 a! m( j; N; W9 | /*向Sheet中写入多个单元格,规模为10*10 */$ K: k! t1 _8 I2 O$ B, m7 M
lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));
/ w& x( J& P6 ^8 o8 V range.AttachDispatch(lpDisp);
4 v) K; z/ U: j- Z) }: w2 c% d: Y" \6 O6 u$ p7 g; P
VARTYPE vt = VT_I4; /*数组元素的类型,long*/
T# i/ `, o4 [+ z3 c; l SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/
& x; @ d0 k+ ~1 F- l. c) i sabWrite[0].cElements = 10;& t: N8 f# C: T$ _0 w
sabWrite[0].lLbound = 0;! F9 R7 u# L; i% V* L
sabWrite[1].cElements = 10;
- Z& ?, ?+ }" Z6 B+ ?& U sabWrite[1].lLbound = 0;+ n8 w/ A8 `% R/ j1 q% c
( j6 ^7 m0 P- o2 X" D5 ]3 j$ x% J COleSafeArray olesaWrite;; \' d7 @: q% t1 v. n$ F
olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);/ b5 G' |; J4 a
5 F7 ]. g" F8 X7 e6 w
/*通过指向数组的指针来对二维数组的元素进行间接赋值*/) K) F+ t. [/ ~
long (*pArray)[2] = NULL;# x6 T& @5 _0 P$ h O# O# i P
olesaWrite.AccessData((void **)&pArray);
j4 Z4 R9 x% o8 T9 E, m memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));
) w4 y$ @0 ~+ {2 n0 b+ V' z4 s. y8 W% P
/*释放指向数组的指针*/" z3 E/ T7 ]* k
olesaWrite.UnaccessData();
' Z) Y* U( u6 W9 A1 H7 M pArray = NULL;- [1 t+ h; \ e1 L2 K1 Y
5 F! r2 n1 ^# A3 ?/ K8 v9 k
/*对二维数组的元素进行逐个赋值*/. w4 d; u$ N, z: w
long index[2] = {0, 0};
( r. a& z/ y% U1 k8 s; A1 I' a- ?+ U* C long lFirstLBound = 0;) Q6 d2 k* B8 d
long lFirstUBound = 0;( ~% s. X$ J! G: L8 x6 Y. K% z
long lSecondLBound = 0;
. P i w6 O1 I5 g" V long lSecondUBound = 0;4 A$ |9 e; d& Y: p2 K! _$ q/ a
olesaWrite.GetLBound(1, &lFirstLBound);/ y9 q; V/ i# C) I
olesaWrite.GetUBound(1, &lFirstUBound);
0 @1 y2 b+ P% I" [5 n- C4 j; L olesaWrite.GetLBound(2, &lSecondLBound);% E2 l/ ?6 i9 D2 ^) N: m2 k
olesaWrite.GetUBound(2, &lSecondUBound);
& ?$ m( Q/ \$ w% d: r( t* d for (long i = lFirstLBound; i <= lFirstUBound; i++)
8 {4 r7 _, ~: n2 s* f" p {
% s L8 A9 X& }7 L5 r' `6 J index[0] = i;
/ r- t6 b' D2 l; r6 ]2 O! q for (long j = lSecondLBound; j <= lSecondUBound; j++)
( p" N! \2 M; T- z! s {9 ~6 P, H0 z# q2 B
index[1] = j;4 \) z' l6 A6 R9 V9 e( Z
long lElement = i * sabWrite[1].cElements + j; 0 y" Y4 z% t' H9 }9 P
olesaWrite.PutElement(index, &lElement);
2 K9 l- u3 S) Z }8 e$ H7 M( B% i H- p; |: G
}
7 r* T+ b* u* E. F/ H. O1 L# k
; l- C4 h9 ?- }( l- h& k /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/, t5 ?/ @" d- X6 {; S
VARIANT varWrite = (VARIANT)olesaWrite;9 p# \) ]3 B+ }& y( L8 Q
range.put_Value2(varWrite);
$ c) C4 T) v" k* A, Y5 `- }* S# X \4 \' X/ B. e/ s
system("pause");! t/ a+ X3 S0 A5 h, M& Z: {
1 m- L3 U$ Y1 Q, E
/*根据文件的后缀名选择保存文件的格式*/3 y0 _ U9 N; D$ M% w3 a
CString strSaveAsName = _T("C:\\new.xlsx");
% I$ f8 @* U% J7 ?. g9 v# c* R CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));) U" J: E, h) ?' n, x3 r' k1 m- k
XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;" X! e) c& L. s
if (0 == strSuffix.CompareNoCase(_T(".xls")))
; q0 n% Y0 Z( L {( l! Q4 Z8 i* Z! b) V8 r
NewFileFormat = xlExcel8;8 ?7 O# [1 s+ F( b" [8 _' n
}
& S; J4 P8 @* H2 a5 B0 Q; H book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, 3 @: w% G9 Z) G( q' l3 K
vtMissing, 0, vtMissing, vtMissing, vtMissing, 3 v& h; u2 m. {1 Z% f* ^2 I/ i
vtMissing, vtMissing);. F3 i2 m5 i- x* w0 f
. `. F5 Z& h7 W" P7 o) } system("pause");* |$ a! S4 M% N z) Y, G
7 M* A% ~) c* d# k1 M. p3 l1 p1 ` /*读取Excel表中的多个单元格的值,在listctrl中显示*/
: K$ Y+ V9 G( ?* R1 [9 L VARIANT varRead = range.get_Value2();
3 n( B* C7 A: D! q* \" Q0 @ COleSafeArray olesaRead(varRead);; q4 F: H- Y! m6 ~/ A! m/ d
3 T! z* h6 B2 E3 {/ _7 w VARIANT varItem;1 e9 I& L l( t& c D
CString strItem;
2 @' u, _% b. G A lFirstLBound = 0;! X, h! s, u1 X4 K9 Q
lFirstUBound = 0;0 w& U4 ]/ w8 ?4 G: C1 ~# K
lSecondLBound = 0;
/ X/ ], H* J' N. N; V/ H5 v8 f lSecondUBound = 0;
% I3 z. |- @/ b* v3 A olesaRead.GetLBound(1, &lFirstLBound);
0 S8 L2 G: Q) z% q, \) U olesaRead.GetUBound(1, &lFirstUBound);
, p- g& n- u1 g9 H' V5 ` olesaRead.GetLBound(2, &lSecondLBound);
7 x4 }4 P; R$ ` olesaRead.GetUBound(2, &lSecondUBound);
, d0 ?1 V6 ^! V* P2 [$ i8 ` memset(index, 0, 2 * sizeof(long));& a/ V8 N: G0 S+ y* k1 [
m_ListCtrl.InsertColumn(0, _T(""), 0, 100);' }4 U! Z8 N) C8 R
for (long j = lSecondLBound; j<= lSecondUBound; j++)
& Q, k8 b: L6 T7 I {
1 J% n6 H( c1 k) ?% k# D% ` CString strColName = _T("");3 `% j% d( e2 h7 K. d, o1 `) u
strColName.Format(_T("%d"), j);3 g! m2 q- k9 _- b- [3 q- z
m_ListCtrl.InsertColumn(j, strColName, 0, 100);
; j( P6 ^& A/ q- \ }
9 Z# N0 `; g) n; ^) f, C5 n% S' \- g for (long i = lFirstLBound; i <= lFirstUBound; i++)
$ A2 f8 z0 @5 _7 ^, p b {$ i# a9 G* K. N
CString strRowName = _T("");: ?( m( M& V) Z9 s9 V3 P
strRowName.Format(_T("%d"), i);
0 n8 g% a$ I0 M6 w C) {* Y) S m_ListCtrl.InsertItem(i-1, strRowName);: S. D+ }( V( x! x# m$ K
3 v) @9 q8 O% B; E index[0] = i;
: ?% ~1 W' L' A$ H for (long j = lSecondLBound; j <= lSecondUBound; j++)5 `, ^( @- q# ]3 O
{" `) Y5 y) q; K& u0 Q- B* o
index[1] = j;
3 ?" f' Z" z# D3 y1 i olesaRead.GetElement(index, &varItem);
7 D8 Y8 o6 `5 e# Z6 \! j9 U1 k$ M% \- t" w; [0 c: |1 `& w
switch (varItem.vt)" O9 F$ i* K5 [" ^8 O4 V( ^+ A' y
{3 W+ y7 F. M& M- Y, p
case VT_R8:0 l% k# V3 u% B7 D* u7 ~
{; _2 I. C* y! j
strItem.Format(_T("%d"), (int)varItem.dblVal);: R- Q2 w. F5 h" @( {6 I- o
}7 ~4 e- w0 _& E" V
& z% @9 ]* s* S; [0 E case VT_BSTR:
5 n# d% [- O/ A4 r& j& R/ G {5 ] }$ g6 S. t& a1 V
strItem = varItem.bstrVal;
' ?) E* D- @' ?% t1 H }
5 z3 i ]9 J0 \8 i' \3 e' \1 _" Q3 g1 f
case VT_I4:
* g \- ~: p$ z+ t+ W {5 j# U$ Y) n7 {/ w$ P
strItem.Format(_T("%ld"), (int)varItem.lVal);
% `) A, U3 Q. j! f% @8 f }
f" u3 U3 E! Z* ?, A' i! V% e& P9 @6 ^# N) U) ~! @. m
default:- O! ^! b2 X' C- c' p0 r1 C: Q! r9 e& W
{
, j& R+ m/ [' V0 k
+ B& k/ }8 X {1 W& } }- D- z5 [1 ~, \4 H
}
2 x @4 v5 V$ \( M A3 X+ i
$ q9 {* x( k( ?0 V" \1 ` m_ListCtrl.SetItemText(i-1, j, strItem);
5 T" o7 E/ ?3 y7 O }
/ w' M2 b$ K4 R } E0 s+ @4 K: O: E. c+ I
2 F' @& i% T* L4 n/ B; b% X% ~
/ j. C! h3 G8 v1 e$ q2 ~8 _$ A* F4 a9 i4 a* r% _4 F( r
/*释放资源*/
- ?" n- |5 j6 \; q( J. n sheet.ReleaseDispatch();5 j. `8 X" U+ R0 j- @/ N, j
sheets.ReleaseDispatch();* l( g% M! @! b1 E* Q( J- y0 O2 O
book.ReleaseDispatch();
% M. {2 l( D' ^, p. w books.ReleaseDispatch();
* H3 l4 g0 m9 f1 s. U5 u" M ExcelApp.Quit();
8 w S/ @5 H9 y& a ExcelApp.ReleaseDispatch();7 t& Z$ Q9 w; ~+ ?+ m1 s" n
* {6 E" J0 a5 j& {& j |
|