PLM之家PLMHome-工业软件与AI结合践行者

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

[复制链接]

2014-11-8 08:13:41 6752 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表格的操作。
1 r* |. u/ x; K  N  
, B$ p8 O, [# M& z7 l本文源码的应用环境说明:7 _6 K' F6 m  o+ r  G
Windows XP SP3
; m/ C% _9 a- t& f/ k9 }9 kMicrosoft Visual Studio 2010; z- @2 m9 u6 C  c. [
Microsoft Office Excel 2007% e% f9 d; N7 J! c6 U# N
  * L1 y9 q! i3 {; @# }* |' s
1、添加OLE/COM支持。
2 Q8 n  A0 S' P! c% l$ H首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。
1 ]) \# ]* H' f, I8 g2 n  j9 O本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。: j/ g. N* B4 p" V% U
通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。( J7 e/ y4 @+ B1 U$ E
#include <afxdisp.h>        // MFC 自动化类! s6 x# k+ i9 D5 f" g
同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:+ x+ }8 S9 T& ]% ^7 B
// 初始化 OLE 库
& u6 ^" J' p. M# hif (!AfxOleInit())5 _: E5 V7 d  H/ w
{
% _: k7 ?9 Q& e+ U6 t$ s2 }AfxMessageBox(IDP_OLE_INIT_FAILED);
; I7 F% v+ y6 D5 |6 }return FALSE;
/ v  E0 C6 \+ ?6 O& a. T}: w, C, O, l' T3 d7 i
  
2 O7 l4 o7 V0 \* J: u+ f2、导入并封装Excel中的接口
# l7 q* B* a1 B* s3 }  iExcel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。( f1 Z/ a8 d& |& H
由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。# f) a0 L' X+ y: Z3 e  V
VS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择4 F) u7 \- E/ C( Y. N) q
要导入的Excel类型库中的接口。
6 w6 N8 L, b; S: L. u在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。9 [) c" E6 H6 M8 M) ?
  
