PLM之家PLMHome-国产软件践行者

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

[复制链接]

2014-11-8 08:13:41 6544 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表格的操作。
, |& I( i, D; ^: w$ c  
. t2 r9 O5 S' C7 W9 D1 @本文源码的应用环境说明:
6 i4 V( Y5 |: d0 U1 eWindows XP SP3
2 s- }. U+ ~% r2 u8 tMicrosoft Visual Studio 2010+ m: [' v! o$ z; U3 `+ R' w. y
Microsoft Office Excel 2007
9 Z5 |4 d$ s2 Y) b$ {6 Z5 t& e  ( f) Q, C8 `4 @7 y' R9 h$ l& d
1、添加OLE/COM支持。
: V: p6 a4 J  g& t9 F, y2 V! v( ^首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。
3 N$ D' b/ J* K) w& s1 T本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。
- O; t4 F& x3 ^4 m通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。: U/ i$ `; y+ \6 Q/ v- P6 C4 U
#include <afxdisp.h>        // MFC 自动化类
$ H0 w/ d2 s+ s同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:, B3 Z) [) H- q) i  t
// 初始化 OLE 库
0 z9 |, D6 j. J6 @/ T7 d* `* e, M* Rif (!AfxOleInit())
4 r! F6 j7 G8 V, W" V7 B1 o{
) g/ U: ?/ a3 KAfxMessageBox(IDP_OLE_INIT_FAILED);& v% |8 \' X0 c0 W, }+ ?; \# p( o
return FALSE;
0 J: K+ d, \& o4 @6 C- r% O}- j4 _+ }' K8 P- p& S8 B  z* F
  ( X1 A# ]( Y! G. `5 g
