PLM之家PLMHome-工业软件践行者

[转载电子书] VS C++操作Excel详细教程

[复制链接]

2014-11-8 08:13:41 6740 0

admin 发表于 2014-11-8 08:13:41 |阅读模式

admin 楼主

2014-11-8 08:13:41

请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!

您需要 登录 才可以下载或查看,没有账号?注册

x
通过VC实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文主要研究通过OLE/COM实现对Excel表格的操作。
+ a( [# o: x& L# k  0 ?0 ^9 A+ T9 D* m1 h$ G
本文源码的应用环境说明:
# L! b4 S& u0 Y, H6 EWindows XP SP3; J' s, u; N/ V6 K. @* O( ~8 `
Microsoft Visual Studio 2010  j0 J3 O$ X6 k+ g1 o+ [' [8 W* x
Microsoft Office Excel 2007$ [0 H# Z+ h3 F0 l7 k6 l
  
4 A0 q' ^3 E, J9 K& M1、添加OLE/COM支持。" U; |$ w$ |  ~/ S
首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。5 t8 O) Y, d! q  L5 L
本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。
0 s/ [% S! Z+ x" y: ~2 ?  E3 f通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。* L/ W& J' l9 z7 U& s# h
#include <afxdisp.h>        // MFC 自动化类4 C! o( ?6 M# R
同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:& q# [( `7 w  }* c( O. Z" d& |
// 初始化 OLE 库3 C# Z) M: a$ Y( n8 u
if (!AfxOleInit())
7 O- |0 V6 h3 q9 s+ B) ~+ `0 _7 p+ r, {/ y{3 |( [$ Z3 p6 K  F" z
AfxMessageBox(IDP_OLE_INIT_FAILED);4 d* }* t$ f9 }1 Q& X
return FALSE;
4 g9 I* B7 j9 l2 }0 z6 Q. U) x}
3 Q* D  o! B0 t5 P6 s  
4 q" o) F/ K& ]8 o6 R/ d2、导入并封装Excel中的接口- f8 k3 W* i4 Y& D/ ~
Excel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。
9 v; ^; v5 O! j由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。  {" C: ]5 A7 p
VS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择
1 B6 u& Y9 X9 [0 Y  E, i要导入的Excel类型库中的接口。. U9 P6 p) l& [7 p# b( b5 G! h
在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。' n0 J7 c0 B0 V: z3 u/ a; I
  
8 U2 h  h! s# z% g; h本文所导入的接口对应的类和头文件的说明如下所示:3 n8 s3 P6 D, @9 @; V& T7 t
  
& h& V% X, a8 F+ ^6 C% fExcel接口3 x5 `2 U3 d7 m- m9 C& p
导入类2 n- M/ U! F4 ^: p: z% I" Q; q+ o
头文件% L) R7 J5 A0 o) c! N
说明
; C. r8 J, M+ P1 I_Application
' O& K. ~. E4 dCApplicaton, }" Q3 V6 {* Z
Application.h
/ k" S$ U) E3 o/ s; aExcel应用程序。
  T& p: q. N3 n4 `) LWorkbooks
: v8 p! Q, h& F6 ]: CCWorkbooks
. S2 l1 M$ n' f8 D: R/ h; L6 y% _; XWorkbooks.h
( v4 r! |( _4 _& Q) `+ E  ]2 x工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。# r4 m5 ^5 U4 D5 f% n" q6 k
_Workbook, c, r8 ^2 {" N. e) U7 \
CWorkbook
" F6 R' K% Z) A+ f2 D5 Q4 C% sWorkbook.h" k1 l1 c$ w) x2 l
单个工作簿。
9 X+ ~0 i- ]% g3 V8 D4 MWorksheets! p/ ?1 n, I6 M) ?
CWorksheets
2 R( G. v0 R6 t; k& fWorksheets.h8 v3 Y& Q4 }; k# M
单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。
; Y$ t& Q7 _2 c" \_Worksheet
9 H5 A6 A! _' I# A3 R; E5 R& fCWorksheet/ p' E& O6 F. ~& i3 m% w3 n7 w
Worksheet.h
+ _* q! Z% t1 l% d1 d- O" N* ]6 H0 E单个Sheet表格。; T: `7 l: @  s* L8 ?. ], ~  [
Range
; X5 ]3 G4 i- q" fCRange! w# ]5 L4 [* m7 e. p2 O
Range.h
" s* ?- L5 F( n6 \9 c% w* ]一定数量的单元格,可对单元格进行单个或多个单元格进行操作。
6 N2 _, z  D4 Y! S+ G/ I" J* q* N1 R  * f+ ~. g' J' T3 r
3、导入Excel的整个类型库! j4 H5 R* j, Y- `
接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
' g+ o# m" X) J2 O2 N通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:
2 V( z0 l1 n  Z) V1 ?#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
4 k3 }$ }* r6 Z( Z, h  C这行代码的作用是导入Excel整个类型库到工程中。
3 ^/ @. \0 N% j. r6 e由VS2010自动产生的导入代码存在以下几个问题:
$ C6 T! E. h3 G) m(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。
0 X) ]" Y/ G' a/ o(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。
' i) j" b2 [! Q( r; i9 j8 B0 l(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。
& z2 \9 M+ q4 K! l以上三点问题的解决方法如下:
% z4 I- X( R4 j8 }, f(1)仅在_Application接口对应头文件中导入Excel类型库。/ e2 H# s9 ^1 L
(2)对冲突的类型进行重命名。
5 u: n2 b! ~0 b1 |, e, v  n(3)在导入Excel类型库之前,先导入Office和VB的相关库。* C& }& Q9 ?" Z8 y+ a6 X
更改后的导入类型库的代码如下:
8 T6 H. a6 A9 E! _# {5 C: B  # h; C6 d  j( a  S; w2 A
/*导入Office的类型库*/
6 b9 D8 d8 I  J5 R4 V$ X/ c#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \
: }0 z" }9 R$ d5 g9 g. _# brename("RGB", "MSORGB") \
& a5 p  M: E3 A7 m% I1 r; ~2 w% K' Rrename("DocumentProperties", "MSODocumentProperties")
7 d4 ^& Z* {+ T4 x( susing namespace Office;, A/ `; r2 _$ S8 q$ _" a
  