9 c! C$ x$ y* v3 n( w1 V9 t本文所导入的接口对应的类和头文件的说明如下所示:: U; s2 J# S6 t% r" }' s: @- \
  
5 p% X9 M  i- j# \& jExcel接口
6 M7 d/ V) a* E& B. O* V4 j1 B! j导入类' ^6 D4 M6 P1 l: k5 Q- Z
头文件
) J7 e$ a' t# x7 a; e# G: M说明) C& f3 H' f& D6 _" h
_Application
+ U* ?1 q. N4 G9 [9 B6 r! lCApplicaton0 g3 r$ W4 ^& e5 c6 b: g9 `
Application.h
# f$ ^9 A/ r# ]2 NExcel应用程序。
' I; |# N4 T* {6 i+ X3 j0 BWorkbooks
1 l2 v6 y& a# X, k$ _CWorkbooks
5 u" O# E8 r2 d, V% K5 I' Q, a& aWorkbooks.h
# Z% l; F, O# H工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。
3 p/ P# o: X# j6 z8 ]_Workbook
; p' P' x; _, R/ Q. ZCWorkbook
4 B& X2 \+ P! d$ t: v# NWorkbook.h
, A$ M7 G, g; [7 ~单个工作簿。1 P3 b9 ]3 K. G2 D
Worksheets5 ?0 Q# A$ k  {
CWorksheets. y( I8 r; U2 p5 Y: M/ T
Worksheets.h
- @8 a6 X: g6 }4 D) z8 d单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。
0 `( w; Y, Q& ?6 X_Worksheet, a; h- j& [2 |( G3 }
CWorksheet
* {8 e. M0 y& Q7 u! G! g6 NWorksheet.h
; W: J8 q7 f% h1 i9 O" z7 y1 Q单个Sheet表格。
' g2 p1 B5 I5 @: \3 s; h2 JRange0 [6 J: u& R. D; l' s
CRange3 f  _+ ]# ~- a( j9 Y9 h) x* o' ?4 \
Range.h% ^) r5 s7 ~$ O& ^
一定数量的单元格,可对单元格进行单个或多个单元格进行操作。6 \# m) {1 \$ |
  + ?3 Q: N1 X% C2 |! l0 z4 J
3、导入Excel的整个类型库2 e# d; r1 g* s4 `
接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。% m0 D; {1 E/ l# ?9 D  Q8 E- B
通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:' c% w5 n  ^+ M4 x  ?& {/ F
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace! D% x" D0 T, ^. y; P
这行代码的作用是导入Excel整个类型库到工程中。
" y4 k1 [; t4 u0 G3 z由VS2010自动产生的导入代码存在以下几个问题:
' n+ K; y% H5 k" ~, b' I(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。
$ o( Q& N' i# I- J) {+ W' z3 v' g+ e, ^(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。$ Q, t7 n# P0 n/ s0 w* l0 z1 |' X
(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。9 {' w# L5 J5 C4 k! @. e1 ?
以上三点问题的解决方法如下:
; k% Q1 R- z/ b; e(1)仅在_Application接口对应头文件中导入Excel类型库。, x5 z, @- z- H* q: ]
(2)对冲突的类型进行重命名。3 Y& O& E, f  k3 h0 G
(3)在导入Excel类型库之前,先导入Office和VB的相关库。' q$ w& r% ^) \1 ^" O
更改后的导入类型库的代码如下:
! Z- d7 h7 A4 `5 K  t& j, ?6 p- |  
) x- ?& u: r6 G' _/ {! x/*导入Office的类型库*/
: D. i( t" W$ D8 N9 m0 M& _#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \
8 B0 W3 D3 [9 Grename("RGB", "MSORGB") \' Z6 J+ _% b- U, r. z* {* b  @
rename("DocumentProperties", "MSODocumentProperties")8 I# g1 g: ~: A) L
using namespace Office;
+ J, Q; l* @1 O5 A( j  c$ n  4 U, F1 T9 E, N9 g/ J8 e. J& v
/*导入VB的类型库*/! Q% X- s1 K7 D2 k' r9 s5 G! S
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"1 ^  z9 Z& o, V- _! N
using namespace VBIDE;: |, y+ p2 o( z- u! I8 G5 b
  + a. h! u7 F9 U& ^+ w9 N
/*导入Excel的类型库*/7 J; R4 J/ y/ F6 A! T
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \) G% o1 h$ l6 T
rename("DialogBox", "ExcelDialogBox") \
( L' K# L' Y0 K5 Y& D! c! |8 Frename("RGB", "ExcelRGB") \8 N! P, a0 j9 C: X
rename("CopyFile", "ExcelCopyFile") \
0 X/ G. a6 B$ _& `rename("ReplaceText", "ExcelReplaceText") \3 A+ m- L: D# ~% z8 T# @6 D9 b
no_auto_exclude7 O- H3 D; V0 C
Using namespace Excel;1 D* n" p  i. c! v; Q
  
6 S2 k, d) s& [& k& d编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。! ^4 R4 a4 V% @8 X) o; A
  " @9 H! o0 ?9 J
4、操作Excel步骤
. a  p4 W3 C5 `1 w* j  z. S操作Excel的主要步骤如下:
0 y+ w, c# b5 d. t/ ?(1)创建一个Excel应用程序。2 d6 d6 j0 d3 K# S( b4 O
(2)得到Workbook的容器。+ L- w0 z* P- n
(3)打开一个Workbook或者创建一个Workbook。
3 G6 u8 u" d# ](4)得到Workbook中的Worksheet的容器。: |5 ~2 I; T+ v( l
(5)打开一个Worksheet或者创建一个WorkSheet。  W- I7 `8 D7 X4 a. p- L0 o* Q; h
(6)通过Range对WorkSheet中的单元格进行读写操作。
% s8 w8 u* G- V9 Q% C9 v(7)保存Excel。
& Z$ g- s' z7 ?8 z3 d; S(8)释放资源。
. i/ y! d$ P& N# L( p: X6 X) a  
- Y$ S$ _6 S+ i$ o4 U5、批量处理Excel表格: @9 a& O9 D8 f6 w- I
VC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。
$ ~9 {0 y! e  B1 A对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。
0 o9 y$ j" Q5 ]VARIANT get_Value2();. x1 w$ n' ]' R1 C
void put_Value2(VARIANT& newValue);0 a4 Z1 q1 U( A* s1 |/ q
其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。
" R0 M1 D/ y6 [5 D: S; i0 Z其中,VARIANT中实现二维数据的方法可参考
9 b' j7 N4 A3 P6 H# Vhttp://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html
- D' E: ~* t* b* L当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。
# R& u$ ~8 [0 A0 O' K- M  / d( R, u& E! m4 a2 U* U
6、Excel表格的保存& X7 p, x+ g; z3 Z( C
(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。
' ^# G, F. G4 K7 [. `, R* C(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。6 G1 C* @0 I) q7 Y+ ?* ~; ^8 |
SaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。
" L* H+ b8 [/ X  9 Y, V" [  M$ J, Z
7、获取当前Excel的版本1 I5 ?$ ^6 G* C. h: b7 B
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
) o7 k$ K6 \; _9 b4 r7 T  
5 p; ^' O/ w8 d8、示例源代码* |% R5 U4 \% f: t; y9 p% l
主要代码如下:
6 d: P/ `( D- {$ Q1 t4 `4 ]: M$ ^  $ U- H  L& C  v* Z8 P
6 \5 F7 M* c- y" A

/ z( ?4 f  @6 Q4 v4 B    m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);
% }9 E$ A( Y& d" o( a! T; a: B; B. ~0 c
    CApplication ExcelApp;
% s, x' U# a3 s    CWorkbooks books;
  d' \/ u6 e0 H5 U$ r1 n9 B    CWorkbook book;5 X$ o4 \! o  Z3 O9 Y. V+ r+ R
    CWorksheets sheets;" c1 {! w5 }7 j7 X  c" s+ A2 |
    CWorksheet sheet;8 y% v! C+ ~. p  H
    CRange range;" _8 d- \& G" h& m% g! x, y
    LPDISPATCH lpDisp = NULL;
# q5 R2 V8 L6 t: s7 l1 f2 u) W* [0 |, `. P( u; n
    //创建Excel 服务器(启动Excel)
" ]8 ?2 y  P; ]# O3 i    if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))1 {9 z' y& H; X
    {
$ K; @1 H6 v% R* U        AfxMessageBox(_T("启动Excel服务器失败!"));  `' I% x% V: x2 S7 V' g+ W8 f
        return -1;% x; e( c. X( Z4 S$ g" H! l
    }
1 O# d% u2 h; e# r& z4 L) K5 |) O. Y
& p8 [. z9 M  j+ H0 G    /*判断当前Excel的版本*/- T( m$ B/ ~7 z  M. I1 S
    CString strExcelVersion = ExcelApp.get_Version();
( ~- G$ j( d* x. n7 T; J0 T    int iStart = 0;* Y& w# H: k( B# g3 N
    strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);
' I+ g9 d  |, O8 U! Q    if (_T("11") == strExcelVersion)
- \( I9 a- R3 k1 {8 q. p    {# a; K( @( `) s; q) V9 H& A3 `
        AfxMessageBox(_T("当前Excel的版本是2003。"));3 K) d7 R" k9 h# j: }7 V
    }9 d( _& v% y# t
    else if (_T("12") == strExcelVersion)
7 ^. U% S8 j# g& D% t% X# v    {
1 X. `1 b( ~2 s) f0 k# W        AfxMessageBox(_T("当前Excel的版本是2007。"));/ K1 N/ [0 R+ Q4 g3 j
    }" s$ I3 H( y1 K- P# c1 f, T7 M
    else
9 o3 D- C/ a3 e* B$ t' x3 K' u" o    {
  x, _! C4 x9 a- j        AfxMessageBox(_T("当前Excel的版本是其他版本。"));
$ O7 f( Y( c4 Q* L  }    }
5 e# q! ]  Q3 }% I* T+ z
1 S- E  p* u, ~; z    ExcelApp.put_Visible(TRUE);
- n5 A* V/ ^( Q3 `/ a5 }1 G9 b    ExcelApp.put_UserControl(FALSE);# i2 w* H& V! m/ {

! r1 I( x/ H: B3 D& a2 w" w# @    /*得到工作簿容器*/
5 O- H0 B$ @8 v' O! Y9 b& p# H    books.AttachDispatch(ExcelApp.get_Workbooks());! M8 c! B( x, t! c' H! T8 @$ z
) ^' }7 j% h) v
    /*打开一个工作簿,如不存在,则新增一个工作簿*/: V% b( w+ I3 v
    CString strBookPath = _T("C:\\tmp.xls");5 t  Q. g: w, i9 P" z8 q' ~1 I6 b
    try9 h3 H& c' a8 Y* h$ U4 x
    {
, _; O8 f$ D% b$ D+ d6 a' r2 N        /*打开一个工作簿*/
) P- {7 V0 Y# {0 {* H3 }( p        lpDisp = books.Open(strBookPath, " X0 F& t0 \- d! n# l) A( x
            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,  q; P5 n) Q1 ^0 h
            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, " V/ }: S7 ], S9 M
            vtMissing, vtMissing, vtMissing, vtMissing);
- G5 ^% P3 s( S# g        book.AttachDispatch(lpDisp);  x; {$ Z$ ]* a# E4 b! {
    }' [# H- Z. ~5 V' N: L
    catch(...)
) h1 H8 w2 M. E; k    {
, C9 J- A* e* r% a: O% u/ u        /*增加一个新的工作簿*/
$ ]( K7 C6 k# Z: M) S        lpDisp = books.Add(vtMissing);
) z( o& R1 @9 f        book.AttachDispatch(lpDisp);+ I0 k) {6 p! ]6 q1 b) t2 S/ o
    }6 y' r8 |6 `! ]/ c
     
( m7 m! H4 \! d3 ]
" D6 l; x" G; o    /*得到工作簿中的Sheet的容器*/
3 ^7 j7 k# k3 M* i4 o    sheets.AttachDispatch(book.get_Sheets());) x8 `( E0 b1 Z8 X- k
5 p2 V' c3 i3 n, o5 M2 V( A
    /*打开一个Sheet,如不存在,就新增一个Sheet*/
* {7 k% E  W" t. \3 X    CString strSheetName = _T("NewSheet");
( S$ k8 k- [1 r/ {' v' ?    try" Y  p# Q5 i& L$ {! J
    {' p5 Z9 O* ~$ P+ x! n* D4 ~
        /*打开一个已有的Sheet*/0 ]7 M. f$ R9 Z" J" W% G
        lpDisp = sheets.get_Item(_variant_t(strSheetName));$ ?% I! r3 n8 k9 q( Q1 c
        sheet.AttachDispatch(lpDisp);2 Q$ ~, M% i' A9 a  y  m
    }
5 y9 U' g& f/ R/ f- q/ Q5 e    catch(...)! Y* m4 h3 c# D) n: u9 ?; g
    {
( q5 L  _; L* X) h7 h6 k, \7 E        /*创建一个新的Sheet*/, T: w. D6 G8 S7 W0 w
        lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
* X5 y- n8 J( L; j  D* m$ @8 N        sheet.AttachDispatch(lpDisp);; a. c9 V" l3 \; i- p! {( U
        sheet.put_Name(strSheetName);0 l& ~% J7 d4 D# H- [# B, E$ Y, i& T8 @
    }
+ i0 i6 k4 V. {; T, S: ~" G5 F  G! q+ t& S% N1 N, ~6 c/ b
    system("pause");7 n& a8 b) _+ h& T

) f% [+ p1 ~# K" `- l2 H    /*向Sheet中写入多个单元格,规模为10*10 */5 l! W* |, Y1 v1 x! m  x
    lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));9 U: U* R7 o4 y7 q5 s" N  t
    range.AttachDispatch(lpDisp);( Z; F. y, ~+ q/ F  e+ ?) k3 G. L/ m

8 ?: t. P' L6 b: r    VARTYPE vt = VT_I4; /*数组元素的类型,long*/' _7 U3 w" X. ~/ {) ~# [
    SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/
2 s; b( k$ F% z- I7 [0 Z    sabWrite[0].cElements = 10;, K; _' H% Z# {' I! v. Q
    sabWrite[0].lLbound = 0;
  ]: ?" W" B4 j9 F. Z    sabWrite[1].cElements = 10;. G1 U; j0 {, x  t: G
    sabWrite[1].lLbound = 0;
& I- Z/ I4 [  g2 Z1 ~4 I0 j. B5 D" k* ]: c2 x) [
    COleSafeArray olesaWrite;
1 @) y& x0 K0 b# V    olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);" k0 }6 _, W9 M7 d: ?

8 k/ F6 b2 L3 x" I* @    /*通过指向数组的指针来对二维数组的元素进行间接赋值*/; T  c8 _: \( _* j. ]
    long (*pArray)[2] = NULL;- M$ M% d, }4 J% n' Z
    olesaWrite.AccessData((void **)&pArray);
7 R4 s- `5 Y% Z( e& T5 r' v    memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));  R, s# T# ?3 e; a

; ]8 b4 a; _( a9 L! m& _0 W    /*释放指向数组的指针*/% j, a. E; h& z* a
    olesaWrite.UnaccessData();
* x% o6 G9 j5 T" X    pArray = NULL;5 R, {' Y9 m/ G* m

5 z+ J+ ]6 b. C) f$ |    /*对二维数组的元素进行逐个赋值*/. _/ E3 \" d" C! H0 L2 p4 j
    long index[2] = {0, 0};
8 D* }' `# F( x. `8 ~6 l6 E$ J    long lFirstLBound = 0;, F9 g4 A  U2 e3 ]8 M: I, O) g
    long lFirstUBound = 0;
) \# K: d+ _' g: D, r3 W    long lSecondLBound = 0;
0 |$ L8 i, a/ z    long lSecondUBound = 0;
, ?+ N3 G1 v& X: }    olesaWrite.GetLBound(1, &lFirstLBound);3 Z) @1 A  W$ N
    olesaWrite.GetUBound(1, &lFirstUBound);
1 G* O0 ^) H# V! `- o    olesaWrite.GetLBound(2, &lSecondLBound);
& B7 O% F# G  L# \0 |    olesaWrite.GetUBound(2, &lSecondUBound);5 H) }) x' s) f5 _% }
    for (long i = lFirstLBound; i <= lFirstUBound; i++)
% l5 g8 A; c1 l6 R! a9 j    {
$ l" N. ?- @' H+ x4 q7 u        index[0] = i;
3 W& Y8 X2 H+ g7 R" S( @        for (long j = lSecondLBound; j <= lSecondUBound; j++)
# d& u2 j# l: c0 d: o! h        {7 Z. a8 N: `5 ^( f, g
            index[1] = j;! N- M: i% }% i% N' `& |
            long lElement = i * sabWrite[1].cElements + j; % S7 Y8 E" u4 |+ r$ u; `
            olesaWrite.PutElement(index, &lElement);
, ]; J$ Y0 S+ V; i# r5 {        }7 Y  f: r, ~& K3 Z3 @2 d
    }
7 Q0 B' B, |4 j2 U2 P' L1 Z# r1 P4 l! P
    /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/
+ \- i3 j) ~2 c5 E2 @# ~2 N( K    VARIANT varWrite = (VARIANT)olesaWrite;
, ]2 G1 A0 g7 b3 h    range.put_Value2(varWrite);
- _% K: v. |) m' M. h' n, K/ }, s" z5 q8 N
    system("pause");