2、导入并封装Excel中的接口
- M; o: N$ {! r# H6 jExcel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。0 _# ^0 P3 O$ i, p
由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。
( ~9 i1 G" H) R  B3 I7 b" {: CVS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择
5 Q0 d3 G1 P! W, H6 C8 L- L要导入的Excel类型库中的接口。7 [% X2 v3 V$ {' d9 k: O8 p. o
在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。
/ K2 x' @9 }# t: u, F& F! X6 @2 F  
2 ~, L) A& |( S, u  r$ \本文所导入的接口对应的类和头文件的说明如下所示:
6 a! s6 }0 K& _1 F7 h, Q% ?- i  
9 H* B5 R! n, r' H9 T; C8 N$ C* uExcel接口  Y! Z$ J; P/ O
导入类, f& ]% H0 x4 `/ Z  @1 ^9 y( p- N3 ^
头文件
( h$ @6 X: A* z说明7 a* ^' }: r" ]& ^6 v+ z
_Application$ E( n! o: C; Q
CApplicaton
: f6 I1 ^1 B3 S2 xApplication.h
$ U4 L+ L% i2 q2 PExcel应用程序。
5 r! r3 {2 \; B/ K+ f. p, B7 QWorkbooks
8 M$ X7 W% |6 `% a* P, UCWorkbooks
, n+ y9 Z6 f7 |7 ?1 T7 q: mWorkbooks.h5 t$ m9 c5 K) P  }+ D6 b
工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。' y  W/ ]$ ]& S
_Workbook
6 B# ]! o) [4 p& a( D' h. zCWorkbook
& K& j' K9 w4 O8 r; XWorkbook.h0 B& K# X  @6 k! ^0 Z1 O% i1 |
单个工作簿。
4 B1 x3 h! E0 [9 w0 _& uWorksheets6 g4 u3 l4 k  D6 b  g) f2 K
CWorksheets
: z2 Z9 [2 f; yWorksheets.h; q, N+ v9 F9 F
单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。% z; g2 A* O+ X0 u
_Worksheet/ ~: |! S) n2 t6 ?% f& A
CWorksheet. G- d  H; C- G  `9 ~) Z% E$ f$ U1 z# ?
Worksheet.h
5 E- ^" B( \5 `' O单个Sheet表格。7 m$ D- y0 e0 i
Range
/ @) g  O8 Q7 J4 _6 ?* p2 p( PCRange6 H4 E3 c# T) E' }  T8 t. O( y
Range.h
' O6 L: t: N" I  A% P一定数量的单元格,可对单元格进行单个或多个单元格进行操作。
# ~' z0 @- c. E- B  
- w3 Z  [" Z' c/ _  D3、导入Excel的整个类型库
: r& F! \% R& p; a: ]! D1 }, E接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
. ~+ V4 c) [) Y: T通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:
: p1 ]2 M# Z: M" G#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
7 v, R; R# G( P7 n这行代码的作用是导入Excel整个类型库到工程中。9 l! a1 Q, g* K& W
由VS2010自动产生的导入代码存在以下几个问题:
* \/ R4 o  }, G' v1 t8 K(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。2 m4 ?: {1 }! S# ^5 }, C
(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。0 i0 L2 `: y5 }" d  h
(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。$ g: l: N, v4 j- \! {5 M9 ?* ]. u
以上三点问题的解决方法如下:
( B2 W, f1 _. x0 e  W(1)仅在_Application接口对应头文件中导入Excel类型库。' Q7 h1 g6 f" L, |# N8 z
(2)对冲突的类型进行重命名。! t( d( |" E3 G- @; W8 H+ G
(3)在导入Excel类型库之前,先导入Office和VB的相关库。
: |% a5 M. [% O. Q' N0 E0 v3 E更改后的导入类型库的代码如下:
! E4 \. |% _- F1 S/ s! ^) }4 b  
4 w7 b( f( O( ^! B$ T/*导入Office的类型库*/( r' a4 S5 p2 K
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \8 l$ x2 A/ N* _7 V
rename("RGB", "MSORGB") \! E3 @. K& B" j6 j& D3 Q
rename("DocumentProperties", "MSODocumentProperties")
2 L* |# P/ o* [using namespace Office;; _/ s8 _6 X- b( l" C
  
7 h  {  N% k. q/*导入VB的类型库*/
6 F6 O7 a" d7 X& P) Z  t#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
- ^8 I7 ^! F* A: Fusing namespace VBIDE;( }  {6 ]& @/ B7 a
  ! i9 J! f% W! B
/*导入Excel的类型库*/
$ g8 W! @- s  p# \/ x. V#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \) [& J8 U6 Q1 V/ e. W: n* r9 D
rename("DialogBox", "ExcelDialogBox") \8 f! M0 J# c1 }/ g/ ~
rename("RGB", "ExcelRGB") \
4 H2 A: @2 _0 A; R4 F! erename("CopyFile", "ExcelCopyFile") \
+ N& O2 q+ w' I& p" R# jrename("ReplaceText", "ExcelReplaceText") \& c: d% m6 Y3 y5 Y6 L6 a6 a4 E; A
no_auto_exclude
! z+ ?, g7 I8 o& c3 n+ u9 nUsing namespace Excel;
% h9 {+ G, F- C5 f, D3 `  
# Z" D' B. }; P3 p" z5 E& O& W# U+ m; b编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。
; B9 H9 d$ D+ {) {  " C: b) `7 u' V' A7 |6 S
4、操作Excel步骤
6 \% f# d* U% d9 }8 G: K$ T4 j2 c! v$ k操作Excel的主要步骤如下:
% \9 b4 A, `/ s(1)创建一个Excel应用程序。6 d+ }3 r  s$ L7 i
(2)得到Workbook的容器。& i2 Z4 n0 z7 C7 o
(3)打开一个Workbook或者创建一个Workbook。* N2 z  c5 g: r7 j  j  I, G
(4)得到Workbook中的Worksheet的容器。
7 c1 h1 `7 O, R(5)打开一个Worksheet或者创建一个WorkSheet。/ z- t6 W+ a8 M, {# ~4 d
(6)通过Range对WorkSheet中的单元格进行读写操作。
, I$ ^: k# ]% ^- u2 ?3 h(7)保存Excel。
2 r; O6 K$ C; ?(8)释放资源。
& c' N& F/ y4 K. }$ Z( p/ P  
  J- ^- f  e9 g5、批量处理Excel表格
5 d5 [8 ^. Z. N) F/ |VC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。' X& Z! i3 A+ y) j% N& }
对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。
7 `" u7 ?2 t& z. }0 j& A# DVARIANT get_Value2();( d' }- R: L* c( M  H' L
void put_Value2(VARIANT& newValue);
$ [5 o, o$ Q( |+ [: K  m其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。
* ?! H0 T% U1 ]3 C其中,VARIANT中实现二维数据的方法可参考9 X. V. Y  q6 O2 [( G, q4 M1 X, u
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html6 |$ l2 D; }) X" |3 O" ~3 `6 ~& G/ k( O
当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。
8 B1 E( N. v3 X) [/ E7 |  3 y5 W' W) Z  w! x
6、Excel表格的保存
; v6 }8 V6 K+ b9 J9 M6 |4 R(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。1 L3 A+ I/ G( b
(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。/ x& D" D/ l' k$ w4 @
SaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。8 Y: L6 c- A1 J3 p( J) H
  4 ~4 `- L* H( Q+ C# t0 D
7、获取当前Excel的版本$ j7 Q4 m& z3 f' p
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。# s" t6 `* ]7 ~8 Y( G& j
    B2 N1 F! i% M
8、示例源代码
0 T/ w" n, n3 A7 s+ y主要代码如下:
6 }  g+ L6 m: W: M+ v8 k9 ?  
& h' d6 ?* P* {* Q
( }, K. o8 d3 T+ a- B  B6 G' V
! }- d+ R3 u" M" f, ^/ @) w% m, G    m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);0 E; e' {& L. c1 T+ l5 L8 i# d

- O0 J" j% S' L- v    CApplication ExcelApp;7 i. t2 k( P* W# J) q+ M8 C# I
    CWorkbooks books;# Z) i8 X( K( ?6 Y
    CWorkbook book;3 o; e& g+ f9 x5 ], s
    CWorksheets sheets;2 `6 R! ~5 ^- p& w( ^, T- ^, l
    CWorksheet sheet;. P1 X4 M& g, x- X! P$ ^7 P+ |
    CRange range;$ `; c& r1 X4 q
    LPDISPATCH lpDisp = NULL;
. s7 |" q9 k7 G6 w+ R9 ~5 g3 p
$ y9 G9 r- ~& u" e. y2 u2 ?    //创建Excel 服务器(启动Excel)# r' i8 n# Q5 \/ G5 q
    if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))
  S  `$ L3 e2 N5 l  ~' ~+ |& U    {
8 z! H4 a& j! c0 \. j% u% I, }        AfxMessageBox(_T("启动Excel服务器失败!"));
4 N- l/ _$ u$ P+ X% _        return -1;: Y4 }, [0 X* X4 j
    }5 V' [. `& S. |% _# ~! _2 n; b( y6 i
