|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
通过VC实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文主要研究通过OLE/COM实现对Excel表格的操作。
3 w9 j' z; C3 g- ^
' Q; h8 `: O1 \0 ^- o& h! c本文源码的应用环境说明: C. b3 @6 e; t. Z9 z
Windows XP SP3
9 ^* k9 o# v# @ n/ l' NMicrosoft Visual Studio 20105 ]; [7 {5 K' x2 R/ ?. g# w
Microsoft Office Excel 2007
" W6 H9 o7 y5 b0 C
9 S; X& `# H9 P6 L8 f) d& k" B# e1、添加OLE/COM支持。
+ c" m# m7 x! f, X" Y* ^, A首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。8 ~; Z5 W$ \5 w6 ?1 u
本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。
7 f, ^2 R) A6 C通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。
" ^* Y+ F9 r/ b3 ]6 }! K#include <afxdisp.h> // MFC 自动化类
1 F" i; \0 E4 O/ @- k同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:
5 E; j) r4 m, S5 P! O W// 初始化 OLE 库
0 A, x4 p; C" i k, X# Iif (!AfxOleInit())
* G: t# `; |- q6 u/ c+ b8 o/ b8 \{3 j6 y; E1 t7 e$ k; P Z! ~
AfxMessageBox(IDP_OLE_INIT_FAILED);, L# a" E" i: S8 P0 a0 m
return FALSE;
0 h4 {$ t) C0 }1 g: f; e0 h6 P}
# r3 B+ s% N8 i2 T" o
9 v3 ], ?* q Q* D/ ?3 m# C2、导入并封装Excel中的接口
3 I# \$ D m7 gExcel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。; s5 t/ P+ }* P8 Q0 ]- r' ^: q1 Y- l
由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。
( o; z3 C, n4 m. z, i0 T" L5 lVS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择
, H$ P5 k: i4 d* H0 L& v& X* {$ H要导入的Excel类型库中的接口。
8 x. N6 t8 i4 d6 w' J' U# o/ m在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。
$ w) s, h, R" k/ ~ E " C c% @8 x% i# U
本文所导入的接口对应的类和头文件的说明如下所示:) X E, v. Y$ s* X0 `3 H& X$ m
3 F! p; [" T1 }, K& G5 u# M
Excel接口$ |5 M0 a& a- E7 ]
导入类
) @" X; }* p7 C" y头文件. {, {5 O- ~( r# u
说明
0 B& O9 O5 b5 j1 s* `' C_Application
. g. L3 } M" p& ~ W& T0 v0 FCApplicaton
$ D+ v+ d6 z+ h5 `Application.h
/ |0 O& V8 n5 p1 s( WExcel应用程序。
0 p# q" d% ]% n! f4 RWorkbooks
! P* v: [" U0 t4 kCWorkbooks* S/ }5 f, L4 P* A
Workbooks.h
' j* \5 j8 H: N: u1 d9 O6 V6 P) x+ Y. k工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。
' }( Q* A, N# J1 B_Workbook5 K0 d! }9 U; T( z3 f
CWorkbook! {4 O2 f- M9 r9 @+ E9 l6 \7 N
Workbook.h. T5 y+ E u: e0 k( h
单个工作簿。" }$ h1 }+ }1 c3 o" e
Worksheets
0 X2 U5 e' U# M. z3 V9 cCWorksheets
* u5 k# q I T5 TWorksheets.h
# F: {; ] @) J单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。
x, h, c! w1 P. J8 ~% J0 E( T_Worksheet4 c5 r$ d8 A/ c
CWorksheet$ h5 [7 c& m) H4 h3 Z# H
Worksheet.h
3 n% l! M) `) r4 Q, q单个Sheet表格。" R8 i/ M+ ^3 ~5 G# G" Y& {* J, r
Range
0 ]" b b/ }6 y( {CRange+ S0 D" ~& L. ~! ]5 v
Range.h3 ^- u: B2 k6 j S! o. \4 \
一定数量的单元格,可对单元格进行单个或多个单元格进行操作。
5 S9 K# C: t7 h% y
9 f) F( O. r& a: ~, q- @+ h/ M; W/ A3、导入Excel的整个类型库
9 p; o' P4 M' |5 j7 p- Q5 {5 P接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
! C3 Y1 A4 D( c' z) s% `" S通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:& m) i# E# O, S4 G6 ?9 R5 x. t
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace# M+ ?, W$ A3 n& a1 i
这行代码的作用是导入Excel整个类型库到工程中。4 X3 x+ f% {' ` }6 Y3 K4 f7 O9 h7 e/ |
由VS2010自动产生的导入代码存在以下几个问题:! q# O* Q, w5 A* a9 a1 V1 S8 ` J
(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。+ U7 v# E5 q Z- n) U" A
(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。$ `8 e) }8 d0 b G
(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。6 O4 a1 r7 c1 P; C( X
以上三点问题的解决方法如下:! I: ]: ^0 x; J l: g
(1)仅在_Application接口对应头文件中导入Excel类型库。* `# x& ]3 t: G% j2 ]
(2)对冲突的类型进行重命名。6 L& o+ |9 I! o) F
(3)在导入Excel类型库之前,先导入Office和VB的相关库。
# H$ U/ T! I a% J( \ Y更改后的导入类型库的代码如下:
% ~" W |$ v4 }# o% n( E# f 4 c1 h* d; A. q( J) [3 J, ]
/*导入Office的类型库*/2 n0 X0 c# W! h D4 [( C* i
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \8 O: F4 r$ v( {
rename("RGB", "MSORGB") \
( J0 U* n4 }! N/ x+ ~+ b: srename("DocumentProperties", "MSODocumentProperties")8 v7 x5 f! W* `; S$ e
using namespace Office;( }3 Z" w/ k( I. g8 P3 _' a- _( p$ A
3 f6 F( W2 y. T7 `( T; L2 j6 A" @8 W/*导入VB的类型库*/
" ]/ o) v: g; D' V#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
) g7 r. K1 C7 Z: D& musing namespace VBIDE;
: n: K( x: M3 H7 @( V3 ` 1 E! p2 Y3 }3 u9 e+ w" f1 ~% _
/*导入Excel的类型库*/
. x% B+ ~, |1 z8 S5 n# W; ^" y#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \
2 H+ k: K$ Q9 V* W1 S. Hrename("DialogBox", "ExcelDialogBox") \8 v1 M* u# e3 }9 ?4 l' n* @! Q$ K' r
rename("RGB", "ExcelRGB") \8 o$ e0 h, O% e4 @+ T+ B) k' i
rename("CopyFile", "ExcelCopyFile") \
* r5 {" @6 _* L9 h0 ]& ?% irename("ReplaceText", "ExcelReplaceText") \' }& f' Z, W* K( L4 X* Z
no_auto_exclude. {$ U' a/ n$ N1 x+ Y' O
Using namespace Excel;; B2 k; Z. q% M. x& ?3 \% S
! U+ X E) ]. }* ~" O
编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。
7 l! ~9 L* ]7 f$ O5 ]* g7 O , ^. k6 M# u! r C- q) ^! A* P
4、操作Excel步骤2 ~ T; G; `+ E+ r% h. i
操作Excel的主要步骤如下:' m; z5 U# m5 U; T0 q
(1)创建一个Excel应用程序。
( Y8 i3 I- @& h, K(2)得到Workbook的容器。
$ {% j- H. d9 l* i) K0 L& q(3)打开一个Workbook或者创建一个Workbook。5 d7 Z" K0 K8 w2 s
(4)得到Workbook中的Worksheet的容器。1 H+ x( {/ I! i+ B3 Y X
(5)打开一个Worksheet或者创建一个WorkSheet。9 _8 t; w" E; [ Z4 T0 z
(6)通过Range对WorkSheet中的单元格进行读写操作。+ f3 t- _3 [" I- A5 g
(7)保存Excel。7 v# C9 F ~9 X& p
(8)释放资源。
2 ^' d5 q, c$ `! _% p / n) y* @* M& O- }
5、批量处理Excel表格
9 n7 L: B! A) xVC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。
% d( {3 x: y( V4 L, f对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。
) S' ?) r3 c+ Z2 M) Y; YVARIANT get_Value2();
& }1 [3 s' {5 N( H$ Uvoid put_Value2(VARIANT& newValue);$ _; N( w# t2 c! x! G
其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。$ e' d' O# e Q2 K2 g
其中,VARIANT中实现二维数据的方法可参考6 F/ \; j- }6 x/ C( i
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html
% I: {- J1 k1 T, Z: m7 V6 t当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。$ H9 ^; a& {, l4 L& ^
( A" ]5 g: x$ N8 U$ o2 m
6、Excel表格的保存
4 S" E7 g, B6 w% E% o& A" Y; q(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。
' H0 V3 z& F* l' h(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。0 e7 q$ `% G' ^- l
SaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。) ^$ ?+ T7 l7 }7 m/ n
Y& s9 `% b, }; ]+ I7、获取当前Excel的版本5 C; W9 Y6 L( ^% v! E
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
& H( i9 f. b8 s) I/ } & w9 f! L! u5 z0 T4 m7 b
8、示例源代码
7 j6 t1 `6 m9 W4 V, X5 x+ i3 `. U+ A主要代码如下:
8 e% n0 P: j8 m( r$ u
) J# z/ O D; `( k8 Z# n' m$ Q
$ n4 U0 U5 S4 ]" W( `3 U/ }8 f5 ?" l$ q
m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);7 y) P8 t+ A/ n5 L& T
5 p$ T, E9 ^0 c1 u" q
CApplication ExcelApp;
3 d5 N2 j/ C. [# A& b" G- X' i- X5 s CWorkbooks books;
0 w" f: K5 g/ c- z- a" [# [ CWorkbook book;
* U- |# _- {5 T3 g$ Z ? CWorksheets sheets;
% v v6 i' |- r9 c CWorksheet sheet;
% _# z7 e2 d( y1 L7 U. Q# Y5 i! \( R CRange range;; p/ K h. H: _. A9 |8 n
LPDISPATCH lpDisp = NULL;
2 L+ R3 f5 v( C6 }5 R9 Q% f: z8 N/ \! l
//创建Excel 服务器(启动Excel)
2 v5 R0 ^- D4 k7 `8 f3 @; Z if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))
5 |3 T' l, l0 C+ \ {
! n& P5 z/ f% P, |0 y AfxMessageBox(_T("启动Excel服务器失败!"));
4 I/ T& [: L, [9 F, C return -1;& n! x3 B0 H8 T" f1 ^8 q
}
8 P' T; K5 x. ]1 z- i8 E- `
: W5 M8 Q6 E; M, Q* a* A0 J" i /*判断当前Excel的版本*/
/ D T/ a' h, A CString strExcelVersion = ExcelApp.get_Version();
# a; Y* r7 [+ H: @ int iStart = 0;7 r$ L+ r+ d( r; j" s' i
strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);
6 j: g/ U& ^- J f if (_T("11") == strExcelVersion)6 |$ X! B7 l! A5 m0 t
{ m& R: T( R. t8 }0 G
AfxMessageBox(_T("当前Excel的版本是2003。"));
- J- |- X2 I5 r" h! i. I7 ` }
% h5 q7 b7 ]( Q2 U: @4 K- | else if (_T("12") == strExcelVersion) C/ T5 M( z9 E7 B
{
. a2 S' r9 `! F5 h& N* g7 G AfxMessageBox(_T("当前Excel的版本是2007。"));" C. z k" d& H l
}& D6 l {! D' D
else
" X' m$ h* O) @; S3 s {
) z8 O0 \0 f' l* [( [* I: c AfxMessageBox(_T("当前Excel的版本是其他版本。")); C* ~* q" {. _$ o! q, {' `3 A# J, d
}
& t7 z8 x* S# U3 c
9 @+ ~3 a- l' z* c, C. j' { ExcelApp.put_Visible(TRUE);/ N. E6 Q8 W/ P% _$ p( R9 f1 L; H
ExcelApp.put_UserControl(FALSE);7 y& _" E$ B8 i0 ]2 K J$ z
$ r$ m I# }6 A* ]" I
/*得到工作簿容器*/
! y( }2 T: Q6 {5 B books.AttachDispatch(ExcelApp.get_Workbooks());5 s0 [* U' ^3 T# C5 Z
) Y+ S$ C+ O0 x" x( c
/*打开一个工作簿,如不存在,则新增一个工作簿*/
. e; [7 ?/ q) q: }3 o( i/ U CString strBookPath = _T("C:\\tmp.xls");
7 |) _) ^, w0 M try: p! S$ Z$ _ r
{+ f' B! y# ~# {. l" D, X3 N5 ~
/*打开一个工作簿*/- z' `& N' U1 S0 w! f9 [) B3 e5 @
lpDisp = books.Open(strBookPath,
; N& E0 M, f6 u* d7 m' R2 U vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,; q8 m. y' `) n# w' D
vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
8 M& g: l5 X) t' c' ~. P vtMissing, vtMissing, vtMissing, vtMissing);
. m- ~. `# f2 @& t; q7 a e) Y book.AttachDispatch(lpDisp);
: z, U' W& w. L1 y }3 K1 E7 X/ x/ l5 i; H$ M2 [
catch(...)3 Z, u) p8 n4 r; i
{, C8 l* @& f$ Q8 a/ D
/*增加一个新的工作簿*/+ ?* Z/ B" A; l- A% z) U' }
lpDisp = books.Add(vtMissing);% o+ s& ^/ a- D/ j6 |
book.AttachDispatch(lpDisp);. u/ J" {) r( t6 [
}
, Q; G) @' ^- _( @0 N. x - `" R5 E5 I* M Q
% m6 v/ Y* |% h9 a6 Q' i5 ` /*得到工作簿中的Sheet的容器*/
) `/ B+ m3 F0 H& b8 F+ S sheets.AttachDispatch(book.get_Sheets());
6 T( K' c! T. P1 e* V+ v
6 ^" _9 u- l7 O! s! ?0 h6 G# J /*打开一个Sheet,如不存在,就新增一个Sheet*/
5 w* z c" U8 r! H7 k CString strSheetName = _T("NewSheet");
/ S v) h ]& g+ J! O) X4 G) n. t try# e' ~$ ^! f' B0 \) s, u
{
$ a1 g1 ?4 K) Y5 f /*打开一个已有的Sheet*/
7 |! I, k5 S% q2 o o: Y lpDisp = sheets.get_Item(_variant_t(strSheetName));
& t. k/ n: g) a2 m sheet.AttachDispatch(lpDisp);
* {' z7 K; k5 L! |7 K }4 l% v- @0 L( l% m
catch(...)7 | L* Z; o: @, K/ ?. d
{0 k, \0 p9 B$ @( D/ Y+ x$ ]
/*创建一个新的Sheet*/5 F4 U3 i% `7 T) j
lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
* a8 |, E2 j- K8 ~2 @0 p sheet.AttachDispatch(lpDisp);
& [/ |6 S9 Z$ ?$ ~7 ] sheet.put_Name(strSheetName);
6 [0 f2 T0 B3 o) l. } }# T; z$ Z3 f3 s9 X, X Y
. p' c) `' I( U) @ system("pause");
; Y: g( ~4 ~( i* f! j1 M, l0 P+ ]8 x v1 d, B
/*向Sheet中写入多个单元格,规模为10*10 */9 a; `: {7 D" u9 Y f
lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));
, n. a) j2 t8 `2 r# e5 b range.AttachDispatch(lpDisp);( y6 v+ U7 H- l& O. W
8 W* I- T9 w# _+ d$ i3 o1 A& V
VARTYPE vt = VT_I4; /*数组元素的类型,long*/
9 C6 ]! r# d7 U1 v: t2 E SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/: G1 x8 f+ D2 w7 X) E
sabWrite[0].cElements = 10;
+ q6 X/ H+ Q9 w% P( p$ i% t7 } sabWrite[0].lLbound = 0;' b7 Y7 |9 f& C' p7 w3 c4 W# ]- y, E
sabWrite[1].cElements = 10;# n7 a( d9 ~9 _( @( C1 Z
sabWrite[1].lLbound = 0;. E A1 J1 v/ e$ ?; r" N& J
( X1 B7 x- F% m/ w COleSafeArray olesaWrite;+ {* p" C, H C7 S B8 t
olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);
6 o+ Q3 Q" S" r% }
/ }1 c$ C% h4 q /*通过指向数组的指针来对二维数组的元素进行间接赋值*/, i# z/ S' [8 n e/ L
long (*pArray)[2] = NULL;1 X( o$ l* W! l; u3 {5 _
olesaWrite.AccessData((void **)&pArray);& @1 U: ]1 A9 }7 s4 v! G
memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));* W: ]$ e6 l5 I( e
! j* y3 e4 L7 ^- }: y
/*释放指向数组的指针*/
% _: w3 [" z. P% k8 f9 ?% F olesaWrite.UnaccessData();6 J, g0 I7 t0 c* @$ u6 X0 T1 }
pArray = NULL;9 V# \9 ^7 t/ P z _6 `! D+ T
; L) O( g' P8 g: b /*对二维数组的元素进行逐个赋值*/" C9 V& e0 n, B
long index[2] = {0, 0};% `6 J( Y4 S/ h. x, q$ x" [
long lFirstLBound = 0;, @( t/ T+ {: g+ ]
long lFirstUBound = 0;
; p+ r3 E- @4 V7 Z2 |5 @% {4 W long lSecondLBound = 0;# o5 W% A7 x1 H; p- h+ |
long lSecondUBound = 0;
* i" g( b# [) F: k% N4 | olesaWrite.GetLBound(1, &lFirstLBound);2 W+ f! D" E7 I5 `
olesaWrite.GetUBound(1, &lFirstUBound);; e9 @. Z7 v: O6 J. x# Y! W
olesaWrite.GetLBound(2, &lSecondLBound);
" h& W0 y: f0 G# u- [/ {1 B$ ? olesaWrite.GetUBound(2, &lSecondUBound);/ C0 S. `( w) M, I
for (long i = lFirstLBound; i <= lFirstUBound; i++)( A' b5 e; ]! M, U; s. o$ f4 n2 I" v
{
9 B7 n4 e% A4 |% |. [# b2 ~ index[0] = i;$ h/ z9 A1 l% V+ w" V6 {
for (long j = lSecondLBound; j <= lSecondUBound; j++)3 R: e# o) z. o5 Q% P# P* c8 e! u
{
0 J0 s; ]# I5 i# W index[1] = j;
9 d b! {( R, y$ u" U; B* K long lElement = i * sabWrite[1].cElements + j;
4 ]$ v0 J3 G& S$ W% { olesaWrite.PutElement(index, &lElement);
' i/ `' T# a. h; _& y' [2 R: h0 ]4 H% o! Q }/ q3 k$ s* z5 g( d
} s) [* `3 _2 @7 D
: Q2 H2 K: ^3 x; Q2 K* @5 C- X
/*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/
2 V' _. ?2 i7 H# h VARIANT varWrite = (VARIANT)olesaWrite;
7 o% `5 q8 g+ y0 |) u range.put_Value2(varWrite);
& {' k$ s% X8 Z/ P; ^
, D+ g, _ ~& F M: f8 t% A- Q. x0 H system("pause");" V5 H" z7 I/ P3 r
) r. {* |# M1 w9 \ /*根据文件的后缀名选择保存文件的格式*/: _9 J$ ~; c. L; C2 @
CString strSaveAsName = _T("C:\\new.xlsx");9 h) O2 L7 _0 m/ z$ @/ E4 D
CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));5 n5 f& L/ x' s
XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;* O. o( G( i( L3 U$ h6 g1 y
if (0 == strSuffix.CompareNoCase(_T(".xls")))
, _1 \! S) A3 M; r4 V {0 F! S( L- n# h6 f3 ?2 Z
NewFileFormat = xlExcel8;
2 P* Y2 U6 }4 {) N: t9 a }
/ [5 l2 J5 s1 v5 ~ book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing,
5 Z5 E! ` Z/ w$ i vtMissing, 0, vtMissing, vtMissing, vtMissing,
; m4 k/ K' T4 v! H vtMissing, vtMissing);- s1 \ v% d# T: E9 z ?
c5 Q2 Z4 `) c) s5 H( [" A system("pause");
1 s/ G l: k1 h. S
2 d" D+ s. Y+ X4 w+ H( z: F0 s /*读取Excel表中的多个单元格的值,在listctrl中显示*/1 s @, o7 ?+ f: Q' J9 C y3 [
VARIANT varRead = range.get_Value2(); U5 ?2 {# i" m$ J
COleSafeArray olesaRead(varRead);
( E- f! c! R9 b
$ E, Z: s1 v% o8 _; v# U( X2 n VARIANT varItem;
: T& s. N' _! T; T% q% b# V, _3 y CString strItem;0 A$ J, ^; ]2 |6 g2 c$ `
lFirstLBound = 0;
1 R% k J4 {6 U' `: c$ W2 t lFirstUBound = 0;
5 \. _8 o: F; B. E1 G lSecondLBound = 0;5 _3 ]0 D) T1 Q& `9 Q0 B" d
lSecondUBound = 0;4 K' ?) |4 k4 D* y& S
olesaRead.GetLBound(1, &lFirstLBound); s' W" E0 X! W) n9 w/ D. E9 s! S
olesaRead.GetUBound(1, &lFirstUBound);
: P% a" L6 Z3 ?7 J# i olesaRead.GetLBound(2, &lSecondLBound);9 P' {, G3 g7 K2 y$ U& I/ U
olesaRead.GetUBound(2, &lSecondUBound);
/ Q! X, V1 ?8 u7 i/ B memset(index, 0, 2 * sizeof(long));- W' K) f4 \3 i9 q8 F6 Z
m_ListCtrl.InsertColumn(0, _T(""), 0, 100);
9 W! ]; I( ]" r3 D& a0 z for (long j = lSecondLBound; j<= lSecondUBound; j++). W* W0 M! C" @" h0 ?5 B
{( L( ~& u4 a7 J1 z
CString strColName = _T("");
8 o5 I5 b4 u4 G+ x5 i( a2 ` strColName.Format(_T("%d"), j);
C0 u0 [2 y4 b( \- t n m_ListCtrl.InsertColumn(j, strColName, 0, 100);$ U1 z1 ~2 |" C/ U
}7 }' T2 M4 i1 r, X
for (long i = lFirstLBound; i <= lFirstUBound; i++)
, o( K! o a9 w; ?( }3 a1 p {
% i& i8 N& ?3 R$ i% Z( A CString strRowName = _T("");
8 b* X$ N' @+ n' }0 D1 Z( s strRowName.Format(_T("%d"), i);& `. W1 w) x. j' s1 N) r
m_ListCtrl.InsertItem(i-1, strRowName);
8 _- c/ ]5 k4 k h: X7 U0 r) p: Q) u( K. V/ x# f& G
index[0] = i;
+ @9 A `, C: Z, y6 S& n for (long j = lSecondLBound; j <= lSecondUBound; j++)
' ^9 r4 \. x; \$ I- L- z) A { C# O" g/ c9 b# }8 ?, }
index[1] = j;
9 ?9 \* j: E5 V6 y, a olesaRead.GetElement(index, &varItem);) S; l; [8 J( \( ^4 n; q) @" a
5 x) ~0 ?8 _ u" f/ a
switch (varItem.vt)
4 w1 k G) U# R9 I) f {; O& f- J2 u* w' h6 G
case VT_R8:
, `5 W- g8 z7 W) m {
0 V7 r; L7 g, @% F& f9 b) v strItem.Format(_T("%d"), (int)varItem.dblVal);
/ K/ r' Y. n1 e/ i! k }9 \, u0 Z( N" x7 e/ ]
$ Z! Z2 k$ S$ C+ }/ _! O case VT_BSTR:
5 F' J: c' s2 T+ i9 I! e {
" l" Y8 i: N J( r' \$ m9 ~! K strItem = varItem.bstrVal;3 a8 j# A( P( r) n! \# ?
}
" [8 f0 ?4 R' {" Z) ]' K) P* ]8 }* W1 d6 t
case VT_I4:
: k0 {. Z0 U) r t/ z9 ] {6 L7 b: g) s: V5 T9 K
strItem.Format(_T("%ld"), (int)varItem.lVal);
0 C. G) `- d7 I2 X9 u2 z. M) J2 ? }% N/ d7 p9 O& r6 t& a
C) _! [: o/ Z0 x9 b2 c default:% ~9 [! {% r. P3 f% P2 {6 c; B; }
{- M( j0 N) s6 |
3 Z8 |1 o! @$ G& c }* B0 N* Y9 D: V6 W; ^4 p$ w: z: h7 k
}1 @* b. h4 q9 v) j" f) K
& I; C& l, @9 s5 S9 E$ f m_ListCtrl.SetItemText(i-1, j, strItem);7 i# U) m. B5 H D8 H- y+ W
}
+ y" [$ M4 b" z. j5 K8 [7 Z, D }
! a+ l1 i6 r: R8 D
3 m5 x+ b! N( v2 w0 ~" f3 J( L% x& q2 v% K" s- ^/ |$ @6 L
8 X1 ?/ L' \. v( u9 h9 I /*释放资源*/" J1 }' F) M8 R: Y5 l' n
sheet.ReleaseDispatch();2 n( `$ B. ]4 U7 I/ a" k
sheets.ReleaseDispatch();4 q9 X1 _; n5 a8 s
book.ReleaseDispatch();
- ~2 c8 [+ k/ E: Y9 o books.ReleaseDispatch();/ W+ i4 g5 ]( u; x$ B# x
ExcelApp.Quit();8 ]0 Z; F; g# ?; j" ~7 K' W/ c
ExcelApp.ReleaseDispatch();
5 p" c# k# e T4 k
2 O) b, G& t1 V/ Q" [# ?7 w |
|