% ]% }9 _: f) K. {* ~/*导入VB的类型库*/# N- Z5 B5 t  w* N) ~3 N7 x; c
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
5 o; O+ X. B: Dusing namespace VBIDE;  G) z8 n( s' l1 G# }, B7 m. C& Y( l
  
1 i7 Z# r; p& C! W- w/*导入Excel的类型库*/
! d7 q0 ~$ {6 ~- v0 E1 g8 ]#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \! U  d! d: m; E7 c( Y6 q' h
rename("DialogBox", "ExcelDialogBox") \
* c4 R, f# w0 ?7 E& xrename("RGB", "ExcelRGB") \/ n6 N0 d! u1 x
rename("CopyFile", "ExcelCopyFile") \' T3 M1 J3 ^' N9 o/ J; g# P' F
rename("ReplaceText", "ExcelReplaceText") \: Q: L3 Y! d; c, j( H
no_auto_exclude
" U  d8 f& s0 a" MUsing namespace Excel;
) A, U2 s$ h, z! y7 M1 ^  
0 s! }7 J- G7 x& s6 _0 {% k7 S; M1 m编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。
% Y! }  {* \& Q1 v  
6 u  n/ O. B% W# Y! z, E4、操作Excel步骤
% B+ p. d5 X; T操作Excel的主要步骤如下:6 z/ F0 a% t* L( \
(1)创建一个Excel应用程序。; U) R" G, _. Y+ ~& `/ M
(2)得到Workbook的容器。
0 ^* c9 Y# J7 h9 g5 o(3)打开一个Workbook或者创建一个Workbook。( Y/ h; g7 ]0 Y2 t
(4)得到Workbook中的Worksheet的容器。! q- w+ r+ r9 j6 f
(5)打开一个Worksheet或者创建一个WorkSheet。
6 l# I/ a; [) T! g(6)通过Range对WorkSheet中的单元格进行读写操作。
) n  D% A) O" ^/ r. s6 M(7)保存Excel。0 p8 C  d2 s. \+ ]
(8)释放资源。
9 ?3 s) X1 c8 F  + O. R$ D7 u# R& h% F
5、批量处理Excel表格; H  w8 S; h3 L" [7 G2 X1 H7 C5 L' N  f
VC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。
- i9 S) E: p7 Z对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。) U) r( T+ L+ n* k$ K+ g6 d
VARIANT get_Value2();
# c8 s$ X! E. Cvoid put_Value2(VARIANT& newValue);& s& \6 h. {0 ?" v
其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。
2 O' ^$ `& L3 s1 O/ G' c' i其中,VARIANT中实现二维数据的方法可参考% A. Q6 R' u3 L+ I$ ~7 Q
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html. U0 |0 J" |  y' q
当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。
/ E; Q) F- ^' m: `  
+ [3 E, F1 g) F/ G: r7 D' |6、Excel表格的保存. ]9 r! \" K0 d. J; d
(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。( w  c+ w; B' _* j! H0 x& k" I
(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。7 t7 V5 ?' O) |: Q/ V
SaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。
9 [% L' p  q8 F: M, F6 K! [  
/ ~5 [5 x; m+ H5 T7、获取当前Excel的版本3 _# ^9 e+ s1 ~7 W# G9 r
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。1 L* d  d. y: r" q1 g" C
  
. @5 G; i2 `+ K3 N. Y6 w2 J8、示例源代码
2 V. {) F% X) J; ]5 b主要代码如下:9 m; L1 g' A$ }% A. _! s
  6 M4 l- a' q. i- J2 ~) R: n& I
( }4 s+ R! `- I
) q0 [  v; A- G( |; ?
    m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);5 l/ v" Q* m. E1 O! ?

  v8 W5 V: n+ a* [    CApplication ExcelApp;
7 T6 `- l. n6 N9 n" [3 y' ?( e    CWorkbooks books;
" [/ Z) ]$ z' o0 N* B0 I0 ?1 T    CWorkbook book;
) ~& S5 a; I2 N    CWorksheets sheets;- n$ a$ B  x- B
    CWorksheet sheet;
8 j" y9 N. O& h! J. c$ e    CRange range;
- P" j/ z% x" @) N* D. x* I' M    LPDISPATCH lpDisp = NULL;
* C' m% _/ x& W! i7 C! x$ i1 g' N6 a3 j4 Z
    //创建Excel 服务器(启动Excel)  h: K3 A1 ^, l
    if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))
9 g, C! g5 I) d0 R    {
& T' [% k8 {; |# I0 I; v  a5 }! M9 z        AfxMessageBox(_T("启动Excel服务器失败!"));
5 l- x6 |( m1 u8 n$ b        return -1;
' u' M* {2 v( l: D% f    }' A7 b  Y. u; ?. m
# @; Y5 \( F7 ]
    /*判断当前Excel的版本*/* R" ?0 N# G( w( U0 ^! \* d# {2 ~
    CString strExcelVersion = ExcelApp.get_Version();0 f  p) f' f* s8 ~& L) O
    int iStart = 0;7 x! R& u8 N: k: U5 }8 E
    strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);
2 D1 ^' E( P8 H+ j$ l7 G7 B7 ]  S    if (_T("11") == strExcelVersion)
5 x# u# X8 n# G+ @5 k% Z/ m/ f; I    {
, c3 `& x$ P( B4 F        AfxMessageBox(_T("当前Excel的版本是2003。"));
) r" u1 ]# I: w2 f    }* j/ A5 ^/ ?' ]7 n
    else if (_T("12") == strExcelVersion), _1 B( J- L0 K+ f
    {9 V$ H+ j; r- f
        AfxMessageBox(_T("当前Excel的版本是2007。"));
. L: _7 |+ L2 g    }
) e! F# M* `' Q    else
, ~9 U: I3 v' z0 w9 E0 W    {; C& y. K0 L1 S/ s2 l1 N0 r, |
        AfxMessageBox(_T("当前Excel的版本是其他版本。"));1 Z& h; U  P. R& o
    }- J0 C' d0 m5 p& x7 W: {6 a
& n- }- K/ i# P/ |! N
    ExcelApp.put_Visible(TRUE);; w( A, D( d, @0 l) a7 ]
    ExcelApp.put_UserControl(FALSE);8 k  r- ^1 d4 u- J; d& B9 v  Q
' |+ j1 S9 V. K9 Y, @
    /*得到工作簿容器*/
5 u1 T( Q3 o8 k- K& l  w7 r    books.AttachDispatch(ExcelApp.get_Workbooks());
9 K: @0 P/ @2 B  l- V
2 `3 [# s: Z* x    /*打开一个工作簿,如不存在,则新增一个工作簿*/
3 q1 f. V( h% f    CString strBookPath = _T("C:\\tmp.xls");, `9 W2 o, m) K" M) N
    try
/ ^5 p* e$ I' p) P    {' w! c! e, X# b
        /*打开一个工作簿*/
: F  t; D: ]( p. A, I5 m        lpDisp = books.Open(strBookPath,
* Y) W0 b/ b6 ^, X" K8 N            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
- K8 ^7 w( a9 b6 ^' Z! C6 t            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
+ w2 R* d* T3 ?+ c4 O/ `8 [            vtMissing, vtMissing, vtMissing, vtMissing);# x( m7 v7 }2 s6 H* M- [
        book.AttachDispatch(lpDisp);6 A) w# u( v6 N6 h
    }
. ~/ [( L7 Z9 u    catch(...)
+ e* b1 }- x! J3 _2 g8 @" {6 E    {
* ~0 [: B2 `7 \* R        /*增加一个新的工作簿*// ^) P6 |. V4 P5 }! m
        lpDisp = books.Add(vtMissing);
0 B7 n& t, f5 E1 o3 Y5 ^0 R0 O. s        book.AttachDispatch(lpDisp);
7 V. t& q5 H$ b# H% x    }
$ ?9 y9 M9 u1 G0 p6 U/ g     
. i# b3 |! T: s( ^4 l3 |5 C
( c( a. X0 @  @, {# Q    /*得到工作簿中的Sheet的容器*/  k$ j, M* v7 ?1 B' G8 K# Z* V7 X
    sheets.AttachDispatch(book.get_Sheets());$ Y. i; O( G% ?. q# G4 ~  c9 h
; I! f+ J3 ?. `( n: J. F# b' ?, Z7 |
    /*打开一个Sheet,如不存在,就新增一个Sheet*/7 v/ c+ z) v- N( z* D" Y8 c6 s
    CString strSheetName = _T("NewSheet");
+ ~$ y2 _8 L3 |& x: t: m    try; R, g6 H  H& W5 r9 D
    {: H( p' G$ Z2 |, h" e+ n
        /*打开一个已有的Sheet*/8 {% c. Q1 E# y# l( s
        lpDisp = sheets.get_Item(_variant_t(strSheetName));
, H1 s1 A* E2 S        sheet.AttachDispatch(lpDisp);
" @$ k0 p. N& ~7 k* z    }
3 f; _9 D; d, L    catch(...)
3 @( K7 m: h' t) G) Q) }    {
8 @8 {9 |) r% e( w: A6 W* W        /*创建一个新的Sheet*/
+ o# o6 w' |1 \! R        lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
2 i0 I: r/ n. f) I' d: R1 {        sheet.AttachDispatch(lpDisp);. ^& s+ f& I* |9 ]6 W8 S; E
        sheet.put_Name(strSheetName);
8 G, j" d$ R) }6 I8 Z$ {% s    }( v* p7 Z. o* {6 {6 f
& Z1 b% }1 d& U7 D
    system("pause");, B% l( O& @( v( ]
* v# N1 B( D# x+ ^2 t
    /*向Sheet中写入多个单元格,规模为10*10 */9 ~3 {3 \4 Y" C, V
    lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));7 X2 [4 n8 C9 J) p; z
    range.AttachDispatch(lpDisp);
( l- H% Y, x% `! R) `, X
8 U# k/ `" d) N) V% C    VARTYPE vt = VT_I4; /*数组元素的类型,long*/
8 s* l" u# q7 Q  v6 w    SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/! W; T* `9 v' s7 \$ I" E) c
    sabWrite[0].cElements = 10;0 W5 e0 T; Q2 R4 e
    sabWrite[0].lLbound = 0;
( \7 @$ P5 w' ?5 @    sabWrite[1].cElements = 10;
. v+ R1 U; i% m+ S% d& \6 d' {! ^" w    sabWrite[1].lLbound = 0;# U- ]. D3 ~- J8 c+ D1 M# J; O
- I/ O+ G% ?7 X( k& E7 B; n
    COleSafeArray olesaWrite;
  X* J" h' N% p# U  t, p- ]/ e    olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);
! }: D  g9 X% f. p( f$ X* p& n8 ~# u+ w. \
    /*通过指向数组的指针来对二维数组的元素进行间接赋值*/
; M, h, N4 i% z+ ]$ W    long (*pArray)[2] = NULL;
$ }: c0 ^! T! N; P' @    olesaWrite.AccessData((void **)&pArray);; ]7 z" P7 u. v& n7 c) h
    memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));9 G* b+ H# i. v. \9 x1 ?" `) z! S

! z9 x1 j5 \( m* q$ F% t. L    /*释放指向数组的指针*/
! I/ z& ^% i3 _* p    olesaWrite.UnaccessData();; {; A% g; \! m! z' V4 p5 S- u
    pArray = NULL;
% j# k, N2 Z& D( N" S% [- X2 y/ r, d3 u  E# f- E' e+ a
    /*对二维数组的元素进行逐个赋值*/2 S$ i0 e' i  N6 O  z* z) i0 ]  V
    long index[2] = {0, 0};$ K" P, P; F% b
    long lFirstLBound = 0;& n( o. I  F/ o
    long lFirstUBound = 0;+ H' k0 D% x* m1 s0 Q& V7 ?, g
    long lSecondLBound = 0;$ w) x8 r. ~" f6 m- e7 V
    long lSecondUBound = 0;- q$ P; d9 u. V& y
    olesaWrite.GetLBound(1, &lFirstLBound);
- s1 Q( R& U  `$ c    olesaWrite.GetUBound(1, &lFirstUBound);$ K3 ~2 k+ Q- }' \" y
    olesaWrite.GetLBound(2, &lSecondLBound);
2 T3 k9 {0 R! V! K0 ^$ s  k# X    olesaWrite.GetUBound(2, &lSecondUBound);' |  E" n  V2 m2 m% D" b
    for (long i = lFirstLBound; i <= lFirstUBound; i++)$ L: E  d0 m: F1 n9 U1 D7 o
    {
7 x" B- T* G1 e! ~) ~  m! q7 g        index[0] = i;
- Z9 Q4 s5 v% P( Q4 O7 ?        for (long j = lSecondLBound; j <= lSecondUBound; j++)
. j! T# _1 L6 Q6 V' i3 G        {
7 Z/ o4 V- |! F! a) S+ v) z            index[1] = j;
* N1 W/ b- Q9 O, p3 Q            long lElement = i * sabWrite[1].cElements + j; # Q0 o' a, ]) Z: c/ B" o; k/ D
            olesaWrite.PutElement(index, &lElement);! u; P; k- [9 A; l
        }
, o% I' V, b' Z    }
, i8 o1 A# w" v1 ~$ Q
8 E) M; i. @& ?1 ^0 L" ~# H; x$ Q    /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/
. u# s+ r' c3 g; N# R' T    VARIANT varWrite = (VARIANT)olesaWrite;$ g  n9 f( c, g. i2 u, |/ M2 J
    range.put_Value2(varWrite);9 R5 C: a& @, U& Z$ L' h, _& G8 {% n
1 j* H9 o: f5 C% `
    system("pause");4 H7 W+ ~. w9 @
6 T- n5 X# C0 z! z9 K7 c- v" S4 k
    /*根据文件的后缀名选择保存文件的格式*/( l( O- i# h- D$ J6 }; ~+ `
     CString strSaveAsName = _T("C:\\new.xlsx");
- n6 W: c0 Q0 i$ Y2 J    CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));) ]! i1 j: I4 Q4 g8 E5 I: G+ z
    XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;4 n# `( g, q0 E8 Y) O- p
    if (0 == strSuffix.CompareNoCase(_T(".xls")))6 I$ U4 D1 z' T* ?' D0 r' e
    {
! o1 @2 }! Z! Y- J; r        NewFileFormat = xlExcel8;  m' ]9 n; @, o
    }# m1 h8 V+ |7 A9 n9 [8 c( p
    book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, 8 m* S# x* Y; Y4 X8 F
        vtMissing, 0, vtMissing, vtMissing, vtMissing, # _/ {  {( E* w3 g9 i8 {, Z9 Z
        vtMissing, vtMissing);
: s9 N2 u1 h$ D7 ]0 ^; [& @. ?* _+ j! }! s) p5 K
    system("pause");; h8 m5 ^0 Y* D; R* d2 @

  R+ m, O9 `  h" P6 T4 o1 ~    /*读取Excel表中的多个单元格的值,在listctrl中显示*/
! U( G  b& {+ U* n# D5 ^- ]( `8 S" o    VARIANT varRead = range.get_Value2();4 p1 l5 L: ~' W' S3 A
    COleSafeArray olesaRead(varRead);
