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

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

[复制链接]

2014-11-8 08:13:41 6635 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表格的操作。" _! G4 h5 Y' y; E4 `7 ]2 o  v. ^
  & x0 p- @; w! |1 |5 D
本文源码的应用环境说明:
! M$ x) [! p: wWindows XP SP33 R* v0 ?+ i  N! H/ _' M$ T
Microsoft Visual Studio 2010+ ^( j* g0 B9 q$ ^- w: O6 l) g* V
Microsoft Office Excel 20078 N) g8 J4 a9 a
  2 P+ f! x( y+ |/ f
1、添加OLE/COM支持。
6 S8 N1 R2 @" U! O首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。
, J3 |; i" ]( B2 a1 Z6 b本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。
4 a( y. |" s3 L: M" s$ M通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。+ I# C# K. |3 Z$ ?$ Z/ V. C: c
#include <afxdisp.h>        // MFC 自动化类- O0 J2 m$ V3 y: _- [
同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:9 c& H- d; a* J6 X1 s  E
// 初始化 OLE 库7 g" z7 v# E& E
if (!AfxOleInit())
+ V4 ^8 B  A1 W3 D5 A{
8 v4 Y9 H  o4 @2 wAfxMessageBox(IDP_OLE_INIT_FAILED);
6 [" q. ]( Y9 l% o, Preturn FALSE;4 n$ y* a* @! W# a$ ~. x% j
}
1 Y6 G/ V' u- |4 X  ; [( p8 G+ n8 u2 N: x
2、导入并封装Excel中的接口
# P7 t  O% {* [" tExcel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。
( X! |$ ^& k- q. c( s, P+ ^6 h/ i由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。
$ q8 u% W, o/ CVS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择! a4 K4 u: U" _: f6 Z+ I
要导入的Excel类型库中的接口。
1 Q0 W* N' y5 |: C# ~1 m在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。; x* _8 j! J' \0 Z4 P
  4 E  A  w0 B1 m( Y0 a! k" z
本文所导入的接口对应的类和头文件的说明如下所示:5 }3 b& K4 l( g$ D# ^" J" _9 C9 i  @
  
5 ?- w! j' a" P& C0 f' r+ HExcel接口
8 f) @: z/ m% [/ E导入类
* U* e9 C% d; A& c) G- M头文件
  w3 A' b5 k! m# a& m- S% L说明
) S  j2 k; m5 b3 d/ x* x" {6 ]_Application
  e4 H$ y) C0 b  ^2 U- }+ R9 }. DCApplicaton% H% ~7 R" `+ W" Q4 z! g
Application.h! V0 E" n$ j' a. U
Excel应用程序。
' l( E: r  N& \Workbooks1 h% Y0 g, [( _' }) Z4 a. z9 o: p
CWorkbooks
1 V! R8 @  Q5 _, H( N8 D$ _Workbooks.h
5 Z3 Z; d4 }3 H! U- E9 n5 k0 i' _工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。3 N8 J0 C4 Q! D8 D
_Workbook& H+ V8 v0 P. T
CWorkbook+ z6 a  V0 E9 W) Q7 q) J: [
Workbook.h1 ~' V: a/ s( f0 H1 ]0 ]2 e$ f+ d
单个工作簿。
* J6 ^/ X) Z0 Q( I& F% VWorksheets
! K. f# @4 U/ ^7 Y. l# T! LCWorksheets
6 o0 d' P+ U! H9 }Worksheets.h* h" x7 l( y" _7 j5 c% U8 q
单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。
% q: e+ |. \; a* ?- o8 _; p" x_Worksheet1 h- x) H( q& k: Z; x7 S, k" H
CWorksheet3 W1 ?3 ], Y# c1 w( ^+ i
Worksheet.h
7 _! l) a! X& f$ \单个Sheet表格。
/ m2 S' }& u0 vRange, b& J  y  u- Z
CRange9 z! Q1 H7 h2 S, d
Range.h3 h9 r4 R  d# j1 T! F. I
一定数量的单元格,可对单元格进行单个或多个单元格进行操作。
4 b, _  E5 r  u$ E  B- T  
" [) G. a$ Y0 X3、导入Excel的整个类型库6 S# S, A8 ]1 k) L# |0 `
接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
7 n6 }! ~8 ?$ o8 w. N! z% B$ \3 t( B% O, q通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:
* L2 o+ {7 w) t  ?4 B1 \#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
- L6 l: f0 J/ D2 I这行代码的作用是导入Excel整个类型库到工程中。
- Z  Z6 v" [# i! \( W! \由VS2010自动产生的导入代码存在以下几个问题:- d# B6 P" Q; U! B3 I$ O5 M
(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。4 d( c0 ^# U) p0 P# P
(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。
) v* g1 V1 t, p5 d" d, O5 r6 A& r(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。6 \2 Y$ H) n- t. f/ v
以上三点问题的解决方法如下:
/ r  o% w; n- N0 [' o6 v(1)仅在_Application接口对应头文件中导入Excel类型库。* H( u& e) }! F
(2)对冲突的类型进行重命名。
: a8 v8 t- ~! q(3)在导入Excel类型库之前,先导入Office和VB的相关库。
" O8 H: p$ q0 M& k/ v更改后的导入类型库的代码如下:
( D2 W6 P# F: O( r7 G2 @4 j  
4 u- S8 Z, s& I4 {9 e3 t/*导入Office的类型库*/4 @  X% F  U, t. S, z- p
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \4 ]/ u' |' p' K* f, e2 O$ w
rename("RGB", "MSORGB") \
" t- N3 y' n) F' x0 S6 Urename("DocumentProperties", "MSODocumentProperties")- n5 A" i+ ?: r
using namespace Office;! I8 t/ @& W# f8 J- o! D5 }
  ! N9 ]( v: `) n# g, l& ^. a
/*导入VB的类型库*/
; _7 R; C4 R, R& j#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
$ \- v6 k" f5 }! Susing namespace VBIDE;
1 T; w# p. s  m  , l6 K% U2 k/ p" S9 s  g1 H
/*导入Excel的类型库*/6 ]; J) F( n( y: @( E& g3 l! ^
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \  y, s, G: E+ j$ r  ^
rename("DialogBox", "ExcelDialogBox") \, M! w2 y: X! w8 [
rename("RGB", "ExcelRGB") \: o) S  \) p0 G% f5 I7 ^
rename("CopyFile", "ExcelCopyFile") \* g# e# u! T+ I5 |* X& h
rename("ReplaceText", "ExcelReplaceText") \
; E8 h( J0 p3 g$ t; }# h+ l2 Wno_auto_exclude4 n2 P# x" _5 P+ ?
Using namespace Excel;
' P8 ]4 H0 a7 f5 i( B  
1 v4 U5 H0 x* }( ~5 Q# D5 X编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。1 o* i, g% M  Z4 g
  
2 d9 \1 D) P7 O8 L4 A4、操作Excel步骤4 r# M! r, e$ I: X) E, t
操作Excel的主要步骤如下:# V9 L1 U$ G; H1 ]
(1)创建一个Excel应用程序。# d6 q& z, b, T
(2)得到Workbook的容器。& ^! x# \1 S. J) w
(3)打开一个Workbook或者创建一个Workbook。
5 D) B& b5 ?- \  l(4)得到Workbook中的Worksheet的容器。
: F2 o. |6 e; l# t" _(5)打开一个Worksheet或者创建一个WorkSheet。) N# G9 c1 K. G# b# P& C2 y  g
(6)通过Range对WorkSheet中的单元格进行读写操作。
  i8 j; K  i( H" X+ N5 c(7)保存Excel。
! K* [) r5 Z6 v; b(8)释放资源。
; X( m$ h; W  B+ ~" n; d, U# ?  2 ~# d2 u' M; ~% J2 j
5、批量处理Excel表格
  R  W' y9 U0 V% h. WVC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。3 H6 N' H1 q2 x2 _, j, n0 l
对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。! e' q* {5 B1 ]; l
VARIANT get_Value2();
" V/ P  X6 {8 ~2 t, Vvoid put_Value2(VARIANT& newValue);
; p+ K. ^$ S; v% z) F8 X其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。6 M7 g* @& S6 Z; F9 d
其中,VARIANT中实现二维数据的方法可参考+ q; {5 r0 w8 o; K4 F3 C  `
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html' t' L! D, Q, T% z& w$ P
当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。
/ m! o! v3 @0 H6 I  
  c" x$ p  U6 T4 J* X. I! Q6、Excel表格的保存
" F5 C/ ^; k  o6 L/ A(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。7 F1 U: @6 c8 z9 w! Q4 R: j. j
(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。
/ x. u) p* J9 v8 KSaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。% H# ^: M) b0 }% [) i
  
4 f; N$ Z* Q; u4 T; J7、获取当前Excel的版本% R( w, B$ _6 l9 n4 W5 ]
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
. z+ i; K2 z' p* W9 m5 m  ^+ R( c& r  4 o, ^3 |: G% X; @$ C7 [
8、示例源代码
: I5 G) d" y: u1 }4 A8 V主要代码如下:, T* C; Y, d" N; }+ b4 X+ R% {
  ' ?1 ^! X& r1 o% j

" B7 C1 r3 ~' w5 O" i0 z* W& `9 A" f' ~% g
    m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);
) D) a* N! y8 z" j, {) t1 m/ l2 Q- E# m9 C5 [1 M
    CApplication ExcelApp;
* o  u' c6 O% j7 j( b    CWorkbooks books;
& o4 U$ J) d# `9 F5 o( N1 M    CWorkbook book;+ I: d( \" U; F
    CWorksheets sheets;
; v5 G3 V: r$ H& U( X. C8 K- `    CWorksheet sheet;) K. [& \% l% M4 t
    CRange range;
1 `$ _8 J# r0 i3 \3 z* H    LPDISPATCH lpDisp = NULL;4 x! {4 \. o/ g: c! e2 h5 ^

0 t  k2 Z, h$ B+ J( w  L: ?    //创建Excel 服务器(启动Excel)5 s' ^5 b9 j+ r6 K5 s4 d
    if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))
+ y4 M/ |2 X; v    {
+ T6 e+ q5 C5 Q! k! P% M        AfxMessageBox(_T("启动Excel服务器失败!"));
% C; J3 a- X5 ]+ I  U6 y) g        return -1;
" V+ s) O5 m/ W2 D3 j. J( I    }# K0 d( @$ B) K6 P

) O8 N- Q/ Z0 D$ v3 ], {) M    /*判断当前Excel的版本*/9 F0 J( [/ q6 A3 y# B
    CString strExcelVersion = ExcelApp.get_Version();
4 Y' M6 ~/ f  h. |: {9 Y" r    int iStart = 0;
2 ?; p! X  y1 ^0 \3 Y    strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);
; l8 N. I$ G: Z2 N    if (_T("11") == strExcelVersion)7 L" S# n5 B6 f5 v' U  C! [
    {
5 `/ |6 l9 C4 r. p        AfxMessageBox(_T("当前Excel的版本是2003。"));% k4 W0 S% B! R/ P/ a
    }
1 d6 ^# I7 i! p- B( L( [9 @    else if (_T("12") == strExcelVersion)3 ]( c& `! I: _5 A! E
    {1 o1 K$ B1 F( l" R9 J& j
        AfxMessageBox(_T("当前Excel的版本是2007。"));# X( u& l1 F6 I8 R  O/ R/ T
    }
0 R( s, u. U9 V, X( F2 M( ~    else1 Y7 R- A9 ^: {) O
    {
' ~% f7 A, T* r* `( z        AfxMessageBox(_T("当前Excel的版本是其他版本。"));7 n! V0 d% ~, L, d, c7 M+ G
    }7 T! O1 N+ M6 w7 N1 w

0 x9 w/ }/ `) ^: ^    ExcelApp.put_Visible(TRUE);
& P1 r  S) B) K    ExcelApp.put_UserControl(FALSE);2 O9 p( ?. |: E4 X8 V: P; v4 F/ a

; h9 Y$ o9 z- R5 M    /*得到工作簿容器*/. a9 M% q7 g" ?0 l6 |
    books.AttachDispatch(ExcelApp.get_Workbooks());
1 c# \6 K) j/ k. s8 j0 Y3 A
( C' K/ J3 e; H( G1 A    /*打开一个工作簿,如不存在,则新增一个工作簿*/
+ n5 j! k8 l/ A) B+ d8 I! I    CString strBookPath = _T("C:\\tmp.xls");
; Z: A  v7 o9 r) q3 M    try
5 u6 N3 z( b% X  v    {' K; ]3 @; \0 D
        /*打开一个工作簿*/6 w' x* R' y3 c# \( m, Q. J; e
        lpDisp = books.Open(strBookPath,
/ Q, l2 e2 q. ^/ @2 H            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
$ w& ^; _$ ]9 R( }7 I            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, & O9 a- V3 y, {) b( U
            vtMissing, vtMissing, vtMissing, vtMissing);
1 s3 ?& v3 ], L) g2 [3 m        book.AttachDispatch(lpDisp);6 ?- {9 K5 j3 W3 O# s" L
    }
, ^4 s; q: K6 e' w  A9 c; v* b& i    catch(...)
/ {5 ?4 d, @3 l! i, Q    {: U9 T$ E3 V  J. u0 R
        /*增加一个新的工作簿*/
% U6 ]$ i* H7 u/ W! j        lpDisp = books.Add(vtMissing);
, }2 `. v; _' B* F$ m% y! K. `        book.AttachDispatch(lpDisp);9 D  n. i$ k' Y2 Y
    }! O0 G7 i  T) v1 y7 K9 t
     
9 m7 q3 s% y5 H) s# Q1 k; {" J1 ?3 h1 Q4 U, k3 z; B% x
    /*得到工作簿中的Sheet的容器*/
- e# a) V, l/ J- W* O5 U3 F    sheets.AttachDispatch(book.get_Sheets());8 d( t& p& V$ ?: l9 V4 {

+ p5 x( t+ ]4 R  _, @* U7 w' O    /*打开一个Sheet,如不存在,就新增一个Sheet*/3 F! w$ D* K& G- X* [
    CString strSheetName = _T("NewSheet");
- [" o: C) ?) [/ u  c$ }    try3 x5 b2 ~$ D/ A; M( L, m' A
    {
# o* k: T9 z6 `6 i, G        /*打开一个已有的Sheet*/5 }$ o1 p  C2 k
        lpDisp = sheets.get_Item(_variant_t(strSheetName));
9 l2 O. `/ r7 v+ a& i        sheet.AttachDispatch(lpDisp);
6 g' e# u5 c; Z7 p3 L, a! R    }
7 B# z  Z- D: K  W( H    catch(...)
; G$ o8 \7 G  j- @& I    {
  k# }1 b1 L) c& ~& N: y        /*创建一个新的Sheet*/% _. u9 v* {& u: |+ s& g. R
        lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
# T5 J. V4 i9 ?: N3 x" Z        sheet.AttachDispatch(lpDisp);* r. a' a6 Z% f  D4 E" Y7 |  [. r
        sheet.put_Name(strSheetName);
6 T7 T% L+ N; u2 F9 G" k    }
" U6 A( q$ J/ I0 [5 B
6 D7 X: F4 J7 A3 {/ F    system("pause");
) p: s0 U, @" _/ |) C$ T2 O, {) ^* H1 c
    /*向Sheet中写入多个单元格,规模为10*10 */
- Q/ V. r8 |1 E' r3 f/ s) X    lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));
+ q; \, T3 q7 \3 G6 }, I' d) w    range.AttachDispatch(lpDisp);# s" x4 `9 w: n# E

9 }6 ^% p: j' L    VARTYPE vt = VT_I4; /*数组元素的类型,long*/1 C0 P7 }0 d6 s+ b" z' c" G
    SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/
6 g8 |- a3 v% k4 ^! a    sabWrite[0].cElements = 10;
" U2 b2 M  t: d: r9 z' S1 S7 C    sabWrite[0].lLbound = 0;& a' V2 X# R; k
    sabWrite[1].cElements = 10;
/ D! H4 n: q3 M$ z# _. E# U; ^    sabWrite[1].lLbound = 0;
$ |# |  x$ a7 O3 }
( H9 L# b3 O1 A7 b8 l  W    COleSafeArray olesaWrite;& k) {# v3 ~$ e4 `# c
    olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);- R) B( r! D/ D

5 ^, u  T" }, Z& s    /*通过指向数组的指针来对二维数组的元素进行间接赋值*/
( T& a1 [: n1 I& u$ R    long (*pArray)[2] = NULL;5 K% r- ?4 H$ d6 e
    olesaWrite.AccessData((void **)&pArray);! Q( {% k+ Z' m2 ~& A
    memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));# x0 O; G: U1 u2 ~5 ~2 h

' E! B! D0 L2 v6 r    /*释放指向数组的指针*/
: G( q) U( I& I6 j- \    olesaWrite.UnaccessData();
& l  W* e3 l5 J5 K, `    pArray = NULL;
% J0 T% A! V5 A9 u: u- c- I# f9 K  u
: @* t/ F7 N! F$ {1 C    /*对二维数组的元素进行逐个赋值*/
" x* v. t/ \$ c    long index[2] = {0, 0};
, k0 p8 _; @4 w9 d6 F    long lFirstLBound = 0;/ U( c7 g7 m0 h! O. J: X6 o
    long lFirstUBound = 0;
! F6 d; i9 V( }& T3 N2 o7 ^    long lSecondLBound = 0;
0 h# i/ ?" u; }( s* R    long lSecondUBound = 0;* S( p1 U% f5 K3 V7 C
    olesaWrite.GetLBound(1, &lFirstLBound);
3 Y5 V7 w- w; ~0 g. t/ c! W    olesaWrite.GetUBound(1, &lFirstUBound);
# R; N: ]5 ^* [' n9 D    olesaWrite.GetLBound(2, &lSecondLBound);7 \6 Y* J( ?% l2 m! X6 ]
    olesaWrite.GetUBound(2, &lSecondUBound);6 ^3 _  r) T* ~8 [6 Q, q1 `% s
    for (long i = lFirstLBound; i <= lFirstUBound; i++)
9 H* N; |$ O5 j8 B3 ?5 c9 j9 B    {0 R7 _1 ~4 d, G0 x1 [
        index[0] = i;
( p: f0 o4 K# ~, o  A, X! b+ k' K        for (long j = lSecondLBound; j <= lSecondUBound; j++)
, {2 @. S: H) q* A        {
6 i& \3 ]" O1 V' w# Z; f2 T            index[1] = j;
/ y* y2 V- g5 ~4 c' u& T3 _) x- V( d            long lElement = i * sabWrite[1].cElements + j;
6 {- w  A! s( i- B" ?7 S            olesaWrite.PutElement(index, &lElement);, [6 I4 n0 S0 _: _  O
        }
% H3 `/ x1 q3 J! w5 ]0 T    }
6 h7 x2 ^0 N1 o: f( ~+ r
  k6 ?3 `$ N. {; M    /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/, ~1 B  L0 b8 H( l4 B3 r! x
    VARIANT varWrite = (VARIANT)olesaWrite;
: U# _3 P& [# z3 c8 g9 R2 H0 |& y    range.put_Value2(varWrite);$ w% w1 M# a, O* a0 Z+ k0 ]
  H6 W% [- P+ l2 f6 f0 N
    system("pause");
& c& h$ G3 p1 G4 i# W! [2 ~! n9 d# z, C* R. H% W; E, H
    /*根据文件的后缀名选择保存文件的格式*/9 c# r) C/ q; c- ^! S' @
     CString strSaveAsName = _T("C:\\new.xlsx");
! A2 M5 G9 H8 \$ g    CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));
$ a, L. B) ]2 J. L- t# n5 V& C    XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;
1 Z. F7 z' K7 H, F    if (0 == strSuffix.CompareNoCase(_T(".xls")))
9 f" e, Q& o3 L$ |0 ]    {
# K! p- x. r5 ?1 r( I        NewFileFormat = xlExcel8;$ Y. ?. G* O1 b9 D
    }
4 ^. o  K5 V: S: ]4 j    book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, * o. {) u% D+ k8 F$ A' B
        vtMissing, 0, vtMissing, vtMissing, vtMissing,
% v1 z7 ^  b& c; J7 a- j4 A( z        vtMissing, vtMissing);* B, n, y4 m1 {5 b- Y- U. `$ K
$ b; [8 V: S+ ~6 f6 ~
    system("pause");
1 r' M  p# A3 i6 U
. i1 I: L5 C, [; H    /*读取Excel表中的多个单元格的值,在listctrl中显示*/
6 s! h, l$ [6 K    VARIANT varRead = range.get_Value2();
" X( L( Z4 g. [. J    COleSafeArray olesaRead(varRead);
9 E, s1 K6 `' \/ b: Y, ]
( E' ]4 l, h5 e. b6 d+ R    VARIANT varItem;
! C+ \3 B5 c8 _, q& {3 e) i4 _& n" N7 f    CString strItem;
8 @( j* N. _) p, _4 c' p3 L& E    lFirstLBound = 0;, [- P* K7 W& u' Y  B
    lFirstUBound = 0;+ u6 B% d( z" M  R9 G
    lSecondLBound = 0;* G. ~( A9 M9 K! Z* |
    lSecondUBound = 0;
% \! C: g, o( p; f6 f5 Z0 `4 j    olesaRead.GetLBound(1, &lFirstLBound);9 X0 D0 l9 y: U# h7 P
    olesaRead.GetUBound(1, &lFirstUBound);
" Z; f6 H7 p( Z- ?1 V    olesaRead.GetLBound(2, &lSecondLBound);
# {6 f& t* N8 F: A, a    olesaRead.GetUBound(2, &lSecondUBound);
. A  r# V/ J* N% s' u* R9 Q    memset(index, 0, 2 * sizeof(long));, z, L' X# c; U; F7 m# {+ U) p0 M
    m_ListCtrl.InsertColumn(0, _T(""), 0, 100);- H: A4 ~. T6 w: X( M: _% q! ^+ \
    for (long j = lSecondLBound; j<= lSecondUBound; j++)9 f5 w- [' l/ p% n( g
    {
* q- ~& [9 Z6 C$ F% K) @  `        CString strColName = _T("");' f+ @, |: T% N. K/ p9 F- {7 C9 b
        strColName.Format(_T("%d"), j);
0 x; y4 P4 }# c8 u& I- I  y3 e        m_ListCtrl.InsertColumn(j, strColName, 0, 100);( H# V/ ?0 j" W. ~4 L& K! g. W. ]: N
    }! P; o" m4 N" M7 c& s
    for (long i = lFirstLBound; i <= lFirstUBound; i++)
8 T8 H' P' R9 q" d1 q) z    {
, y3 V/ s) _) ]& M' f        CString strRowName = _T("");( {# d2 i" d+ ?: [, [$ ?( I
        strRowName.Format(_T("%d"), i);
8 Y- Z( u' Q' J& C; r        m_ListCtrl.InsertItem(i-1, strRowName);4 v% Z1 L% ~% ^8 h! O
5 d" r+ v. C$ D  `) P/ @* D
        index[0] = i;
; f" Z7 h$ J$ e        for (long j = lSecondLBound; j <= lSecondUBound; j++)
- H( r2 Z& f/ }/ h, o        {
8 U; L! [4 R# c0 z            index[1] = j;
6 N+ g4 ~  D) f# S) H            olesaRead.GetElement(index, &varItem);
) S0 g4 r* Y/ b( n) f& V1 t
: W2 j$ W; j5 ]            switch (varItem.vt)  W; {1 `" g8 x, ?
            {
, g, ^; W  m; {! p% p4 d            case VT_R8:# m% v, n  K5 a( s3 V' y* D
                {7 M. ~# Y9 o* R' V& N# Q* @) T
                    strItem.Format(_T("%d"), (int)varItem.dblVal);; j  A$ \9 n+ I; W1 s
                }8 p/ y0 W/ E, e, U) z$ u4 A+ d. c

! k$ ^& Z. F/ u            case VT_BSTR:
: `; \3 r$ D& l                {. j) G* s' T$ \1 K7 |
                    strItem = varItem.bstrVal;
/ u( I9 h, _: @6 V5 P7 i+ [$ q                }  Q0 T! t3 H0 X. a6 z! v* G( w" B
% a6 |+ ^" z) s# s$ O6 }
            case VT_I4:) L& d) M4 F/ m0 Y
                {
3 ~4 d/ f/ y+ o                    strItem.Format(_T("%ld"), (int)varItem.lVal);. T& c( P, G5 @6 P
                }& c, R7 X4 j! G$ C% A

, Z- Q6 v4 |0 K$ h5 b5 J7 z+ u            default:
; p. m$ A& O6 o& j7 ]6 _                {
3 E$ P; {& o5 k/ ]9 @  D0 H0 y4 ?# k
                }
/ r3 w7 a4 X2 @% v( q            }
: v" c3 X. x/ m1 i* A( ?
: T9 x4 h$ t4 L) ~            m_ListCtrl.SetItemText(i-1, j, strItem);, ?8 q% X* l0 F6 I" ~# G- w# U
        }
* R& ?6 o7 D6 J3 F    }( U# l6 \5 a( N
# I: l3 c/ s& E7 [

( E3 ^8 U5 p3 x, z0 R6 D; c& @. j( d4 O, v8 O" g: P
    /*释放资源*/
! ]) y  A7 \: b" H1 ~    sheet.ReleaseDispatch();- i7 X% Q5 |. Z+ S% L% i
    sheets.ReleaseDispatch();
$ |! y! O# F$ R5 V% J  X    book.ReleaseDispatch();
& G0 {; R! h# m    books.ReleaseDispatch();
) O. j/ W3 }, h4 q" S    ExcelApp.Quit();
, e! q5 c$ L$ ^" c    ExcelApp.ReleaseDispatch();0 D, y& q  {7 V1 I: K5 f  L9 c
7 @' A9 v2 b- f, ^' @1 c
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了