|
|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
通过VC实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文主要研究通过OLE/COM实现对Excel表格的操作。
; `5 ]" K1 m0 H9 Y 5 J6 n& b$ A: `7 i3 b( t9 o) i* |% }
本文源码的应用环境说明:# h: r6 W: ?8 G9 I; M1 S5 n
Windows XP SP3
. w5 h- l( M* J) EMicrosoft Visual Studio 2010. Q6 n% `- M- |: d
Microsoft Office Excel 2007
" L4 E; r, v$ j: Y* F : j3 T, k! r" B3 P' ?
1、添加OLE/COM支持。
+ ~: D6 f5 k/ Z% @首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。
+ n$ m/ Y1 C! [1 Z1 a( C本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。
3 g5 D! c& H# M% H9 L' q: x通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。) q4 A* ?9 A6 s
#include <afxdisp.h> // MFC 自动化类( c; B" }2 t7 p9 h8 M6 y
同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:% H& ~* ?$ k& K, {: T2 ?
// 初始化 OLE 库
+ _: a: T3 z2 Y. Y2 R* V$ N( L$ Iif (!AfxOleInit())
2 l% ?, {! M) I/ _{
) u3 U9 y9 a! |7 f8 a* uAfxMessageBox(IDP_OLE_INIT_FAILED);
( V5 o+ V) B/ k2 o1 k+ [0 ~return FALSE;
. W- f4 s5 S6 L q- z}
% k5 L. G' f/ q6 H7 y3 ~ ) u: P9 t, ~' N4 ^# O/ z
2、导入并封装Excel中的接口
9 B) M: H1 L, y. ~& U; f( U3 eExcel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。
1 ], x1 U* h& p% q2 w' S2 ^ { k Y由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。% F) v3 a5 s" \* c
VS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择3 G0 R8 ]: G# X u7 `; ?9 J
要导入的Excel类型库中的接口。
V* x$ ?. M& w# r3 P0 q在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。
" y% G& S: ` B2 x" F9 T3 |( a
2 D+ F( R1 w" L, D. G/ A本文所导入的接口对应的类和头文件的说明如下所示:" L% {; I; f/ ]* v
0 n% v/ I+ g1 P+ V
Excel接口
9 @. |4 h# { s W/ Y导入类
& C, K- Z" Q% S2 \8 S- ^: Q0 p/ L; }7 V头文件
~4 y$ [& J; m$ K说明
# P! O0 o3 ]( V& }) \1 q; n6 F_Application
& `& `9 }9 _+ e* m- f3 \6 T* TCApplicaton
5 {% E) k# h$ w$ C, |- l' ?+ vApplication.h
# u+ J& N1 S x5 w6 _5 l5 F6 pExcel应用程序。
, g Q5 `; w6 ]4 R5 MWorkbooks1 H8 E: x M w4 U1 c
CWorkbooks
: t, I& `+ |2 b1 x5 ~Workbooks.h8 E% ^2 b: U) e, h& H# F# g
工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。2 @0 q+ n- I3 ]( L, O6 L! c
_Workbook
6 m6 ^) e- [5 `& f; T, DCWorkbook
% S& o1 i# i' jWorkbook.h* ?) J& ^6 d% I8 W& P
单个工作簿。
9 Q' e- @& ]1 H3 c2 S _4 o2 B3 `Worksheets7 m+ X0 Y( n' G* B
CWorksheets6 x# a0 N2 a1 E* B
Worksheets.h
0 q) h5 M" n- P3 z8 v. _单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。
: J* i( H& H' {! o9 z% m. X_Worksheet
( O; d- t9 ?2 t6 U' v% BCWorksheet7 M. ]& G; V. I( O# `- ^- C/ g
Worksheet.h+ H7 F- R; k8 T. I
单个Sheet表格。) q3 r6 Z7 q; I
Range
: u! |1 _' _' F' `" D, QCRange
0 F% q6 z( ?/ A' tRange.h
$ |7 D6 v3 t& l( U+ i2 x9 k& V一定数量的单元格,可对单元格进行单个或多个单元格进行操作。, b. ]7 H% \1 B7 U
. p' T* ^, \" V1 x$ j3 ~3、导入Excel的整个类型库5 |7 T( R3 N8 _6 w' e/ g, I+ `
接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
0 K' F' q+ N8 H2 X8 F+ H4 O通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:( p9 M D; A# `! a- C
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace% o. Q) H% q" X. Q8 O6 @
这行代码的作用是导入Excel整个类型库到工程中。3 ?1 A$ H, `( }' b
由VS2010自动产生的导入代码存在以下几个问题:
# j \. P8 r4 U# z" ~0 H(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。
2 ?( @6 B% S0 [* }" a(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。
# {9 U$ q2 R% t, m, a8 p l(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。/ ]/ g0 P1 m4 {! i
以上三点问题的解决方法如下:7 |' C* `) d. ~; h3 r2 ^1 w
(1)仅在_Application接口对应头文件中导入Excel类型库。& s/ Z8 e8 b+ E: _9 j. k b
(2)对冲突的类型进行重命名。, K5 I5 X2 f! ~& ?! {
(3)在导入Excel类型库之前,先导入Office和VB的相关库。/ s5 Z* T9 z/ w& H% @7 R
更改后的导入类型库的代码如下:
3 y; ?% ^6 a" {6 g7 o1 h* z5 {; s. b
0 `; g$ Q! i8 @; T% O/*导入Office的类型库*/
( P' O: @' B H% V3 |% t5 B#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \! w1 r0 P, I( ?
rename("RGB", "MSORGB") \
6 q |2 C8 L7 c0 Z5 e; {1 jrename("DocumentProperties", "MSODocumentProperties")
3 [* z( T% _1 O! B; ]using namespace Office;# b+ i3 n& l" A# J2 A0 m h
' Y9 j7 s: ^; [, H3 p' `8 ~
/*导入VB的类型库*/
/ L+ a8 l' [5 w1 T/ R: U: z9 j#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
# }$ r9 ~0 c3 dusing namespace VBIDE;
( q8 Y$ a+ r! j3 C2 n 9 W R5 N$ T' g* @
/*导入Excel的类型库*/
- T( J! A- i( I( B! c#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \ o* T* Z2 u8 {1 N# E3 D* |
rename("DialogBox", "ExcelDialogBox") \# w2 [5 y' i" S+ b8 t
rename("RGB", "ExcelRGB") \
' @4 S/ F- u7 }1 Krename("CopyFile", "ExcelCopyFile") \4 `' Z$ r, W: E. G+ Q3 w
rename("ReplaceText", "ExcelReplaceText") \- Q" ?7 @# m$ Z& \! G( a; e( T
no_auto_exclude/ w+ ~% \4 Q, J- f
Using namespace Excel;
9 w3 r7 l, V3 ~9 R% d/ x
( n$ N1 @3 |, M( |: E编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。0 v- {/ n( e4 d7 c, K
: y) J" ^# X& g, a& H4 U" I4、操作Excel步骤
3 |6 e0 M1 b; F9 t2 m: t" F操作Excel的主要步骤如下:
2 \" `: s4 ~" S/ [4 c( Z% Z(1)创建一个Excel应用程序。
" Z, q. K0 D6 Y. L(2)得到Workbook的容器。
( Y* [5 W( @6 W, z `0 Y(3)打开一个Workbook或者创建一个Workbook。2 b! @" K) Y0 |. L
(4)得到Workbook中的Worksheet的容器。# t- a: }7 I0 l- ^
(5)打开一个Worksheet或者创建一个WorkSheet。/ E1 f# ^ J. Q2 K0 E1 E
(6)通过Range对WorkSheet中的单元格进行读写操作。( R. p1 ]. R# l8 u( H4 x! i
(7)保存Excel。
) E* M& p) K7 ^* f+ ](8)释放资源。
c6 F& G: b, y- F
. U; [/ G e2 C9 ?6 A C5、批量处理Excel表格
( X8 K$ Q ~# K; ]4 \VC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。
& C# R! @5 _( V8 P7 ?: I4 Y对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。! D' n0 `/ [, O$ I: P
VARIANT get_Value2();# k& X* A' \: W
void put_Value2(VARIANT& newValue);4 A+ ~5 q, e1 N
其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。
8 Y) i1 E7 {* B- Q. n其中,VARIANT中实现二维数据的方法可参考4 Z% s5 P5 I* {8 t5 G3 m$ X
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html+ h; F5 l# q# W& I' J
当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。/ |; D# a# `# V5 h$ @; i
; y1 w7 A9 T: N# m" P
6、Excel表格的保存3 R$ G& K8 T7 J
(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。! }1 |" G% c } w$ o/ p0 w
(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。
5 n7 F8 s. @( Y; V% ?9 x7 I/ DSaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。/ D3 V$ w6 A9 {. w* N. M9 a
4 a+ s$ N/ t6 ]7 O5 v6 L* r
7、获取当前Excel的版本
% o& ~) C% {5 d, p( e# v可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。+ s) p# W) p7 J5 D
; K2 u" ?8 @! G9 L O
8、示例源代码/ c1 O B+ P, }3 F2 k% w3 x! z4 {# `
主要代码如下:) o$ B, J+ t) n7 \6 o
# K5 D! n4 B, k$ p9 a% d+ o. v1 o0 T* c
7 d/ P; w8 J. ^7 k+ n, t* F" R m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);
7 g$ k$ H- E' ?) O
+ q' a; V& U' n+ ~$ c; P CApplication ExcelApp;
0 V% v6 w3 q8 a9 t0 i+ B CWorkbooks books;
# I) G) w P( _" u* D5 W* ~ CWorkbook book;
, l4 m2 y3 M& c; K! t) `) |1 v CWorksheets sheets;
9 e" C2 T7 D4 u) P7 u$ s( `% e CWorksheet sheet;
# Z" x- i$ \& [ CRange range;* w5 X& m! d) L5 u
LPDISPATCH lpDisp = NULL;
1 D& q) x& \0 \4 h* G! w$ i- C2 o' G9 L9 b% l$ w
//创建Excel 服务器(启动Excel)' N$ Z8 C) ~1 o' { [
if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))
6 v% `! T; u2 v7 }7 u! Q$ N {! u6 v* q( C5 `2 L& @" K% Y- i
AfxMessageBox(_T("启动Excel服务器失败!"));4 Y0 h G/ s$ u3 K# F1 u: c; s# w! A
return -1;
* c9 b S7 h# k, M }
0 G* U+ Z( R* I V; x/ m Y
1 @( W5 L- s7 k' H5 S) R /*判断当前Excel的版本*/" e# }: v3 y1 q( L5 D; l
CString strExcelVersion = ExcelApp.get_Version();, ]5 z2 l. P) ~8 R7 t
int iStart = 0;+ D; }$ W; l) Q1 }7 U G* o& O
strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);
, y$ j" i5 @8 W+ f/ F if (_T("11") == strExcelVersion)
1 h1 t/ W- h) I) c+ k o- T {
' F6 L8 N! e% _8 u b AfxMessageBox(_T("当前Excel的版本是2003。"));& O$ ]8 t, m% F4 M \* I
}1 ?# f) C5 b7 {- i0 Y3 p
else if (_T("12") == strExcelVersion)
' S2 D7 F% I3 w* P! I. [ {
7 ?( q; J5 d# z! c7 ` AfxMessageBox(_T("当前Excel的版本是2007。"));
" x* `7 { \4 p/ Z }
1 w3 V* U# R. l+ U! ` else, A5 L8 S1 ]+ M0 @; ~- v5 S
{
) `3 G# G, j. R* _4 ?, w AfxMessageBox(_T("当前Excel的版本是其他版本。"));
6 ^: j. `; {, `) w. L# g: ?& [ }+ Y9 _# L6 w3 o, ^3 Z4 P
8 a( Q+ v, [* e
ExcelApp.put_Visible(TRUE);/ z* b- m- x. M2 q- N
ExcelApp.put_UserControl(FALSE); E( m9 [# X) Y
8 p$ i6 u6 _6 N" L7 H /*得到工作簿容器*/
O" E* |' ?, T& Q5 B% X% T books.AttachDispatch(ExcelApp.get_Workbooks());
s0 \( B/ o1 v, U# ^, e( E. |# A& S% p, }2 d
/*打开一个工作簿,如不存在,则新增一个工作簿*/( K* m! r- u3 A$ I% W
CString strBookPath = _T("C:\\tmp.xls");: [) P5 M! O! O3 P) Q
try4 n. \0 E$ n, f/ _. y
{
/ R+ e1 o* i/ a+ d9 w7 `4 G /*打开一个工作簿*/
6 u) v- H3 m! w9 I, X lpDisp = books.Open(strBookPath, % b! R/ ]0 b* C5 L# R: p
vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,8 ]; b7 z! a. Z% m# y' {# Q& h
vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
! c/ ]0 m0 R' N1 n vtMissing, vtMissing, vtMissing, vtMissing);
. V' m6 M) a* i book.AttachDispatch(lpDisp);
+ `: u y7 a) p. _ }) k; m* i. e; D G7 x
catch(...)) W1 l6 d* z8 T% }7 p: x
{# v' L5 H2 k' @; e8 w
/*增加一个新的工作簿*/3 a0 b: X- N G: L
lpDisp = books.Add(vtMissing);
: y' T) y' S( f9 ~4 g: R book.AttachDispatch(lpDisp);
0 E9 l \0 a, w7 q7 W }- H- n& P& W. D2 t
. k9 c+ X6 ?+ Z1 S( }% H
7 \$ d7 X6 |2 F) v$ l
/*得到工作簿中的Sheet的容器*/5 V" ^9 e$ c2 ]. V# j6 e
sheets.AttachDispatch(book.get_Sheets());) C$ D/ j' z: y/ l
, ~0 B' Y$ N; W, S9 e j3 ^
/*打开一个Sheet,如不存在,就新增一个Sheet*/
2 T f1 l+ i7 o, z$ }8 {- _ CString strSheetName = _T("NewSheet");6 P D8 A9 t' |, h
try
1 n9 A& ~' ^/ s3 H. H+ {8 T {: K* |7 I" d' i( O3 B. T: l
/*打开一个已有的Sheet*/
6 M7 Y+ t. P! W' f: v, P lpDisp = sheets.get_Item(_variant_t(strSheetName));1 \ Q5 Z1 Z w# z$ S9 T8 o
sheet.AttachDispatch(lpDisp);
, ^9 k* x. V: e7 D- l7 I# G3 O/ f }
- Z# D5 \0 H, x8 Z% \! L5 m' U0 _6 a4 M catch(...)
9 N5 v) D2 e8 z. Q {8 b! T$ j* Q1 y% F/ C% w
/*创建一个新的Sheet*/ p4 G* Q6 j$ z6 K* l: v+ ^
lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);6 d6 C5 y3 |# @+ ]
sheet.AttachDispatch(lpDisp);3 m4 L* U$ } j$ ]. C$ ~1 Y
sheet.put_Name(strSheetName);! }& c! e! }9 j4 v
}& |. p( g! n- K7 T# D- G6 p2 j
& Y- \( X5 P! N Y/ C( X0 l system("pause");
4 H( p8 L1 l! N4 s/ e0 ]: u7 n+ i
3 L0 E) W! b* L /*向Sheet中写入多个单元格,规模为10*10 */) }0 b# V% D+ J4 F& B' k2 i
lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10")); K3 R% E, V2 C; G1 |
range.AttachDispatch(lpDisp);
8 o) y2 p* }1 @. h. e" ]/ E/ V# n0 J# y8 t; G$ q* X ^4 j
VARTYPE vt = VT_I4; /*数组元素的类型,long*/
# R d# W2 [0 _7 K2 q. W H( R" ? } SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/
. O$ V) H2 W, B) V sabWrite[0].cElements = 10;) {( f/ l- a. `5 I( x, v& B
sabWrite[0].lLbound = 0;/ q3 {* Z; r* F
sabWrite[1].cElements = 10;1 E8 b3 E( [- F! |* b @# \/ K
sabWrite[1].lLbound = 0;
( b9 S; Q/ y/ K: G Q+ Y
# C( X5 j( ^: a+ O! p" D- P COleSafeArray olesaWrite;
/ Q3 n; R! n% _7 r, k olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);
! u4 C$ }1 M) I: t( O
1 O: e4 ]+ N/ s4 l2 g- _0 u /*通过指向数组的指针来对二维数组的元素进行间接赋值*/
2 m8 t% p! F* E1 i long (*pArray)[2] = NULL;
* K4 k/ H3 T$ z$ S olesaWrite.AccessData((void **)&pArray);
3 ~$ g5 C3 i- b* H$ H memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));
0 T, z7 t2 d* ^" R4 m% d. o- |0 ^2 L* _' @, `& V& g2 v& J
/*释放指向数组的指针*/
7 E/ ]8 Q7 j5 ] olesaWrite.UnaccessData();1 R7 m( j" R0 ]0 d+ N
pArray = NULL;
- _7 T4 D1 ]! W i
' G0 N# @. H/ V+ v. D /*对二维数组的元素进行逐个赋值*/
: Z$ Y0 ^: z, ?4 J5 C+ W% g" N long index[2] = {0, 0};2 D1 E* c! k( h2 e3 `) n/ ^3 I
long lFirstLBound = 0;
}3 ^4 b& A( } long lFirstUBound = 0;
$ ~: Q7 S; ]7 T( `) z: T long lSecondLBound = 0;/ V. l9 {/ a" X# |
long lSecondUBound = 0;1 y5 m% U% t3 G7 p
olesaWrite.GetLBound(1, &lFirstLBound);
8 W0 q2 p- I: P' |1 Y olesaWrite.GetUBound(1, &lFirstUBound);6 c' m( }; W! S* b
olesaWrite.GetLBound(2, &lSecondLBound);
6 O5 @5 K0 P0 ? olesaWrite.GetUBound(2, &lSecondUBound);
6 s7 v0 y5 Y# V2 K1 `. x for (long i = lFirstLBound; i <= lFirstUBound; i++)3 N; ?$ Y$ Y4 C5 t6 J& W
{
- P3 o3 n3 v( Z: B0 o index[0] = i;6 A8 i3 K1 p7 x
for (long j = lSecondLBound; j <= lSecondUBound; j++)
0 t$ Y+ L, |2 b% [. x {- g. t: a/ o2 E7 j7 E8 t7 ^+ y1 O
index[1] = j;
$ Q% O: V: n" g+ _+ J long lElement = i * sabWrite[1].cElements + j; * B# X2 P0 N2 y4 O& }
olesaWrite.PutElement(index, &lElement);
4 c, n$ L, X' _3 v0 y9 Q }$ ~- @) ^' d$ y* t7 s
}
# m5 J, p/ ?6 ]" M6 o* q# Y( c1 K& J: B2 Q% t- b
/*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/- l4 F4 J6 O+ i# d
VARIANT varWrite = (VARIANT)olesaWrite;
3 ?7 B( g1 j$ K" a1 q! y range.put_Value2(varWrite);
9 R* w: f7 T6 ?+ X7 f* F% x+ Q4 b$ T B% \% w
system("pause");8 l B/ w) f* }/ \4 a5 F( Q
; I3 |* T- a: T" o* k2 `+ S& M /*根据文件的后缀名选择保存文件的格式*/& w7 F9 a* ]; \6 F+ D! F8 [2 P
CString strSaveAsName = _T("C:\\new.xlsx");3 R( y( Q' ~/ p! N+ w
CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));
# E4 y# H. k6 a# E' {* H XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;8 q2 W# E+ w# @& [
if (0 == strSuffix.CompareNoCase(_T(".xls")))
8 ?3 f, a" n- S- u8 { { X7 M# c. U N G) Q, X5 s
NewFileFormat = xlExcel8;
7 O, h8 J- m {6 g5 c+ p7 y5 p }
0 Q% G1 i1 F. B2 q2 o( g3 _ book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, 1 K; k8 m9 l" j( L @$ b: O! f
vtMissing, 0, vtMissing, vtMissing, vtMissing, # x% q& R9 g8 h7 L {/ ~
vtMissing, vtMissing);
& k3 v- l8 p0 {# w. o
" w2 c' \+ [8 k; Q. c system("pause");" D* l2 z. N& D8 ~" n) q, s& A
/ f# i* D# ^2 c7 T! ~ /*读取Excel表中的多个单元格的值,在listctrl中显示*/
- Y1 J7 w% g/ {. Z8 n3 t0 G8 l* Y VARIANT varRead = range.get_Value2();
4 ^* e7 ^, s5 K COleSafeArray olesaRead(varRead);4 }. f! t+ E% |: F2 w# c
' K6 z2 z" g6 G& I! x0 m VARIANT varItem;
) R, K7 t1 a& Q5 X, ` CString strItem;* a3 P ~5 W \3 i7 u
lFirstLBound = 0;5 W0 q' k4 S+ y% f
lFirstUBound = 0;, S: c A) l' Y" i) q0 X
lSecondLBound = 0;
. ^% z. ]4 h2 Z2 ]# C lSecondUBound = 0;+ a! w w8 r1 H# c" m
olesaRead.GetLBound(1, &lFirstLBound);
2 N% E _- @& U& a' {4 O7 U% z, h olesaRead.GetUBound(1, &lFirstUBound);; `. m3 i+ q# f" ]% s7 U$ L
olesaRead.GetLBound(2, &lSecondLBound);
- Y; t% _9 Z# m' ~- u olesaRead.GetUBound(2, &lSecondUBound);, U# b( W" y8 B1 e/ W$ ~* j" l
memset(index, 0, 2 * sizeof(long));
/ ^3 b; f- X( c; [ m_ListCtrl.InsertColumn(0, _T(""), 0, 100);
2 p3 c) Q5 n: i$ i0 T/ c for (long j = lSecondLBound; j<= lSecondUBound; j++)# C1 ]' g Z, E# Z- j; @/ _; _8 m, U
{
, k3 b, [: y7 H; h# N0 v CString strColName = _T("");7 o1 T, F4 E' o# H! e; p) Q3 w
strColName.Format(_T("%d"), j);( R" S, r' c5 e/ \) S% W
m_ListCtrl.InsertColumn(j, strColName, 0, 100);, P) G+ e7 \' }* ^6 J- N; @
}
& l1 G2 a3 ^! f) o6 Y( U0 s8 w for (long i = lFirstLBound; i <= lFirstUBound; i++)
' F# F% F5 D, {. a! i( a {) [2 @- {$ P9 W% k3 b5 e
CString strRowName = _T("");( Z: H- ~4 n0 f; V' s; b3 d; U! T* Z
strRowName.Format(_T("%d"), i);/ s7 }5 n) v5 f* W
m_ListCtrl.InsertItem(i-1, strRowName);
: M4 k- l% Q/ K9 s
( I- d6 d" \' r5 `! P$ m index[0] = i;
' L' m4 s3 W' T: L G for (long j = lSecondLBound; j <= lSecondUBound; j++)
# E9 l2 M# Z. H% j3 ] {
" i: x9 i4 C7 { index[1] = j;
. [4 e9 q" |2 n6 f- L$ K7 j5 S olesaRead.GetElement(index, &varItem);5 G& ~2 [0 G9 s' y+ W4 q
, J$ v: l# p, s6 D, @
switch (varItem.vt)
8 p8 h( h% Z9 s6 F {. n# K, c, ?/ Y
case VT_R8:
0 J9 }4 F4 L( Q! @# e& A* h {+ v3 w/ B$ g8 J' g2 F4 Y# a! {
strItem.Format(_T("%d"), (int)varItem.dblVal);! r) z0 s* ] _
} {6 @, d* H, w) L9 `7 f
4 S1 s$ P2 P" U+ ~7 Z
case VT_BSTR:3 l* p2 c1 f. f% c/ q' j) N$ s M
{! z8 }' `- C+ r# L n
strItem = varItem.bstrVal;
2 f$ C1 x7 c* B* O7 x6 R }, U0 d5 B# G r: P9 o
8 O9 X/ I( H& [8 u* A
case VT_I4:4 n8 K9 A' ~) Z. g
{+ M9 W1 d& H, L' h& T% x4 r
strItem.Format(_T("%ld"), (int)varItem.lVal);
+ G5 L5 d2 Y' x3 t: j }
8 N. y3 P, V% _. S0 I; L: @- E! s7 O
default:, \0 H0 T! u* |6 e8 ^
{# j- M- G7 {# E! v+ q5 B
' J! Y6 q$ K( v1 t4 m
}& P: ?5 n8 f% O1 `: x
}+ H4 M0 E7 i2 W5 Y2 |2 { i4 @( ~3 @
8 u% Q$ o5 v6 {+ ]! W- n4 A1 V m_ListCtrl.SetItemText(i-1, j, strItem);
9 S" t1 ]# L$ R0 j0 N }, |+ d. a5 H8 x; T# x; E; ]
}
8 v p( q+ _6 e0 a, U8 B( x$ c
0 v4 Y; Z H+ {/ J/ l4 n- d
3 ~% C( Y) S8 U9 Y; y9 t2 m& ?% |" J9 j* | D4 K0 \: |0 `& \
/*释放资源*/2 |& N1 m; R) G
sheet.ReleaseDispatch();
, E# e7 S3 f/ y, b: [ sheets.ReleaseDispatch();
/ R- d( j- \/ }# h. v: Y" S book.ReleaseDispatch();
- f' I8 A6 z7 ]2 P; A3 [ books.ReleaseDispatch();4 T) @3 \' k1 {, X; j
ExcelApp.Quit();
W+ |3 D/ x6 K6 } u8 ?% f ExcelApp.ReleaseDispatch();
! X; h( r; `; Y$ f& Q0 \$ ^+ E) w, g: c% A
|
|