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

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

[复制链接]

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

2470

主题

1275

回帖

8万

积分

管理员

PLM之家站长

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

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

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

x
通过VC实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文主要研究通过OLE/COM实现对Excel表格的操作。" l- a% N8 `6 x3 `' r
  % c8 `6 V6 T( U8 R0 F0 @+ ~5 D
本文源码的应用环境说明:# |4 j1 p+ Q+ ]( [: t! O  ]8 _
Windows XP SP3: R4 w$ Z6 U# n/ E% W
Microsoft Visual Studio 2010
  E. g8 L7 v4 A( E$ iMicrosoft Office Excel 20079 v% m+ V3 z7 k
  
' I! I0 C# N' _: p7 U1、添加OLE/COM支持。
/ V, y0 _* o# U首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。
% F* j. `7 n- O3 c) K本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。* x& J/ j& }+ j. ^
通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。
$ P: z1 ~( y+ D% @. J8 L5 ?+ Y#include <afxdisp.h>        // MFC 自动化类# K: u8 w' x1 s  Q. R5 E5 ?
同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:
6 z+ x7 {% x" x0 Q1 k0 N// 初始化 OLE 库, G- g+ f# C) x0 ]' g0 V* y! `
if (!AfxOleInit())& c- b  p; k) o4 j' E. V
{
+ x% T- ^0 O8 ~6 B  ZAfxMessageBox(IDP_OLE_INIT_FAILED);
1 ?* s- o4 N6 o# [$ hreturn FALSE;
3 I1 D+ V9 ]4 _" W}& _) N; H& _4 Y  g. ]+ c
  8 m7 k1 X) f; j6 y) Y1 f: `) ]
2、导入并封装Excel中的接口, s  w6 @6 ~5 z7 i" ?0 |2 J
Excel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。6 W2 ~0 t1 |8 D$ |
由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。* U" v* ^: s- E; s* S! O& V1 @$ J
VS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择
  A+ n2 H5 N* Y: _0 h要导入的Excel类型库中的接口。
& f6 h% m3 c7 @6 A% \8 Y" N在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。/ [1 K& N& i; ~: W
  
9 |) Y& Y0 _' q" H. [. d! B本文所导入的接口对应的类和头文件的说明如下所示:
8 e$ B" R8 v9 n/ Y6 H( O  
* X# X- S2 |3 rExcel接口1 ]* F5 F4 t# L, q
导入类4 }$ N  a, W* \
头文件# \9 m+ {, Z1 f7 h" b7 x
说明) n- T5 \  d+ K# f1 k) d, a% I+ b
_Application
7 G+ o" e8 e9 F. y; g, mCApplicaton
. y* R& P; A9 iApplication.h: S( ?- h6 H9 k
Excel应用程序。7 T& O4 |: R% v" \
Workbooks: k9 D2 D, Z5 v  {
CWorkbooks9 k' ^' O" e$ [3 V  W4 V% T
Workbooks.h
' E: V: Q3 c1 S工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。9 e4 p6 r1 m3 u9 Z' G& ?2 B7 y
_Workbook
7 T# f# K9 o0 C' C% w0 z0 sCWorkbook/ s8 ^% @% i" N% L- f
Workbook.h
0 f7 |+ Z  D$ V# G单个工作簿。
; _* S' K6 P' c1 X% ?Worksheets5 @' K6 U0 V7 M1 |9 ~( M
CWorksheets) ^' v: k6 j; s& y% y8 s/ J
Worksheets.h4 Q5 I) ]+ U/ ~+ t/ q1 O
单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。
) r: g8 X# x: C) s/ B& ]- ~: [8 r_Worksheet
5 r+ K/ Z8 Z9 ~4 Y. q. w$ H, oCWorksheet
, m+ G9 ^! l: F' hWorksheet.h
0 [% T, }: l9 H6 l( ]6 H5 M+ x单个Sheet表格。
% M( E3 C) u' I( t; L4 @/ e+ R! k* @6 [Range  O' O' ?- R. B- l: V
CRange1 A, b# {9 T" @# c
Range.h  L+ N5 K: B4 j3 Q
一定数量的单元格,可对单元格进行单个或多个单元格进行操作。; ?1 s7 N1 A/ w7 n- ^# j
  % y( b7 {# }2 z( M, q7 ]  F4 q: O
3、导入Excel的整个类型库
9 t1 U4 l9 I0 K2 R0 n4 p7 `接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
7 [, G! q! u! w) Q3 [1 [/ o通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:
$ S5 W& K  u! `9 z#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace0 p' l9 |2 e$ ?. h
这行代码的作用是导入Excel整个类型库到工程中。7 t* w' C& y4 X5 n' _
由VS2010自动产生的导入代码存在以下几个问题:  Z! B" e. p3 ~6 s
(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。
! d6 g) L9 z/ \' y(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。! c& m7 O8 X$ P9 p7 [& x
(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。- H) l: P& p  F: N1 {8 w  w
以上三点问题的解决方法如下:6 U; a$ I/ n! T9 V
(1)仅在_Application接口对应头文件中导入Excel类型库。
, I  P: ~- B& {9 w/ h; L& q(2)对冲突的类型进行重命名。
1 F& G4 [& e: c' |/ E, s" {- K3 R8 [(3)在导入Excel类型库之前,先导入Office和VB的相关库。
9 I) N2 N6 L! Z; X# c. _更改后的导入类型库的代码如下:; G  I- f$ L9 m4 W; j
  
3 w6 F) q; i, Z6 O/*导入Office的类型库*/6 C/ {* Z0 `" G3 Z2 n  t6 Z  q
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \
% s2 M* G0 M2 ]; V) u0 U/ Vrename("RGB", "MSORGB") \
; }$ c; j% c. @1 p" k: c8 qrename("DocumentProperties", "MSODocumentProperties")
+ G4 ^7 |3 X9 e0 J3 Ausing namespace Office;
3 f; |" r! H$ Y  
1 z: I9 N) J& w: n& e/*导入VB的类型库*/
- G! ~# @9 R# d1 P8 \" X$ Z#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"5 f# x$ P: `6 N, w& r- P/ ~
using namespace VBIDE;$ X9 v- l- J3 s1 B' P4 l7 g
  