1 m+ ]- O1 n7 I. X# z% B7 w
    /*判断当前Excel的版本*/
( O* F5 l) J. ~    CString strExcelVersion = ExcelApp.get_Version();
7 ~2 D8 c2 X/ j* ?% p( h& Z    int iStart = 0;- m7 d% H* R+ A8 Z( R, I" I
    strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);
9 G9 w; U! i2 M& n# q7 e* n    if (_T("11") == strExcelVersion)
# g0 S9 j0 W# N+ |6 X    {3 Y% s2 w! [) @- p# H4 t$ W& O
        AfxMessageBox(_T("当前Excel的版本是2003。"));
) w5 m6 E* ?* }: ^! B7 |. |    }% Y+ j, k- \% T6 p
    else if (_T("12") == strExcelVersion)
0 x) m4 J4 d9 P7 q    {
7 B+ T) V5 F) V& g1 {        AfxMessageBox(_T("当前Excel的版本是2007。"));
0 S! k7 f3 Z! q6 E0 [8 X0 W    }
2 O0 \# q3 W7 ~# E. o. ?    else
, b" @& e3 p# o( E& _* W4 X    {
: l8 x: L/ g6 N1 k8 h" ^        AfxMessageBox(_T("当前Excel的版本是其他版本。"));, V  Y: {3 j0 |/ B  i
    }
