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

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

[复制链接]

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

2470

主题

1275

回帖

8万

积分

管理员

PLM之家站长

积分
82162
QQ
发表于 2014-11-8 08:13:41 | 显示全部楼层 |阅读模式

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

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

x
通过VC实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文主要研究通过OLE/COM实现对Excel表格的操作。
7 I6 b& p; @( P8 f3 v  
6 `: D# u6 j9 Q# I' M* c( [  H本文源码的应用环境说明:
8 |# f# N0 L) `, z: Q2 n5 {Windows XP SP3
6 d) ?; n3 ~( A9 V. Q# R. CMicrosoft Visual Studio 2010
( M4 P& o: ]2 I' ]% _3 hMicrosoft Office Excel 2007
8 G* e& K: c# B( r  A  
/ s7 Q* n: N& @3 ]- q1、添加OLE/COM支持。
8 ?! y0 A0 c" D3 m  u* m( m首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。
, [6 f' D# F. d本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。  i# J/ U2 L8 \8 J/ j% _
通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。9 r8 c% C3 J3 X; S: [8 h$ k
#include <afxdisp.h>        // MFC 自动化类
' T% [6 Y; H+ o+ G8 p6 E( I; b同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:( M, J) O0 p' v/ ~. p; H. l
// 初始化 OLE 库, s* L% [4 N0 B: x
if (!AfxOleInit())
0 b9 u1 \3 Z4 R{
+ A1 _- }1 \1 U1 c6 {& TAfxMessageBox(IDP_OLE_INIT_FAILED);: {  W% Y5 q+ V! x6 Q) |0 R! B& A
return FALSE;8 T, Y! e( j" e0 s! [
}+ D) b' j( J2 `/ S& S3 |5 q- \
  $ o% P  D" m) D( f9 c( P2 U8 n( @
2、导入并封装Excel中的接口
+ |  Q, V" ?5 D9 P3 b* Z/ kExcel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。% ?4 Y; q8 {, s/ j1 F9 |
由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。
  _; a& F# G, p9 _5 }VS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择
  b( Z. j: ?) \  y: _$ w& j要导入的Excel类型库中的接口。
8 N- I2 z+ ?: _' ~在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。9 v* b& N# G3 A
  
* y$ r( l. H* p" D本文所导入的接口对应的类和头文件的说明如下所示:
) ~4 a6 w6 ~/ C, T7 B/ G( \0 a$ ]  5 e$ @5 |; }& L: n+ q6 T
Excel接口
! r1 q0 `2 L3 Q4 e$ I导入类% g1 {# }" S8 i7 ~$ }
头文件
. r! T6 q4 h0 z3 o0 I说明
& \' X) h" u& F; p  ]1 \_Application
* @6 ?+ s6 Z5 e0 G! a- }. j- vCApplicaton
8 ]5 e' j  s+ B( j2 t. yApplication.h
$ \6 ~7 l# ]& x. l4 Y5 C! TExcel应用程序。
4 `* ?4 g/ \% zWorkbooks
1 Z0 q) _0 a4 Q: G& z9 WCWorkbooks5 L3 l( @( z2 H  G/ s) d9 X4 U' o$ h
Workbooks.h
* |' \6 a& l# [% }" Y! a工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。
: U! f! \9 v0 H0 p& Z8 Y/ R) ^7 L_Workbook
7 w5 X9 l' K6 e# P: `CWorkbook" N9 t5 w8 l7 d5 n5 x6 _: N6 s
Workbook.h$ ]* I- t! F( I
单个工作簿。6 \1 @6 i) v! j+ d0 t* X
Worksheets' g2 \. x) E: M) y
CWorksheets5 ^" B9 ~) A, ]8 ~
Worksheets.h! T6 B% _) e0 P
单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。
0 d1 F; G6 d$ E0 H' Q0 {_Worksheet
, U7 y0 {9 S$ d! c4 hCWorksheet* T3 _( K7 d1 j
Worksheet.h( @: y* _4 ]" A- u
单个Sheet表格。
9 ^( W) @$ k" G3 `; P& rRange' m  l1 f  f  B' }* D, i7 {! c1 s
CRange
* X1 Y! b' Q9 f, I* m( iRange.h
) O) r" e' A5 n7 C# q一定数量的单元格,可对单元格进行单个或多个单元格进行操作。9 `( v/ g2 E, d+ \4 W3 B
  
