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

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

[复制链接]

2014-11-8 08:13:41 6648 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表格的操作。9 _# ^! O7 p$ ?. f2 [
  : a- L* J0 l9 p; `2 B, N
本文源码的应用环境说明:
8 g( z& }& d/ \, n' {2 n; ZWindows XP SP3
+ P4 q& t! y7 L1 H- g) iMicrosoft Visual Studio 2010
, Z- X# a2 s( g+ g- [2 T6 LMicrosoft Office Excel 2007
/ w8 J+ j* Z3 l& `  
0 M! h( @  d: J1、添加OLE/COM支持。
3 m- z1 J( \3 E8 T9 s; a首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。
1 c+ \, B: G' F本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。/ h/ k- L; g+ E7 s7 p( Z
通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。  ?& o; l+ G0 A0 @1 b8 O9 J! x0 x/ h
#include <afxdisp.h>        // MFC 自动化类
) V4 S+ G/ N" X: g. n同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:
# O* K- }1 r- z. [7 g( d// 初始化 OLE 库
  l& p! v7 @( s8 j" Aif (!AfxOleInit())
1 f* [; {) X* q( v0 V{( T% L3 }* x- X8 @! e
AfxMessageBox(IDP_OLE_INIT_FAILED);) o5 o0 \5 q1 o7 V1 y
return FALSE;
% h# b9 M- p" a, s' h6 _}) {( u& P1 l% W# w/ q
  
( Y# B* V: W6 P, F7 s1 m6 U6 w; {) E2、导入并封装Excel中的接口
8 `* y2 {( C1 |1 @6 xExcel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。
8 A0 q, w  Z, E- N/ }由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。
2 [% `3 |3 K7 G5 QVS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择+ |3 f8 h- {* `# ]( {
要导入的Excel类型库中的接口。
& R% J3 ^" j4 D( A8 o在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。% a% X2 ?, Q! d  G1 G/ a
  
# g" l7 n% M4 d% x! T, ?本文所导入的接口对应的类和头文件的说明如下所示:7 j/ K9 z. u6 L- Q( s. w6 b
  2 ?+ v* N/ r( v, @5 {/ U7 ^1 k" Y
Excel接口
2 w2 o* o7 V" I6 j( h3 o3 X' U/ R导入类$ K% n' w; x+ C
头文件* T+ E  I8 t' r1 r( H6 A9 n, @
说明5 B1 t" l: I2 H: d
_Application
7 _( W% e& Y. Y8 KCApplicaton( \4 a" `: V, m- O4 z( F! h0 D
Application.h. i! ?$ r1 q" J4 `; o" p2 Z; ]+ m
Excel应用程序。3 z% y  Z: R2 Z" q6 T
Workbooks/ c  x5 ^; i1 y2 T5 O. r' ?
CWorkbooks
4 M5 w4 u5 ~5 q; k- SWorkbooks.h
+ o- h# v4 |) z" X  N% Z工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。
5 Z3 z. B- L& D4 h8 ~_Workbook
0 R* Q+ N8 i4 z# |CWorkbook6 r7 B; @  f! D9 Z- A
Workbook.h/ `3 m2 O' g! _, T
单个工作簿。
9 [* I& Q, s$ _! E0 bWorksheets
7 c+ q9 t1 U& ?. FCWorksheets. l. i; i- t. I! k: q- C& T
Worksheets.h0 b; Q7 A- ~4 |4 S. F, [
单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。6 _% P8 P# X) b' ]
_Worksheet- V0 p( V' |; p+ s
CWorksheet# N  D# H0 G5 d: R
Worksheet.h- u2 Y( ~( _7 N- \
单个Sheet表格。
6 w1 o- q& ~7 k$ D/ e' Q& |/ kRange/ q9 L/ h/ b$ q* h, f' a  l5 L# A
CRange' ?' b( T6 n3 u6 J, H' h7 T
Range.h
; y# R6 I  b( t! v: |) `一定数量的单元格,可对单元格进行单个或多个单元格进行操作。7 V3 A+ s. d% D+ p- F3 @4 B7 V
  : v# [- @( z9 ]# g! }9 y
3、导入Excel的整个类型库6 z; S& S/ Y+ ~' K, L
接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
9 A- ~! n" p; f% M通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:0 C6 w9 t0 J! B* H  L9 d
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
6 G) k1 z& _- t8 `  V3 I这行代码的作用是导入Excel整个类型库到工程中。
! V+ c5 \8 B, I0 y7 s9 ?由VS2010自动产生的导入代码存在以下几个问题:
, }* V7 o* ?: J4 y: Z(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。7 r9 F+ o& x. F9 i1 |% |% k  t
(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。
5 \& u% M- j1 V" c" k1 n(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。  ]1 P8 v6 `5 X! X, V& |" @1 d
以上三点问题的解决方法如下:+ `1 u4 H$ A5 u, I
(1)仅在_Application接口对应头文件中导入Excel类型库。) \1 D0 u% n1 h4 r+ }
(2)对冲突的类型进行重命名。
' i8 v& T1 R1 k(3)在导入Excel类型库之前,先导入Office和VB的相关库。
5 }; Y7 N7 Z6 Y5 ?/ c+ U更改后的导入类型库的代码如下:
+ r* T$ ]1 }( A. s$ n% N  
* H- t$ F8 S% D( m+ B/*导入Office的类型库*/
7 K9 M: m9 r0 W#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \" n' |! ]* v' F
rename("RGB", "MSORGB") \& D2 a! ^5 B9 F+ e
rename("DocumentProperties", "MSODocumentProperties")4 Y4 I  W3 j$ X$ Q  L4 t# t
using namespace Office;$ Z0 s% y8 \) s5 y7 w9 g" x; O6 Z
  
6 j& L( W4 `; M2 z/*导入VB的类型库*/
5 g4 X5 z+ F% h# i9 |  ~0 `#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
1 D% d3 s+ M+ [using namespace VBIDE;
+ i2 U& H5 H8 _  
6 @1 L& S4 I4 W" E$ S3 T/*导入Excel的类型库*/, w1 f& x5 n" m
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \
1 g, |3 g$ I# m; c: ]rename("DialogBox", "ExcelDialogBox") \( V* e& l: K" V
rename("RGB", "ExcelRGB") \
+ ~9 W  s( l& T) N" s! z+ k% H; ?rename("CopyFile", "ExcelCopyFile") \1 i  S4 d6 P9 B. }+ ^% \# C( ~
rename("ReplaceText", "ExcelReplaceText") \
: a7 O# q4 e# t' v4 p& A7 Jno_auto_exclude2 U, t  ]( [$ c& e4 z5 f8 ~
Using namespace Excel;
% D4 e/ [; O4 u& A  
5 ]4 G/ X& R7 }0 ]7 A编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。7 \& k9 c8 o2 _+ b$ j
  
: a& [4 `1 m0 W7 T1 ]: B. p4、操作Excel步骤. b6 t+ F. F% F/ N2 O8 t  L- ?/ u
操作Excel的主要步骤如下:
7 k, P- d7 j9 C( T: N7 ~2 A(1)创建一个Excel应用程序。
2 k8 u2 I7 E  Y" W" W. {(2)得到Workbook的容器。
7 G  J/ B. T; X: J5 i- i' h$ L+ b(3)打开一个Workbook或者创建一个Workbook。
$ g7 ?' ?. t) m1 L+ [(4)得到Workbook中的Worksheet的容器。
2 b! \! @& B/ N3 X  Y1 u(5)打开一个Worksheet或者创建一个WorkSheet。
# Q; {4 }8 X' [, ^% U+ T(6)通过Range对WorkSheet中的单元格进行读写操作。# @+ @5 S) I7 g" c1 F
(7)保存Excel。0 l4 T/ Q. f. g& X' }) `6 h
(8)释放资源。0 L# a; k( ]; L' s2 T
  / ^: j! ^2 O: j6 P5 R8 |
5、批量处理Excel表格
9 N: c/ N( Z2 B" j. N8 @, ]VC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。
" S& \' Z! k1 Q* d9 i& b对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。
3 m  p" _: `1 L: aVARIANT get_Value2();/ s6 }3 n; ]2 D# M
void put_Value2(VARIANT& newValue);% z+ Q$ U  _* b- v$ Z4 ~1 t7 ], U
其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。/ M5 g2 @/ V8 x+ t: k- r% I8 g
其中,VARIANT中实现二维数据的方法可参考" ]- H/ }# p0 g. t
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html
  H5 y" b/ ^6 e8 o9 D' _, |" u当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。& I$ [% P) g" P* j1 A. @( M* O
  ! p  E( i& ]! M& B  g
6、Excel表格的保存
& ^4 N* L, o! I" b: Y& ]8 i& {(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。
8 M! a6 v( x+ S9 _( H3 X" h(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。9 P  s) L# I0 h
SaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。% P  @6 ^9 G# N1 o; i
  
) G* d: _2 o, @' K: U  r8 V5 \7、获取当前Excel的版本) r. s4 v3 |8 O7 \; W
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
: t* e( h% j7 v" z& T3 z  
% H% B3 a. F' Z$ l! l' a2 ~% d8、示例源代码( _3 ~& \2 g) K# b; ~* ^
主要代码如下:
2 o6 s& m( X7 ]3 q# P  
' k0 y+ l# u% h) j0 I5 Q6 J* f
# G1 K  @* A& U4 R* G: Z
/ [0 K6 N* f, C9 U! d+ G    m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);) i- d2 Z. u/ @- M. H9 p9 S2 ?

+ Z4 B  c1 E6 _6 Q    CApplication ExcelApp;
8 P- M' V  g* F& y9 ?; s    CWorkbooks books;3 r* h/ w  r( P: B
    CWorkbook book;8 |- K' E8 G* X7 X9 U% F
    CWorksheets sheets;* ]1 |- X+ q( K$ @
    CWorksheet sheet;( v# a' D: W. s2 i% c
    CRange range;
# d& G$ v5 `0 f$ c) ?    LPDISPATCH lpDisp = NULL;; N- T( k& k/ @

( B# f1 \- ?4 P) U- J# s    //创建Excel 服务器(启动Excel)
$ I- y$ e; v2 z1 H& T* Z    if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))( m6 N, f2 [* O
    {
2 q& o: G/ k0 `& C9 a, }7 c        AfxMessageBox(_T("启动Excel服务器失败!"));# O9 O8 I7 ~  l: Y  K9 b# S# B* |8 M
        return -1;* d3 k9 s& j2 b. [& \* h, n# _; j
    }
! o. T: P) j! r4 u$ ]2 ~8 j9 e% ?8 m
    /*判断当前Excel的版本*/( {1 Z6 v" J/ I6 u2 P% O3 w' U! C
    CString strExcelVersion = ExcelApp.get_Version();
+ z1 C; O2 i. b- s9 O    int iStart = 0;
* z" W8 V2 {0 w    strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);& o! D# ^" [, O2 \( t! V7 b
    if (_T("11") == strExcelVersion)
8 d) ~7 G. U- v. \    {
/ g0 w6 @0 V, Y5 c7 ^" f9 B8 x        AfxMessageBox(_T("当前Excel的版本是2003。"));
3 J1 m3 E! ~$ c/ [) }# k    }
( Y7 w4 o: l# z" s$ l8 I8 m    else if (_T("12") == strExcelVersion)
6 `5 {& r  k) A7 G% f. ^) m: b9 o; l0 ^    {' Z7 X& N6 O, P8 x6 q' P5 R
        AfxMessageBox(_T("当前Excel的版本是2007。"));
9 L7 F- i  D5 t    }6 P* C/ F  j6 j1 L
    else
& u* k' B9 {2 ]/ ~9 l    {) H8 C' |; Q1 Y
        AfxMessageBox(_T("当前Excel的版本是其他版本。"));& u' `6 N- ~- N- M' n
    }
% P4 ]. Z" J( H. [& w, k4 L% N: I7 C# @
    ExcelApp.put_Visible(TRUE);8 Y" p; |# I9 k9 m  J
    ExcelApp.put_UserControl(FALSE);7 w; x; i& I1 y1 a& k9 n: A+ R
% S  G& M6 X! \
    /*得到工作簿容器*/7 v6 Y1 J5 Q' C
    books.AttachDispatch(ExcelApp.get_Workbooks());
" Y& B- {8 N/ @$ n, N( ]( g8 s( j7 x0 y+ j$ {
    /*打开一个工作簿,如不存在,则新增一个工作簿*/% O, \9 p' a8 f) H6 c' ^
    CString strBookPath = _T("C:\\tmp.xls");+ o4 x( F0 y9 t& s* D9 ?
    try# S0 _& p- ~# d
    {
; p7 w4 b1 o$ V% m" T/ d        /*打开一个工作簿*/
5 m, z/ }# w! m0 J. A0 U' f( k% b' p        lpDisp = books.Open(strBookPath,
5 \% N6 d7 c5 L+ c7 K  S2 a            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
, c3 u: [- n& {" N0 H            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, 5 _  k% ^; P, O$ F
            vtMissing, vtMissing, vtMissing, vtMissing);
; W+ a9 _1 H/ o( M$ w$ Q" }+ @        book.AttachDispatch(lpDisp);
( U, |' }& J0 V; t% `" V    }
/ s, N0 [* _+ ^    catch(...)
% J+ F: x5 B' g, A# s  E    {
5 ~, g4 ^" C6 S* R) A        /*增加一个新的工作簿*/
8 [. t8 `/ V! b' w, m        lpDisp = books.Add(vtMissing);
0 G4 P, j4 m2 G2 Z        book.AttachDispatch(lpDisp);
. e5 G* u7 d) `3 z    }
% w7 V( n( K" \  }% n, Y     ( D8 Z' B% `" w; z5 M) N

/ n8 P' n7 ~  U$ {, t5 M$ L3 i    /*得到工作簿中的Sheet的容器*/  c2 W) A5 l4 f
    sheets.AttachDispatch(book.get_Sheets());
! G7 [0 J7 O" o4 S  i- g" p+ Q1 o8 p, @% F
    /*打开一个Sheet,如不存在,就新增一个Sheet*/
4 A/ e& `8 o% R6 r7 e    CString strSheetName = _T("NewSheet");
9 i1 u! C4 |0 }# g    try
, c' t9 W& `( E1 r( i6 k    {" X2 m  q' [+ I0 E" X
        /*打开一个已有的Sheet*/  G0 X8 `! t+ j7 c# d- ~$ u: ~
        lpDisp = sheets.get_Item(_variant_t(strSheetName));
1 L- h$ A1 Z( e+ J% h: k! M        sheet.AttachDispatch(lpDisp);, n: |# x8 v: _
    }
7 Y0 z4 P8 a# r% _5 X    catch(...)
* p& y# T; }( S1 \    {
% }+ q0 w+ H2 S0 l  K4 y2 X        /*创建一个新的Sheet*/
4 y6 ^' I) ^4 \- R        lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
$ _- Z4 A' c+ \7 M1 E        sheet.AttachDispatch(lpDisp);- \; U( f8 J- N
        sheet.put_Name(strSheetName);
/ C7 [% ~- ~! P7 E8 `    }8 y5 u& j8 H6 t, G$ ]1 P
+ i: ^; |* ?9 K' v- H
    system("pause");
) H* C* n* x1 _+ S4 ^% J! C# a! h" ^" v% n; [/ }
    /*向Sheet中写入多个单元格,规模为10*10 */5 s- M. E! V& O
    lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));
! m% C: o* X' {" K+ J4 ~) w; `- ^; m    range.AttachDispatch(lpDisp);& b2 V: F8 d4 Q' f, Q5 D* Q. p) o
. q0 Q- O. A6 M0 ^9 v
    VARTYPE vt = VT_I4; /*数组元素的类型,long*/
$ j, q( V  y$ ^( }- b3 F    SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/' v$ S1 ?# ]* l6 m  V5 i
    sabWrite[0].cElements = 10;+ H9 q& B* R' h
    sabWrite[0].lLbound = 0;
' E* I- v  T. A$ k; J    sabWrite[1].cElements = 10;7 f" ^9 C/ H5 w! R7 [( f5 E
    sabWrite[1].lLbound = 0;0 h0 V! n, F4 }  n- M6 w3 o
1 |1 y! x4 I1 e
    COleSafeArray olesaWrite;* _1 r; i+ L) Y3 A8 O( j) [1 f
    olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);+ c3 x9 P3 V. v* `) v

) V# L, L- I( G' a) }    /*通过指向数组的指针来对二维数组的元素进行间接赋值*/6 L/ `9 {6 A# {8 t
    long (*pArray)[2] = NULL;4 Z8 R/ t. U6 O( @; _/ F1 U! ?
    olesaWrite.AccessData((void **)&pArray);
$ q/ |# [1 F9 L9 v    memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));
" a$ W. P9 P' H( z5 J- V- r7 ?  I% B9 Q% f- \) L! O- {+ [
    /*释放指向数组的指针*/8 [9 _/ q/ N" l, s1 B
    olesaWrite.UnaccessData();
9 l, h$ e* Q7 [, A+ l) }) R    pArray = NULL;
, n, l1 i! p/ u
' R) ]/ l" s4 G; [    /*对二维数组的元素进行逐个赋值*/, c* X5 n6 C% T  [- w
    long index[2] = {0, 0};
2 M+ ~/ C" X# j6 I# ?    long lFirstLBound = 0;; n; z/ T7 G  g1 v- B
    long lFirstUBound = 0;
) v$ v! H  J8 \* ]7 D    long lSecondLBound = 0;6 \2 K- X6 F7 o, b$ r6 b& j; H
    long lSecondUBound = 0;9 ]; C7 j% k1 b0 X' y; Q" X; X
    olesaWrite.GetLBound(1, &lFirstLBound);
2 I' Y& w4 b* v& k" u    olesaWrite.GetUBound(1, &lFirstUBound);
( S) \+ d- G$ ^6 L5 T    olesaWrite.GetLBound(2, &lSecondLBound);
7 I6 g. P# L  K0 @2 ~4 n2 a) g    olesaWrite.GetUBound(2, &lSecondUBound);
6 T3 G9 v# N* R, ?7 C    for (long i = lFirstLBound; i <= lFirstUBound; i++)
: o2 E! I: G- }% R" B( ^    {1 _) @( y3 S! q* O5 p
        index[0] = i;2 o; {" k6 ?. ~6 f. s
        for (long j = lSecondLBound; j <= lSecondUBound; j++)7 u2 j' Z# K) n! e3 V, ?, s, t- @% V* H$ }
        {1 I% I3 y4 W/ }. L, s4 x! `6 z
            index[1] = j;8 q7 v5 V6 k+ I" J/ V* A, _
            long lElement = i * sabWrite[1].cElements + j;
# Z6 I/ U/ w2 t" J2 w4 y! K            olesaWrite.PutElement(index, &lElement);  D4 K" t+ z% @5 ?) }. M5 P2 E
        }. |6 |- S9 t8 l! D; J- w( `/ ~
    }2 C5 V2 V9 ^) @, |
7 t: I% I5 r! c5 _" i
    /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/
5 y& }, \: t! l1 [1 T/ ~8 [    VARIANT varWrite = (VARIANT)olesaWrite;
7 V. W. Q" {8 Y( W6 k, N    range.put_Value2(varWrite);* m9 N8 a% B# c, N$ Q2 o- [

# m. O( \; C! M' m5 P6 [3 a( m3 B    system("pause");% @; ]8 v; A: U' c" m1 S

- |: }7 ?5 v0 d- J4 ?    /*根据文件的后缀名选择保存文件的格式*/
' y' S: d3 R4 A: w. o     CString strSaveAsName = _T("C:\\new.xlsx");
7 \+ @; w6 e  J) u    CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));
) f! q! A& @; g& d  |( @) V# }    XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;/ Z7 A; s/ V: f. Q/ D1 R
    if (0 == strSuffix.CompareNoCase(_T(".xls"))), B) F, R: Q+ [% u: S
    {, p6 x% @( k: v8 U$ b  w' t
        NewFileFormat = xlExcel8;
  Y  ]1 f' [5 R! ^5 L: v    }  F# H- G% X4 S
    book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing,
4 Y; L8 d- z( t: v& \2 J' ]  f        vtMissing, 0, vtMissing, vtMissing, vtMissing, : v7 I% S# N/ x, [/ ^" ?% r
        vtMissing, vtMissing);
, w% X$ l" v1 u4 t" \
8 _; J; B/ e! p) s( i    system("pause");/ Y+ v; D' n* K" O" i; c

0 u) Q+ `: R0 m( d4 ]! I2 z% c! n/ D    /*读取Excel表中的多个单元格的值,在listctrl中显示*/
' L- W+ u) P4 C0 Y* S" T    VARIANT varRead = range.get_Value2();
; P. R. J8 h$ I1 ]' ~9 Y    COleSafeArray olesaRead(varRead);2 Y+ m3 G; I+ |6 s; T$ i

/ q& q( X3 a9 C  d    VARIANT varItem;
4 t9 b8 n: n3 U4 V3 U( H/ J    CString strItem;- B3 E4 U& b3 `$ O1 I
    lFirstLBound = 0;* @  `* ~+ R% R6 n* f# k9 W6 Y! }; P
    lFirstUBound = 0;9 F$ x7 n# i5 Q. Q8 n
    lSecondLBound = 0;9 T& w! `2 L" q' C7 \! T' C% ?
    lSecondUBound = 0;: Z) h% i  L1 h$ P" t; y
    olesaRead.GetLBound(1, &lFirstLBound);
