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