- Q8 M. u, o' y  ?/*导入Excel的类型库*/
5 u% {  {+ |4 u0 W( ?8 s#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \
: O7 |, J! E: ]: E# @rename("DialogBox", "ExcelDialogBox") \' v: G" b/ t9 q& F0 \$ P
rename("RGB", "ExcelRGB") \, Q- o9 T# B% f; O% W& B. Y" p
rename("CopyFile", "ExcelCopyFile") \8 c4 w; {) L  ~! [% c  Q5 s" D4 g
rename("ReplaceText", "ExcelReplaceText") \8 l/ ~( b' [* U3 V- ?" l
no_auto_exclude
  |9 L$ h: X2 y7 Q8 }7 D2 G; {/ F1 XUsing namespace Excel;! S) o  z+ I1 Z7 @
  % c7 ]# A& \' G+ s0 c: m& L! g
编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。
, ?& I  ~( {& |# j0 W! L+ C9 K  
& K. f3 y$ J2 |+ I$ \+ g4、操作Excel步骤7 C) _; Z$ I- Q1 B. `! K& Y
操作Excel的主要步骤如下:
' x4 T+ n* ~8 H! v+ G3 x- q(1)创建一个Excel应用程序。5 z7 f6 g0 q) x
(2)得到Workbook的容器。5 P' G( I5 z3 Q- C( C
(3)打开一个Workbook或者创建一个Workbook。
0 G& P, W, t( T+ q(4)得到Workbook中的Worksheet的容器。
: ^; K( }4 {- N2 \7 H(5)打开一个Worksheet或者创建一个WorkSheet。
6 E% l, t( D, t8 v(6)通过Range对WorkSheet中的单元格进行读写操作。
% Y% r3 m# h& e) s9 p: g(7)保存Excel。1 B+ I* I8 V7 Z4 e
(8)释放资源。
. m7 p  f  b/ \! W  ) J3 k( ^0 I) S" t0 _: l
5、批量处理Excel表格- g! x8 p5 x8 s& D& Q" t7 E
VC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。* i, V$ ^5 U3 u' u8 w( g" \
对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。
5 t% ^3 g( m$ _$ M! x% v7 N2 VVARIANT get_Value2();
! V4 r7 l: x: t. s7 |void put_Value2(VARIANT& newValue);3 \5 ]$ ~1 s4 A6 f; O  W2 B/ Y
其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。- h9 f# `' O/ P, g
其中,VARIANT中实现二维数据的方法可参考; g& {3 t/ b% t" M
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html
& U7 ]" @+ z* v% Z) Z当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。
) T0 S: @1 K; {: i  
! e' g7 ?. G7 T1 `& a6、Excel表格的保存
6 d+ q! V  }/ t# T: B+ F! e( @0 I(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。
5 o5 n- ?8 F3 D4 d8 d(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。
: X/ Y% @. X0 J+ O* T" gSaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。
" K2 K' h3 Y) }0 y6 s- x$ z  " h. I. i) a! J. g( g) ]1 w
7、获取当前Excel的版本
! n% v; }( w* c- G$ X6 R/ v. M$ {9 j7 \可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
& P. t- X$ S/ P9 ]6 T" W, t  " K. n; @5 c) \& N+ t; z
8、示例源代码1 Z4 |) W5 ]: N# l
主要代码如下:* w" y8 ~) B" k
  3 q9 Q, `+ W# Q
. C9 _$ u8 S% ]# @3 }- Y' t+ j2 K( R- F
6 v3 n8 K; P2 g
    m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);* Q: g- n' B( V( l: t. E% @
9 u! m! w) ?1 M
    CApplication ExcelApp;
5 M0 t  y8 e9 |+ _- P- g    CWorkbooks books;) ^8 k6 V$ A/ s. g: [+ D
    CWorkbook book;
7 a% B! c- J) `5 z5 l( x6 m    CWorksheets sheets;) |* m3 n) t5 i' I
    CWorksheet sheet;