* A% D8 T' n$ a' _) G8 P6 K+ K    olesaRead.GetUBound(1, &lFirstUBound);
( h) a2 y6 T4 ^6 z% j    olesaRead.GetLBound(2, &lSecondLBound);4 |5 i1 D! f( u* n
    olesaRead.GetUBound(2, &lSecondUBound);
0 ?+ U8 X7 ?, `9 N1 t* S    memset(index, 0, 2 * sizeof(long));
  R* A2 k( k$ E- o; w4 X- T    m_ListCtrl.InsertColumn(0, _T(""), 0, 100);
. c7 G7 b: |6 \# B: F    for (long j = lSecondLBound; j<= lSecondUBound; j++)
3 j3 R( d) T6 T    {
4 C* ~  x; Y' U9 k1 f        CString strColName = _T("");7 h7 a' X3 K" V2 M9 b
        strColName.Format(_T("%d"), j);
  ?! }( V/ X' _3 x3 \. m9 Z        m_ListCtrl.InsertColumn(j, strColName, 0, 100);; l2 M% P. A9 n; f4 X
    }6 Z& ]7 U' n: S( d/ w1 G
    for (long i = lFirstLBound; i <= lFirstUBound; i++)
  Z6 N3 v  ^! U% V4 C    {2 ]  c. f# P; X* K$ l
        CString strRowName = _T("");+ d( ]( L1 F4 j& ?7 u# r6 {7 ]) ?
        strRowName.Format(_T("%d"), i);$ I+ L) _4 H. v  z
        m_ListCtrl.InsertItem(i-1, strRowName);
+ b6 t" B. T+ R2 H
' m- Y9 D; d. E, L2 }        index[0] = i;/ i$ X) j2 Y) t- N
        for (long j = lSecondLBound; j <= lSecondUBound; j++)0 ]4 _: p  G4 m' u# b  _, t) s
        {. b) l) m1 O5 e* a
            index[1] = j;6 D/ N7 o* e# y3 W/ S' h  N
            olesaRead.GetElement(index, &varItem);
/ b% }% p1 i5 q' N/ P8 L0 _/ r( c# D6 h* g7 Z) Z# W, X+ R7 [1 I
            switch (varItem.vt)9 R4 |: T" B( N& e% }
            {
- t3 G* [' P8 V$ |) y0 ~) |! N            case VT_R8:1 P  L2 ]5 e) X" D! G. T) h2 {% F
                {) c9 L% n8 b9 T( h) b' K
                    strItem.Format(_T("%d"), (int)varItem.dblVal);
6 {- F0 B+ R& P5 h                }
( i, g; H6 {: n  G" a
1 k+ k& m  M2 _5 O( T2 o+ F            case VT_BSTR:
0 y( z3 o5 v$ \1 G2 g9 n8 O+ _+ z- z                {
0 u1 ^5 W' ~+ k                    strItem = varItem.bstrVal;& n6 W+ h. J3 `1 m7 C
                }