8 N: B& f/ f, A9 ]3、导入Excel的整个类型库! K' L  M! Y: A( K" `. R. |' I
接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
! W) Z1 n0 m8 r) j通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:0 s( |5 z/ a* G% o+ c
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
4 c5 ]! \* C/ z8 C) x这行代码的作用是导入Excel整个类型库到工程中。' m' Y+ |; j1 p3 p4 k! z, h
由VS2010自动产生的导入代码存在以下几个问题:& q) y* |2 ~8 N3 h1 x# I* z
(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。) w6 j# }- g5 T8 i" Q
(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。
& J! T/ y6 r# ~$ k$ {  l(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。
! m) `0 d" \- {以上三点问题的解决方法如下:
8 H/ B" Q. Z; L4 I+ j' d(1)仅在_Application接口对应头文件中导入Excel类型库。) t- J- o0 {3 D7 R0 t) Y' R
(2)对冲突的类型进行重命名。
& C" M& v: m0 [9 {" G& @6 o(3)在导入Excel类型库之前,先导入Office和VB的相关库。
& C  a( x- H" [; z更改后的导入类型库的代码如下:
6 e2 t$ o7 [- b5 Y1 |5 X+ s  
% @9 B3 J! X! F$ H2 M  w* [  }/*导入Office的类型库*/
! o8 ]' z& [! D9 Z& Q8 n#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \
) `; \9 p- ~" c) y" [1 lrename("RGB", "MSORGB") \
. ]. U2 [) r' k5 I6 Brename("DocumentProperties", "MSODocumentProperties")- A: {6 [2 a# ~! Q$ z
using namespace Office;
! x5 P2 g$ g' I; R6 C  ( _  }/ B. s3 \) x
/*导入VB的类型库*/
$ }/ y; u  D$ u7 |4 ?#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
0 M2 L/ Q. w# {- O$ f" C: pusing namespace VBIDE;6 J  ]! Y! Y6 H2 Z
  
+ J$ X. `; v) m( J/*导入Excel的类型库*/
" ^0 R+ o6 U; c  U0 }#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \
0 w" r% H3 ]# O0 Rrename("DialogBox", "ExcelDialogBox") \- i6 [+ T# O: |6 e$ z5 N2 G% w2 y$ C
rename("RGB", "ExcelRGB") \  z9 p, H" f0 D# W
rename("CopyFile", "ExcelCopyFile") \
; g! o) N3 \8 @+ U! A* ~rename("ReplaceText", "ExcelReplaceText") \+ i" E4 g/ B2 Y. ~, y2 ]1 P5 F
no_auto_exclude" J" }6 R5 l  ^) b% g  [' Z9 Y
Using namespace Excel;4 U. x( m  C+ U8 Q$ N
  8 m: Q/ _5 x' N/ e5 l
编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。% X( l# ^' j/ L8 ~
  
* s7 H( ~; {% v. [4、操作Excel步骤
5 J5 K% k, Y, G# J操作Excel的主要步骤如下:' I  V  h& H, X* b- K9 i4 Q3 F! z
(1)创建一个Excel应用程序。# T0 |$ w7 M+ @7 Y
(2)得到Workbook的容器。' I! t3 H, \+ U7 b! C" Y( `/ m' R
(3)打开一个Workbook或者创建一个Workbook。
+ R% a4 k' z4 {(4)得到Workbook中的Worksheet的容器。* T( N/ y9 w0 F8 b
(5)打开一个Worksheet或者创建一个WorkSheet。
  j# h$ k: d5 D& {' d6 l5 ^2 K(6)通过Range对WorkSheet中的单元格进行读写操作。4 a8 F) D( {/ I  |6 P  b9 J9 L
