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

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

[复制链接]

2014-11-8 08:13:41 6768 0

请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!

您需要 登录 才可以下载或查看,没有账号?注册

x
通过VC实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文主要研究通过OLE/COM实现对Excel表格的操作。
, q1 x% Z) m2 o. q$ T" Y9 s  3 Y5 I1 S) V2 j3 V/ H) Y
本文源码的应用环境说明:
' q  ^" l1 a- g7 i" n( z" oWindows XP SP38 z$ Z. u# O2 P- l: w+ a
Microsoft Visual Studio 2010
1 w  w- i- i5 b( u6 JMicrosoft Office Excel 2007
9 d1 s4 I' {2 P' z8 v3 y  
. d$ J" L, o/ b  Q0 }! a1、添加OLE/COM支持。9 C) u- H# \& ]2 d5 {3 @
首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。% d& Y) o0 E# F" L/ e2 m& t- G1 x
本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。2 c" D0 r9 ], m* a
通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。5 S8 F2 R; o/ Z! V& T
#include <afxdisp.h>        // MFC 自动化类
) h5 t+ O. r+ w) u/ X同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:+ l8 f- ?) z3 w" M) Y) W+ j. a
// 初始化 OLE 库
' i& o& f* `& B4 L) a" `if (!AfxOleInit())( V9 x6 g+ T1 W# g' E
{: `$ t/ x4 ]8 @3 _) a. z
AfxMessageBox(IDP_OLE_INIT_FAILED);5 p) N- w" b" Y1 l
return FALSE;
0 u  p# v2 h, h' J3 q9 S" f}- q' F* V0 ~" T+ `3 \/ `1 Y) e  O
  
- G* w7 a/ u2 I1 N! X( _$ H! I2、导入并封装Excel中的接口
5 M/ d2 C3 a+ c5 H; LExcel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。% Q1 [) e9 w9 ^, X
由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。
$ O" s  q  F0 x3 T6 lVS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择
/ _1 U  L  {. V# k) S: n2 `, U5 Q要导入的Excel类型库中的接口。
, f% Z/ Y* ?& ~7 m9 I在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。
# F: J1 i' {1 ], y$ O5 `5 U7 a- b  ) X, v: b; _3 W' O& I
本文所导入的接口对应的类和头文件的说明如下所示:
3 I2 s' a6 P8 ]$ S+ A/ `  
- H7 M$ F& q4 A- wExcel接口: I4 J7 }4 G$ A
导入类
; T( P6 a6 X. u, c8 ~0 @( K头文件6 l) t( d6 ?  Z1 c* Y7 v- n) k. D
说明
! t% n( t) @4 T$ e5 h_Application
- n4 o3 O; Z! f& C/ }- M7 wCApplicaton" \7 B" R& B' B) z  @& W  l
Application.h
3 U7 J6 [  T/ r8 I/ DExcel应用程序。
2 \1 Z  P4 A, QWorkbooks
( G# T9 e/ z# ]. k$ \- [* QCWorkbooks' w1 ?: [- L0 @& S
Workbooks.h* C* O3 C/ m" Y
工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。
. J2 S% ^5 Y) I1 v( K2 V_Workbook
) n2 r7 X8 F2 v8 {CWorkbook
$ T9 Y# [- U- i8 s: k" B( ?; uWorkbook.h/ h- H' |6 P' i1 B+ }
单个工作簿。
, z& T/ j* G6 o: S' ~* B6 N% c+ LWorksheets7 f# ?/ C  Z* M  j$ r5 _5 l( `6 x
CWorksheets
2 j+ U; H8 Y0 A& L- i. ^Worksheets.h
. z8 \6 m5 M8 g! T4 [( b) n+ u单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。, ?: e& H* K& G/ b: C: w7 S( V1 ~
_Worksheet3 |9 q# y; }2 R
CWorksheet
* ]( B# |* r- b% n% F# JWorksheet.h1 J# C) ~9 W" Z7 m4 q
单个Sheet表格。  u  g; I& U: x* Z3 ]* ]
Range
4 O4 n! U# V- s$ kCRange
9 K1 s% t! {9 S5 r8 H" ^) L& i/ jRange.h
8 p1 K$ N9 v: @3 Z6 A, A1 A4 N一定数量的单元格,可对单元格进行单个或多个单元格进行操作。& R3 a; |4 s( E6 W7 q* P8 A
  8 Q# r" T0 D5 _/ |
3、导入Excel的整个类型库! }5 V" b" q: w: b
接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
' d+ _# s$ Z. i通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:6 @) J% F+ H3 i! w# I, N
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
# f0 ?/ C. b3 I, x这行代码的作用是导入Excel整个类型库到工程中。
+ \! g5 ^$ E- X/ w* e5 C0 f由VS2010自动产生的导入代码存在以下几个问题:) N2 i* d' W% n. \& d, ~
(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。
4 h) D! c2 ^! V/ I. {7 x. M(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。
2 _' v; N. T7 F( y5 v* W(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。; J, M9 A7 F4 `* s
以上三点问题的解决方法如下:0 \* o. V3 @0 H6 W4 S% N
(1)仅在_Application接口对应头文件中导入Excel类型库。
8 B! ?+ `( n. i: O; B(2)对冲突的类型进行重命名。
2 b9 M9 ]# k* Y* k: F(3)在导入Excel类型库之前,先导入Office和VB的相关库。
, Y4 g; |+ Z  S  J更改后的导入类型库的代码如下:
( `. {! e( i/ W$ _+ S3 R' D( t+ m  
# n: p8 s3 T' k. q8 d/*导入Office的类型库*/* O' E0 J4 d6 Z. j. l& H9 G
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \, B# L3 t  ~, w" H
rename("RGB", "MSORGB") \
' ^+ X8 }  a: w- Z" Mrename("DocumentProperties", "MSODocumentProperties")
. l( C! q- B6 K$ @using namespace Office;
1 v8 V1 Y4 ~) c5 ?8 k& x  0 _, Z: l! O2 u! V
/*导入VB的类型库*/
8 @) l' c7 n3 A& q2 ~6 i  \! Q. z#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
: p' w, H7 g' i9 cusing namespace VBIDE;
3 o/ @4 N! K6 }6 z4 T  
! l6 V* W9 D3 @0 H/*导入Excel的类型库*/$ m1 M$ m3 u9 ]( J
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \# ], W( ~' @9 M, ]
rename("DialogBox", "ExcelDialogBox") \) p  x9 v& p5 l& `
rename("RGB", "ExcelRGB") \
* ^% }: I% I* U- U" [rename("CopyFile", "ExcelCopyFile") \
: u2 b% J7 @, Y2 arename("ReplaceText", "ExcelReplaceText") \8 A) G% {& b; f- C+ X# k; W5 N' k4 L
no_auto_exclude
% Y; b3 }2 u0 w( l8 q3 sUsing namespace Excel;
5 E1 t; n8 m# p% O4 _0 R  . g' F6 u+ P) }( o0 H
编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。% _" `% R1 p  @, t) e6 v5 P
  
7 z' r" M* W  a, L# \; a6 Q3 O& Q4、操作Excel步骤
6 _0 ~" [3 Q4 w9 ~4 N8 }操作Excel的主要步骤如下:
0 r0 A: S  ~/ t% L; `(1)创建一个Excel应用程序。4 V' `+ `4 U3 d7 H3 ]
(2)得到Workbook的容器。
* F' \6 V* w" D3 R4 o. N(3)打开一个Workbook或者创建一个Workbook。
( z1 g/ \) }& U$ S" k- i2 B4 d(4)得到Workbook中的Worksheet的容器。
% |. I# q* c2 y+ a! I$ k(5)打开一个Worksheet或者创建一个WorkSheet。6 p6 G# E, V- W5 v
(6)通过Range对WorkSheet中的单元格进行读写操作。
6 A  D* e+ P  h/ @9 ?8 ?7 ~! K(7)保存Excel。
2 n, z. F" T$ L" v8 N; a(8)释放资源。  u- H. A) x9 m1 x. _1 N
  % X8 ?& Q0 w1 `
5、批量处理Excel表格
/ F& r' i" y! [+ C$ MVC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。
6 q: |2 y+ Q6 E8 @7 d; e对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。: O% D5 ~$ `0 o
VARIANT get_Value2();! A' i; r* U( Y
void put_Value2(VARIANT& newValue);
0 ?( o+ y: O. w7 v- }. k* E其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。
! c: _$ }) Z8 H& B其中,VARIANT中实现二维数据的方法可参考1 l2 u4 Z  [- d% x; c
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html
) h8 m2 C  e. T4 E+ A& ]  R当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。2 H8 r9 j" ~8 s/ P
  + D  _% w9 d$ G  l. L1 s$ `4 }% ?
6、Excel表格的保存
; L3 x/ Q! z+ X4 P0 M2 Z(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。
! `' |- y/ M# m) R8 [9 c" C(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。: Q1 {# ^# M; G6 P+ L* q6 b% \
SaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。
' ]! F: _/ k$ w/ y( U4 c9 a" X  
/ X3 G; s0 b, e0 H9 m$ z, Y# G7、获取当前Excel的版本
* }! {8 k6 ~7 {- s& x3 K可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
2 I$ \1 o) ?3 v' R: g$ |  
5 }0 @/ }* A$ I8 [$ D; `' F8、示例源代码
" p, ]+ D) f8 \( F主要代码如下:$ ]' j. s. G+ N: \" I+ ?  q' H# ?
  
% ^) b5 }! q1 Z$ Q  f0 @
+ j+ Q( }( M! K( Y5 \
) q: g" i9 @; Q) ?2 j* S  {# o' l- k/ N    m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);2 c! k* I% b. h' \

, g* C3 \. U, o; }* U    CApplication ExcelApp;
+ x" D2 J/ A' y* O- `: C* V    CWorkbooks books;8 F" ~8 c" J: F+ N
    CWorkbook book;