8 i7 S: r3 [% \% N  m& m  d) G, h: n7 s1 \
    /*根据文件的后缀名选择保存文件的格式*/$ O2 O7 C0 Q% ^. Y9 J- c
     CString strSaveAsName = _T("C:\\new.xlsx");
2 E: j2 q& P- j4 W7 X    CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));0 Z8 ~7 Y" t6 K4 L6 Y) ^! e
    XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;0 ]" X; r/ g, f, ]
    if (0 == strSuffix.CompareNoCase(_T(".xls")))
, B) X" x% _' E' R" x    {9 @% d% k2 l3 [- V0 L0 v
        NewFileFormat = xlExcel8;
) v& Y( _) X# z! o    }
0 ~" e5 W# E7 {# @+ T- C/ S$ ?    book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, * X/ w- Z  K9 J0 \- I1 R
        vtMissing, 0, vtMissing, vtMissing, vtMissing,
0 L7 R' s* M1 h; Z+ x. o        vtMissing, vtMissing);
. e+ I' j) G0 S  L6 W$ E. J7 T
/ @$ B. J: U' F7 ^( _  X% v- {    system("pause");, @  }! ?  C& o- x) \

  ?# h7 E+ G* Q+ @    /*读取Excel表中的多个单元格的值,在listctrl中显示*/
: v. ^# j! z. f7 ?$ \+ Q' l: p    VARIANT varRead = range.get_Value2();
0 J4 X0 y: W) r1 R, |" |3 d    COleSafeArray olesaRead(varRead);: z3 W3 g" L4 n% c2 t1 N
* y% g1 t6 Q! P: [
    VARIANT varItem;
  V: b0 r3 J8 h/ h$ z- ^    CString strItem;/ K/ V8 i; |3 w2 b' t
    lFirstLBound = 0;" h7 e0 Y3 D/ N. w/ i. O1 }
    lFirstUBound = 0;. z8 G- ?& m3 O* {+ K; i' K
    lSecondLBound = 0;) j' {/ B5 Y$ n" c( U. D
    lSecondUBound = 0;% l" Z3 E" d5 S& E; `5 B: ?# L" k+ Q
    olesaRead.GetLBound(1, &lFirstLBound);
& ?  L( c# c* i  i; c! P7 E9 H    olesaRead.GetUBound(1, &lFirstUBound);) C. g, u: S7 K9 u& p$ Q
    olesaRead.GetLBound(2, &lSecondLBound);5 l1 n1 c! f' G1 Y- a7 C
    olesaRead.GetUBound(2, &lSecondUBound);- W, S* p5 k% g: M5 s& n9 {
    memset(index, 0, 2 * sizeof(long));
4 V& X5 E$ q4 n& [! T; G    m_ListCtrl.InsertColumn(0, _T(""), 0, 100);
1 r3 @: b/ ^  b/ o, p6 k    for (long j = lSecondLBound; j<= lSecondUBound; j++)
4 {" T) J# j" _4 @; V9 R( F    {
' q: s( n" ~; R+ c8 o9 Z; [        CString strColName = _T("");5 e# m) _; x/ y1 s# S) }
        strColName.Format(_T("%d"), j);5 V) _7 _! L7 n+ y! k
        m_ListCtrl.InsertColumn(j, strColName, 0, 100);0 H+ @# J. g8 P1 C: p, N
    }4 f0 E& G/ \9 I2 n& n4 M( l
    for (long i = lFirstLBound; i <= lFirstUBound; i++)
- l, l' z3 v; j) y2 x    {' J3 m+ b3 W3 `2 N; E
        CString strRowName = _T("");
* Y* C, X: U1 f4 }' N. W0 E) V        strRowName.Format(_T("%d"), i);; P8 K% l) o5 O* {8 }7 d: U
        m_ListCtrl.InsertItem(i-1, strRowName);