, r& s) Q4 n' ~% C" A+ }$ M2 M5 q" v
1 F; y7 z7 p( k( r    ExcelApp.put_Visible(TRUE);6 ?: j3 ]# [/ J
    ExcelApp.put_UserControl(FALSE);, r, E  |0 P- p, W- f

8 [$ E2 Q/ d$ A2 c! C& D5 F, a    /*得到工作簿容器*// a3 c* E2 j/ d3 d9 Q
    books.AttachDispatch(ExcelApp.get_Workbooks());
& T9 P8 H3 J" B7 D$ f4 a7 ]# d2 @3 t) Z4 o4 ^  Z
    /*打开一个工作簿,如不存在,则新增一个工作簿*/' P6 }! Z7 \5 K3 o' U$ r0 O" y0 u
    CString strBookPath = _T("C:\\tmp.xls");/ f9 [. O, u) a: g
    try0 W; b/ C9 v/ z' W' N/ k
    {
% T, ?' e  h* t        /*打开一个工作簿*/2 @% G9 s4 r+ T
        lpDisp = books.Open(strBookPath, , Q( F4 d$ |) s9 f1 ^( W
            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
) Q4 g  f. C# g7 Y: E            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, / a. w; \' o6 o) k8 j( A
            vtMissing, vtMissing, vtMissing, vtMissing);
4 ]5 M; Y6 |1 t# ?5 P# N) E1 v        book.AttachDispatch(lpDisp);- u- {2 j' ~" B7 H1 O/ J
    }, L' o" W3 z' b" d1 Y3 c
    catch(...)! N+ Y4 ^. b( F  E+ X
    {, Y2 d% ?, T5 h) Q
        /*增加一个新的工作簿*/
  K: u2 w" z  G" J2 d        lpDisp = books.Add(vtMissing);
, j- w5 C2 k% ]0 V. b( U        book.AttachDispatch(lpDisp);+ w  r8 [  ?6 Y# O. ^5 [  t' _
    }
  J# a/ w6 g8 U  e     1 w$ g2 w2 ?! ]' W1 p0 T, M

$ b8 s4 W9 L6 n, T. `2 w    /*得到工作簿中的Sheet的容器*/
( E' s" O# [( q1 E/ f    sheets.AttachDispatch(book.get_Sheets());+ R/ {: q; g( J/ S; q
# f' k8 N6 t8 K+ y) _! i
    /*打开一个Sheet,如不存在,就新增一个Sheet*/* ]* B# D, q9 K4 W$ X8 t# F: [2 U
    CString strSheetName = _T("NewSheet");5 e0 ~9 j9 z) d" K
    try$ P6 G7 Y2 r$ N. l
    {* R) Q& N# z$ l6 H/ C1 Y2 H* \
        /*打开一个已有的Sheet*/! s5 A/ A+ }! ~* X$ D
        lpDisp = sheets.get_Item(_variant_t(strSheetName));
4 j6 u  p8 f' E1 T8 g4 ^* P5 @6 w: P  i        sheet.AttachDispatch(lpDisp);
% b, l: L/ X7 f3 T    }9 z8 m% ~+ X3 f
    catch(...)
2 J( |! _/ K7 o4 n- B    {- {6 y+ w: Z) U; Y" T* h$ b) E, K
        /*创建一个新的Sheet*/
( S. L6 A8 W" \5 R3 G9 v9 [$ \        lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
' R# g" @" T6 \        sheet.AttachDispatch(lpDisp);
- ~0 u, T6 j3 k) Y* Q6 J! w, z/ U        sheet.put_Name(strSheetName);; g# E8 V9 Z5 P
    }
: s/ [9 A- l- y6 A1 `2 K* c/ _0 C
    system("pause");, C# K( _7 n7 f9 {
; X: R* ?) I7 j. l+ p+ ^
    /*向Sheet中写入多个单元格,规模为10*10 */
% v) T6 a: Y. ]( ]; v    lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));
# E% t) e8 g( X' ~    range.AttachDispatch(lpDisp);
' v# j. O5 `9 {" U: J' X# {& H: P/ I2 N3 {
    VARTYPE vt = VT_I4; /*数组元素的类型,long*/