(7)保存Excel。7 Z& O3 _" I, K/ q" n
(8)释放资源。
% ~' D: s  b4 X0 y) D$ O/ `. K. W  
4 r+ P1 H" {" T& O5 e: Q% \5 t5、批量处理Excel表格, E0 y( r- N+ d' e/ L
VC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。
& q( [: A) @. H7 X5 M对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。# i/ I7 z) k& G1 f" `  Q7 T
VARIANT get_Value2();0 c) g8 I# Z1 y* ]7 i
void put_Value2(VARIANT& newValue);3 ]$ O( W6 p) ]$ I$ e
其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。: x0 ^* n  P. X( I9 _4 z
其中,VARIANT中实现二维数据的方法可参考
- V0 l5 @- s" w7 t: k9 {3 L5 B) shttp://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html
! H' K7 A% Q. k+ `' u8 Y) L当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。
6 E& g8 n: x  \4 s/ C/ ^  
, |$ _8 j0 U0 b! w% i* A/ c3 m4 w6、Excel表格的保存
. e7 s) f. C  R% d: n+ e/ G! M- Z(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。9 j, n; ]0 \3 M6 C& z5 Z
(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。- w5 Z9 C+ t$ p7 ~
SaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。& z" K+ v0 n; m% M
  3 t# M% r( @+ l" y0 X# i) ?3 W- e& n
7、获取当前Excel的版本
5 m, C7 a7 s7 F% P8 z$ p% `7 k可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。6 M5 C9 g  e  X  r8 K% e
  
, T% Q% [- p( A8、示例源代码' X. I0 r  O: e" R& O) }( ]
主要代码如下:7 D$ f+ p) D4 o) s8 }$ D
  
# W+ T! O  j4 }, U; {) [) r( E# X0 `; T/ V' k3 U

9 V* T$ f1 }2 l* }& h& X    m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);
4 q( M$ H4 C8 d$ k, b* w5 @( [5 a% h5 w7 V+ C8 T
    CApplication ExcelApp;
! F4 }9 _' w8 F  Q3 I# K    CWorkbooks books;  J3 Q- h' ?* R) o
    CWorkbook book;. v4 Q  w  I5 S+ n  n# L
    CWorksheets sheets;
8 s+ h6 {: r. L- O) Q    CWorksheet sheet;# G& P7 O0 r& \! q  R
    CRange range;6 N: W  m9 E% U) Z) W- p1 O$ n
    LPDISPATCH lpDisp = NULL;
( c1 i3 H4 M9 u1 Y  _2 K: m5 v2 W
    //创建Excel 服务器(启动Excel)
! b* u$ k  a1 S, n$ r6 P8 f! F5 K    if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))+ b! V# I) \3 i* q9 o1 f) B& B" R
    {
/ X9 V6 t4 m4 @3 I9 F3 A, ?        AfxMessageBox(_T("启动Excel服务器失败!"));. i$ ?: Y, m. Z1 b4 M9 k; U: R
        return -1;6 M8 Q4 P$ M+ p- p
    }5 U/ E$ Z" a3 p0 j( t$ H7 Q
7 x% n3 d1 J2 O$ S5 G4 C# @( k" O
    /*判断当前Excel的版本*/: @: P- I& D; I2 _' x+ Q3 a
    CString strExcelVersion = ExcelApp.get_Version();- J! k* S, B" h& A/ `, [0 o, {
    int iStart = 0;