* o/ j7 `( s, d% ^0 `' n. i8 n' I9 q" L; k0 P2 `, B: |  ]/ k
    VARIANT varItem;( Y, t' _# x6 g+ F/ y% f$ A) l  ~
    CString strItem;
# [  I' y+ i; }! `    lFirstLBound = 0;$ m( B( Q+ c9 j# ^. Y
    lFirstUBound = 0;- \2 k% m3 z" {2 r
    lSecondLBound = 0;
( M& H, C* @9 q$ m' \    lSecondUBound = 0;
5 u# _4 b% ^, A' G" z    olesaRead.GetLBound(1, &lFirstLBound);
- ]8 M/ z4 v) O( n  S# _    olesaRead.GetUBound(1, &lFirstUBound);
3 {1 H- x1 `, t" W    olesaRead.GetLBound(2, &lSecondLBound);5 ]0 _; n! V0 E7 G1 v
    olesaRead.GetUBound(2, &lSecondUBound);6 x3 L. W7 r1 \
    memset(index, 0, 2 * sizeof(long));
* V, J  }  H) s1 f! e3 l5 h8 S    m_ListCtrl.InsertColumn(0, _T(""), 0, 100);# f- B; T  D% z. j4 [
    for (long j = lSecondLBound; j<= lSecondUBound; j++)- q9 r8 e+ b6 I& c" o
    {" K/ c2 g  U! }/ i  R- T7 Y5 u
        CString strColName = _T("");
! V$ u: q# }  _  M2 q: O        strColName.Format(_T("%d"), j);, }( H# L' N1 _: |
        m_ListCtrl.InsertColumn(j, strColName, 0, 100);9 b4 `" S+ B0 h9 @5 ]& C! w* E
    }
# d, r# F" C4 g4 y% {4 |3 F    for (long i = lFirstLBound; i <= lFirstUBound; i++)6 m: W' T8 s! k4 m6 J& |: q+ f/ D5 C6 {
    {
, M- s& {. \5 Y& K% G+ P, B' w, k        CString strRowName = _T("");" z$ S* I' e* y: n8 [2 w
        strRowName.Format(_T("%d"), i);0 d  V0 y7 l9 Q  h2 h
        m_ListCtrl.InsertItem(i-1, strRowName);
4 z( G) y3 R6 b5 V/ X2 U; T9 t0 b, G! `0 R& N- p% B
        index[0] = i;
, u4 w$ q4 f# J2 J6 }        for (long j = lSecondLBound; j <= lSecondUBound; j++)6 \6 Q* f( K" l7 i7 O" H
        {. I- J& R& Y# M7 _5 h
            index[1] = j;
7 Q: c, J0 B1 Q8 @- A. R) F            olesaRead.GetElement(index, &varItem);
5 Q* N. @3 [; p: S2 x+ w# n4 b0 _( g5 d
            switch (varItem.vt)7 H/ p$ P" I) l% \9 n3 g* u+ |) j; ~
            {0 J. n% k5 S; |! U& ]3 J
            case VT_R8:
# S, P$ T0 H5 T& o$ |                {% Q8 a4 I: f, U( J+ Y5 H6 M
                    strItem.Format(_T("%d"), (int)varItem.dblVal);
. e+ p1 g2 d3 E4 I                }
% N2 a/ x& ~1 [  B* M! p) w5 T; t; ^1 g6 d6 C# w0 j& d' b, g7 j
            case VT_BSTR:
( J, M( l) F9 ?: v. h                {: \" L  K. \3 V2 p; p
                    strItem = varItem.bstrVal;  n4 w9 T$ ]5 x3 s
                }
% w1 ]: F) P( w4 q* X0 z( R3 s; M6 i  f$ t6 L3 x
            case VT_I4:8 ^. o, p( `6 B! j  J3 }, E
                {, S" q3 J+ J3 {! V  s0 s: M3 T9 b9 b& V
                    strItem.Format(_T("%ld"), (int)varItem.lVal);. p: d+ J- n8 T' v
                }
# I7 X+ G; T1 J' h' S
2 B: S( i- B5 y% f# S) F            default:) G( V/ H* f$ i1 M% z% M
                {# T! R# T( M* {9 ^4 W

7 L/ d" d) t9 R4 k- z" j                }
/ o4 L( S9 P1 _& J: Q            }+ J% h' ]4 o9 y3 G5 s) G

- l# g0 h5 e8 J6 |' }            m_ListCtrl.SetItemText(i-1, j, strItem);
4 d) A9 A5 |" _1 F2 x) r% F        }
) I, `9 a* w& U% |9 I    }$ q  i6 h+ m9 l- t7 M3 J
8 y0 F! h% ]7 O1 O7 B; C
& T1 U4 u. p; m; n% |" i
2 \' f1 b2 `4 W: b/ t+ z, s
    /*释放资源*/! s* O+ _# `" C4 ~, ~$ ?
    sheet.ReleaseDispatch();! Y3 j* H1 q* F) U2 Z# s1 T7 l
    sheets.ReleaseDispatch();! {( Y2 b9 T( V: g5 W# x9 ~
    book.ReleaseDispatch();8 g3 p  E: e, b
    books.ReleaseDispatch();
8 o, f4 D# a$ N: n    ExcelApp.Quit();
( ?) E* v3 o; J" ?  b    ExcelApp.ReleaseDispatch();
% K6 V$ O5 k/ J% D# e# {$ ~! n. S" l$ T7 X& `
上海点团信息科技有限公司,承接UG NX,CATIA,CREO,Solidworks 等CAx软件,Teamcenter,3D Experience等PLM软件,工业4.0数字化软件的实施\二次开发\培训相关业务,详情QQ 939801026 Tel 18301858168 网址 doTeam.tech
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 注册

返回列表 本版积分规则

  • 发布新帖

  • 在线客服

  • 微信

  • 客户端

  • 返回顶部

  • x
    温馨提示

    本网站(plmhome.com)为PLM之家工业软件学习官网站

    展示的视频材料全部免费,需要高清和特殊技术支持请联系 QQ: 939801026

    PLM之家NX CAM二次开发专题模块培训报名开始啦

    我知道了