3 ?: _* o+ c' b& Y
4 S( {2 Z0 I) `8 p1 y% J        index[0] = i;
% ~' G) x  D# d        for (long j = lSecondLBound; j <= lSecondUBound; j++)( I: t2 Z0 U: b7 D: {& i
        {
; f, d3 ~' h; u# C3 Q6 j5 g, z- h" [! {            index[1] = j;$ A" p: }/ @' X* [
            olesaRead.GetElement(index, &varItem);4 n( E9 X1 F! ~, S+ i

( h" Y/ I3 N$ @% U            switch (varItem.vt)
( ^. u! S! U) t: }; A            {
% K6 e. d+ Q" ^& F* ~            case VT_R8:- I5 A. `. u5 P& S3 X! l% K, F
                {6 U! M4 B, ]! F6 N
                    strItem.Format(_T("%d"), (int)varItem.dblVal);
* t3 l* z$ i4 P' _% U                }
' }9 v7 ~% Z7 J4 ?2 j/ {' }& |5 c, f2 t
1 w6 [& ~" I$ o. q            case VT_BSTR:2 r0 f1 J, m7 L3 _3 `
                {1 n/ }2 R8 y+ l7 x
                    strItem = varItem.bstrVal;
% w4 O  U, J3 D+ V2 y3 U8 x- v: [                }# H3 V8 D+ r% c
9 A, c$ H5 C, v; x
            case VT_I4:, e8 M2 i' H+ L; m
                {' Y. B4 B) u8 t% N1 B. }
                    strItem.Format(_T("%ld"), (int)varItem.lVal);. X% \8 i, k% e* ~+ I. _
                }* ?+ K3 _- U$ S6 j% e

* l5 y. _/ d  g) }9 F6 J            default:
8 K9 _4 [! l- U5 e# ^                {
) g. ~0 E# ~# w
' ^+ j& M5 K5 r2 }3 X                }* q* }. c& t% y& ]/ l4 A5 a
            }
; ?# s  k9 |5 j. U: r/ C4 g) {- Y' t" e: Y5 s( M
            m_ListCtrl.SetItemText(i-1, j, strItem);& ]9 B* G% B, k  r. m
        }
6 p& G: g0 h' U    }
: O( b7 u! N+ M/ A& a0 V/ Z/ U  F: H2 u2 z0 W
" s( }# o3 O* P, T  e

3 q6 ]% A* g7 [. h' S# A    /*释放资源*/5 M# y1 c' S6 l7 g( L) D1 J! _1 O
    sheet.ReleaseDispatch();
7 I: h; A$ p& s- o. c# R, C    sheets.ReleaseDispatch();# t* H: w2 a4 y* ~7 S
    book.ReleaseDispatch();5 V5 l! k: |% |9 [8 x
    books.ReleaseDispatch();/ u$ q( r: ]+ ?+ h7 |. ]. N1 A
    ExcelApp.Quit();
8 X3 f4 l5 u) b. a/ v, k9 j/ L, u    ExcelApp.ReleaseDispatch();
( A1 c* J' J4 F
2 R+ R# c: i3 T: O2 ]( ^6 j
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了