|
|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
通过VC实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文主要研究通过OLE/COM实现对Excel表格的操作。
, q1 x% Z) m2 o. q$ T" Y9 s 3 Y5 I1 S) V2 j3 V/ H) Y
本文源码的应用环境说明:
' q ^" l1 a- g7 i" n( z" oWindows XP SP38 z$ Z. u# O2 P- l: w+ a
Microsoft Visual Studio 2010
1 w w- i- i5 b( u6 JMicrosoft Office Excel 2007
9 d1 s4 I' {2 P' z8 v3 y
. d$ J" L, o/ b Q0 }! a1、添加OLE/COM支持。9 C) u- H# \& ]2 d5 {3 @
首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。% d& Y) o0 E# F" L/ e2 m& t- G1 x
本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。2 c" D0 r9 ], m* a
通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。5 S8 F2 R; o/ Z! V& T
#include <afxdisp.h> // MFC 自动化类
) h5 t+ O. r+ w) u/ X同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:+ l8 f- ?) z3 w" M) Y) W+ j. a
// 初始化 OLE 库
' i& o& f* `& B4 L) a" `if (!AfxOleInit())( V9 x6 g+ T1 W# g' E
{: `$ t/ x4 ]8 @3 _) a. z
AfxMessageBox(IDP_OLE_INIT_FAILED);5 p) N- w" b" Y1 l
return FALSE;
0 u p# v2 h, h' J3 q9 S" f}- q' F* V0 ~" T+ `3 \/ `1 Y) e O
- G* w7 a/ u2 I1 N! X( _$ H! I2、导入并封装Excel中的接口
5 M/ d2 C3 a+ c5 H; LExcel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。% Q1 [) e9 w9 ^, X
由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。
$ O" s q F0 x3 T6 lVS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择
/ _1 U L {. V# k) S: n2 `, U5 Q要导入的Excel类型库中的接口。
, f% Z/ Y* ?& ~7 m9 I在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。
# F: J1 i' {1 ], y$ O5 `5 U7 a- b ) X, v: b; _3 W' O& I
本文所导入的接口对应的类和头文件的说明如下所示:
3 I2 s' a6 P8 ]$ S+ A/ `
- H7 M$ F& q4 A- wExcel接口: I4 J7 }4 G$ A
导入类
; T( P6 a6 X. u, c8 ~0 @( K头文件6 l) t( d6 ? Z1 c* Y7 v- n) k. D
说明
! t% n( t) @4 T$ e5 h_Application
- n4 o3 O; Z! f& C/ }- M7 wCApplicaton" \7 B" R& B' B) z @& W l
Application.h
3 U7 J6 [ T/ r8 I/ DExcel应用程序。
2 \1 Z P4 A, QWorkbooks
( G# T9 e/ z# ]. k$ \- [* QCWorkbooks' w1 ?: [- L0 @& S
Workbooks.h* C* O3 C/ m" Y
工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。
. J2 S% ^5 Y) I1 v( K2 V_Workbook
) n2 r7 X8 F2 v8 {CWorkbook
$ T9 Y# [- U- i8 s: k" B( ?; uWorkbook.h/ h- H' |6 P' i1 B+ }
单个工作簿。
, z& T/ j* G6 o: S' ~* B6 N% c+ LWorksheets7 f# ?/ C Z* M j$ r5 _5 l( `6 x
CWorksheets
2 j+ U; H8 Y0 A& L- i. ^Worksheets.h
. z8 \6 m5 M8 g! T4 [( b) n+ u单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。, ?: e& H* K& G/ b: C: w7 S( V1 ~
_Worksheet3 |9 q# y; }2 R
CWorksheet
* ]( B# |* r- b% n% F# JWorksheet.h1 J# C) ~9 W" Z7 m4 q
单个Sheet表格。 u g; I& U: x* Z3 ]* ]
Range
4 O4 n! U# V- s$ kCRange
9 K1 s% t! {9 S5 r8 H" ^) L& i/ jRange.h
8 p1 K$ N9 v: @3 Z6 A, A1 A4 N一定数量的单元格,可对单元格进行单个或多个单元格进行操作。& R3 a; |4 s( E6 W7 q* P8 A
8 Q# r" T0 D5 _/ |
3、导入Excel的整个类型库! }5 V" b" q: w: b
接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
' d+ _# s$ Z. i通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:6 @) J% F+ H3 i! w# I, N
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
# f0 ?/ C. b3 I, x这行代码的作用是导入Excel整个类型库到工程中。
+ \! g5 ^$ E- X/ w* e5 C0 f由VS2010自动产生的导入代码存在以下几个问题:) N2 i* d' W% n. \& d, ~
(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。
4 h) D! c2 ^! V/ I. {7 x. M(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。
2 _' v; N. T7 F( y5 v* W(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。; J, M9 A7 F4 `* s
以上三点问题的解决方法如下:0 \* o. V3 @0 H6 W4 S% N
(1)仅在_Application接口对应头文件中导入Excel类型库。
8 B! ?+ `( n. i: O; B(2)对冲突的类型进行重命名。
2 b9 M9 ]# k* Y* k: F(3)在导入Excel类型库之前,先导入Office和VB的相关库。
, Y4 g; |+ Z S J更改后的导入类型库的代码如下:
( `. {! e( i/ W$ _+ S3 R' D( t+ m
# n: p8 s3 T' k. q8 d/*导入Office的类型库*/* O' E0 J4 d6 Z. j. l& H9 G
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \, B# L3 t ~, w" H
rename("RGB", "MSORGB") \
' ^+ X8 } a: w- Z" Mrename("DocumentProperties", "MSODocumentProperties")
. l( C! q- B6 K$ @using namespace Office;
1 v8 V1 Y4 ~) c5 ?8 k& x 0 _, Z: l! O2 u! V
/*导入VB的类型库*/
8 @) l' c7 n3 A& q2 ~6 i \! Q. z#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
: p' w, H7 g' i9 cusing namespace VBIDE;
3 o/ @4 N! K6 }6 z4 T
! l6 V* W9 D3 @0 H/*导入Excel的类型库*/$ m1 M$ m3 u9 ]( J
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \# ], W( ~' @9 M, ]
rename("DialogBox", "ExcelDialogBox") \) p x9 v& p5 l& `
rename("RGB", "ExcelRGB") \
* ^% }: I% I* U- U" [rename("CopyFile", "ExcelCopyFile") \
: u2 b% J7 @, Y2 arename("ReplaceText", "ExcelReplaceText") \8 A) G% {& b; f- C+ X# k; W5 N' k4 L
no_auto_exclude
% Y; b3 }2 u0 w( l8 q3 sUsing namespace Excel;
5 E1 t; n8 m# p% O4 _0 R . g' F6 u+ P) }( o0 H
编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。% _" `% R1 p @, t) e6 v5 P
7 z' r" M* W a, L# \; a6 Q3 O& Q4、操作Excel步骤
6 _0 ~" [3 Q4 w9 ~4 N8 }操作Excel的主要步骤如下:
0 r0 A: S ~/ t% L; `(1)创建一个Excel应用程序。4 V' `+ `4 U3 d7 H3 ]
(2)得到Workbook的容器。
* F' \6 V* w" D3 R4 o. N(3)打开一个Workbook或者创建一个Workbook。
( z1 g/ \) }& U$ S" k- i2 B4 d(4)得到Workbook中的Worksheet的容器。
% |. I# q* c2 y+ a! I$ k(5)打开一个Worksheet或者创建一个WorkSheet。6 p6 G# E, V- W5 v
(6)通过Range对WorkSheet中的单元格进行读写操作。
6 A D* e+ P h/ @9 ?8 ?7 ~! K(7)保存Excel。
2 n, z. F" T$ L" v8 N; a(8)释放资源。 u- H. A) x9 m1 x. _1 N
% X8 ?& Q0 w1 `
5、批量处理Excel表格
/ F& r' i" y! [+ C$ MVC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。
6 q: |2 y+ Q6 E8 @7 d; e对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。: O% D5 ~$ `0 o
VARIANT get_Value2();! A' i; r* U( Y
void put_Value2(VARIANT& newValue);
0 ?( o+ y: O. w7 v- }. k* E其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。
! c: _$ }) Z8 H& B其中,VARIANT中实现二维数据的方法可参考1 l2 u4 Z [- d% x; c
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html
) h8 m2 C e. T4 E+ A& ] R当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。2 H8 r9 j" ~8 s/ P
+ D _% w9 d$ G l. L1 s$ `4 }% ?
6、Excel表格的保存
; L3 x/ Q! z+ X4 P0 M2 Z(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。
! `' |- y/ M# m) R8 [9 c" C(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。: Q1 {# ^# M; G6 P+ L* q6 b% \
SaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。
' ]! F: _/ k$ w/ y( U4 c9 a" X
/ X3 G; s0 b, e0 H9 m$ z, Y# G7、获取当前Excel的版本
* }! {8 k6 ~7 {- s& x3 K可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
2 I$ \1 o) ?3 v' R: g$ |
5 }0 @/ }* A$ I8 [$ D; `' F8、示例源代码
" p, ]+ D) f8 \( F主要代码如下:$ ]' j. s. G+ N: \" I+ ? q' H# ?
% ^) b5 }! q1 Z$ Q f0 @
+ j+ Q( }( M! K( Y5 \
) q: g" i9 @; Q) ?2 j* S {# o' l- k/ N m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);2 c! k* I% b. h' \
, g* C3 \. U, o; }* U CApplication ExcelApp;
+ x" D2 J/ A' y* O- `: C* V CWorkbooks books;8 F" ~8 c" J: F+ N
CWorkbook book;
. U: u& s! V5 U" O CWorksheets sheets;6 Y2 E8 U* M0 a, @6 I0 v2 Y* e
CWorksheet sheet;
1 @5 y. Q# v5 c$ T, Z7 L2 T* }) ]$ R CRange range;- ^2 R) w6 F3 E1 y
LPDISPATCH lpDisp = NULL;
% ~3 L' J: i& O( K* M O0 i+ A6 N: v: C) w5 t* X
//创建Excel 服务器(启动Excel)( q! Z0 c# n! ]$ Y: A+ ~+ H
if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))& m2 H! c! j& _/ g! y% b
{. q, \) u/ z$ Q/ s+ V* j ^/ Y( l
AfxMessageBox(_T("启动Excel服务器失败!"));
* N0 G3 ~' |1 [* j3 [. F/ N; r return -1;
) x& N% {7 ], B; K }
6 {, N6 V8 {' c3 p$ P( b( X1 D* ]! d
/*判断当前Excel的版本*/, F3 J6 r3 i% H$ o3 I% j
CString strExcelVersion = ExcelApp.get_Version();( A! p& J4 A, e: |/ }
int iStart = 0;6 a I* @( [; z( M
strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);
, x) e5 }+ t) C9 v& O if (_T("11") == strExcelVersion)
; N/ o6 T; F% @, W# O' u9 f {+ k2 p8 q7 b2 E2 A4 H
AfxMessageBox(_T("当前Excel的版本是2003。"));
* J1 g& B# j/ G# v }
1 @9 B# f, a3 F* p4 }# p p2 W else if (_T("12") == strExcelVersion)
/ d+ w) t6 P. D9 C4 F9 f {+ z! R- r. h: M' u9 Q8 {, {% [
AfxMessageBox(_T("当前Excel的版本是2007。"));
$ E( Q$ N% J* _- _7 I0 d }
) |& H$ ~6 U# C3 [' m else
. ~! K# M5 i4 I/ ` {) N0 B5 \* u: S* T# R# N
AfxMessageBox(_T("当前Excel的版本是其他版本。"));3 z& f1 ?& Y% ]0 ^
} F3 i; }3 ] u7 s6 C. `
; g H7 \' s* V3 u3 |! y" t6 P4 {) l& T7 N
ExcelApp.put_Visible(TRUE);
1 {; |- _% A7 q% B! s, ?0 f4 j ExcelApp.put_UserControl(FALSE);
! @# B7 @/ c/ Y# j! H5 `- J' m4 k' O# }0 L4 m% B
/*得到工作簿容器*/( ?9 { t) a, ~) ~$ f" u/ M
books.AttachDispatch(ExcelApp.get_Workbooks());; z- f. n3 O) r' |5 Y
. s2 a/ C, }: V+ a$ q /*打开一个工作簿,如不存在,则新增一个工作簿*/ c) P( ]: ~2 L# W8 x! v
CString strBookPath = _T("C:\\tmp.xls");8 R' U- C# S8 U& n1 P4 |
try
+ M9 I* c" f5 V/ Z& E2 d {
+ K/ Q% ?& |+ x /*打开一个工作簿*/
' F" L- g4 }7 j lpDisp = books.Open(strBookPath,
% O3 o5 Q. S1 D4 d. L O8 ^ vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,, W+ X/ h1 Z3 a; S* W
vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
- M, ], V% }9 t7 I& ] vtMissing, vtMissing, vtMissing, vtMissing);
+ q* Z8 K+ k, e& G! H+ ~3 t$ G& i book.AttachDispatch(lpDisp);6 |; j$ y! U* n! E# b
}" `- A0 K+ e- {* M
catch(...)1 }8 Q" H3 I8 u# ]! B8 j
{" x- z- O4 J& K, W, J) }( W7 [: B
/*增加一个新的工作簿*/
6 V2 T" S& l# }# S8 G lpDisp = books.Add(vtMissing);1 Q) B% ^6 v K+ `; A7 A
book.AttachDispatch(lpDisp);8 ~" |3 O! M- C/ N: {5 a
}# V4 b+ e7 h/ U; D9 T2 S$ H
; B, c0 R2 B9 w4 Y: h7 }( A* N+ T
* J* `& ]" f) Q! S; t& E: q
/*得到工作簿中的Sheet的容器*/! |9 e+ A2 q s) v* k% j
sheets.AttachDispatch(book.get_Sheets());1 B) z2 ~3 z9 f7 E7 _
( u G' R5 |3 N# A: H9 d N9 A: ~ /*打开一个Sheet,如不存在,就新增一个Sheet*/
; }( Q5 y4 e4 d$ _. }+ Z, @ CString strSheetName = _T("NewSheet");
1 ?' G9 l/ n" L7 t try$ N: G3 b. H# n5 g; |) b# i$ I
{
: U1 C7 _4 L. g. \" l" b! p# W, ^ /*打开一个已有的Sheet*/
& q4 O$ O4 F/ d0 Q$ H lpDisp = sheets.get_Item(_variant_t(strSheetName));% }9 P+ J& k" P& U7 b
sheet.AttachDispatch(lpDisp);" s" }9 L/ f9 [% d
}
/ g; U# |8 [8 ^: e( R catch(...): n% J1 x. J2 R! j
{) v. C7 R. k' m
/*创建一个新的Sheet*/
: ]" t9 X# _0 I3 [4 G lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
5 Z2 K* H( z* O$ V( `" R sheet.AttachDispatch(lpDisp);5 X1 b; D1 F% L6 A* T
sheet.put_Name(strSheetName);* }: R/ b! I9 Z" N% l
}0 z8 r7 N6 Z. o
6 K% M! E! X2 H, b8 | y3 k
system("pause");4 H ~4 g: n X$ x# N
0 v! w6 x8 n9 `. }8 Q* [
/*向Sheet中写入多个单元格,规模为10*10 */6 f5 q! `. M, v/ Q6 U/ f
lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));
* B2 p2 m5 f9 z( o+ a8 j U range.AttachDispatch(lpDisp);
4 v, I1 P: {2 t& U1 i5 J+ v! Z* C* t" i" A9 ~8 i9 L+ C
VARTYPE vt = VT_I4; /*数组元素的类型,long*/. m& b6 T" k& c6 J9 o9 r$ q; w: o
SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/
* k% h8 [ y, X1 l/ R sabWrite[0].cElements = 10;
$ C7 d; w0 _- O sabWrite[0].lLbound = 0;
/ s1 D9 @: p4 _& B# n9 K" [ sabWrite[1].cElements = 10;: H: T+ p8 E' O* b
sabWrite[1].lLbound = 0;- S, ~8 i: M4 l: A# y
6 r; ?% M" C! y2 y) Z2 C# a
COleSafeArray olesaWrite;
; c; x2 e z E9 u: z& n olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);2 X1 I j: I! S8 c- N& t, ?
: c+ l8 T3 Y; t" B1 m
/*通过指向数组的指针来对二维数组的元素进行间接赋值*/, a9 O0 ~ X1 g$ B7 d& B
long (*pArray)[2] = NULL;- z. S3 a. v( m. N- q" R
olesaWrite.AccessData((void **)&pArray);* y$ U5 \' H8 E) c
memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));8 {" @' O: c- \; }. U( f# K
) `2 k% h# S$ h ]4 H; y: [
/*释放指向数组的指针*/
- O% c [. L: [* |! F# J. W/ r olesaWrite.UnaccessData();
: E/ u( M i" X4 H& v" H% x pArray = NULL;
! f3 w& C( B* w- p& I6 Z! T7 q5 ]+ D7 ~; W3 k& i: `! ?
/*对二维数组的元素进行逐个赋值*/& w/ n+ R5 m9 |
long index[2] = {0, 0};' v2 A! M- V& Y% x3 x. c8 \0 C D/ `
long lFirstLBound = 0;& x. B, ]! f7 N3 m. a$ q
long lFirstUBound = 0;1 l- T1 l9 d H) n8 `' \; `
long lSecondLBound = 0;
z0 V+ b6 L, L1 r2 G1 {- @ long lSecondUBound = 0;
! \& y' I$ m* R7 D& R: C olesaWrite.GetLBound(1, &lFirstLBound);; C" f) A6 G) o2 }
olesaWrite.GetUBound(1, &lFirstUBound);( g" H! H! A& W! W
olesaWrite.GetLBound(2, &lSecondLBound);
4 w1 \2 [# V8 g olesaWrite.GetUBound(2, &lSecondUBound);
8 H0 |. T4 K T( z0 ] for (long i = lFirstLBound; i <= lFirstUBound; i++)
2 M, A3 v: _3 v8 ^; v0 ] {: a0 M. X* o s9 n: t* ?+ L
index[0] = i;: m% \4 N! _+ L& ?! p( M3 E
for (long j = lSecondLBound; j <= lSecondUBound; j++)* `9 b0 Y# G" E, T! @
{2 G) T( {6 H8 Z% \
index[1] = j;4 T: e. ?9 K6 |0 A. p2 ~! o2 c
long lElement = i * sabWrite[1].cElements + j; 0 _' u+ \6 ~4 B6 @ ^7 \) o
olesaWrite.PutElement(index, &lElement);
- o) S7 I1 m* J }
& a* V2 S6 h* P. T; W }0 Z: k* b. @! Y( e% F7 ^
( c$ Y; W" s& }. p* r9 y
/*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/
* K* L/ T% c! F4 v* p VARIANT varWrite = (VARIANT)olesaWrite;
) x3 f- ^0 N& R* F( z" b) m range.put_Value2(varWrite);* k2 k# \* X6 R3 N
6 K8 [# X( T: g! T system("pause");4 D2 }+ l7 z" k5 f1 g) X+ X7 c
3 w- W* R9 I9 S/ G! t# n" J+ K
/*根据文件的后缀名选择保存文件的格式*/
5 U: [% [+ w7 S CString strSaveAsName = _T("C:\\new.xlsx");8 s0 Y2 u% E2 c; t# m: R% t( d P9 b9 X
CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));: p* T: X# R) z- T9 x5 H3 l
XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;- ~! L; d. R/ {2 {
if (0 == strSuffix.CompareNoCase(_T(".xls")))
8 Z4 h2 i2 y) J$ @/ ^ {! z! E, `8 w" d; I' p- n
NewFileFormat = xlExcel8;& D: }, V% `; n' @
}
2 F2 F8 p |3 g$ l3 V+ h book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, & d% C g+ s3 p, b) M
vtMissing, 0, vtMissing, vtMissing, vtMissing, 1 S8 o" {# f% c: v1 C
vtMissing, vtMissing);) Z5 d6 B- A% v, K3 c2 ]1 \8 ]6 @
; x) ]. T9 [/ j0 }) \, N. m" `' @ system("pause");) J' b( q9 M' e) f( p; U
5 R+ e, G8 t/ l0 R( k4 M1 V /*读取Excel表中的多个单元格的值,在listctrl中显示*/
+ P- V# P# x W1 T VARIANT varRead = range.get_Value2();
5 r$ n* i' O5 U* p) W9 b/ G COleSafeArray olesaRead(varRead);! W) g5 m% `/ \' I% T
: m! B6 g; g2 y! u% S, K9 r VARIANT varItem;' D/ }) W/ k0 [: s
CString strItem;* _% U$ r! _& X% H
lFirstLBound = 0;# L0 V b! D9 y w5 K
lFirstUBound = 0;
7 | g: b, V" C% ?1 L) M" H/ t6 T lSecondLBound = 0;9 C S5 s' u+ k
lSecondUBound = 0;: V" J$ y$ X3 }( m0 S g- g- L
olesaRead.GetLBound(1, &lFirstLBound);3 p1 U3 `9 W4 H' d7 b5 T
olesaRead.GetUBound(1, &lFirstUBound);) L5 o2 M' U4 Z' N
olesaRead.GetLBound(2, &lSecondLBound);. T7 a4 M/ ?3 O3 r& G7 J7 h1 d. g
olesaRead.GetUBound(2, &lSecondUBound);7 J0 L6 T- G+ r0 j6 P0 v% O
memset(index, 0, 2 * sizeof(long));
' l1 o5 ^9 f% x m_ListCtrl.InsertColumn(0, _T(""), 0, 100);7 X6 h* o$ y* |2 E! U/ z
for (long j = lSecondLBound; j<= lSecondUBound; j++)8 z5 P* D0 k: [+ g
{4 c4 Y* M6 N& Q6 |
CString strColName = _T("");
, b L1 k' f: a* g) Z- J strColName.Format(_T("%d"), j);
* n2 x) L" O0 f5 Q: ~/ r3 e m_ListCtrl.InsertColumn(j, strColName, 0, 100);& V$ N9 o* ]) N1 v
}: u* M' S/ N r. [7 f5 }7 j
for (long i = lFirstLBound; i <= lFirstUBound; i++)4 b! I* ?4 }$ {4 g; l# l5 `
{
' e; Z7 E4 _8 } Y H CString strRowName = _T("");
* e* Y" p. I5 {0 n7 V strRowName.Format(_T("%d"), i);9 X1 i3 ?/ O( u. r. J( c9 ?
m_ListCtrl.InsertItem(i-1, strRowName);
) M; U$ e1 @. W3 ], T9 m- w7 ]" J9 u: Y# q& ^% z% V- O; s. r
index[0] = i;+ \* F: ?7 A O1 Y; `& Z1 |
for (long j = lSecondLBound; j <= lSecondUBound; j++) u4 m1 I% {- y0 F$ w5 n" ?' A
{
9 e" F: m& Z: b$ Y, ^ index[1] = j;
3 S* h% W: b/ M, \6 c! w3 C5 m$ X olesaRead.GetElement(index, &varItem);( X' Y, E; y* m+ s
. G+ [- Z. c1 `/ q switch (varItem.vt)
( l4 Z4 l, Y& u6 l) ` {
S+ i. }4 I1 g4 y7 [ case VT_R8:
% i1 Z% Z4 c" x. _ {, ?* O1 J3 {. m! {
strItem.Format(_T("%d"), (int)varItem.dblVal);
5 [1 j% m! h: g* [+ B: s, K }; d3 p: [+ A9 g x
$ X( k! j' ^: y! z" ` case VT_BSTR:/ z: u4 ~; U/ r2 {! h( [
{$ G# ] O9 P' _) q+ S. s
strItem = varItem.bstrVal;
5 R: F7 ?1 V; F" g1 v% n$ o4 {$ [- T' u }* b+ j E3 T$ P# Z
9 @& m" b4 \) Z$ z* ] case VT_I4:# s0 Z! D) z) u" G0 H5 ^" @: U
{
1 B$ r; i+ t- \& T( [" T! h. L0 b strItem.Format(_T("%ld"), (int)varItem.lVal);
0 A) ~% I+ h+ F5 z9 n2 w$ B0 o }
. Z: @( N5 F' c" } t9 T4 F
4 X6 \$ w0 d, D$ j7 y default:, R* K9 G# _1 [5 L
{! ^! T# u' ]) `5 E; F5 Q7 u
& A5 I" z5 R6 {; \( j; x
}
# s! R, U9 O6 w( f }
1 {- }7 o6 r5 C6 \2 O5 O2 ]1 I: g" G
4 X1 s, q3 I6 k3 A7 g* U; B3 W m_ListCtrl.SetItemText(i-1, j, strItem); B0 o1 U8 M9 e
}2 j- Q7 ~+ h A; g
}
1 b6 a, X0 E# i D9 u: i5 r% M& s; {" Z' a( H' y
3 D' G( |, T! e/ T
- ]' n- \* W' @& N$ L /*释放资源*/
- M7 ~( d; P4 T8 I; e, G/ r; E sheet.ReleaseDispatch();
" Q. s" P2 U' z# J sheets.ReleaseDispatch();4 x* h1 N) y8 w7 x- m
book.ReleaseDispatch();( d4 O. ^) p+ K
books.ReleaseDispatch();! B$ U3 u+ o, o- ]3 F+ }
ExcelApp.Quit();2 \$ E' Z, x5 U9 r
ExcelApp.ReleaseDispatch();2 m/ }. S, s1 z, \& T* \0 X
# ^+ s( ^; `5 p1 F3 f
|
|