6 w0 l) b0 L! h( g- q  Z) p    SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/3 z, r4 H% b3 y! _" }4 l
    sabWrite[0].cElements = 10;" O! z4 _9 N* Q8 J
    sabWrite[0].lLbound = 0;* B$ @/ U- C5 |6 w/ q- F
    sabWrite[1].cElements = 10;
' Q3 n" ~4 Q3 {    sabWrite[1].lLbound = 0;
7 G4 v; j+ ]' y+ l- S
' z0 p% i' B: P5 I! f9 O. L    COleSafeArray olesaWrite;
2 f- J- ?, O( \7 p* l5 e- `- X    olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);
3 q$ y" U( L; A9 B: M
& T8 M6 l+ C- u1 ^8 @- B3 w    /*通过指向数组的指针来对二维数组的元素进行间接赋值*/! P' g7 z8 L6 Z+ V# g: z0 I
    long (*pArray)[2] = NULL;
+ j, @: H' a# G& Y    olesaWrite.AccessData((void **)&pArray);4 l. I0 D6 |/ d8 f( ~; @( C! [- H
    memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));9 q! H5 n. B% u4 G

/ z. Z! L9 U7 N& l5 W    /*释放指向数组的指针*/
0 d% b$ s8 e- J3 E: \    olesaWrite.UnaccessData();: ~3 I8 j6 Y. v* X: v( I
    pArray = NULL;' F; c1 U" z) D# s7 q2 O, M: X

5 p9 y7 L" G2 w( x8 j/ w1 i    /*对二维数组的元素进行逐个赋值*/
( t5 p# P. _( z    long index[2] = {0, 0};  T( @( Y/ ]" {: ]# I, S! r  i
    long lFirstLBound = 0;- I) L4 `; c7 q  D/ {
    long lFirstUBound = 0;
& `% k' L/ g6 A4 H& l0 {, j% _    long lSecondLBound = 0;
) y: j* |" L2 {+ G  S" @    long lSecondUBound = 0;- @" n" r, ?8 F
    olesaWrite.GetLBound(1, &lFirstLBound);
& _# j, T$ c! ^" ]9 g    olesaWrite.GetUBound(1, &lFirstUBound);
+ u, g- g( k) C  c7 B    olesaWrite.GetLBound(2, &lSecondLBound);8 X& i% K, ~" M0 G3 W7 T1 }
    olesaWrite.GetUBound(2, &lSecondUBound);
/ e& F( f% u8 k4 Q4 E; G( K' S    for (long i = lFirstLBound; i <= lFirstUBound; i++)
" e' Q3 Y5 V+ x    {, D  n( E  b4 t8 |6 ?, g
        index[0] = i;
5 G8 q8 }' L% [" \- L0 Q        for (long j = lSecondLBound; j <= lSecondUBound; j++)
( _$ D+ {0 a% O+ K- C' i        {
6 P' Z; [  r7 d* v: B            index[1] = j;
' w$ ?0 y0 s2 X4 o: U+ V  ?+ _' x            long lElement = i * sabWrite[1].cElements + j; 1 V0 f- w% \" F3 J' g3 u( b
            olesaWrite.PutElement(index, &lElement);3 _0 `0 ^6 |$ y& r
        }
" }9 ?! `- Y2 p1 o& X6 U0 _$ p    }% Q' T; S6 A8 h: X; N$ |2 R( u
- ^/ b# a: b3 U( ?% a; w, \
    /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/9 F1 A1 u: Z% t
    VARIANT varWrite = (VARIANT)olesaWrite;1 L  Z5 p, V8 C6 t' o! M. ~
    range.put_Value2(varWrite);
2 C3 g  a2 p4 e$ b
2 R* K( p9 a% l: A& k    system("pause");6 P9 l3 z+ o0 d1 ?8 }
! o: @! O8 M6 k! O2 H4 A6 k& k( W+ i
    /*根据文件的后缀名选择保存文件的格式*/
9 K( L4 w' k: |8 Q. G$ Z     CString strSaveAsName = _T("C:\\new.xlsx");, ?( D$ c+ W3 B- \9 p
    CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));
8 T; r4 w4 Z' t+ E; g    XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;$ I7 o1 x; z+ E; X- }4 l
    if (0 == strSuffix.CompareNoCase(_T(".xls")))
& I: P* k1 O6 l2 o/ ?    {
4 G2 A: |; D" a/ h- ~8 z        NewFileFormat = xlExcel8;
' H* ~6 `, X# c# E* y$ @    }' w% J* P! _5 Y$ a
    book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, 6 ]: H" [2 W2 @# q: D
        vtMissing, 0, vtMissing, vtMissing, vtMissing, . W: P( ?! }5 B& D4 n
        vtMissing, vtMissing);
