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

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

[复制链接]

2014-11-8 08:13:41 6732 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表格的操作。
3 S. T1 c9 W4 z( U  
/ q# ^7 j* w5 e, n+ Y& Z& V本文源码的应用环境说明:
% [  A/ O6 V# h! sWindows XP SP31 m' @) g) E% }9 L- V1 H
Microsoft Visual Studio 2010# l/ n! C# \2 J0 I
Microsoft Office Excel 2007, |" C- d& c  j( I% B
  
$ z" I) A/ A( l4 R$ z, k3 ?1、添加OLE/COM支持。' x& E4 h; M/ |) \: m4 v
首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。
4 A/ f& m* O/ @6 e( O2 J本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。
/ E6 J. m5 J( g1 e+ a/ v0 L  l5 J通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。
" g9 M5 d4 q# A: k1 z+ N" I#include <afxdisp.h>        // MFC 自动化类
& ]. |2 t  v" Q* B$ P同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:7 V$ d9 r- ^$ l! A3 q5 D4 ~
// 初始化 OLE 库
3 B7 G' g8 T7 f4 }, Jif (!AfxOleInit())/ o  a$ L0 e9 E
{
; {: E( A1 z! g& \AfxMessageBox(IDP_OLE_INIT_FAILED);; h+ n: d1 c/ ]
return FALSE;, }& W, e: i% G' r3 [
}
, Q" a, H8 x; f3 ~, R4 B  # v8 t2 y4 X* V# o- h6 `; d2 X% g+ v
2、导入并封装Excel中的接口6 \7 W& i! X% |) g- c
Excel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。
/ g) X2 |) J1 [1 X1 W' m/ x由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。0 t  x; t( m. m2 o& C. F
VS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择4 ]8 N4 S2 T1 K* x, C, v( U  D; n
要导入的Excel类型库中的接口。0 o6 _8 [0 C' Z5 ]0 j8 f" D* F
在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。
$ l" }) m$ ?3 [3 k  
% g" s( D$ m! p/ {- C8 A& Z本文所导入的接口对应的类和头文件的说明如下所示:
; V9 _$ I7 ~7 y9 n, y% p  * O2 _# V" y1 M0 H  `
Excel接口
9 n4 ]# G  S. P导入类
3 ~. s; f6 I8 l2 q% Y头文件
3 j' k" S2 u1 ~$ ^0 k说明
1 ]( B5 E1 n: W( j  M% }_Application# v! C$ q" `, {1 V$ {# |" B% h. d
CApplicaton  V4 }; {" M/ T" f
Application.h, o0 ~. N" D# _1 Q/ j
Excel应用程序。" f, d5 S1 J+ |% ]; d. |
Workbooks; k, t+ P. r' L( U
CWorkbooks% t8 Z0 B8 ]6 N1 \7 b
Workbooks.h) C5 d4 A0 B( ~. ]& o
工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。5 Z5 j' x( M" s! I2 g$ {/ ^) S( j$ e
_Workbook& p/ c2 w5 Z7 O. x) J3 s
CWorkbook
+ u7 F' V7 E9 N6 K  rWorkbook.h
! A9 q: C. B$ I8 q单个工作簿。
/ H- y) g1 G- m' J4 AWorksheets
4 i4 J) t& A6 z; ~& \CWorksheets
% `( u. [: _# S" i/ g% J: \Worksheets.h
2 O0 |0 X9 {& x  H% |8 t单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。9 i; R1 a+ O& G$ t
_Worksheet- J7 u% T. D$ V* y
CWorksheet
5 g7 I8 j7 T1 @& T3 q* OWorksheet.h
$ `# {9 }2 Z8 i3 W0 P单个Sheet表格。
* |8 Q) e) a- n1 Z( ?( G' |$ Y4 x# URange5 H& Y9 a/ q* u. X1 n7 F% d+ y% o0 @
CRange& ]" i9 v/ }6 C& m2 r0 R& j3 l( w
Range.h/ E* M$ z% N- c) P; C
一定数量的单元格,可对单元格进行单个或多个单元格进行操作。% g9 [8 t9 Z# F1 r- a8 c
  
$ ?' P6 [- A3 }8 |, I6 ~2 V2 u3、导入Excel的整个类型库$ V8 |6 H9 f1 b) R* I
接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
" \* E& p3 M! A' u% r- W通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:
! r8 F, A( f9 L- F; P#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
' Y" I5 `" W7 s这行代码的作用是导入Excel整个类型库到工程中。2 R, |& V: H/ x+ U5 L9 x6 D' \
由VS2010自动产生的导入代码存在以下几个问题:
$ l3 A8 g9 O8 P# o(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。
+ E3 q. Z  R4 K! ~% m(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。
' e( F+ O! X+ Y& m  _  U, k(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。
3 `; X8 C% x8 B! P, P以上三点问题的解决方法如下:  U1 V8 c4 [3 W* J& I: z/ r
(1)仅在_Application接口对应头文件中导入Excel类型库。% r1 T  f! M. }6 F
(2)对冲突的类型进行重命名。
% z2 U- P# s0 h3 q( \5 C  G! \(3)在导入Excel类型库之前,先导入Office和VB的相关库。
, L8 D) D' T7 q更改后的导入类型库的代码如下:+ x7 e% \! x8 E0 o  I
  , L3 b. r8 I  d
/*导入Office的类型库*/2 S0 F5 b) S* q+ G+ j/ l3 w/ W
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \% |0 ]& h( X: I8 @" D
rename("RGB", "MSORGB") \
: @2 C1 I7 o6 Q! _- F1 erename("DocumentProperties", "MSODocumentProperties")
0 @# s8 d6 {' y' lusing namespace Office;
0 R: p4 p5 L7 S" I+ \, ~# M  
, m7 e( {0 D+ U" e2 J  ?  g! h5 h9 l/*导入VB的类型库*/
7 O( j1 @3 ^+ s4 n#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
" o" F3 w" F$ W8 X  i- C7 Gusing namespace VBIDE;
2 l" X6 G6 A! \; j8 ?  t  
7 C# T( I) L8 M* q2 b; w* Y/*导入Excel的类型库*/
4 G) |: h. g& D' w) X#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \
; g5 ]5 M& ?; K7 v7 yrename("DialogBox", "ExcelDialogBox") \5 h( x0 o7 c, d, ^* R5 Y6 w
rename("RGB", "ExcelRGB") \: Y/ ~; C* d) q+ v. e
rename("CopyFile", "ExcelCopyFile") \1 a9 J0 N3 `" ?2 \5 l9 |
rename("ReplaceText", "ExcelReplaceText") \3 O; X6 u1 P$ [. d) r4 k
no_auto_exclude
" f3 }2 g0 \: P3 A7 R$ Y1 }Using namespace Excel;
: A0 ?; `8 y. l% b- k5 y( S  9 `. x8 e" z1 r3 y. j5 x1 ?9 M1 D
编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。! K0 c0 r7 Y1 |% {& r9 _: j
  
7 z4 X4 N. [$ u% x4 G: b- ]4、操作Excel步骤4 R1 \; b$ P  ?" Q; Z( `; A
操作Excel的主要步骤如下:0 e* g" u; ]+ k! m7 I7 [" ]5 B
(1)创建一个Excel应用程序。* m* A) m0 J7 p7 v5 G4 }! A
(2)得到Workbook的容器。
+ Y" u* D6 c0 }3 `# A) Q' L  E$ E3 I(3)打开一个Workbook或者创建一个Workbook。% f" O* h0 ^- x  y3 a2 j
(4)得到Workbook中的Worksheet的容器。5 r3 l4 I- g) z' y
(5)打开一个Worksheet或者创建一个WorkSheet。2 z) W, }8 U* Y# A9 o0 ]% O+ x
(6)通过Range对WorkSheet中的单元格进行读写操作。( h) Q2 ?/ P: B* {0 o) |  n! b) c
(7)保存Excel。
  ?4 b4 @7 W  F3 L) P(8)释放资源。/ Q3 `2 R: w$ ?: X+ H$ }/ C% Q
  2 m# X5 t, M. u! n: Z4 o6 u* i
5、批量处理Excel表格
! c% g) t" t7 l% S8 ^# H+ f2 KVC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。" B) C, i6 @( e# a7 [# j9 Q. `
对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。
$ u5 J2 B, K& B& o6 T( C3 g; zVARIANT get_Value2();
# L' n8 {3 {1 v8 Wvoid put_Value2(VARIANT& newValue);
. I8 b* G( p" R5 a2 W3 P其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。
' a2 |8 n& Q% M" d其中,VARIANT中实现二维数据的方法可参考5 ~  E/ G5 I$ n7 h
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html
! g: b7 [+ ]0 y" a当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。
/ Y) {4 V9 h) G/ V$ t  * j9 g0 n0 k' u
6、Excel表格的保存% |3 g9 @, `7 ]. [% H; Q5 x
(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。4 v# b8 N0 T/ m% s$ ?  o
(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。' a6 R& c! _' j1 U' J
SaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。! ]! z6 Y7 W1 i" C" ~( |) Y1 e, b
  + L, F/ Z4 N/ a. _
7、获取当前Excel的版本% a0 [4 P3 R. b  U# G
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
% v, f1 p( N/ M# h  , O" Z" k, f* b, R
8、示例源代码7 I4 i( Q$ k3 l$ [5 X0 w8 ?; E- Q
主要代码如下:
5 S. N/ ?; N: [$ j" f! Y. N+ }, H2 E  0 R  e. Y; A/ D5 r& M7 r9 X
8 R% e4 j! G' N! X$ T% w+ y
0 B- F" l; s" [8 x
    m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);2 W) l* M7 u  u. x5 P& N% }1 d

4 _1 \: I( h7 S* W  k5 O    CApplication ExcelApp;
# S. W0 j4 t$ [6 P' E& D- G* N    CWorkbooks books;6 d/ H: w. F! O- R
    CWorkbook book;
- G4 _( A2 ]. T" U7 J    CWorksheets sheets;
! w- ?) l" U* v    CWorksheet sheet;
& H5 F! e/ a6 i    CRange range;
8 l! v5 u2 z/ N    LPDISPATCH lpDisp = NULL;6 j" U  |3 `  ]; B1 C6 R, u3 [% i

/ i4 V% i7 n% m1 p" a1 T: x: H    //创建Excel 服务器(启动Excel)
6 z# [  ~6 ^7 a5 ~5 q3 {+ W* C. R5 |    if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))
, V6 |7 G- p) E. A* g    {
9 M, c+ y$ }* j8 ~7 F4 W& L9 `        AfxMessageBox(_T("启动Excel服务器失败!"));* L% j. O$ W3 F; p) s
        return -1;
+ G) D; w9 Y3 ^4 f0 Y5 S& Q- P    }* ?6 S) e3 c8 j
" q5 g/ j  ~2 f
    /*判断当前Excel的版本*/0 k3 _' f8 m  A, t4 m$ Q4 u- X
    CString strExcelVersion = ExcelApp.get_Version();
- e$ k+ D; r& n$ |9 P: |    int iStart = 0;  j: {7 y  z2 s5 X3 d+ D
    strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);
( d' o+ i2 B1 J    if (_T("11") == strExcelVersion)9 _' H, I9 N! R8 j
    {+ j  q4 ^) k  ]6 E1 @$ g
        AfxMessageBox(_T("当前Excel的版本是2003。"));( Y# Y) ^0 m/ f$ n7 B
    }4 Q4 l4 G" d: T4 I
    else if (_T("12") == strExcelVersion)
- ~' ]: Y2 H$ q0 N+ |% T; W4 e    {5 A/ F5 z; N1 P) \$ @% l
        AfxMessageBox(_T("当前Excel的版本是2007。"));( V: N/ ?" ?  N+ Y7 k4 u0 s; Z9 h1 `
    }5 q# D" t" K! _2 d8 E/ U
    else