. U: u& s! V5 U" O    CWorksheets sheets;6 Y2 E8 U* M0 a, @6 I0 v2 Y* e
    CWorksheet sheet;
1 @5 y. Q# v5 c$ T, Z7 L2 T* }) ]$ R    CRange range;- ^2 R) w6 F3 E1 y
    LPDISPATCH lpDisp = NULL;
% ~3 L' J: i& O( K* M  O0 i+ A6 N: v: C) w5 t* X
    //创建Excel 服务器(启动Excel)( q! Z0 c# n! ]$ Y: A+ ~+ H
    if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))& m2 H! c! j& _/ g! y% b
    {. q, \) u/ z$ Q/ s+ V* j  ^/ Y( l
        AfxMessageBox(_T("启动Excel服务器失败!"));
* N0 G3 ~' |1 [* j3 [. F/ N; r        return -1;
) x& N% {7 ], B; K    }
6 {, N6 V8 {' c3 p$ P( b( X1 D* ]! d
    /*判断当前Excel的版本*/, F3 J6 r3 i% H$ o3 I% j
    CString strExcelVersion = ExcelApp.get_Version();( A! p& J4 A, e: |/ }
    int iStart = 0;6 a  I* @( [; z( M
    strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);
, x) e5 }+ t) C9 v& O    if (_T("11") == strExcelVersion)
; N/ o6 T; F% @, W# O' u9 f    {+ k2 p8 q7 b2 E2 A4 H
        AfxMessageBox(_T("当前Excel的版本是2003。"));
* J1 g& B# j/ G# v    }
1 @9 B# f, a3 F* p4 }# p  p2 W    else if (_T("12") == strExcelVersion)
/ d+ w) t6 P. D9 C4 F9 f    {+ z! R- r. h: M' u9 Q8 {, {% [
        AfxMessageBox(_T("当前Excel的版本是2007。"));
$ E( Q$ N% J* _- _7 I0 d    }
) |& H$ ~6 U# C3 [' m    else
. ~! K# M5 i4 I/ `    {) N0 B5 \* u: S* T# R# N
        AfxMessageBox(_T("当前Excel的版本是其他版本。"));3 z& f1 ?& Y% ]0 ^
    }  F3 i; }3 ]  u7 s6 C. `
; g  H7 \' s* V3 u3 |! y" t6 P4 {) l& T7 N
    ExcelApp.put_Visible(TRUE);
1 {; |- _% A7 q% B! s, ?0 f4 j    ExcelApp.put_UserControl(FALSE);
! @# B7 @/ c/ Y# j! H5 `- J' m4 k' O# }0 L4 m% B
    /*得到工作簿容器*/( ?9 {  t) a, ~) ~$ f" u/ M
    books.AttachDispatch(ExcelApp.get_Workbooks());; z- f. n3 O) r' |5 Y