. z  N: e0 t* \7 f3 }    strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);! n+ d, u3 R9 ^5 t5 I9 i
    if (_T("11") == strExcelVersion)* Q, G8 m) {' v: t+ y
    {/ a! m  P# [4 I& [7 \
        AfxMessageBox(_T("当前Excel的版本是2003。"));. S5 [' d% D1 v9 t4 A
    }6 {% x4 ^1 d/ z0 C' h: C
    else if (_T("12") == strExcelVersion)& e5 o/ e( F/ L. ~: t6 K. a
    {
% x+ l& [! M) r( G0 c        AfxMessageBox(_T("当前Excel的版本是2007。"));
) |0 n, R$ z  f" i/ d    }
5 U' E7 _! F/ o- o. S    else" V( q1 S) r2 \9 u
    {# t+ M$ T" k; I( U
        AfxMessageBox(_T("当前Excel的版本是其他版本。"));5 Y9 z- E9 d1 V1 }7 X0 W; O( W
    }
" [% `5 z* b  Z/ o
' `' ~  @# X5 H2 D( s- I- m& E8 P    ExcelApp.put_Visible(TRUE);
# T/ i  r5 f# u: y0 q    ExcelApp.put_UserControl(FALSE);8 d' J5 T- L  a2 z' ?

$ g4 P9 {. |& l" `1 w5 l, A    /*得到工作簿容器*/$ c/ t1 R; f: ]+ b5 t/ C6 z% h
    books.AttachDispatch(ExcelApp.get_Workbooks());
6 v. z1 h; g+ f4 v  j) G0 W# {- W5 [* b7 }& R
    /*打开一个工作簿,如不存在,则新增一个工作簿*/$ I. ?" q3 K& t$ f: P8 W
    CString strBookPath = _T("C:\\tmp.xls");6 T7 J7 r+ }+ W$ X8 D" f
    try
, r2 Z1 _4 W5 T* f+ ^* r0 u    {
4 W7 }- g" ~; Z9 V        /*打开一个工作簿*/" P) l* _% F: t) b& t( a
        lpDisp = books.Open(strBookPath, & e( t/ q1 {( \
            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,% l- k0 e# ~- q" h' T) p4 E
            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
9 V7 L$ S) l3 ]' }; A- J1 `7 u            vtMissing, vtMissing, vtMissing, vtMissing);
# W9 ~6 P, p( r6 a        book.AttachDispatch(lpDisp);
2 J! C* W# r( E    }1 i, o3 B' l3 j2 M' t* ]
    catch(...)# Y- M3 P: D% e2 F! g8 u
    {) s) \& c5 N7 t) e, x& `
        /*增加一个新的工作簿*/$ ]' r2 ^5 r& h3 j# m
        lpDisp = books.Add(vtMissing);
) o) L2 J8 z" A$ v5 b1 G        book.AttachDispatch(lpDisp);# m/ X! i9 r2 S2 x  ?! t+ I! ^
    }
% [7 H* A( p, X  t" c' ?2 z% P     
, \* Q) Z9 j+ H/ ^$ h$ g
, h5 l8 e) M% J# R: u+ ^0 o    /*得到工作簿中的Sheet的容器*/
3 M1 Y/ |/ U& A8 D9 v    sheets.AttachDispatch(book.get_Sheets());- U) \5 l" v! J, p+ U$ l

( k2 v5 ]& K  m1 @! B# P    /*打开一个Sheet,如不存在,就新增一个Sheet*/
; u2 ]5 n: o& |+ P    CString strSheetName = _T("NewSheet");5 [5 N$ t  ?7 z1 x3 N0 B) o2 b
    try
1 Q/ e  l6 A- F7 C: w    {
) Z9 U, u  a' F$ }+ ]& X        /*打开一个已有的Sheet*/4 c) q1 J% B! z$ u
        lpDisp = sheets.get_Item(_variant_t(strSheetName));
* |- l/ \5 M! `( }# y  g        sheet.AttachDispatch(lpDisp);
6 x# [8 q4 G6 J! n3 r" U6 Y( ]; z    }
! l+ ^% z6 }2 D# b    catch(...)$ C5 V* j2 V; T6 X3 U
    {8 Y( S+ b( K: m$ n7 Q( `& b+ q: [
        /*创建一个新的Sheet*/
) v8 |% t4 h0 g7 ^7 y1 O        lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);& r/ I1 E- V3 z# q
        sheet.AttachDispatch(lpDisp);, B, I/ z; F$ |- j$ Q# L; H2 w
        sheet.put_Name(strSheetName);
6 Q4 M! ~" N- _1 j, \6 ^    }- Z7 |1 P5 `# l' T, N1 Q
7 X+ m5 l/ Y; @5 p3 e. A$ S- t
    system("pause");8 Z$ [: z) f9 y

' z4 \! u+ ?8 M, x# O    /*向Sheet中写入多个单元格,规模为10*10 */) t  s8 f/ ?0 W- o( c% P, m7 d
    lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));
% m! ]2 q/ T: o2 j+ y    range.AttachDispatch(lpDisp);% f2 ?" N+ h. k* K9 `! A2 K
1 K% ?2 B' V! i! E
    VARTYPE vt = VT_I4; /*数组元素的类型,long*/8 B* Q: a- L* }5 E! U: ]
    SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/* V8 ]  |5 d* O( J
    sabWrite[0].cElements = 10;
4 C, m. [$ L& u& z    sabWrite[0].lLbound = 0;
* A$ s% X# a. m! v1 K$ C    sabWrite[1].cElements = 10;
' t- O. L' Y, E% n8 j    sabWrite[1].lLbound = 0;7 U2 y- F$ W& z) y' ]
0 }" l" K. }! @, u* \6 T5 z
    COleSafeArray olesaWrite;. R; k0 L' V: P7 ]' `
    olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);. A7 g; [+ a! P3 x

# X# Z( y; i4 X3 h    /*通过指向数组的指针来对二维数组的元素进行间接赋值*/4 Z( e- B; Q* b& X
    long (*pArray)[2] = NULL;
" H3 F3 i& S5 x+ `% P    olesaWrite.AccessData((void **)&pArray);
' |8 S/ v( S% j" H# c    memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));
8 b- h8 d5 g5 F( _$ k; ]+ ?8 J" L0 m) ^' {# w# O
    /*释放指向数组的指针*/
$ V# U) r% {6 o  z  X% C$ Y    olesaWrite.UnaccessData();& Y' [8 J% t3 Q1 Z% r' v  W& x
    pArray = NULL;
, X7 o- }( d( ]+ g% K' ]( c( [* I  N
, l& E. e' g2 j1 \$ T* {    /*对二维数组的元素进行逐个赋值*/6 q' G: P1 ^. [6 V
    long index[2] = {0, 0};
+ U; p2 _- k5 C; D3 F* j2 [3 {2 S    long lFirstLBound = 0;
+ i2 [/ C9 T" [$ W- r% M7 J+ }/ K    long lFirstUBound = 0;
! g) b* B  {9 w  z    long lSecondLBound = 0;
1 q; G8 A2 f- H) E5 c; v: B    long lSecondUBound = 0;
4 Y! M$ @# H$ ]* U: F2 N* h7 P    olesaWrite.GetLBound(1, &lFirstLBound);
( ~4 ^9 F+ J: e$ W, x9 G' Z  r' n    olesaWrite.GetUBound(1, &lFirstUBound);8 J7 s6 m2 e0 u
    olesaWrite.GetLBound(2, &lSecondLBound);! l) b  ~& w& Y" u5 ^$ J
    olesaWrite.GetUBound(2, &lSecondUBound);
6 y9 T' r' S- Q7 i9 v6 ?1 j8 ?1 _8 k    for (long i = lFirstLBound; i <= lFirstUBound; i++)
5 l1 S2 t: a* Z9 m" t8 k+ B. |    {8 p; m; Y% U. k0 j
        index[0] = i;% B: a0 f2 h0 V- i
        for (long j = lSecondLBound; j <= lSecondUBound; j++)
% x3 ^4 D& u0 v; x        {  O2 c" x. g$ ^1 Z- f& n2 {6 L/ @- L
            index[1] = j;9 o; B, q$ i/ [) v; L" l  H. P
            long lElement = i * sabWrite[1].cElements + j;
* A$ h; b8 a" ~6 Z            olesaWrite.PutElement(index, &lElement);4 b( h. U5 j2 s7 O
        }
" E) l5 s) C8 ]. e7 e    }# `- K1 z! H4 P  V
, F5 G# G, g, c6 q' m
    /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/
" Q1 k" E' M3 u6 V" f    VARIANT varWrite = (VARIANT)olesaWrite;9 _  Q( U! {0 s# g2 ?7 ?/ Q& d
    range.put_Value2(varWrite);( \7 X9 d( k6 u, }# H

# N# \$ |, |3 p2 o: t    system("pause");
$ [2 J4 h. D7 y8 C+ A+ G5 [- K4 V$ S% B' K8 _$ J' q
    /*根据文件的后缀名选择保存文件的格式*/. N! E& V& u) s* ^: p1 E( X
     CString strSaveAsName = _T("C:\\new.xlsx");
2 Y  u# K$ O( J0 N    CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));
. q1 [- {( Z, g' f* U    XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;& [$ u& t+ J, J& ^1 f, H
    if (0 == strSuffix.CompareNoCase(_T(".xls")))
7 ?* h0 m) a5 y/ Y1 Y4 c1 R4 n4 i    {% P2 e8 t" m0 w; m7 Q
        NewFileFormat = xlExcel8;% x/ O9 e/ U5 X8 O; [
    }
9 i) f& f: W& ?- N8 v, e  Q. q* ~    book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, 6 T0 v) {9 H) q3 J! h' S
        vtMissing, 0, vtMissing, vtMissing, vtMissing, 4 T6 B, l/ x/ t* f/ S
        vtMissing, vtMissing);
0 R3 j+ K% W5 H, |' p( U9 p( ~
' n2 T# v) K' k2 N: r: ~    system("pause");
5 `0 B; \/ L; g: ~
( l- _( S2 F2 c+ c    /*读取Excel表中的多个单元格的值,在listctrl中显示*/9 G2 E" a1 C2 X0 Y% [1 K
    VARIANT varRead = range.get_Value2();
5 N& G7 W3 s: m- k7 K& L    COleSafeArray olesaRead(varRead);
  T+ G0 D' U8 E+ y& |8 h( B* V
( d' R' n3 \. R$ a$ x/ ?: @+ f    VARIANT varItem;
  ]2 y' q( i" m0 F    CString strItem;
! U+ \$ ]1 v  S4 B* ]8 t    lFirstLBound = 0;( c; j4 y& I, o* \* u" u" G. `
    lFirstUBound = 0;: v4 ?$ T$ p( R: N/ x& ]/ \8 H) m
    lSecondLBound = 0;2 u( O' O; ^" Y" P3 G+ @
    lSecondUBound = 0;% z5 K# j, O& ]+ N/ v) N
    olesaRead.GetLBound(1, &lFirstLBound);
$ h% f$ w8 k% c4 |* S3 C5 A    olesaRead.GetUBound(1, &lFirstUBound);' c- h' M3 I0 s+ C, a/ B# E
    olesaRead.GetLBound(2, &lSecondLBound);0 f1 P: x' z2 O$ o$ e, h
    olesaRead.GetUBound(2, &lSecondUBound);& h9 q9 M: s" v4 l$ y. X
    memset(index, 0, 2 * sizeof(long));6 _$ @( j2 Z! S
    m_ListCtrl.InsertColumn(0, _T(""), 0, 100);
) ^5 v5 z: A$ g0 l& H: G+ G    for (long j = lSecondLBound; j<= lSecondUBound; j++)) T( V; g  s" t' ]6 Y, V/ R9 [
    {4 U! k8 S0 D7 a7 p* B) W8 a/ n
        CString strColName = _T("");
; x2 j% q& M) p        strColName.Format(_T("%d"), j);
# v; Q: P- w; E5 N1 \# a8 N3 x        m_ListCtrl.InsertColumn(j, strColName, 0, 100);
) {* X# n4 r$ I/ o- n    }! ^/ T! T5 R$ S1 M5 v
    for (long i = lFirstLBound; i <= lFirstUBound; i++)  Y# h$ I6 g  x  q4 h1 Q
    {
, d3 I' D5 d  P% c+ ?; O        CString strRowName = _T("");# V* s9 j8 S5 X; Q" Q
        strRowName.Format(_T("%d"), i);- v' [! E$ w7 v
        m_ListCtrl.InsertItem(i-1, strRowName);. `2 @" d% H6 A' U& B8 R, P

. F& T1 b, [0 M" C# f, D        index[0] = i;! a. l$ P3 h7 @% @! I
        for (long j = lSecondLBound; j <= lSecondUBound; j++)9 ?. v/ C6 w2 A- J/ K
        {  e; s' S0 f. G$ g
            index[1] = j;
* ~* V/ F3 o4 B& z            olesaRead.GetElement(index, &varItem);; M7 t0 {4 R' A' p( @& e

1 E. W: f8 C/ u            switch (varItem.vt)
, u& ^+ @% E$ j% I0 f* s& z6 o            {1 s$ G. B. Q8 N+ J7 N* g* V
            case VT_R8:0 M: c) H% K/ R# F# T( w
                {
9 o3 }/ S- d+ j                    strItem.Format(_T("%d"), (int)varItem.dblVal);5 \- O4 w; {; L% A. h
                }
1 ?7 E! P9 T: }" ]2 m3 ~3 i; B2 J* M& h" l& T+ }$ o" `
            case VT_BSTR:
4 m! H+ p, Y: l$ L$ Z, B                {: a) A$ f9 M: ^+ ^/ R
                    strItem = varItem.bstrVal;
9 `4 q! i. @; r( l                }7 P4 I* |% a  F/ b

0 j. J8 S& b9 {& ]; W            case VT_I4:
3 a( u- @5 G4 e) v9 t                {$ Z/ Y, m, C0 `* j( z2 ^
                    strItem.Format(_T("%ld"), (int)varItem.lVal);
6 v9 N* e$ V* ~6 o3 r  [  {                }6 ^+ h+ w1 q, z. V8 s

% U- @5 i' A. v" C- ^) I            default:
' h) m$ l. d1 Z6 _; w- K! Y7 m                {
2 n- J9 W& L4 e3 J% C7 G0 o. @6 y. L# U3 w6 p/ A+ g2 o
                }& r' x7 S! @; Q% U% W5 A
            }0 e9 G2 m! R+ M
' A8 v- |! }9 Y* b0 @
            m_ListCtrl.SetItemText(i-1, j, strItem);
. @# W+ _. ]( H9 P) L! v3 ?8 |7 f- x        }
- _0 u4 |) w) i* B: W( h( P    }
2 W0 I/ p) n2 w2 f  D- o" Q) D& |, d0 f& i- ]) ?
7 E( [& O# F" l9 t

- O. L  M; X) k    /*释放资源*/
- F; S" H! p' C, ^    sheet.ReleaseDispatch();+ _2 f6 \# J- k; I7 y0 o
    sheets.ReleaseDispatch();+ T  w# J! e. W; R+ ?6 h$ {
    book.ReleaseDispatch();* J0 [5 y5 \# C4 r9 P) M
    books.ReleaseDispatch();+ ]8 k6 n, K1 {) q  V' F
    ExcelApp.Quit();
# Z# _! o* Z( f5 ~# b    ExcelApp.ReleaseDispatch();
0 k2 g: C; e+ q, Y1 @: o! o  I; V6 `) T6 }/ K; R* k  P
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了