# v3 F0 s8 k- I. z' ]    CRange range;
- q0 k( l' ]% F" M: f    LPDISPATCH lpDisp = NULL;7 W- }5 m" i8 k7 b8 n

$ F" b+ Q& F; }8 O  T, X    //创建Excel 服务器(启动Excel)
" ?8 M0 |& q+ M. b' f# G4 n    if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))8 y$ Q6 @5 Z7 X0 c0 I2 \+ D3 z  }; g
    {5 ~  V1 a$ c/ _- m/ E- O
        AfxMessageBox(_T("启动Excel服务器失败!"));7 s7 T& _% R! Z# P
        return -1;" ]; v! q% ]  S' j' k) W# C9 e* V: m
    }
" l. ]3 a- w5 L4 e4 k' I6 R
' y; s) I( S9 h" k2 z8 O0 ?1 X1 A3 t    /*判断当前Excel的版本*/2 q" P# l; i1 C' L; D; l/ J
    CString strExcelVersion = ExcelApp.get_Version();/ [' D" t% @/ n: Z5 M# f
    int iStart = 0;: s0 Y9 R0 K$ |( H
    strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);5 K. {" L2 j# X+ H# `6 }1 P  a9 R
    if (_T("11") == strExcelVersion)( b& ?5 d" z# D2 `. i: x6 J8 e6 k: S
    {8 _8 L" ?7 N9 b8 @: O# g& B" @2 e9 p
        AfxMessageBox(_T("当前Excel的版本是2003。"));0 }! I+ z- i% f- O. a5 U
    }! l5 s! J5 @7 B; e) {
    else if (_T("12") == strExcelVersion): R6 Y: M$ f, r4 F7 I) @9 j
    {, a+ J3 y, H% q
        AfxMessageBox(_T("当前Excel的版本是2007。"));
( v* d* y5 X# u2 m    }  c. [0 U! v" d$ E# v$ |/ Q- u
    else
1 O' Y" {0 ~# v    {
/ x2 x  k- Q' J; A8 p9 k3 Q        AfxMessageBox(_T("当前Excel的版本是其他版本。"));
) a+ |! B) f5 O    }
8 G0 a6 f$ h5 e" A) _& C$ o
1 [3 {8 T7 f( O; N    ExcelApp.put_Visible(TRUE);" G1 q# J# P4 E  ], s! J, a4 p( r
    ExcelApp.put_UserControl(FALSE);) }# v* v9 n) }: }
( w) M4 K+ c2 W( ?0 w" N
    /*得到工作簿容器*/
; `4 x: w' i9 }$ G6 @    books.AttachDispatch(ExcelApp.get_Workbooks());
8 B; q# G1 e; b5 m9 s/ ~0 ?6 F. R: y2 n- O% C! a  J+ O
    /*打开一个工作簿,如不存在,则新增一个工作簿*/
$ f! B6 X% p3 \7 }% @3 Y    CString strBookPath = _T("C:\\tmp.xls");
- H% n& L) \+ Q3 m4 K) N    try' u( k! Z1 O  l& y# A/ X
    {, r: a! A! @& q; A
        /*打开一个工作簿*/
9 k7 U6 _2 f8 g        lpDisp = books.Open(strBookPath, ( w1 B  J5 M5 X9 G+ u5 U: `
            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
* g( G  L& X+ |/ f* U) S            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
% u+ f  p/ b- ?  c+ A            vtMissing, vtMissing, vtMissing, vtMissing);& r, C; f3 k& U6 ]" O
        book.AttachDispatch(lpDisp);
7 B% Y' _5 F! ]8 |) }! ~0 ]    }- G/ T# G9 h" o5 i( ]- q+ Y
    catch(...)
  w  P3 E; s/ W! H- L    {
# d: y7 X: L8 k        /*增加一个新的工作簿*/5 p9 W$ u7 S! c# s4 G! [
        lpDisp = books.Add(vtMissing);
, H3 L9 @) C/ S        book.AttachDispatch(lpDisp);+ D! |9 s) G, s. C
    }