. s2 a/ C, }: V+ a$ q    /*打开一个工作簿,如不存在,则新增一个工作簿*/  c) P( ]: ~2 L# W8 x! v
    CString strBookPath = _T("C:\\tmp.xls");8 R' U- C# S8 U& n1 P4 |
    try
+ M9 I* c" f5 V/ Z& E2 d    {
+ K/ Q% ?& |+ x        /*打开一个工作簿*/
' F" L- g4 }7 j        lpDisp = books.Open(strBookPath,
% O3 o5 Q. S1 D4 d. L  O8 ^            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,, W+ X/ h1 Z3 a; S* W
            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
- M, ], V% }9 t7 I& ]            vtMissing, vtMissing, vtMissing, vtMissing);
+ q* Z8 K+ k, e& G! H+ ~3 t$ G& i        book.AttachDispatch(lpDisp);6 |; j$ y! U* n! E# b
    }" `- A0 K+ e- {* M
    catch(...)1 }8 Q" H3 I8 u# ]! B8 j
    {" x- z- O4 J& K, W, J) }( W7 [: B
        /*增加一个新的工作簿*/
6 V2 T" S& l# }# S8 G        lpDisp = books.Add(vtMissing);1 Q) B% ^6 v  K+ `; A7 A
        book.AttachDispatch(lpDisp);8 ~" |3 O! M- C/ N: {5 a
    }# V4 b+ e7 h/ U; D9 T2 S$ H
     ; B, c0 R2 B9 w4 Y: h7 }( A* N+ T
* J* `& ]" f) Q! S; t& E: q
    /*得到工作簿中的Sheet的容器*/! |9 e+ A2 q  s) v* k% j
    sheets.AttachDispatch(book.get_Sheets());1 B) z2 ~3 z9 f7 E7 _

( u  G' R5 |3 N# A: H9 d  N9 A: ~    /*打开一个Sheet,如不存在,就新增一个Sheet*/
; }( Q5 y4 e4 d$ _. }+ Z, @    CString strSheetName = _T("NewSheet");
1 ?' G9 l/ n" L7 t    try$ N: G3 b. H# n5 g; |) b# i$ I
    {
: U1 C7 _4 L. g. \" l" b! p# W, ^        /*打开一个已有的Sheet*/
& q4 O$ O4 F/ d0 Q$ H        lpDisp = sheets.get_Item(_variant_t(strSheetName));% }9 P+ J& k" P& U7 b
        sheet.AttachDispatch(lpDisp);" s" }9 L/ f9 [% d
    }
/ g; U# |8 [8 ^: e( R    catch(...): n% J1 x. J2 R! j
    {) v. C7 R. k' m
        /*创建一个新的Sheet*/
: ]" t9 X# _0 I3 [4 G        lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
5 Z2 K* H( z* O$ V( `" R        sheet.AttachDispatch(lpDisp);5 X1 b; D1 F% L6 A* T
        sheet.put_Name(strSheetName);* }: R/ b! I9 Z" N% l
    }0 z8 r7 N6 Z. o