& F4 A$ m" A( X! y& S    {
5 Q, `' `$ {+ x: |" \6 C  ~        AfxMessageBox(_T("当前Excel的版本是其他版本。"));7 p! d+ f  H. b' H
    }( B# ^' ^. M8 `7 Y

2 J; O. n  B* n1 B% z    ExcelApp.put_Visible(TRUE);
% m- V& C* S5 N    ExcelApp.put_UserControl(FALSE);
) O6 z) _* q5 b$ t
) O: s" s/ D& ?    /*得到工作簿容器*/
+ P. [% c9 `! P    books.AttachDispatch(ExcelApp.get_Workbooks());$ `+ ?) w: ^7 H

) R' P9 c! D8 ?" u8 X    /*打开一个工作簿,如不存在,则新增一个工作簿*/7 T+ V5 Z3 T& h$ _& T; `* H
    CString strBookPath = _T("C:\\tmp.xls");
3 E# `; N/ I4 ~9 }% z    try
% m) ~# K' u6 X2 P$ n  f1 ?, P    {
2 R$ ^! M: h- @% A        /*打开一个工作簿*/
: s3 K2 E  T/ }. C& ~- ]; P        lpDisp = books.Open(strBookPath, , a  ^1 F8 A, E% F- K& x$ N$ l* M
            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,& C2 ?6 c0 k# s& ]9 L
            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, - q( z# y/ s- Y' u$ d& B1 I
            vtMissing, vtMissing, vtMissing, vtMissing);7 M! I- k' x2 h: c" b% G
        book.AttachDispatch(lpDisp);
$ C' z" o5 H- m. L! j9 I0 x    }
. z* {' V* R/ f8 M' b    catch(...)2 j" l! c% Z  G5 w" D% @
    {( L. v% d2 b/ a- `
        /*增加一个新的工作簿*/
9 }, H* [6 A5 t5 [& R        lpDisp = books.Add(vtMissing);
+ `5 h- z7 |; }: U        book.AttachDispatch(lpDisp);
7 z/ C# _3 W( q8 _* x) i9 h    }
; V' G! z1 \; x  ^' b& v     
8 k: A1 m+ U9 s- I, d6 R1 _4 o  Z9 U+ K
    /*得到工作簿中的Sheet的容器*/
$ c  P( C" @" D' s, X+ W6 j. _    sheets.AttachDispatch(book.get_Sheets());: a" `# d: e, \1 |

0 A1 j; `! n. k) N    /*打开一个Sheet,如不存在,就新增一个Sheet*/* d  z5 g9 k+ l/ \( S
    CString strSheetName = _T("NewSheet");' P! f3 H( F$ w4 f& o, B
    try" r7 B9 C  [6 i  B& F6 ?! T+ s( v# s
    {
% N2 B5 r* g8 C; e: ~+ n! u- ^4 G        /*打开一个已有的Sheet*/
  a7 V5 N: ]2 e2 o        lpDisp = sheets.get_Item(_variant_t(strSheetName));
% w& V$ e0 V, i: J- |        sheet.AttachDispatch(lpDisp);
1 N; Y( w0 v/ ^    }
- ?2 L2 C; N  V    catch(...)4 a4 K9 f) P- ^6 g$ M  o& k
    {
/ S8 X1 ^% `! l( i6 Z        /*创建一个新的Sheet*/: y9 W1 e5 V* z/ g6 s  \- W5 J
        lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);9 Y* M. z6 T7 L( Q
        sheet.AttachDispatch(lpDisp);
# ?8 r1 p- ], m        sheet.put_Name(strSheetName);5 W' l4 X. O. k( c8 k9 m
    }
- y3 {  d; Z* e( b/ L
; U) g+ s. t6 i) W9 n; T4 u0 x    system("pause");
0 z  t! `+ q4 i# H
& X( l  r1 g/ E    /*向Sheet中写入多个单元格,规模为10*10 */5 u9 I" B' j) l
    lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));
% S. h8 c' J5 H* ?  ^! D    range.AttachDispatch(lpDisp);
8 u  J7 z7 }% e" s
+ G+ i8 V. a& L3 x    VARTYPE vt = VT_I4; /*数组元素的类型,long*/8 O* |; B" g0 f/ b1 {# W
    SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/( d; a$ Z0 y1 o& [, h
    sabWrite[0].cElements = 10;4 j3 d8 z  u. r7 T+ T' |6 n2 F+ r
    sabWrite[0].lLbound = 0;
  T* v/ k+ C1 F2 p( k' F; o    sabWrite[1].cElements = 10;
9 a) P! {* a& y) c7 s% f+ g# A    sabWrite[1].lLbound = 0;
# S$ U" I+ L) z( p& U( \' B% o% F2 \9 T* O& M
    COleSafeArray olesaWrite;* D; l* i" J! S4 V8 X& x) D+ p
    olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);0 f. F2 p$ a9 |
* E2 Q- b" r( e5 K: `" H0 l
    /*通过指向数组的指针来对二维数组的元素进行间接赋值*/
7 o* A+ X  u" u8 t' d9 I; _) @0 B    long (*pArray)[2] = NULL;
2 c5 l) r2 W5 a) f, C    olesaWrite.AccessData((void **)&pArray);, D9 c+ a8 o1 S1 @5 K7 [
    memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));# {) l( n: p# A0 x# S9 c
- F. Q' ^4 N, \
    /*释放指向数组的指针*/
/ q7 S$ |9 c! t    olesaWrite.UnaccessData();0 G7 l; [- D( K1 _' j2 s4 y3 l" \
    pArray = NULL;
; F5 ]( P  W" }; u
) e2 |, E8 W# C. e& ^    /*对二维数组的元素进行逐个赋值*/
6 e7 W+ O8 O, K    long index[2] = {0, 0};6 `( a; d) X* F: \5 W. o9 E6 ]
    long lFirstLBound = 0;
! A! F8 g/ K  N+ n* b5 p    long lFirstUBound = 0;( |+ `! Z( `6 G
    long lSecondLBound = 0;
7 U  Y- |; K) t1 Y    long lSecondUBound = 0;
8 c8 Q% V1 R4 a' O, z% d    olesaWrite.GetLBound(1, &lFirstLBound);5 j: H5 r, y( l! }+ C/ B. R5 K% T
    olesaWrite.GetUBound(1, &lFirstUBound);
0 m5 V1 M+ H" P9 O    olesaWrite.GetLBound(2, &lSecondLBound);
& h  s( z0 J/ U9 ?- u! {    olesaWrite.GetUBound(2, &lSecondUBound);3 X3 ?4 k+ m- F6 w
    for (long i = lFirstLBound; i <= lFirstUBound; i++)
. R1 a% _2 {5 y( C    {
! S' m7 b* k8 _  a8 z        index[0] = i;3 W- `/ N1 [, k& O( P+ f( f
        for (long j = lSecondLBound; j <= lSecondUBound; j++)! `- L$ F4 L! Y, T
        {$ t- g( _! E7 `  x0 [# p0 y! U  t
            index[1] = j;
. g" b9 A& D- q+ U! B, ]( A9 H            long lElement = i * sabWrite[1].cElements + j; " Y" y* {# t1 k" P+ H
            olesaWrite.PutElement(index, &lElement);
( E( X6 x5 C* |& C" y$ V4 z# S        }5 f- s2 m2 X, B. \6 v
    }
" O. x. D7 P4 g; r
% o" R  e2 t: f  F- w    /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/
2 d, U1 T& _4 o5 W/ x. c' O- R    VARIANT varWrite = (VARIANT)olesaWrite;
' M3 s) ]5 o5 v7 Z: H  X! ^6 a    range.put_Value2(varWrite);
" s. G( a$ j" ]6 X/ f7 L2 P* j4 K. `6 h' S0 ^- c
    system("pause");- g4 P$ K5 T7 n
3 `8 r; A/ w4 s- s
    /*根据文件的后缀名选择保存文件的格式*/$ _: Z' ]; G( v3 B0 o* n; K
     CString strSaveAsName = _T("C:\\new.xlsx");. u% i" A: R# d1 v* q* `$ d: Z) E
    CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));( e' A2 }$ v  j
    XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;& \# H# t3 b. M( T0 ?
    if (0 == strSuffix.CompareNoCase(_T(".xls")))
. Y/ r0 b/ q* M- @    {3 Y! ]& K& _- v4 O! D/ L2 m9 S. a0 ^
        NewFileFormat = xlExcel8;: @& E3 E& ~! s" E, {
    }
7 ~- _: @2 G) e    book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing,
: f0 X9 ]( r+ z- X  }        vtMissing, 0, vtMissing, vtMissing, vtMissing, ( Q% _8 H" |3 w* W5 |) K" V
        vtMissing, vtMissing);
; L) {3 d: O! }- l& ]& e" @& @
( e% H( D8 G5 e  Q" @    system("pause");; B4 s( U9 d7 d7 ^) k# K( a4 [/ ^

8 B# f/ U! `3 a3 m    /*读取Excel表中的多个单元格的值,在listctrl中显示*/
( ]9 _& P8 ]$ V  W2 n+ f    VARIANT varRead = range.get_Value2();
# t% ^/ J% T3 {) k    COleSafeArray olesaRead(varRead);
( M2 ]% V5 n- e& Z3 d
4 ]* H" ]4 D& j2 J/ `    VARIANT varItem;
: r% i3 ]3 C0 [" K    CString strItem;
+ h/ H% _* j4 }  T9 W2 _7 ~    lFirstLBound = 0;6 z  E$ W/ j  m
    lFirstUBound = 0;+ }$ [; x* |7 X7 O3 s3 w' b
    lSecondLBound = 0;
  p3 U3 E0 H1 u+ f: m& H    lSecondUBound = 0;
: R/ E7 {3 h0 @: l) S: j7 a    olesaRead.GetLBound(1, &lFirstLBound);# u' L* ^6 G' v% ^' M% U6 Z
    olesaRead.GetUBound(1, &lFirstUBound);# }  M+ C  \; T8 ~& i, Y! O" m
    olesaRead.GetLBound(2, &lSecondLBound);. v! p- z) l  s% M  b$ F
    olesaRead.GetUBound(2, &lSecondUBound);7 h& y2 c* a5 u
    memset(index, 0, 2 * sizeof(long));
