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

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

[复制链接]

2014-11-8 08:13:41 6730 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表格的操作。
4 j, ]! @4 l$ r/ Y& M3 }  
' U; X1 T( f* _: f: @& j! T本文源码的应用环境说明:0 c! L4 G! N9 {: h( q% p1 F. ~5 x
Windows XP SP3
. r0 y- b$ w" L5 J1 [Microsoft Visual Studio 2010
* v/ H  t) Y3 l% ^! VMicrosoft Office Excel 2007( t4 G" y7 H5 H8 U! |
  + a# Z6 J  P, {. W
1、添加OLE/COM支持。8 e  E' u- |! \3 ~0 F( @/ C
首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。) L1 y+ |* @7 O  }, ^) w
本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。
) p6 z3 h: o  {/ V& t通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。& `2 V. D. Y1 P: ~- N
#include <afxdisp.h>        // MFC 自动化类: ^' I, d% Q; X
同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:
2 \4 G8 ]! C, Q  z& Q% {// 初始化 OLE 库
/ I$ x) ]4 z* f! }if (!AfxOleInit())
! \* p5 c1 R5 c{
* B6 b' H  }* u* F! \AfxMessageBox(IDP_OLE_INIT_FAILED);
, c% G! e' Y+ H# ]6 ?8 `/ l5 Breturn FALSE;9 a* O& k2 T$ w) n
}0 z! N8 }5 z3 m: \6 a( N
  1 D- t7 f" m4 Q2 f9 }6 P0 E% O
2、导入并封装Excel中的接口
6 n' B$ n! w" A0 sExcel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。
" v, @, K& r/ ]4 T由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。
; m  w& c3 Y1 sVS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择
/ |  k- Q- w6 E# A3 l要导入的Excel类型库中的接口。: Z: Z5 J( Y6 c, b& J1 U( g
在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。
% r% {7 z/ Y7 D4 B  
: V7 }; G* Q3 o1 z, r7 S本文所导入的接口对应的类和头文件的说明如下所示:
2 l- Y2 \! T; ]/ n  " A8 Q0 P; `- c5 C$ z1 t
Excel接口5 Z& s4 J6 w' Q
导入类  j( y% Y4 i/ c8 h& D
头文件, I! p4 [$ x: f) E, o
说明* p6 V2 G$ \, H4 j" Q  l5 \6 a
_Application
% o0 K9 F* z+ H  \: MCApplicaton8 E( Q6 P5 L7 s4 h
Application.h
' a% e5 p% G# IExcel应用程序。
& l6 _" O7 X) z9 _Workbooks
. ?6 k( @$ S+ Q! o: z" LCWorkbooks- p8 d1 l: L( W, n# m
Workbooks.h
, `- M, {: |; p/ V. c' k工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。+ [7 ?+ Q# g' r5 m* d& E$ [
_Workbook% P" a6 D; u- Y/ J4 K3 m' s6 \
CWorkbook3 o, W2 Y. T# n9 ^  B$ U
Workbook.h( d1 F- @- ^# t3 ]4 w
单个工作簿。
+ N" Q/ m6 }# _" n0 t8 YWorksheets
( k/ z; O- V4 oCWorksheets
0 [- x. ]9 T$ k' Z& @0 m0 |9 a' U0 hWorksheets.h7 p6 R8 f+ j2 }
单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。% M& f6 ?* C! N  V! M' w% \
_Worksheet
0 I) V# g; I6 kCWorksheet
% I) m3 q& A4 I% u% U8 u0 pWorksheet.h" h( i/ e' V! W( I4 D
单个Sheet表格。
! I1 O* l: ^' {+ TRange
8 v$ L9 O6 _3 T; D+ cCRange- h4 @6 H& k' X/ P
Range.h1 Y( y; ~- A& {
一定数量的单元格,可对单元格进行单个或多个单元格进行操作。  K/ l( g# s6 ^, }
  3 Q1 ?' ~/ _. z; k; x6 }5 T
3、导入Excel的整个类型库: v( c" g9 d+ |* B/ g# r
接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
% K. n* v- |1 h7 s: S通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:4 J: y1 a, \/ B
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
# z- r: P, V  }# C" H7 B$ O这行代码的作用是导入Excel整个类型库到工程中。
0 Y6 g' a" g9 H  i; P* `1 `由VS2010自动产生的导入代码存在以下几个问题:/ ~6 t( w  b% X
(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。
' @; `2 A2 C$ c/ N% h1 I& M3 k(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。
: f& T) U& t2 r2 T- T3 J7 l, A4 ?0 D(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。& [3 S9 p5 [) `
以上三点问题的解决方法如下:
$ K7 p1 Z  z: Z2 P(1)仅在_Application接口对应头文件中导入Excel类型库。
  V' p/ M# y- d0 Q(2)对冲突的类型进行重命名。
/ v  K8 }8 P# |1 M1 A, B5 n- q1 h: r( ~(3)在导入Excel类型库之前,先导入Office和VB的相关库。
" R7 S& j/ r/ M% H, A0 G. q; V1 S更改后的导入类型库的代码如下:
: i& i% b2 B# S# ~5 [  Y  4 g4 t1 G( t0 H: {, [' {
/*导入Office的类型库*// K' |  G7 O. {% p3 \' Z# x# c, x
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \
" Z5 |8 D6 @# C; k# I8 r" Nrename("RGB", "MSORGB") \# n/ }4 y& c: j/ \: r6 d- B7 W; j
rename("DocumentProperties", "MSODocumentProperties")
2 N- j% }3 K  i" k! tusing namespace Office;
& b" C4 r- p0 K0 R3 T0 Z5 v$ N  
5 T* u( }/ S% \: y6 ]+ v1 G/*导入VB的类型库*/0 m% F8 r% B: v" V  ?$ F+ o$ Q
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
7 N0 s9 G: j+ I) P5 }5 ?, K5 G/ Jusing namespace VBIDE;
0 X1 v: {  X6 s. ~9 N& P  
: X) R# n- w8 Z/*导入Excel的类型库*/
9 e" g& o1 ^& J) f#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \' E' Q; |, O/ f$ n5 Y
rename("DialogBox", "ExcelDialogBox") \% L. h( F) s  C+ m6 p
rename("RGB", "ExcelRGB") \
7 l. M# A( h7 o$ nrename("CopyFile", "ExcelCopyFile") \& y* l6 W, A$ m/ ]: }
rename("ReplaceText", "ExcelReplaceText") \
7 R; j1 F8 @- lno_auto_exclude
' g+ c5 m5 {) j8 y& B' gUsing namespace Excel;
) o6 u! s. K4 Q! f& G  % g; k  z( ^- e# E2 `7 Z- Y
编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。
% C, \0 ~  k  T( L7 v+ s( w  
( M1 e# B1 \9 d6 e' t# W$ b4、操作Excel步骤: e, W4 B; f, |
操作Excel的主要步骤如下:
$ Z$ H6 t, m+ x9 |(1)创建一个Excel应用程序。: X( W2 N2 j0 {! [3 O/ D( I1 j
(2)得到Workbook的容器。
$ g( C- x* m% A4 K2 j/ {6 `, {(3)打开一个Workbook或者创建一个Workbook。
' r/ V  b; e9 B6 b3 t% l4 K(4)得到Workbook中的Worksheet的容器。5 U( }% i( P9 l7 s
(5)打开一个Worksheet或者创建一个WorkSheet。
8 X( W* w6 c$ `" I" r(6)通过Range对WorkSheet中的单元格进行读写操作。
9 y- U* d* ^. f& a+ a, r2 P2 |(7)保存Excel。
5 H; y8 T' D" c5 H/ R(8)释放资源。- e/ M+ `7 D9 Y' M, S! P6 S' e, H% D- ]
  ! k9 H3 p+ Y/ N0 O! N( t+ @6 V
5、批量处理Excel表格
3 a# D. {% h2 B+ d6 Q- YVC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。
4 j; O* ~. ]8 {; \+ S+ w对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。. P  m% {% o# \2 j" W3 `0 q; T
VARIANT get_Value2();) p; U$ _4 t7 w) d
void put_Value2(VARIANT& newValue);4 b$ A- k" i6 s1 }9 Y+ N) J  j' m
其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。6 L, a) R& \; Y: Q6 A8 J% Y
其中,VARIANT中实现二维数据的方法可参考* h0 W/ \! L% T" E9 B" o+ w3 g
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html
+ ~8 {8 K! \, v% ~4 P5 d( U当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。
9 G  d" h. ^- ~8 T3 z  
! `- o% g# T# o$ k8 e6、Excel表格的保存; d0 L- m( @7 R
(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。7 G- U* O0 }! J2 T+ k0 Z# M7 Z5 f- L* i
(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。
! E7 {; V4 {, {/ _) ESaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。! K4 S0 v6 L- K+ D' I8 a
  6 W9 i7 x6 l( M
7、获取当前Excel的版本. n& ~8 A& I& K7 K3 e0 X, j+ |# E
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。9 v( `  `' @- N+ ~" Q. a' F4 V
  ' s% d6 m' o7 }, {2 v9 J! ?( b
8、示例源代码- F( @8 s% B" ?. G% h% v2 X
主要代码如下:4 i+ k+ H+ `3 F! z
  ( j4 h: M# l7 W, P  z( [

4 T2 ~  B& _0 r1 _- d# Q6 s  w6 V% Z+ r7 q- \/ Z1 A
    m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);% a6 I* u% I5 ~- N
; a# O/ ~; n& X
    CApplication ExcelApp;* j3 t& y& A) \& z
    CWorkbooks books;
( q9 n5 `1 |; j3 a# M1 C    CWorkbook book;0 }$ S  b/ v4 ?4 F7 o
    CWorksheets sheets;
$ K4 O4 T! L# c6 @0 O4 S    CWorksheet sheet;9 e! r$ F- n; W
    CRange range;) t- ?! ?7 Y! b9 Y  |  e" a5 H" P
    LPDISPATCH lpDisp = NULL;; e* D' w- Z2 `+ `, e. A5 g

1 v. ?4 F0 I4 E2 M    //创建Excel 服务器(启动Excel)
# z* ]% O- I8 {2 r    if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))
  V* l& U& ]1 y8 u- f    {
" J; ~5 K* x) A0 W9 R4 l        AfxMessageBox(_T("启动Excel服务器失败!"));
7 Y# w; J& d; O3 ^0 h" s        return -1;9 i) ?. X3 H, Z& C
    }
% W+ {' }3 B/ M# O2 o' N6 K1 U' c5 i8 ]) T
    /*判断当前Excel的版本*/
1 S) q  {7 `6 `    CString strExcelVersion = ExcelApp.get_Version();
6 |4 y) i* K/ u5 _    int iStart = 0;$ |" K& r0 B1 P; H. S5 i" i
    strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);
7 {* y0 k/ P6 i6 z2 h0 I: A; |    if (_T("11") == strExcelVersion)5 i5 l# @: w3 m% O) x" o! D* k
    {0 {, B1 C2 _% s* [
        AfxMessageBox(_T("当前Excel的版本是2003。"));% g$ ^. w0 b% }: J- G) a4 o
    }, @4 Y. ]" m- {  }8 C9 F+ ~
    else if (_T("12") == strExcelVersion)
! g2 w& s) ]' T  ^/ S7 h. I    {+ Y( ^; u/ L7 ]
        AfxMessageBox(_T("当前Excel的版本是2007。"));2 I4 w! ]- Q; G3 M1 i3 u
    }& J# z# N& o; `
    else
" G6 O! m) Q& Q4 @& Z- M8 V& F* i2 O    {& I0 r5 x# J2 O$ L1 h
        AfxMessageBox(_T("当前Excel的版本是其他版本。"));
3 V1 ?. w1 E, P* t! i- p, p    }
  J9 G" K- `7 [8 r* C& `% [/ T7 E. k. Y; u% n, Z
    ExcelApp.put_Visible(TRUE);
! d( m7 S8 d" W; n    ExcelApp.put_UserControl(FALSE);) |; g. \- a% K' v8 T' i. [
& e) Z) [5 ?2 _5 j
    /*得到工作簿容器*/2 L, q, J' M& p
    books.AttachDispatch(ExcelApp.get_Workbooks());+ ]* Q+ H8 n1 G) w
5 f5 I1 J& L/ V: z+ V5 @. T
    /*打开一个工作簿,如不存在,则新增一个工作簿*/5 g3 N* a: ~: e; V( U8 |8 Y* `
    CString strBookPath = _T("C:\\tmp.xls");
6 b$ y$ s' F4 E3 g7 c5 Q8 i$ f- G    try& ]  e" M, e& i" W$ F
    {0 f$ f$ ~5 }9 j
        /*打开一个工作簿*/
/ D1 a# \1 w1 m) W" a        lpDisp = books.Open(strBookPath,
) P5 b% v5 _) ?0 q1 Q$ Z            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
& J1 Q  O6 S" {            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
; O) b* A/ }9 f3 j( j0 U* O1 z            vtMissing, vtMissing, vtMissing, vtMissing);
% q! v  J5 c' g8 T4 T, j% a        book.AttachDispatch(lpDisp);
% f7 U. W. D3 s# u( }  |7 z0 I' i    }
* b8 V. F& S0 V2 E: y    catch(...)
5 t5 r# C6 o& {: S, ^$ U    {. J5 r+ p# I( V- T" |" w
        /*增加一个新的工作簿*/
1 }  {: B% A+ R& s3 u: Y        lpDisp = books.Add(vtMissing);7 n' [5 N6 E" k. o! N
        book.AttachDispatch(lpDisp);
/ C* x( d+ c& ~* v' z    }( d8 T. R8 `( D% T& i3 h$ \( R
     
6 s! v% B- w6 M+ J$ r( v4 C
/ N( i- v7 u: t; x" s    /*得到工作簿中的Sheet的容器*/- U7 i8 e( s* z5 \9 m4 X
    sheets.AttachDispatch(book.get_Sheets());
5 {$ g' \" j! @* p% y8 c1 w6 \, n3 |. y/ a/ b3 w
    /*打开一个Sheet,如不存在,就新增一个Sheet*/
% g# w) I$ _& a+ \0 J: E# L7 x    CString strSheetName = _T("NewSheet");
- R% @( M2 j" @" ?    try! P  M' Q- n2 ?
    {
; A  Y+ \( s" F4 y5 [- @$ S7 X        /*打开一个已有的Sheet*/
6 u# a  A: O' R! W5 b( G6 u2 A# x        lpDisp = sheets.get_Item(_variant_t(strSheetName));
* C" G) H; i" S! n        sheet.AttachDispatch(lpDisp);
# Q! z- i6 A% |0 I) C    }
5 ~2 i9 z" ~# O& ]" \4 S+ U    catch(...)6 D; Z; w6 {' Z7 E! \' n
    {
- a% Y9 A( S: h& C- u1 A        /*创建一个新的Sheet*/4 _- p# {. f' ^
        lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);0 B- J/ o, p" V3 d5 Z& [! b: i1 e
        sheet.AttachDispatch(lpDisp);' J3 [+ y  _& m, h% h
        sheet.put_Name(strSheetName);# N% w3 B, F. y  z. a
    }
, d7 ^5 i+ L. |9 q/ u6 Z' O
& w! F4 c5 c2 \3 w5 C    system("pause");
8 o1 K1 \, i5 I. y' M  o) \. O% l# v! ]1 Y- Z# h
    /*向Sheet中写入多个单元格,规模为10*10 */. x; G, w) y0 i
    lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));! D8 V% A0 n; P$ y
    range.AttachDispatch(lpDisp);( y5 O' ?$ y& a% s! B1 g
7 N2 N4 b3 G0 L1 F
    VARTYPE vt = VT_I4; /*数组元素的类型,long*/+ U" \/ U9 }# u" }
    SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/
  J( _" a: l: F/ X4 |" }    sabWrite[0].cElements = 10;! i, B7 O2 S- a9 V0 D1 c4 {
    sabWrite[0].lLbound = 0;
7 K+ a7 ^$ y& j# l8 c  z5 b3 i    sabWrite[1].cElements = 10;
% N, b6 X& n( }9 J6 {    sabWrite[1].lLbound = 0;$ ?! I7 h# u3 |  B

; e8 L( K2 g1 w    COleSafeArray olesaWrite;" m. A1 x. S9 V  r  F) V5 Q/ `
    olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);
/ F# ]* g1 \2 r3 R1 |
+ i- N, r. U* K7 X: k  B    /*通过指向数组的指针来对二维数组的元素进行间接赋值*/
( |* u1 n+ h5 Y0 `    long (*pArray)[2] = NULL;+ y: l& B  f( u+ O- o" c7 z
    olesaWrite.AccessData((void **)&pArray);
4 ~, N7 w/ g8 I' n    memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));
& F  C: b' _! x! `8 y3 h# I8 x
4 S2 A: W! L; d) M1 d8 Q/ i5 P4 Q    /*释放指向数组的指针*/9 j) ]2 i/ ?5 y, \& G: Z
    olesaWrite.UnaccessData();4 g! ^- H! I* H4 U7 @& E" p, \1 k. h
    pArray = NULL;: ]- s: q+ a- x. N; F. K

1 L2 U0 [$ N# B3 E    /*对二维数组的元素进行逐个赋值*/
& f  f$ f) a* Y, M0 `    long index[2] = {0, 0};8 }+ D% C9 G) c: y6 z7 `8 J8 W) X
    long lFirstLBound = 0;( X3 Z! r1 E6 {
    long lFirstUBound = 0;3 @2 O, n* D- b2 C  `" T. g+ O
    long lSecondLBound = 0;" Q5 A" J" y$ Q# r
    long lSecondUBound = 0;" K" @7 J) L! K% q3 C) i5 U
    olesaWrite.GetLBound(1, &lFirstLBound);
2 e* N) u5 Q- k' s: h" }    olesaWrite.GetUBound(1, &lFirstUBound);8 k. [6 T; b) F- O5 x) b
    olesaWrite.GetLBound(2, &lSecondLBound);$ {' `2 u9 z/ I1 Z
    olesaWrite.GetUBound(2, &lSecondUBound);
! Z3 l( M( k: |: X5 b    for (long i = lFirstLBound; i <= lFirstUBound; i++)
! }8 t  N7 L1 ?$ s8 G3 D    {
% b' g; s: b8 D* p' o6 D8 p. ]        index[0] = i;+ S5 {  v& S/ u
        for (long j = lSecondLBound; j <= lSecondUBound; j++)
5 @: b% j% T: ^$ @9 P8 T        {
4 G/ E3 z6 d7 }) }* s            index[1] = j;
2 t$ a5 Z$ [8 L- W            long lElement = i * sabWrite[1].cElements + j;
6 y% Q% Y% i* k) l. m# G, Z            olesaWrite.PutElement(index, &lElement);5 e% R0 K( a- M; b; {; k* F
        }$ h& o" r2 O! ~
    }
% H4 y" m1 ]3 v# X+ z5 \" y+ x; q( x6 x! H) D
    /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/
2 R% Z+ h. f5 e    VARIANT varWrite = (VARIANT)olesaWrite;+ E' W5 n+ W$ i' d
    range.put_Value2(varWrite);
# q  S* U+ t0 }# G
9 W! d- u: ?# q    system("pause");
4 l9 Z7 Q. c5 s, v# V$ W& M4 u( Z/ Q# j& q9 Q. m) v+ d3 E
    /*根据文件的后缀名选择保存文件的格式*/
( T" a/ [) t/ k, k5 _) ?" ^     CString strSaveAsName = _T("C:\\new.xlsx");
6 R) c* J' q0 T0 T# Q8 O  ?    CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));
) h1 F- B7 @1 E  j( R# `  T' [8 t6 O    XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;
# {; A6 K: D& ^; H; N) {4 b) F    if (0 == strSuffix.CompareNoCase(_T(".xls")))1 S7 }1 J0 y9 A  y: a6 B' r8 E
    {
  ?7 q$ d, }8 x6 @0 b: H& l0 n        NewFileFormat = xlExcel8;
: ?( r6 l$ g& n/ Q    }1 N9 h) l) B' Z* U0 K
    book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing,
/ V4 d0 a  Z$ t0 L        vtMissing, 0, vtMissing, vtMissing, vtMissing,
0 [) r4 ~) \$ q9 Y/ i8 ]# W7 Z        vtMissing, vtMissing);
4 p; `- Q: G  @+ F7 D
9 B8 ^  T+ z1 \. _9 W+ m7 s    system("pause");: l: `( V% @+ B' f
& \" \- s" Q9 x% b5 }! X
    /*读取Excel表中的多个单元格的值,在listctrl中显示*/% O7 q  g. H* N! n0 M
    VARIANT varRead = range.get_Value2();9 ^. l( i8 C9 f" _# P
    COleSafeArray olesaRead(varRead);2 D% Y% X- I# ^& H) J$ c! v
' z# I; o$ _9 J  R0 ~" z
    VARIANT varItem;
6 {; [0 Q( _) U! |7 g  a: d: g    CString strItem;" w" o( d7 v, B; p5 f! O3 B
    lFirstLBound = 0;
, Y: t1 |* _1 c0 b6 ~    lFirstUBound = 0;  Q, \  ~- s, V/ z" l
    lSecondLBound = 0;
: e+ w; k) V: t. F+ J    lSecondUBound = 0;* Y7 M5 U* T, {: e
    olesaRead.GetLBound(1, &lFirstLBound);: N4 t( o* e0 g5 d+ J
    olesaRead.GetUBound(1, &lFirstUBound);
2 B2 y* w2 J2 T    olesaRead.GetLBound(2, &lSecondLBound);
. u2 ^% H) {. j7 o1 c5 u4 G, e    olesaRead.GetUBound(2, &lSecondUBound);" [5 I+ S  N# E1 U9 M
    memset(index, 0, 2 * sizeof(long));. ]1 d* ]; j9 H( R. Q# N) F" @  j
    m_ListCtrl.InsertColumn(0, _T(""), 0, 100);
" d' I8 ^6 F' Z7 o8 [    for (long j = lSecondLBound; j<= lSecondUBound; j++)# v# O  t( P* ?$ P
    {5 o2 Q3 I0 D& ]( A: I& a
        CString strColName = _T("");
. m% j5 w* C' X% o1 z+ R        strColName.Format(_T("%d"), j);
7 ^8 V6 w5 @- O7 e        m_ListCtrl.InsertColumn(j, strColName, 0, 100);
2 ~' R3 z. I/ d1 e0 Y' K7 @  w8 a    }
# m/ P, H3 s5 N    for (long i = lFirstLBound; i <= lFirstUBound; i++), Z& [, p% d; }  m( {  _( Z
    {
% [9 y( y, G9 v( E+ R        CString strRowName = _T("");
8 }' b5 m3 @0 h6 u. w3 w7 P" A  u        strRowName.Format(_T("%d"), i);
6 i- ^7 p* v9 h, Z        m_ListCtrl.InsertItem(i-1, strRowName);
* O1 [; i- v( B9 M9 @: J$ |) }9 T# X, @% D! j4 l" W
        index[0] = i;
3 F" f; q6 n# e, R5 ~        for (long j = lSecondLBound; j <= lSecondUBound; j++)) @" f1 M! d9 T( C1 |9 {/ Q4 o* E: p9 x
        {. ^, V+ p9 W) S5 J) M9 ]' _
            index[1] = j;
, i$ k5 L& j8 H6 R7 y            olesaRead.GetElement(index, &varItem);9 A7 M* }" A7 @. h, ~

' V' E! Q! }3 p: i4 ], Y/ m2 A            switch (varItem.vt)
4 g" l1 m7 I  y8 x& i- y7 L            {0 C/ t$ s% w1 @0 M% Z+ r0 j. d6 W
            case VT_R8:
3 k4 G$ P1 s6 r5 a8 p7 h                {# E) n& S# Z# G
                    strItem.Format(_T("%d"), (int)varItem.dblVal);
  J4 w& T+ U1 e                }
2 v1 j4 [& l) v2 A8 P3 B* [0 I7 C% ~8 O( W( l) F
            case VT_BSTR:
' P' E: {% G9 X6 R                {
! Q4 M: R5 R# f& c3 k                    strItem = varItem.bstrVal;7 t5 w5 V6 |3 R  m& Q/ a* J4 |
                }
! e' B2 S; Y( [9 S3 N7 q8 }2 K1 p% d6 ~/ @1 m$ y6 D
            case VT_I4:* E4 T" M4 R6 x
                {, J; F9 a, Y, r# _
                    strItem.Format(_T("%ld"), (int)varItem.lVal);+ |; J8 [; w: w* u
                }
% t5 h, d9 W0 a" x$ D" q" p1 j4 S
            default:
. `5 t" v$ k2 e* u& ~                {+ H, D: X& d6 t/ R& h" t0 x
6 k4 h$ \8 b- ?( n/ U/ C
                }
$ x' F2 S+ m  S" l            }
. u3 x7 N4 Z( }% y# V$ A7 Z# M
8 k& K$ D6 v2 ~+ b( q6 a. L9 d            m_ListCtrl.SetItemText(i-1, j, strItem);
6 C3 \5 g8 O: L6 \9 {        }- A$ c; h% R9 z% _- A
    }: q% i2 P( U& n7 ^% m

. u" @7 Y6 C6 t' k, q2 j1 B7 o- \5 n9 |6 J. R* s
' O. ^$ e$ W  d0 [
    /*释放资源*/" b) G  L/ x+ S& x9 f- C
    sheet.ReleaseDispatch();
' X( J7 }, D% t5 R. C  Q    sheets.ReleaseDispatch();
9 F% N2 `$ M4 c( u& x    book.ReleaseDispatch();% t; I. m; Y& t" k  Q
    books.ReleaseDispatch();
3 v$ |$ x3 ^1 c' W5 m6 c    ExcelApp.Quit();2 Q4 Y8 r2 ]8 |" m8 w
    ExcelApp.ReleaseDispatch();
3 H! X7 M+ H! ?. Y! U) b( R: V& ^/ w8 P  |9 B
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了