2 @% ~/ x6 [( J  g5 \9 M
0 }6 N- J0 P, H4 g    system("pause");
1 K& |" I* K0 h) P/ z/ c& M
) w! C3 i: M& {/ i+ W7 n9 V' u    /*读取Excel表中的多个单元格的值,在listctrl中显示*/
, z: J# h* j- T; ~6 g* i( u    VARIANT varRead = range.get_Value2();
, p$ x! U. c9 ?3 L    COleSafeArray olesaRead(varRead);4 s, G4 d. H( Z; ?
; b) \$ m- @& m  O. @0 {
    VARIANT varItem;
% q& N: i' |% X: W" p3 t" @. l' t( Z    CString strItem;) W0 J7 I# t0 J9 q' K
    lFirstLBound = 0;) y. T0 |) P+ j, T( K
    lFirstUBound = 0;
# \  c% w% i+ R1 w1 V% C    lSecondLBound = 0;
# i# i! \5 L7 l5 l    lSecondUBound = 0;7 Q8 b2 n/ ?% p/ n# m
    olesaRead.GetLBound(1, &lFirstLBound);
& Y( r( b2 e* E) V% `1 K6 I    olesaRead.GetUBound(1, &lFirstUBound);& s9 O* G. ]+ h# G$ ?* b
    olesaRead.GetLBound(2, &lSecondLBound);
  O) F4 w9 X  s3 ]/ r    olesaRead.GetUBound(2, &lSecondUBound);" j; d/ n5 N/ T3 T4 t, ]7 F6 {
    memset(index, 0, 2 * sizeof(long));
5 N0 h) p) p; C    m_ListCtrl.InsertColumn(0, _T(""), 0, 100);. F( [3 d- ]/ x
    for (long j = lSecondLBound; j<= lSecondUBound; j++)4 J2 I* |6 Z) G! b% d5 f- {+ W: f
    {5 ^0 |% Y3 K0 y
        CString strColName = _T("");
) Q' S: a; m1 v* {& {+ O; F6 ]        strColName.Format(_T("%d"), j);
$ G! j; A' o$ U. y        m_ListCtrl.InsertColumn(j, strColName, 0, 100);
: w0 D7 J% E- N1 c5 P( O6 Y    }4 M. x& S) S' M+ a% T  K
    for (long i = lFirstLBound; i <= lFirstUBound; i++)1 U5 f: W# M) Q0 A2 G7 z
    {
6 r9 e; c; L1 n. A9 w) Y/ ~) L2 s        CString strRowName = _T("");
& o: q. \. }% x0 E        strRowName.Format(_T("%d"), i);
9 D4 F( q7 n7 I. A1 b6 H- R6 O1 \        m_ListCtrl.InsertItem(i-1, strRowName);( Z# ]. Y: f+ k3 l( l' y+ F

4 e1 t! d8 {+ O        index[0] = i;
) I& Z5 |% j+ w% ~; M5 p' q        for (long j = lSecondLBound; j <= lSecondUBound; j++)
( c& ^" D; g7 r2 {- x& R) ^0 N        {4 W8 l  ^+ T1 y1 B: e2 ^& k% U/ `
            index[1] = j;" k* ~5 t! b6 G% N$ E
            olesaRead.GetElement(index, &varItem);! L' c; m) k7 t

5 x) m) l, W$ @9 r/ @! G6 d  f$ j            switch (varItem.vt)7 R+ L6 O8 a# \
            {
/ \( H% _* k# ]# o' j' \, B            case VT_R8:
5 c  w# {) B  i6 O/ B# T4 F                {  i3 p# z$ }2 ]* D$ t
                    strItem.Format(_T("%d"), (int)varItem.dblVal);
. g- R2 [' x1 o5 y                }) ~8 M% n, e* U: c/ d& }; b  @* C

- I3 _; ?# w8 |* I. i7 W3 ~' w            case VT_BSTR:
" P' l7 c. A& S% X  ^8 M3 H( c                {
: Y8 K" U0 q( ]+ I5 V: l8 E6 O                    strItem = varItem.bstrVal;
2 Y9 L( Q1 b, ]5 x" U                }
1 y' f7 g0 d0 F7 @& ^/ I/ H$ h# u& c4 S3 I& \2 C0 X
            case VT_I4:
& P' E, x4 ~; i1 N# ~/ i5 g, J; T                {3 I" p5 g* s6 [' V/ t
                    strItem.Format(_T("%ld"), (int)varItem.lVal);
0 l* X! G% S, n* n$ ?. z& ]                }
5 u/ L0 [0 x1 e9 V+ O# A" [
' A  N; {0 B3 H* r# Q* l1 ~            default:
+ A& B5 w1 K$ b; ]- o4 B7 A+ h                {: a% r: ^8 o9 B5 D+ J

6 a, E1 F4 R8 x( i                }
* L7 y9 Z4 C, l- B4 {            }
/ b* g6 c+ r& D& X% i+ z7 g
* U5 U. _6 W0 n7 u7 J. G3 |            m_ListCtrl.SetItemText(i-1, j, strItem);" ~' U1 v! @! S: M, b2 e, `
        }. j) k& d! |" d& n
    }+ q2 t/ U) K. z+ k