% E- e; Q( F: ~' Q. k2 Z/ M4 K
7 p! d" ?" P4 I) d! e. C            case VT_I4:
+ @6 `) o; D( _: v/ ^                {& O8 a  s% o3 G# c! [1 F, h
                    strItem.Format(_T("%ld"), (int)varItem.lVal);
% W$ B5 E, F. Q$ ?" ~; \/ W                }0 A# }- P6 z- z# v' p! _

" s7 _+ B# ^5 p0 V. A            default:  S4 p5 Z( j0 K; `9 |0 M
                {
$ \+ A  |7 S9 H# `& U4 T  j' `; R6 I1 ~$ o1 C
                }
3 j' j# c+ w- Q( z; t            }4 j; g4 z2 H$ M- b( X6 a

7 o# B' ^" u# ~/ }            m_ListCtrl.SetItemText(i-1, j, strItem);
# j* f, v  l+ q# U/ V        }
) S8 d" n. y/ V0 r, ^    }  w# N7 A. ]4 g3 B; }6 X: \
/ F1 f3 [- d9 E0 b  m
7 i- g& ^( E4 K' m# B- a
" B1 }- r5 R& u6 W
    /*释放资源*/+ T' N8 j. Y/ j2 W9 y! @) [. H4 P
    sheet.ReleaseDispatch();
! u, R" v, A6 G6 \    sheets.ReleaseDispatch();
# X  t  P( ^4 [* W+ z, ?    book.ReleaseDispatch();
0 E/ a, |, Y1 D. L: g) s- z- q    books.ReleaseDispatch();% y# \% G6 M$ L4 \' W  t: y
    ExcelApp.Quit();
$ ~' K% a/ s1 ~    ExcelApp.ReleaseDispatch();* F1 K) y' T) n) x$ k  l
# m) ?, L7 q; c, Z" M! D0 W: ^
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了