6 K% M! E! X2 H, b8 |  y3 k
    system("pause");4 H  ~4 g: n  X$ x# N
0 v! w6 x8 n9 `. }8 Q* [
    /*向Sheet中写入多个单元格,规模为10*10 */6 f5 q! `. M, v/ Q6 U/ f
    lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));
* B2 p2 m5 f9 z( o+ a8 j  U    range.AttachDispatch(lpDisp);
4 v, I1 P: {2 t& U1 i5 J+ v! Z* C* t" i" A9 ~8 i9 L+ C
    VARTYPE vt = VT_I4; /*数组元素的类型,long*/. m& b6 T" k& c6 J9 o9 r$ q; w: o
    SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/
* k% h8 [  y, X1 l/ R    sabWrite[0].cElements = 10;
$ C7 d; w0 _- O    sabWrite[0].lLbound = 0;
/ s1 D9 @: p4 _& B# n9 K" [    sabWrite[1].cElements = 10;: H: T+ p8 E' O* b
    sabWrite[1].lLbound = 0;- S, ~8 i: M4 l: A# y
6 r; ?% M" C! y2 y) Z2 C# a
    COleSafeArray olesaWrite;
; c; x2 e  z  E9 u: z& n    olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);2 X1 I  j: I! S8 c- N& t, ?
: c+ l8 T3 Y; t" B1 m
    /*通过指向数组的指针来对二维数组的元素进行间接赋值*/, a9 O0 ~  X1 g$ B7 d& B
    long (*pArray)[2] = NULL;- z. S3 a. v( m. N- q" R
    olesaWrite.AccessData((void **)&pArray);* y$ U5 \' H8 E) c
    memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));8 {" @' O: c- \; }. U( f# K
) `2 k% h# S$ h  ]4 H; y: [
    /*释放指向数组的指针*/
- O% c  [. L: [* |! F# J. W/ r    olesaWrite.UnaccessData();
: E/ u( M  i" X4 H& v" H% x    pArray = NULL;
! f3 w& C( B* w- p& I6 Z! T7 q5 ]+ D7 ~; W3 k& i: `! ?
    /*对二维数组的元素进行逐个赋值*/& w/ n+ R5 m9 |
    long index[2] = {0, 0};' v2 A! M- V& Y% x3 x. c8 \0 C  D/ `
    long lFirstLBound = 0;& x. B, ]! f7 N3 m. a$ q
    long lFirstUBound = 0;1 l- T1 l9 d  H) n8 `' \; `
    long lSecondLBound = 0;
  z0 V+ b6 L, L1 r2 G1 {- @    long lSecondUBound = 0;
! \& y' I$ m* R7 D& R: C    olesaWrite.GetLBound(1, &lFirstLBound);; C" f) A6 G) o2 }
    olesaWrite.GetUBound(1, &lFirstUBound);( g" H! H! A& W! W
    olesaWrite.GetLBound(2, &lSecondLBound);
4 w1 \2 [# V8 g    olesaWrite.GetUBound(2, &lSecondUBound);
8 H0 |. T4 K  T( z0 ]    for (long i = lFirstLBound; i <= lFirstUBound; i++)
2 M, A3 v: _3 v8 ^; v0 ]    {: a0 M. X* o  s9 n: t* ?+ L
        index[0] = i;: m% \4 N! _+ L& ?! p( M3 E
        for (long j = lSecondLBound; j <= lSecondUBound; j++)* `9 b0 Y# G" E, T! @
        {2 G) T( {6 H8 Z% \
            index[1] = j;4 T: e. ?9 K6 |0 A. p2 ~! o2 c
            long lElement = i * sabWrite[1].cElements + j; 0 _' u+ \6 ~4 B6 @  ^7 \) o
            olesaWrite.PutElement(index, &lElement);
- o) S7 I1 m* J        }
& a* V2 S6 h* P. T; W    }0 Z: k* b. @! Y( e% F7 ^
( c$ Y; W" s& }. p* r9 y
    /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/
* K* L/ T% c! F4 v* p    VARIANT varWrite = (VARIANT)olesaWrite;
) x3 f- ^0 N& R* F( z" b) m    range.put_Value2(varWrite);* k2 k# \* X6 R3 N

6 K8 [# X( T: g! T    system("pause");4 D2 }+ l7 z" k5 f1 g) X+ X7 c
3 w- W* R9 I9 S/ G! t# n" J+ K
    /*根据文件的后缀名选择保存文件的格式*/
5 U: [% [+ w7 S     CString strSaveAsName = _T("C:\\new.xlsx");8 s0 Y2 u% E2 c; t# m: R% t( d  P9 b9 X
    CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));: p* T: X# R) z- T9 x5 H3 l
    XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;- ~! L; d. R/ {2 {
    if (0 == strSuffix.CompareNoCase(_T(".xls")))
8 Z4 h2 i2 y) J$ @/ ^    {! z! E, `8 w" d; I' p- n
        NewFileFormat = xlExcel8;& D: }, V% `; n' @
    }
2 F2 F8 p  |3 g$ l3 V+ h    book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, & d% C  g+ s3 p, b) M
        vtMissing, 0, vtMissing, vtMissing, vtMissing, 1 S8 o" {# f% c: v1 C
        vtMissing, vtMissing);) Z5 d6 B- A% v, K3 c2 ]1 \8 ]6 @

; x) ]. T9 [/ j0 }) \, N. m" `' @    system("pause");) J' b( q9 M' e) f( p; U

5 R+ e, G8 t/ l0 R( k4 M1 V    /*读取Excel表中的多个单元格的值,在listctrl中显示*/
+ P- V# P# x  W1 T    VARIANT varRead = range.get_Value2();
5 r$ n* i' O5 U* p) W9 b/ G    COleSafeArray olesaRead(varRead);! W) g5 m% `/ \' I% T

: m! B6 g; g2 y! u% S, K9 r    VARIANT varItem;' D/ }) W/ k0 [: s
    CString strItem;* _% U$ r! _& X% H
    lFirstLBound = 0;# L0 V  b! D9 y  w5 K
    lFirstUBound = 0;
7 |  g: b, V" C% ?1 L) M" H/ t6 T    lSecondLBound = 0;9 C  S5 s' u+ k
    lSecondUBound = 0;: V" J$ y$ X3 }( m0 S  g- g- L
    olesaRead.GetLBound(1, &lFirstLBound);3 p1 U3 `9 W4 H' d7 b5 T
    olesaRead.GetUBound(1, &lFirstUBound);) L5 o2 M' U4 Z' N
    olesaRead.GetLBound(2, &lSecondLBound);. T7 a4 M/ ?3 O3 r& G7 J7 h1 d. g
    olesaRead.GetUBound(2, &lSecondUBound);7 J0 L6 T- G+ r0 j6 P0 v% O
    memset(index, 0, 2 * sizeof(long));
' l1 o5 ^9 f% x    m_ListCtrl.InsertColumn(0, _T(""), 0, 100);7 X6 h* o$ y* |2 E! U/ z
    for (long j = lSecondLBound; j<= lSecondUBound; j++)8 z5 P* D0 k: [+ g
    {4 c4 Y* M6 N& Q6 |
        CString strColName = _T("");
, b  L1 k' f: a* g) Z- J        strColName.Format(_T("%d"), j);
* n2 x) L" O0 f5 Q: ~/ r3 e        m_ListCtrl.InsertColumn(j, strColName, 0, 100);& V$ N9 o* ]) N1 v
    }: u* M' S/ N  r. [7 f5 }7 j
    for (long i = lFirstLBound; i <= lFirstUBound; i++)4 b! I* ?4 }$ {4 g; l# l5 `
    {
' e; Z7 E4 _8 }  Y  H        CString strRowName = _T("");
* e* Y" p. I5 {0 n7 V        strRowName.Format(_T("%d"), i);9 X1 i3 ?/ O( u. r. J( c9 ?
        m_ListCtrl.InsertItem(i-1, strRowName);
) M; U$ e1 @. W3 ], T9 m- w7 ]" J9 u: Y# q& ^% z% V- O; s. r
        index[0] = i;+ \* F: ?7 A  O1 Y; `& Z1 |
        for (long j = lSecondLBound; j <= lSecondUBound; j++)  u4 m1 I% {- y0 F$ w5 n" ?' A
        {
9 e" F: m& Z: b$ Y, ^            index[1] = j;
3 S* h% W: b/ M, \6 c! w3 C5 m$ X            olesaRead.GetElement(index, &varItem);( X' Y, E; y* m+ s

. G+ [- Z. c1 `/ q            switch (varItem.vt)
( l4 Z4 l, Y& u6 l) `            {
  S+ i. }4 I1 g4 y7 [            case VT_R8:
% i1 Z% Z4 c" x. _                {, ?* O1 J3 {. m! {
                    strItem.Format(_T("%d"), (int)varItem.dblVal);
5 [1 j% m! h: g* [+ B: s, K                }; d3 p: [+ A9 g  x

$ X( k! j' ^: y! z" `            case VT_BSTR:/ z: u4 ~; U/ r2 {! h( [
                {$ G# ]  O9 P' _) q+ S. s
                    strItem = varItem.bstrVal;
5 R: F7 ?1 V; F" g1 v% n$ o4 {$ [- T' u                }* b+ j  E3 T$ P# Z

9 @& m" b4 \) Z$ z* ]            case VT_I4:# s0 Z! D) z) u" G0 H5 ^" @: U
                {
1 B$ r; i+ t- \& T( [" T! h. L0 b                    strItem.Format(_T("%ld"), (int)varItem.lVal);
0 A) ~% I+ h+ F5 z9 n2 w$ B0 o                }
. Z: @( N5 F' c" }  t9 T4 F
4 X6 \$ w0 d, D$ j7 y            default:, R* K9 G# _1 [5 L
                {! ^! T# u' ]) `5 E; F5 Q7 u
& A5 I" z5 R6 {; \( j; x
                }
# s! R, U9 O6 w( f            }
1 {- }7 o6 r5 C6 \2 O5 O2 ]1 I: g" G
4 X1 s, q3 I6 k3 A7 g* U; B3 W            m_ListCtrl.SetItemText(i-1, j, strItem);  B0 o1 U8 M9 e
        }2 j- Q7 ~+ h  A; g
    }
1 b6 a, X0 E# i  D9 u: i5 r% M& s; {" Z' a( H' y

3 D' G( |, T! e/ T
- ]' n- \* W' @& N$ L    /*释放资源*/
- M7 ~( d; P4 T8 I; e, G/ r; E    sheet.ReleaseDispatch();
" Q. s" P2 U' z# J    sheets.ReleaseDispatch();4 x* h1 N) y8 w7 x- m
    book.ReleaseDispatch();( d4 O. ^) p+ K
    books.ReleaseDispatch();! B$ U3 u+ o, o- ]3 F+ }
    ExcelApp.Quit();2 \$ E' Z, x5 U9 r
    ExcelApp.ReleaseDispatch();2 m/ }. S, s1 z, \& T* \0 X
# ^+ s( ^; `5 p1 F3 f
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了