|
|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
通过VC实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文主要研究通过OLE/COM实现对Excel表格的操作。! S N: Q) l! `2 s
7 X: E9 a* h. k8 f0 N! F8 r/ z I
本文源码的应用环境说明:( k, N) `1 Y* R$ D5 X' ?
Windows XP SP36 ~' t% W8 j( I; u! A
Microsoft Visual Studio 2010
9 t2 R5 G$ M; {; f2 Q* ^$ h6 zMicrosoft Office Excel 2007
! E" Q4 _. G2 b# c5 U 6 P7 J g# b: ~' o! P: ^
1、添加OLE/COM支持。* C# S* g1 ^% Y5 L6 ^- v/ h
首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。. y0 H+ K9 }* n9 H; b* Y, |: p
本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。
' Q( {: l% |5 a5 L) E通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。5 `$ |3 z$ E% p8 }6 e" p! V9 M
#include <afxdisp.h> // MFC 自动化类
7 M$ c; \" |4 b) O同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:+ E1 M0 `9 d, F! w8 U! A7 a* }
// 初始化 OLE 库1 W: A7 ~( a+ C
if (!AfxOleInit())6 v! p {0 x: a: C
{1 ^: Y `* ^: _! U7 z
AfxMessageBox(IDP_OLE_INIT_FAILED);
$ b8 O# k$ o3 a) \/ Vreturn FALSE;5 _/ Y: v; b( `$ H" M/ E
}2 J8 I$ v0 W7 P7 Y% M
6 a8 N2 P, k6 `8 k' l
2、导入并封装Excel中的接口" D0 S. Q: g4 V8 M
Excel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。
/ }; B! f- A3 c) ?) i' a) G3 M6 _由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。
3 f/ o6 q: z' x: E' {% JVS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择3 G A3 p$ q* r& v, L% n
要导入的Excel类型库中的接口。
; ], j+ `, ^: H0 v- p在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。
5 [. s' a, m9 n, u6 X1 G6 Y
7 W4 y+ Z8 U" e6 w/ ?+ Y本文所导入的接口对应的类和头文件的说明如下所示:
' B9 [6 o% Y7 d- w% j
' o, g% n [: z1 m6 d: @( t' i- @Excel接口
( R! T7 d. r' o0 Q/ L5 v J导入类
! b/ X! |" v) i( Q) F头文件
# |9 B/ s& J) W% j/ W9 [说明
/ ?9 K7 z& {% v! q: c, P) \_Application3 s0 N" o$ k! l+ G5 q
CApplicaton
. g, ~3 I- Y& ? JApplication.h
+ e- h8 F9 M) F7 KExcel应用程序。
% v9 T" r4 `/ fWorkbooks O1 m2 D# l7 G( e1 R
CWorkbooks
( s/ D7 \6 z/ z/ `9 a ^Workbooks.h% } F3 e" e, k8 ]7 ]% R" Y
工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。5 [+ g6 e0 }8 |
_Workbook7 w8 D* R$ n) k' ]- O2 ~
CWorkbook
- l9 Q$ F# M. I2 [" f: P- k6 tWorkbook.h0 w3 ~/ N8 [/ E& Z4 u3 O; u! H
单个工作簿。& ^) f1 x" n2 M4 g& h: F, D4 I
Worksheets h( g4 J' R: p# t- @
CWorksheets
6 U, Y! X& A# v" ~Worksheets.h3 M, L( o h8 o
单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。! D/ E( z6 ?# ?/ b! q
_Worksheet9 N- ~2 N) `8 P0 v- m! m3 A) f+ q
CWorksheet: J( G' n% ~7 `/ l- l$ e+ G
Worksheet.h
8 H# c) l* Z0 O. [0 r+ T单个Sheet表格。. I. G& H5 [1 c+ M5 u: [( o7 l
Range% t- ]2 S" ^7 v" W8 U
CRange1 I* D- A Q% x) \2 Q
Range.h$ y/ T0 C; c3 A: W
一定数量的单元格,可对单元格进行单个或多个单元格进行操作。& D/ M2 m. T- l* x" P, u$ D
# @" C5 n5 [" q) |
3、导入Excel的整个类型库9 c% K& M+ @4 Z: U) ~$ z* z
接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
2 E3 o F% m( H8 J5 [* ?9 |通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:
X4 e: }' b. m7 `3 e. ?#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace; Q& T! V* `$ _. ]
这行代码的作用是导入Excel整个类型库到工程中。( W: B" x9 G, [
由VS2010自动产生的导入代码存在以下几个问题:7 y* X! f9 H- o% i9 j
(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。6 v: u; V9 Q: L! c- [6 h7 M
(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。
i/ q$ T' c% t/ ~ j, D+ s0 l(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。( s- w7 y& n3 r
以上三点问题的解决方法如下:
- Y7 F7 [1 S8 W2 N(1)仅在_Application接口对应头文件中导入Excel类型库。
6 P' o* V! d6 j6 ]( ^/ X. i(2)对冲突的类型进行重命名。 A5 J; |* q& g( C! v3 }: A0 ?
(3)在导入Excel类型库之前,先导入Office和VB的相关库。
( `9 C7 G, d9 [8 ?, P- L/ m更改后的导入类型库的代码如下:
" P& A S! B( {! l, E# I
' C9 D2 t# l3 V7 D& u# x/*导入Office的类型库*/3 i8 v* ]: M$ R6 w9 J& |/ A) P3 X
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \# A' G0 O# F' z# P
rename("RGB", "MSORGB") \
0 C0 ]/ P, C) ~2 }9 K! Wrename("DocumentProperties", "MSODocumentProperties")" d5 x) \! l2 I
using namespace Office;
; h U- h6 ^* s3 R
4 H3 C) H# p- ~7 w6 U- J; I! ?/*导入VB的类型库*/
6 J. k- u& Q, x: W$ P: Z" V) U#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
4 B' u5 n/ u8 M# }) c$ {; t5 n$ qusing namespace VBIDE;
! V* c9 e6 Q% u) g7 z& e
9 v* ]2 f8 Z! P- e% |8 R! [& o/*导入Excel的类型库*/7 F T. p% y4 i$ t3 g
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \% p" H% M- ?& W& g; X; L
rename("DialogBox", "ExcelDialogBox") \
0 [) q5 e. d- |5 jrename("RGB", "ExcelRGB") \8 U+ w1 E( ]* Y b) x6 v& d
rename("CopyFile", "ExcelCopyFile") \
1 Z% H0 v U$ ^, D Y! u8 qrename("ReplaceText", "ExcelReplaceText") \
4 f4 H* X2 R$ o: L' e* Vno_auto_exclude" U+ O- T2 U1 H& o" t9 `
Using namespace Excel;
/ K/ w0 s) H4 h. t( M! k
9 d ~8 Z: `! ~$ m编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。# R0 H& I0 L; e$ Z1 }
( `7 [7 X, x! o) N9 g4、操作Excel步骤# E. n& b& {- B2 [8 D. x/ l% F9 C8 ~# O
操作Excel的主要步骤如下:. h8 o$ G. ~/ U( D( j }, ^
(1)创建一个Excel应用程序。0 t1 |- ~% v& n' \: f; a9 g# S
(2)得到Workbook的容器。
4 O7 M3 D1 S3 _$ H$ m8 @0 c(3)打开一个Workbook或者创建一个Workbook。" d* k) ]& f+ M2 S
(4)得到Workbook中的Worksheet的容器。
6 [+ J0 X" b: ?& l% p" N: m6 f(5)打开一个Worksheet或者创建一个WorkSheet。
# O3 m3 h+ v4 E(6)通过Range对WorkSheet中的单元格进行读写操作。
% u$ G5 I; i+ j(7)保存Excel。
' b: y4 V l# r( K% ~0 L, U8 Y1 F(8)释放资源。* ^; s }% [; S2 Y
8 o1 U) H# ?5 I& @4 _5、批量处理Excel表格
$ i- W* w7 P1 W7 }9 Y$ FVC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。
9 O$ B3 Z/ z' E: _8 p8 J对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。
6 \# w% X0 g. cVARIANT get_Value2();
- G* B. p1 Y, Y# |void put_Value2(VARIANT& newValue);' ^) {; q) x& D! T4 u% T
其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。! l/ t3 B' l" n% A9 z
其中,VARIANT中实现二维数据的方法可参考0 _: R" N5 S* Y% i7 } b3 P/ S
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html, |8 s6 B/ d! w u1 a9 q0 ?& ^
当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。& _- `8 H' f6 B4 r0 Z: f
' d4 B5 J* ^- T
6、Excel表格的保存
9 U0 X4 X1 m% ](1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。
# v6 `/ {) ~$ s/ i(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。
4 E& f: [. Q& SSaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。, \, A [% q1 S; w
1 i+ P2 U: ~5 E* f# x7、获取当前Excel的版本( B/ ]$ e& Y8 \6 D* K
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
& Z0 W$ n; Y$ n5 I4 ?$ a $ Z6 K% F7 ^1 y2 o9 d* f0 k
8、示例源代码
; g% G9 x& h3 U6 _. h2 [( N主要代码如下:
5 l4 L0 R" I8 w+ l% V9 P" y) ` 7 Y' Z. Y# f' F
( s! h& Y% D% a* O% K
3 x, Y; B. l# {
m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);
" ?/ G0 l Z" Z; h9 I+ D* H) [' @% Z7 A* f$ [. j
CApplication ExcelApp;" l4 |0 v) U* G7 x
CWorkbooks books;' m( s6 _- d. G( c$ P* f n3 @
CWorkbook book;1 }: ?3 z( |" t
CWorksheets sheets;
|5 z5 A4 d% D' g N& B+ S( ] CWorksheet sheet; c: _# @ e! o" s4 R4 u
CRange range;1 C4 Z; b7 ]& @! S8 ~6 q
LPDISPATCH lpDisp = NULL;
( S6 n1 ?- s! q9 V/ f: P/ X& b3 M) j4 q
//创建Excel 服务器(启动Excel)$ k( `- j+ L- |7 k8 U- z4 b- x
if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))
- c4 i# R& `; B* M {
2 w, L5 l" [6 h3 h, P: x' n AfxMessageBox(_T("启动Excel服务器失败!"));
; l2 u; S) ? X0 h" L return -1; t" C% C5 w) H% v
}2 d9 C' u6 u( E$ Y4 ]6 x" ]
9 B, F+ ^6 N {/ X' H$ F7 z) w
/*判断当前Excel的版本*/9 B9 a" D: Y' k, a1 t6 M* }
CString strExcelVersion = ExcelApp.get_Version();8 U9 x8 ]6 t; L+ `: n- ~9 j' J
int iStart = 0;
+ g# T. C0 m5 S5 _6 I% W strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);
8 F5 \2 m5 s: n if (_T("11") == strExcelVersion)
+ E: H9 g! u6 m4 v. a7 \, i {; K9 w" Z) q& z% P+ c% f& Q. `$ a
AfxMessageBox(_T("当前Excel的版本是2003。"));/ |% E4 i& Z! j1 U, C
}
2 C" s8 e: p& B3 r( t else if (_T("12") == strExcelVersion)3 f: B& i `) U% ^0 [! h
{
7 p# H0 @7 f' R& V; q7 w- ^; h* m AfxMessageBox(_T("当前Excel的版本是2007。"));+ I7 {( H, t3 f; ]4 C
}) o8 G# n# j; Z6 ]7 J+ `$ V* z
else: E% o; p/ v3 r2 B \
{
+ |# D1 H7 A* K AfxMessageBox(_T("当前Excel的版本是其他版本。"));5 \; H1 E V' u5 h! Z9 e0 F2 {1 F
}
8 O- {& q, G$ }7 [& H- L. o+ s p7 p% t" `
ExcelApp.put_Visible(TRUE);
; z* f3 d( C, E8 J+ ^7 G, h ExcelApp.put_UserControl(FALSE);# q) u& J2 B2 Y6 C& k% r1 Q; z
& j/ [# [4 M/ D0 }# s /*得到工作簿容器*/
! {2 w" Z; M* c+ ] books.AttachDispatch(ExcelApp.get_Workbooks());) X% \4 Q) _2 X J
2 |: S' Z4 I! f7 V5 l6 V, |+ d /*打开一个工作簿,如不存在,则新增一个工作簿*/
: G. p+ Z* v* K, \' w CString strBookPath = _T("C:\\tmp.xls");$ I8 E1 O: Y2 c& e9 V5 t( W
try" U' A: l2 S) S4 n6 V0 Q$ \7 M
{" S- s2 E/ Z( o
/*打开一个工作簿*/0 ], ~+ Z7 G D. b
lpDisp = books.Open(strBookPath,
2 E5 U0 N( ]6 O/ `' }- q vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,: f6 h' J2 Z: T( k* Y9 q' C* U
vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, ) {% d* w2 n7 n1 T" Q
vtMissing, vtMissing, vtMissing, vtMissing);
0 S \& D% u2 N2 C* {. v1 _ book.AttachDispatch(lpDisp);/ a" W9 {# u5 g2 y
}- C5 i4 g9 R( i+ ~; I: a
catch(...)0 @, k e* S2 Y7 M8 Z
{4 R- }7 B+ o6 ^$ P
/*增加一个新的工作簿*/
7 P6 T' S- B. q/ l lpDisp = books.Add(vtMissing);
\8 @* `/ ]1 G/ Y" D book.AttachDispatch(lpDisp);
% L7 Q( Y! V& G" [! @ }
6 b9 c5 q+ A2 P/ s/ B - L- u7 [8 e) H4 U p" o/ U& m0 N; J
* k* W; Q o8 z" q
/*得到工作簿中的Sheet的容器*/, D" \/ g& ?$ r. _
sheets.AttachDispatch(book.get_Sheets());
9 K$ J" I" K& Z; }
! g& ?# x: i* C! B /*打开一个Sheet,如不存在,就新增一个Sheet*/' ]; t, W2 N/ r" t. U8 A
CString strSheetName = _T("NewSheet");3 V0 v; T& _9 N* f5 {! D- A
try s- D0 ~! }" ~2 k
{' _) h# W. F8 ^: o+ d* W
/*打开一个已有的Sheet*/
; {( @6 Q$ r: O9 Q lpDisp = sheets.get_Item(_variant_t(strSheetName));
8 y- s6 j! D+ ^- W, P; Z sheet.AttachDispatch(lpDisp);9 h/ k1 v3 b ?0 G: q
}' {2 A. w7 r/ d1 s$ \' h9 Z
catch(...)3 O! J" A) V8 y7 J. ]4 u$ r% b8 m
{
9 V! o R* o& f) y! ?, R- y6 ~6 A& V /*创建一个新的Sheet*/
; C& _; w* n1 R, @' Z; j! { lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);0 p Q9 j9 R i- }
sheet.AttachDispatch(lpDisp);
; X) Y, z" G9 g5 P* `2 k sheet.put_Name(strSheetName);7 Z; j( u/ V8 |& O
}' M( h9 a( B6 z/ Y; ]
1 }8 t8 H, d$ {: E1 ?% y: {2 ^
system("pause");( |/ I+ l. p7 ?9 F O) I/ C3 X! V
) H8 I9 ^5 G, C3 Q0 ?4 m /*向Sheet中写入多个单元格,规模为10*10 */
0 j6 O4 y6 i" i$ c9 \. d$ G lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));' {7 L9 V) q! [6 V( R$ V" I
range.AttachDispatch(lpDisp);
7 K" c# a- |4 S6 O3 L1 u. F3 e A: U/ {/ S5 T9 ~% c4 K: }1 r
VARTYPE vt = VT_I4; /*数组元素的类型,long*/1 m/ m1 S0 g2 A7 d$ [
SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/
6 {/ _+ L& I! p! ~9 B& h sabWrite[0].cElements = 10;( B+ U( i/ Z$ o
sabWrite[0].lLbound = 0;
% Z' c% j- d2 B( u# ?; e, Q sabWrite[1].cElements = 10;5 E6 l. i' T# A, e6 t5 n
sabWrite[1].lLbound = 0;
6 a! i0 [! e$ |2 `) w. p7 U" S2 l% a6 c; o* n
COleSafeArray olesaWrite;9 y5 e2 i' s6 S
olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);
$ I; G4 S$ [) e/ i8 h( g
1 M$ {5 q1 ~- j7 ~$ Q4 ]* C, F /*通过指向数组的指针来对二维数组的元素进行间接赋值*/: r! {- Y7 J" s1 \
long (*pArray)[2] = NULL;
' f- n' H0 p2 H. j) I! D olesaWrite.AccessData((void **)&pArray);' n; ^4 W& c T% }# C
memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));5 C7 }% P5 D2 n H1 o
# l7 ?0 m4 `! N
/*释放指向数组的指针*/
N, C! ^ C& q; O* R: a* u0 M olesaWrite.UnaccessData();1 J$ B/ a4 V; s. I) `& j* Z
pArray = NULL;
& P% O( K" g4 f7 N7 c* B1 \5 I/ d& D
/ I. c4 T7 M% i( w! g6 V /*对二维数组的元素进行逐个赋值*/
6 D _7 Z# [/ h* y long index[2] = {0, 0};
6 h+ s+ j, S1 K& ?3 B: P. ? long lFirstLBound = 0;; E; }; F, x) ^" |# }; `# B B
long lFirstUBound = 0;
7 g R5 j* X# B: g1 P; S long lSecondLBound = 0;
3 k1 q: o& ?7 }' }4 [0 M6 s& S0 h* O long lSecondUBound = 0;: V0 y. V, r/ i0 j- Q7 L7 I4 O$ F5 c
olesaWrite.GetLBound(1, &lFirstLBound);% m$ ?; m5 S% e; x9 C
olesaWrite.GetUBound(1, &lFirstUBound);
3 k! d$ f4 ~' i' z: u! _8 E% S7 Z olesaWrite.GetLBound(2, &lSecondLBound);/ w/ `2 [3 W z/ ~( U
olesaWrite.GetUBound(2, &lSecondUBound);7 L L7 Y ? `$ }
for (long i = lFirstLBound; i <= lFirstUBound; i++)
; w! ?" Z' B% f2 k {' s8 ?, h& }. W3 B- \/ C9 x3 p9 q
index[0] = i;" Y, t) y) k! d4 x/ T
for (long j = lSecondLBound; j <= lSecondUBound; j++)8 ?) l' R3 V6 t/ Q0 f
{
3 W/ A! j5 Y% x index[1] = j;
- x5 e8 ?3 ?7 _! E. {+ h long lElement = i * sabWrite[1].cElements + j; 4 V9 ~5 C' @. M& `) C5 z) n8 e4 s
olesaWrite.PutElement(index, &lElement);& f b/ Y5 B" r2 U8 B: Q
}
' ~/ O9 h; _7 |8 v$ }1 m) J }
) h+ e9 S0 O7 A$ U# ? j3 ~7 o4 |2 \! G2 \7 {+ L/ M. N
/*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/
) F2 ?4 G/ \" K7 `' t VARIANT varWrite = (VARIANT)olesaWrite;
, }! s1 G9 h) S% Y- h range.put_Value2(varWrite);
6 E: F4 O" l8 i4 Y. j
8 P5 H2 {4 ^& |- j system("pause");/ G7 ^) [9 o# g" O4 ?
- H( N. e, ]$ S, u4 D l
/*根据文件的后缀名选择保存文件的格式*/
* g! q5 f2 u4 S' p2 |2 W CString strSaveAsName = _T("C:\\new.xlsx");( a1 t5 h( k) t8 W! g; Q
CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));
! C$ G8 x6 R" E, v XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;( Z" {6 k! Z4 ~7 b/ X* `
if (0 == strSuffix.CompareNoCase(_T(".xls")))
9 _5 d5 I, A" s. I, U6 e# A {
) D5 B2 I# D# w5 w0 a: I NewFileFormat = xlExcel8;: c- w2 d/ a9 B y6 Q4 b& x; _1 r
}
) E" v" i% l) _+ C) g9 B book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, 4 Y7 [; {' w) Q/ R. |$ c. _
vtMissing, 0, vtMissing, vtMissing, vtMissing,
3 l, w& z/ a2 O/ q vtMissing, vtMissing);3 v$ N- v! w5 |5 u) K1 g/ n
' S: o5 g0 e' U# Q6 W
system("pause");/ ^. _) q6 j: V7 Y
2 X, X% y# q. R& j2 E /*读取Excel表中的多个单元格的值,在listctrl中显示*/9 m! U" M4 _: O; F
VARIANT varRead = range.get_Value2();
/ k% B) t3 ^, S5 k: e/ f COleSafeArray olesaRead(varRead);
9 h% P# L k; X) v; x$ Z% }
( y: p# |* \* [! M& ~7 U VARIANT varItem;' t0 Q2 a( S' ~& c" `* }7 i0 k( e
CString strItem;
: L; V$ K& p- Y* ^0 _ lFirstLBound = 0;7 T+ m9 N1 u% O' x
lFirstUBound = 0;
- O& d' b/ P) }3 {4 m1 |* p lSecondLBound = 0;
, I s+ l& D; F, Z lSecondUBound = 0;, p0 f, o7 X. ^0 l3 \3 C( A
olesaRead.GetLBound(1, &lFirstLBound);
4 @" A) W* x ? b3 F' C olesaRead.GetUBound(1, &lFirstUBound);
8 F, {5 Y" y5 c) t( h olesaRead.GetLBound(2, &lSecondLBound);# m( Q8 U& `" A, B0 T. {9 C
olesaRead.GetUBound(2, &lSecondUBound);" e. R" i3 h3 Q& j7 h' o: ^
memset(index, 0, 2 * sizeof(long));$ Y1 Y, B3 {( O- _! x
m_ListCtrl.InsertColumn(0, _T(""), 0, 100);
( a3 ]# Z/ \1 G: Z7 c for (long j = lSecondLBound; j<= lSecondUBound; j++)
1 w7 B. C- f% u+ V; W. v' B% @; c, T {
6 m/ N" {) [ \- E' u# z CString strColName = _T("");
9 D. M2 [" N' i. P: [+ I strColName.Format(_T("%d"), j);
; ~ C9 ~% I" a7 j m_ListCtrl.InsertColumn(j, strColName, 0, 100);5 {( |; {* j1 [: I4 L
}# p! G6 z9 e% U8 y7 y
for (long i = lFirstLBound; i <= lFirstUBound; i++)
1 [8 l% U3 Q5 }& T4 n# ~& j {! _4 u6 d4 w4 q0 S7 o
CString strRowName = _T("");
& a& B4 ?- C5 t8 g6 L3 k strRowName.Format(_T("%d"), i);( R' f" C# J! k2 _9 \
m_ListCtrl.InsertItem(i-1, strRowName);
' ~! F. K" h6 Z O8 Q
4 i8 n3 b& I- b; x" _( {, ]5 _ index[0] = i;( P' s) f* i& E
for (long j = lSecondLBound; j <= lSecondUBound; j++)
. p# T# p! M+ q {# w% _* Y- q& X, u% ^
index[1] = j;
" ?% l, v" O/ r7 J7 h olesaRead.GetElement(index, &varItem);
9 j; n& j. w8 t$ d8 N7 e( I' ?* D
3 V- D/ K; {* b3 _4 S6 { switch (varItem.vt)
$ I, @1 y" K* \ {
( g7 z2 n0 L4 ~( a3 w" P, H- b8 S/ v case VT_R8:
# F: T8 R1 G4 x9 D& e" K$ W {
N6 ?3 ~, o& ?, W3 h; O7 }+ c8 S strItem.Format(_T("%d"), (int)varItem.dblVal);' W, j; L* Q J+ u, y% q! m X
}# q$ O' A" M' k5 f" v& n# e5 C4 Z
* V% W- n% H: ~4 o case VT_BSTR:/ A0 S ~ o% w) K( s+ Y. t5 j/ c, Y( H
{
" V; L, E' C$ `7 n strItem = varItem.bstrVal;$ t$ _# }2 T2 U- b
}
# z( T0 M# k7 Q7 z$ F$ B( r
7 i7 I! l, {' d$ |3 |- j* v& L case VT_I4:
+ r* N- Q0 p( A6 e/ ~8 L {$ j9 R) J+ J9 j+ t, _* a
strItem.Format(_T("%ld"), (int)varItem.lVal);. E* N5 M$ J& A* R3 m; C* F
}
- m$ _% ~+ V8 M# _. E% A q2 b% I9 y) ~9 W( L
default:- m3 i8 d2 v4 b- e
{+ H- Y) l4 w$ W% A9 D. z. o
% E9 V, I0 _5 U0 \- I+ v' J# ? }3 o, |! H" u5 }- C
}- ^9 h( q1 z; m6 Y
2 |! `+ }1 w( O, O ?. d. v7 i/ ]. s m_ListCtrl.SetItemText(i-1, j, strItem);4 h1 m G7 L, h: z" F
}
- b+ w7 T0 H8 {9 c; D% Y0 m. o }
n, o8 M* J$ [3 D' d
( C8 C$ I( \6 |8 K: ~
' \: a+ o; w, e0 p. R0 H
1 c( C* _: B8 q5 Z' p/ q /*释放资源*/+ |) ?% ^$ |! j3 @6 ?5 p
sheet.ReleaseDispatch();1 W. E/ D; m# d, V
sheets.ReleaseDispatch();8 C7 n( `5 U: N& y3 e
book.ReleaseDispatch();
( ?# E; c$ ^8 U! E8 t( n books.ReleaseDispatch();
9 n0 ?+ J" y$ A h ExcelApp.Quit();1 F7 v: X* @; f" r$ x: R
ExcelApp.ReleaseDispatch();9 Z4 j' `& O* m5 \* P9 v" G
- w8 p. l T$ O2 R P) S
|
|