( Q- s& b6 V  H- {7 y# ?  k) M     # P1 y2 F$ G" m1 S% b3 B

! [3 S3 c/ ?) z  @1 W    /*得到工作簿中的Sheet的容器*/
8 u: ?: f9 a6 d9 m0 B6 D    sheets.AttachDispatch(book.get_Sheets());1 e# ]- @5 p3 y# w, l8 b
) l9 Q& D. u9 k- @) G6 I
    /*打开一个Sheet,如不存在,就新增一个Sheet*/
: m/ h  [; X. S    CString strSheetName = _T("NewSheet");. A7 a- Z, g; {5 A* U
    try
! e9 r& H2 g% I    {
9 J" ]) q7 }- K$ G8 C8 L        /*打开一个已有的Sheet*/+ H0 F% r. S) Z/ ~' L. e9 E) `. x
        lpDisp = sheets.get_Item(_variant_t(strSheetName));
5 U/ O$ f. X9 |+ d! ?! S5 S        sheet.AttachDispatch(lpDisp);7 U- v# ?% U; \# W( B0 A
    }
4 h  P% P( y2 F    catch(...)0 Q) O* T& `5 J' Q  A- ?6 U
    {2 Y% ^% X; b  ^, R- Q4 w
        /*创建一个新的Sheet*/
' l( P# [* w. x$ }4 j$ `        lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
0 A8 o8 A5 S3 X- T' X; o! {        sheet.AttachDispatch(lpDisp);  j, U- g* `% n. s7 j
        sheet.put_Name(strSheetName);
- k( o/ S  E8 \7 R    }, p5 ^( T8 `& l! D% B' a( I

7 ]  F; ?# L7 Q7 }+ o+ w/ _' Q    system("pause");
$ S. p. w& B7 r8 I" S) i3 t2 v
! G% n) d, E$ }    /*向Sheet中写入多个单元格,规模为10*10 */# Q0 i$ }$ P8 R7 D! d
    lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));3 T( @) m( X# q
    range.AttachDispatch(lpDisp);% x$ A7 g& g% V7 b5 ^2 d
  \$ }+ Z. f$ k- K
    VARTYPE vt = VT_I4; /*数组元素的类型,long*/% B9 i% E% M) {( f, |+ J! ~- ?
    SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/) [5 ^, w  h1 A0 v% l3 t
    sabWrite[0].cElements = 10;% _. J4 F7 V& H) `9 h% n
    sabWrite[0].lLbound = 0;. B* o7 D3 `  u7 ^- Q& q" I
    sabWrite[1].cElements = 10;, ]* W+ t- f5 I- T: Q
    sabWrite[1].lLbound = 0;
% Z* i0 I8 R- g( H
2 C9 f5 o; {% p( o+ B& [0 S    COleSafeArray olesaWrite;# G* D$ {) Y5 D8 I/ r. [: T
    olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);
: _1 F( o* r, D* ?4 k, T3 v- G0 k& W! g9 ^, p+ V
    /*通过指向数组的指针来对二维数组的元素进行间接赋值*/" A* u0 [% y) O8 H1 Z! u
    long (*pArray)[2] = NULL;
( `2 `1 n: e1 V) o    olesaWrite.AccessData((void **)&pArray);2 ^1 R. q5 J- p* J5 H, I' ~
    memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));
3 F8 Y" f+ j; Z  a) C4 ^* N2 s8 l7 ~* u7 w1 W
    /*释放指向数组的指针*/; e. B, [7 L9 a' V# o$ F! J
    olesaWrite.UnaccessData();2 p% W0 q  g8 `' L& {4 l( e3 ?+ ^
    pArray = NULL;: z) r6 ]( C1 c% y5 k* L/ n1 ]
' i$ `4 n, r; _8 j2 [: z
    /*对二维数组的元素进行逐个赋值*/
; M; s# M# Y0 {, O  q8 X1 c* \    long index[2] = {0, 0};
8 U9 q8 W1 `+ @$ R1 d# Z9 ~    long lFirstLBound = 0;
" d/ p- S# q8 Y- r, `    long lFirstUBound = 0;. Y2 g; s; z7 j- V1 ~! X1 w
    long lSecondLBound = 0;
( M4 G6 z/ q& o. v8 k& i    long lSecondUBound = 0;5 @5 \* H/ P4 z% O0 b7 ~
    olesaWrite.GetLBound(1, &lFirstLBound);
* [/ `5 Q9 M( N: w    olesaWrite.GetUBound(1, &lFirstUBound);
2 F+ G. I# M) N$ `3 X! o! s; X( }    olesaWrite.GetLBound(2, &lSecondLBound);
6 b; G/ k8 s, U: N    olesaWrite.GetUBound(2, &lSecondUBound);
4 |/ h! ?" N/ B7 p    for (long i = lFirstLBound; i <= lFirstUBound; i++)
4 G7 G2 R9 j/ V! p! Y    {
( n( i4 S& q) g6 @        index[0] = i;6 B0 w& }! e: _
        for (long j = lSecondLBound; j <= lSecondUBound; j++)
( F% p" j1 H2 H0 Z        {
9 U* X, b, J$ q* F            index[1] = j;
8 G; ]0 }! z* T' t6 f            long lElement = i * sabWrite[1].cElements + j;
( G4 p* x4 k  O7 g8 v5 c            olesaWrite.PutElement(index, &lElement);
1 B. n1 b( t9 Q        }
) e+ F0 R2 L7 z% u" Y) x5 W    }
" Y0 v* q' Q9 c- ]! f2 ~; y/ @8 ]0 t, }) T9 J& h: @
    /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/
  E% u$ @; \" I$ h    VARIANT varWrite = (VARIANT)olesaWrite;
2 {) [8 M  ]$ ?: u7 ]    range.put_Value2(varWrite);
, ^& P' L. d% Y9 X5 o
; }: d( D+ D) {, ]# U6 b' E2 k    system("pause");6 ^3 h, \9 W; e( t' R. G( S
+ {8 t& K& k$ R  F0 H! a+ [1 o4 `& ^
    /*根据文件的后缀名选择保存文件的格式*/4 M/ e' _5 ~7 M( ?1 ^4 G
     CString strSaveAsName = _T("C:\\new.xlsx");
  a2 C9 `/ o; S    CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));
# i. v( C. I7 e0 u6 p5 B2 T5 L    XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;& j- b; d( ^6 r. [- _1 X
    if (0 == strSuffix.CompareNoCase(_T(".xls")))/ g& z3 _0 N; y
    {
; i( A  |/ |: i, S/ u        NewFileFormat = xlExcel8;( T" R5 |! F+ q! \
    }+ t& O6 e0 T! `
    book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, 5 @) j5 x7 G4 x, K2 y# y
        vtMissing, 0, vtMissing, vtMissing, vtMissing,
2 l: D, v; B& O* O$ K        vtMissing, vtMissing);
8 M" p1 z8 w) ^1 a" D) o! I) I, F" X4 k& e- P0 `& A
    system("pause");