- r4 v4 H' ]4 b9 {9 U8 F    m_ListCtrl.InsertColumn(0, _T(""), 0, 100);
& L, W$ D+ Y+ B! t& i    for (long j = lSecondLBound; j<= lSecondUBound; j++)* w  L5 e" k( [& ?( |! u
    {
' N1 [# P' {# O" }        CString strColName = _T("");
) \- a; n. j# E, V' T" b3 a        strColName.Format(_T("%d"), j);& V; q7 [* H$ m& \7 R
        m_ListCtrl.InsertColumn(j, strColName, 0, 100);
' @8 h7 O7 @6 N# s) o. x7 Z    }
2 `' E) o! s2 B2 r/ O    for (long i = lFirstLBound; i <= lFirstUBound; i++)# Z3 o. P+ v7 P' J, O6 z8 ]
    {
; V0 d# D+ j# A% }: z2 [3 Z        CString strRowName = _T("");
5 D& F3 K; K9 e9 b( S        strRowName.Format(_T("%d"), i);+ M' {- M' k7 F" N7 B% T1 E) |
        m_ListCtrl.InsertItem(i-1, strRowName);4 M3 l9 a3 Z, i' }9 W% h( a
8 O1 W6 p. I; w7 p! m2 e
        index[0] = i;
. o: v; {7 _. ?6 c        for (long j = lSecondLBound; j <= lSecondUBound; j++)5 ?/ O, d0 N/ k
        {. o. n/ h: C; x- s7 i% Y- @) Q3 R
            index[1] = j;# j# V6 N# M& [# L/ o, H
            olesaRead.GetElement(index, &varItem);9 w. o/ X' [6 z, N- K7 F

  |- ~7 s2 P" O            switch (varItem.vt); s( i  f0 q1 [. |2 T! j
            {
# z7 w6 w: W. j2 H: F- _            case VT_R8:0 }, v1 w; q" I3 E: `. J
                {: v" M3 ?* _) q) E3 X
                    strItem.Format(_T("%d"), (int)varItem.dblVal);4 E) F+ x" g1 I# R5 f: C+ g; i8 O9 Q
                }9 p( l  ~6 A8 u
/ n* d! Y1 N* ~8 x/ B! Q5 h) `& ^9 o
            case VT_BSTR:
4 n+ l3 W$ d1 U- E/ o5 v                {7 f$ w/ n3 w9 s
                    strItem = varItem.bstrVal;0 M2 S! J% A- x! g
                }6 v  l" C$ W( c9 L

/ Q0 r1 P7 c8 T* m; c, |0 Z            case VT_I4:6 {$ W5 Q6 u+ V7 {  f7 i
                {
- b7 Q8 h7 s0 H* ]& R1 b8 @                    strItem.Format(_T("%ld"), (int)varItem.lVal);
4 g( V8 {- {9 T' X5 h                }7 R4 x2 x8 f+ ]3 ?* s! U2 t

( x; s8 O2 _1 q            default:  w5 l  l  b2 Z; z1 `* G6 F
                {
) y1 U; G2 f8 T5 {+ X
" Y7 @5 j8 v; l5 U. z7 e* W                }7 p8 n4 N  }( n" K  q- P
            }7 b, ?6 y4 w! E3 |
& n; K1 x- K" V
            m_ListCtrl.SetItemText(i-1, j, strItem);; k+ I" K- Y, D! Z: X
        }2 J2 l7 E  M. }
    }
; R+ ^; E" Z9 m) ^/ z; m* E+ U8 n( `! y5 O6 Q) }1 r

) Y& u/ E. F! z$ Z/ Y, ]0 o* [) D. X5 F0 ]3 X
    /*释放资源*// N% z  z) j* j( H0 X: B
    sheet.ReleaseDispatch();1 g- O& e5 |0 y8 v' n# S, @6 v
    sheets.ReleaseDispatch();# `4 Q( b- [/ T  {$ v
    book.ReleaseDispatch();- d$ X- Q  [, `8 l7 \0 d5 d
    books.ReleaseDispatch();* ^- Y1 V; l8 q( f: x* \
    ExcelApp.Quit();
( y& B; e3 T" R4 X" e: a    ExcelApp.ReleaseDispatch();# ^$ i% h' m: P' N9 t+ _

) l+ c& T2 Z: V* e0 L; n7 B
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了