3 B' i+ m8 P- b+ o1 u0 @0 o1 k  f- t; d0 X" {

4 Q* j- e7 [. u. t$ e, k    /*释放资源*/# D& w4 W/ g* ?) s) H
    sheet.ReleaseDispatch();
. o) G; I+ Q$ t0 @    sheets.ReleaseDispatch();' q& f! j" d1 q$ R* R; P. a
    book.ReleaseDispatch();
8 @. l4 E; e( w    books.ReleaseDispatch();
! C# n2 {8 y6 \2 `3 i& u9 j3 w1 i    ExcelApp.Quit();
( Q% G& U" t$ m    ExcelApp.ReleaseDispatch();! d6 x1 L- S% o$ O/ {" x

; M6 j  z+ B0 O7 {* t( x
上海点团信息科技有限公司,承接UG NX,CATIA,CREO,Solidworks 等CAx软件,Teamcenter,3D Experience等PLM软件,工业4.0数字化软件的实施\二次开发\培训相关业务,详情QQ 939801026 Tel 18301858168 网址 www.diantuankj.com/ doTeam.tech
回复

使用道具 举报

发表回复

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

返回列表 本版积分规则

  • 发布新帖

  • 在线客服

  • 微信

  • 客户端

  • 返回顶部

  • x
    温馨提示

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

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

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

    我知道了