' g5 C" J2 q2 |/ q0 M) ^0 Q9 Z) e- C: [
    /*读取Excel表中的多个单元格的值,在listctrl中显示*// m3 [( U& H/ d: f
    VARIANT varRead = range.get_Value2();
. G7 @1 R) W( ^* ^9 R  F/ h2 K    COleSafeArray olesaRead(varRead);" ?3 V* `# x2 }6 b

$ d$ K# Y& ^- c) ]5 C  _5 d    VARIANT varItem;
2 f7 a" z$ @4 g8 g- ]& d    CString strItem;& A- R$ `! X) H2 a3 j
    lFirstLBound = 0;
; Z6 D; D- p) N1 f/ D$ p( Z    lFirstUBound = 0;2 I7 |$ n( t' j) \/ f9 @
    lSecondLBound = 0;. X3 c% `; k/ C$ ^
    lSecondUBound = 0;
7 _; A( `; @) w: q    olesaRead.GetLBound(1, &lFirstLBound);
1 _8 v; p+ z- V( Q% B$ Q8 N    olesaRead.GetUBound(1, &lFirstUBound);
8 K* E# ]( h7 x; Y* t    olesaRead.GetLBound(2, &lSecondLBound);
9 [. T1 E; J% B7 H* `1 N    olesaRead.GetUBound(2, &lSecondUBound);
6 _) \  O$ V/ C    memset(index, 0, 2 * sizeof(long));3 {) ~2 N% m9 M
    m_ListCtrl.InsertColumn(0, _T(""), 0, 100);
! j4 e! t5 X9 \% N7 v* }0 ^( q    for (long j = lSecondLBound; j<= lSecondUBound; j++)
- \  L- M( W0 d& c$ H% X5 c1 V# Q    {- R4 j- Y% R. T
        CString strColName = _T("");" |5 A6 q0 [, b6 s
        strColName.Format(_T("%d"), j);7 G: g( `/ D: h7 l
        m_ListCtrl.InsertColumn(j, strColName, 0, 100);' U' s! o1 v6 `3 D0 V  `/ R
    }
6 Z# ~7 M5 z' d+ r/ a    for (long i = lFirstLBound; i <= lFirstUBound; i++)
" z: B! s6 m: O! V/ |* @/ F    {
: H- M: Z% {3 K) i( ^( i  @9 ]        CString strRowName = _T("");0 k9 e. g8 L! Z, o
        strRowName.Format(_T("%d"), i);
9 X- s* P0 D+ u) d$ ~5 E8 Z        m_ListCtrl.InsertItem(i-1, strRowName);3 b: Y: e9 O; Z

7 H7 i; t4 D4 V. D$ n        index[0] = i;
: p, i2 K$ `8 g" i; ~1 M6 }        for (long j = lSecondLBound; j <= lSecondUBound; j++)
6 x; v) U( c0 D9 L, M        {
% j6 E8 W: X; Q, t$ i( t8 V            index[1] = j;# Z3 k. L% x- O+ j
            olesaRead.GetElement(index, &varItem);
! |# g& W; U8 ]1 f$ S
0 O5 Z* c: v/ I. J            switch (varItem.vt)
: L9 ~/ X8 Y4 M            {
$ i; F- x. r7 K7 s" [6 `' k) w            case VT_R8:, J0 |3 A& z& B: X5 U  d
                {0 F7 w4 A6 b+ f: e) k0 n  X" D
                    strItem.Format(_T("%d"), (int)varItem.dblVal);
1 m* y( E$ E4 l( I% y                }& K1 @2 H$ x& ]
5 p1 ~( B2 H# X! Q3 A* A7 l
            case VT_BSTR:4 ^# ]) x" d7 k( a3 u7 S8 f$ L4 w
                {
5 U" p5 k: J+ w1 F/ m                    strItem = varItem.bstrVal;/ j- k; W8 W, ]$ U  Q
                }
8 A9 R. K9 N) V9 J; i' u7 s) D0 Q, H
- p, V3 [6 W& T) B0 u9 w- {- [- _/ a            case VT_I4:
) [8 g) L! A* a  ^                {7 I1 y& }9 ?9 Z) h
                    strItem.Format(_T("%ld"), (int)varItem.lVal);
# R3 h) T( _( M9 l# Q) V                }
: g$ U7 M+ F9 W9 ], n1 y( T( }; |
! I, [, w/ ]4 l# L; B4 k: W            default:# |" j1 X! t' R% T- L/ L
                {
* x; N6 K3 F, V  M% G. i; m
( Q, {: k' y" C, \4 |0 I4 E+ r                }
: Y6 j" U: z4 }9 c# U, B4 Z4 R            }6 W0 J- S* J# F! F
3 V8 G+ @" [7 ^
            m_ListCtrl.SetItemText(i-1, j, strItem);
% f* H& z. h! N, Y3 ~        }3 C0 O" ^3 h! N  L, `
    }7 |$ g  \) Q+ N+ N3 j

( [  v6 y/ p' c1 R( _
& D& ~  b4 R+ S3 Y# U1 v! q  N* q; d/ O; A6 p2 w
    /*释放资源*/
% R0 r# d! B3 H  i2 H    sheet.ReleaseDispatch();
& G! Z, g! H- p9 \    sheets.ReleaseDispatch();4 H' N/ Q" c, A3 m" L, X
    book.ReleaseDispatch();
. v# S  C* F+ q  h" b    books.ReleaseDispatch();' U8 @3 w! M- N# \
    ExcelApp.Quit();% {% H+ F8 Z% Q* _3 N
    ExcelApp.ReleaseDispatch();) X: N3 D; F- |8 _- k( Z8 `

- m) a8 y- k, ^9 n8 ^
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了