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

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

[复制链接]

2014-11-8 08:13:41 6545 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表格的操作。2 g4 T7 x% i3 P" a+ d# s/ o
  
% [6 _; |1 P6 ^! ^) G+ W8 M本文源码的应用环境说明:6 V% f+ u) e& S3 i1 ]
Windows XP SP3/ S' e, r, f" A
Microsoft Visual Studio 20104 ^9 \: W' m9 Y* x1 ~/ c% p
Microsoft Office Excel 2007& J; r9 r/ t8 P0 J
  
! c7 v5 m5 Q! }3 Q) E) G$ F7 C  }1、添加OLE/COM支持。
  @/ ?9 r; e$ {0 O( Z! |  N首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。
3 ]0 I6 v4 v. s2 b' S8 _) H$ R本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。: v! x: Y+ @' U) T. i
通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。$ c: r8 J& x) X8 o5 I2 j
#include <afxdisp.h>        // MFC 自动化类/ X% O6 {8 W# ~* k3 ~2 @0 y1 M7 Z
同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:0 |! O# j9 g; e; N/ z
// 初始化 OLE 库) y" D2 O  q9 `; A; a
if (!AfxOleInit())3 E" o2 C1 f0 A: p
{
( J) g& n0 A+ C. ^1 K4 MAfxMessageBox(IDP_OLE_INIT_FAILED);, m; u7 {( r. g+ s3 Y2 b' S+ [
return FALSE;& w7 j' t) O. c( I2 B5 c
}0 |$ [: i" x  w0 K( i
  
  F( Y) k& l" f8 S% L* d2、导入并封装Excel中的接口# p# ~5 @3 ^; `# }
Excel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。
) k0 _- l3 o# m由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。7 `2 P; X) O8 H5 P" z4 {
VS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择) ~7 r4 n0 F3 K% V8 g
要导入的Excel类型库中的接口。/ P8 k7 Z/ x; r- v: W# n" \% E
在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。# i/ q* R% v0 m/ P; G
  
6 D* u0 D& V4 A6 N( {( r) [本文所导入的接口对应的类和头文件的说明如下所示:
* ~7 s) N' ]- ^! p  x) n  / ]( ^7 a8 b4 l
Excel接口3 P# ?* V% t, X3 W- V1 ?- I
导入类- g' M" S; M- W: S% l2 @
头文件: k' C( x! G% }4 ^8 K
说明( e; Q1 [. B. l' E$ m* Y% H) y/ u
_Application5 U- S/ A8 _. D$ E  i
CApplicaton1 |* S; o* R/ [/ f9 e; o
Application.h
0 d' Q. \) ?6 V  {2 }Excel应用程序。
9 @. u& b+ |6 ^8 w; r$ H- HWorkbooks
' N1 `! h& K0 I3 f* |CWorkbooks
. X6 c. A9 V, u. S/ {  ~1 t& ?( ]Workbooks.h8 k# S. p2 G# m) M% b# y
工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。
% u  ^/ |1 J8 p% T/ Y_Workbook; G1 S' G& N* U4 j* `
CWorkbook! u, t+ ~1 K8 f
Workbook.h
# l6 d! t  [2 c9 L1 Z1 ^单个工作簿。$ M1 S5 v- f" s" ^
Worksheets9 r8 H: P! ]" c1 {" y" ^
CWorksheets) i4 J( b& l5 @) J+ J
Worksheets.h  u: v8 N: Z8 }$ [
单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。
# M- B3 P" q8 W( y/ j. x# C4 R7 t_Worksheet
+ [6 c! A8 r, C( W- p7 c( Z1 X1 {# ~CWorksheet
1 r, s# j% M* _' aWorksheet.h
! R4 @' Q8 T, i0 X' m单个Sheet表格。
; U& t$ q* |2 i+ r) h, \! X) b; QRange
- C' P- O7 E1 u0 u$ iCRange# W$ {; Q( B# r; t
Range.h: B2 n5 ~0 u$ y. R6 k
一定数量的单元格,可对单元格进行单个或多个单元格进行操作。/ Q' @1 U4 [* T
  # v# r# H% t, |- j
3、导入Excel的整个类型库
- Q3 }) v4 I7 r7 i2 H) ^* U接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。; f1 ^4 o% x$ h1 F9 Q! I1 i
通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:  T- N. P9 g( M' z* \/ J6 l
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
# H( J6 V; E0 L# }这行代码的作用是导入Excel整个类型库到工程中。2 C0 t- ?- t  l) ]  q- l5 A
由VS2010自动产生的导入代码存在以下几个问题:* [4 `% d! L" I' N' s. u# H: V
(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。7 R( j6 ]# X4 ]! c
(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。: O2 V: Q4 x$ s+ I5 U
(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。( Q& |/ m$ r/ f
以上三点问题的解决方法如下:
/ G$ P/ @+ E! C% |$ v: c' H9 i" i(1)仅在_Application接口对应头文件中导入Excel类型库。* z9 D/ p9 ?5 t3 s& J6 B+ ]
(2)对冲突的类型进行重命名。* _& S" A, M' @& z
(3)在导入Excel类型库之前,先导入Office和VB的相关库。
1 n' P# E: t5 e2 x) x5 r更改后的导入类型库的代码如下:
& v/ A; q: N9 T. M4 N% n  
( F+ j6 |" a4 Q" {3 \4 b/*导入Office的类型库*/
# a. X- z, U* I) j5 U& [#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \
) ^4 I+ F8 J, E# H6 j0 l9 wrename("RGB", "MSORGB") \
- x& U! O. s9 K1 x6 k9 |" }rename("DocumentProperties", "MSODocumentProperties"). e- F. Y) g6 u: N5 T, _; g- d5 q
using namespace Office;! u) n2 ?4 Q( w- Q0 |
  
  N8 j2 B+ x5 f: i/*导入VB的类型库*/" H4 ~+ f" I8 a/ [
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB", y8 X% d5 l, }# J7 U% s; D7 u$ U
using namespace VBIDE;
. i2 ]3 N" L. c9 b  o! s5 I; ]  
% |( b) S( Q, `& n8 y8 r/*导入Excel的类型库*/
/ D6 J- b$ \+ ~) E5 V& d#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \8 `& q5 G, B! l- {" O4 ^
rename("DialogBox", "ExcelDialogBox") \  X- ?) b) L; L# K1 m% Z- v
rename("RGB", "ExcelRGB") \+ c" H5 u5 v% z
rename("CopyFile", "ExcelCopyFile") \
; T8 [! Z1 M$ W. Y2 F/ trename("ReplaceText", "ExcelReplaceText") \$ z6 e- I9 p# ?) Z$ f7 `* G+ K5 a
no_auto_exclude) o5 m4 C7 Q, j3 y7 Q7 b1 O$ |6 H
Using namespace Excel;
3 w3 B: x8 `. S  
4 @0 o/ O  q  A+ Z: X编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。3 J' E+ C/ Y2 X& S3 `
  / H4 d3 x8 H/ Y
4、操作Excel步骤
5 c7 x; k& D7 o5 f8 \操作Excel的主要步骤如下:3 Q9 r% Z1 ?( Z' Q, i6 e0 R
(1)创建一个Excel应用程序。6 z, i5 p' U9 X( [/ I
(2)得到Workbook的容器。. z6 v: x* X' L, Q. G1 n. N: y) R
(3)打开一个Workbook或者创建一个Workbook。
  ?# e+ d# ~$ {2 Q; I' G# i(4)得到Workbook中的Worksheet的容器。
1 v5 H8 \2 C4 W8 \% g1 T(5)打开一个Worksheet或者创建一个WorkSheet。
( \( y8 D% u) i(6)通过Range对WorkSheet中的单元格进行读写操作。
. z" x1 o' J) h' m# W+ O(7)保存Excel。
: V7 ~; N# n: K; K(8)释放资源。
& v; J& c5 {. d) s  
5 i/ I5 V! C* Y) i5、批量处理Excel表格) n9 R5 n: Q  G5 [4 ?+ c
VC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。! |- _1 o: D( f
对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。6 ~5 K1 S: k# N1 K: d* A* `1 j# d8 `
VARIANT get_Value2();
$ q5 |) X8 o0 S8 [7 n/ avoid put_Value2(VARIANT& newValue);; b7 H4 @7 R' b; j, J  y0 I
其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。  T3 ~! J/ Y; @0 _
其中,VARIANT中实现二维数据的方法可参考( ]) G- O! V1 P+ i! }* ^
http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html
$ W% X( x# h/ \# f! v当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。
7 @( G7 w! F  e3 }  0 n- R( M3 S0 R  s1 j) _7 J
6、Excel表格的保存  i2 l; Z2 A6 x" i& g$ l
(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。8 @" |/ h' e+ J+ b' a! Z
(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。) E2 [$ b# S" F
SaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。, [# O. ~1 T9 {' S2 S" u
  5 {! P+ X0 @- Z
7、获取当前Excel的版本* G/ x* c/ Q+ |+ f- t
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
2 f* [+ @8 }- Q  
6 b* M0 Z4 x9 R7 G# u7 t8、示例源代码4 e% z/ b; q- N, S0 I0 E0 R9 j5 c2 N) `
主要代码如下:
$ J; v$ r+ ^  T1 {1 |( N  
. y& w3 _+ `$ ?7 G" f5 L) Z4 z* f- D6 t- ?+ ^& d4 }

& Y; u: S0 E+ E# j2 k    m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);. f5 F0 y6 Z( n- L* }

, l7 g$ Y0 t  R8 V7 k2 z7 `    CApplication ExcelApp;
1 D) p5 j/ H& }) l$ `; y    CWorkbooks books;* N$ C8 N( t; G
    CWorkbook book;. T" q& |' b( v
    CWorksheets sheets;$ G* }# S9 H5 H1 V3 c) @
    CWorksheet sheet;1 t1 a. ?4 I; ?
    CRange range;* x9 O( T; `0 _" z/ v' w% [, P, }
    LPDISPATCH lpDisp = NULL;
" c0 |* A/ g# u/ P* x- ?5 [
" _; Q: s2 T( `8 C0 O5 Y    //创建Excel 服务器(启动Excel)+ ?1 N( D4 X2 {. g/ C
    if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))
1 L% ~- O/ m6 l, r2 h3 E% J. p- W    {
+ J$ O4 L* J& U* R4 E        AfxMessageBox(_T("启动Excel服务器失败!"));( U3 [4 t  g( c8 M) S6 G
        return -1;  x! H" Y$ _! u( F0 `1 b
    }
0 {) x' i; p* X7 _9 t% E4 d
5 M- h! m9 z' [1 b- `9 u! V    /*判断当前Excel的版本*/$ v9 n7 G% j6 z$ D8 f
    CString strExcelVersion = ExcelApp.get_Version();* f8 |8 h# ]# R" Z
    int iStart = 0;# D. C) a; x: d+ `9 m5 @$ r- X
    strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);% \! f. [9 K5 {9 R" s
    if (_T("11") == strExcelVersion)
  b; J6 M. r! J0 r4 D    {9 |6 O6 g: x% }9 J
        AfxMessageBox(_T("当前Excel的版本是2003。"));
# ]9 y9 G, L4 s6 }3 }4 A    }, B8 W5 v; M5 a$ H, [, o: a! Q
    else if (_T("12") == strExcelVersion). X7 S6 V8 k# b  W3 o
    {- d3 H" A' l7 H* {$ p: v6 U
        AfxMessageBox(_T("当前Excel的版本是2007。"));
3 h( `4 x  Q% `8 [% j! _    }
# x( d7 u/ m! t$ p4 _2 _    else5 \9 B  m( G! ?  e. P9 E7 I% ~
    {5 w1 S; I$ K+ ]* s/ A
        AfxMessageBox(_T("当前Excel的版本是其他版本。"));
2 l2 }( C# e' X5 z    }. a$ H& V3 h# B) Q  b0 _

  I& s& m, V3 D! W$ z$ P    ExcelApp.put_Visible(TRUE);1 \! ?+ C9 r% \6 E  H
    ExcelApp.put_UserControl(FALSE);4 Z* w8 ~/ u1 ^- J/ B/ I

: p6 {- ?; J- d' Z    /*得到工作簿容器*/& d8 c4 K5 `! g; x4 |2 E; z/ L$ v) C
    books.AttachDispatch(ExcelApp.get_Workbooks());
1 }6 \5 B4 T6 l4 X* Z
# L3 Q; S$ |; m+ [9 L    /*打开一个工作簿,如不存在,则新增一个工作簿*/
3 M, b5 S' _5 ^9 V% n; ?    CString strBookPath = _T("C:\\tmp.xls");: f8 S9 ]- }! D
    try
. `# D# L7 U7 k- X! v! G7 A2 r    {/ @/ W) K0 S( P' G! R
        /*打开一个工作簿*/
) _. i) @! A' f# @) Y0 t        lpDisp = books.Open(strBookPath, - r& K) R) b" U6 o  p
            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,) ], Y& q5 p4 S( r( l( ?( d
            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
; h7 y" U. d) k( j, h            vtMissing, vtMissing, vtMissing, vtMissing);) Y  V$ l! [1 |9 ]: u9 ?
        book.AttachDispatch(lpDisp);
: r* b) }- F' r8 i. k$ C    }
; J$ \* p' f8 J7 P7 H4 R: T    catch(...)* I$ m2 [3 y2 Z  ~
    {  ~# _8 I+ B3 r7 l$ ^2 Z' E: F/ A* T
        /*增加一个新的工作簿*/
! q5 K# m6 E0 ~2 k0 f        lpDisp = books.Add(vtMissing);
1 \: Q3 Z& a! U& d$ E9 ~9 r        book.AttachDispatch(lpDisp);: D% ^: ?# y$ Z
    }( Q6 d: u, S% R% d
     5 S, P& x: d! y$ d% e, @2 K# B7 G
, C4 K- R9 `: n& J; E% F/ t2 A
    /*得到工作簿中的Sheet的容器*/& L$ F' P* A8 [% v; g) E
    sheets.AttachDispatch(book.get_Sheets());
* z! Q! b- V" L( }4 r9 W8 U. _4 g" |  H* ]3 _: H/ ^  `
    /*打开一个Sheet,如不存在,就新增一个Sheet*/
" |0 p+ v$ q' c/ S    CString strSheetName = _T("NewSheet");
% x- i$ l4 R" l) b, n0 w    try
" h3 ?8 m: ^8 m+ t& c9 |# \- D    {6 i% ~+ C! [) i$ l3 z/ W, D9 T
        /*打开一个已有的Sheet*/
$ h( Q: i/ e2 _: _        lpDisp = sheets.get_Item(_variant_t(strSheetName));4 ]- y- P; Q; X
        sheet.AttachDispatch(lpDisp);! v8 A/ u% n- C1 ^" {. l  j
    }+ k% ^" v7 m" Q7 r2 \; C
    catch(...)
& r8 x! @0 E% u! R6 j    {
, D) F" ~- D9 H, ~9 k/ |        /*创建一个新的Sheet*/  D8 K: E$ a5 T% u& e5 `
        lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
/ N- U( z$ c4 c. q+ a        sheet.AttachDispatch(lpDisp);' u! r% U9 |% g, t
        sheet.put_Name(strSheetName);
# k) |/ t, Y  i/ X! B0 J/ l) k$ y, k* t    }
+ u, B7 o$ q: S/ D# e; R
) i6 T$ u6 J9 {7 R0 K, H1 R    system("pause");
5 P+ L2 |$ B, {8 B7 ^
8 \- |' o, d* C  ^  `% M( U    /*向Sheet中写入多个单元格,规模为10*10 */
2 P/ b; A# }0 I4 P: f9 c0 X$ G    lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));
8 Q3 K- h$ C) g- o; ?    range.AttachDispatch(lpDisp);
; s6 X& q2 W3 I7 z" l- X& F. g4 c, h& [! c4 f% @
    VARTYPE vt = VT_I4; /*数组元素的类型,long*/! h; A% W3 q, x- j7 s
    SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/
0 f/ V9 I, Y3 w1 }; A( Y    sabWrite[0].cElements = 10;
) g0 m$ [# _. Z+ Z$ B7 [$ l    sabWrite[0].lLbound = 0;5 w3 ~; C1 o$ U, F3 U- ]3 A( h* Y
    sabWrite[1].cElements = 10;
9 N- T/ Z4 {  x! R- G    sabWrite[1].lLbound = 0;
1 V+ i/ N+ k/ {0 b
" l5 m- X3 z/ F    COleSafeArray olesaWrite;
, e. ?8 z: k1 T0 a7 [1 ^# `! U    olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);
4 }) |& t& s1 \# A
8 k4 }8 @5 _. D5 n  A7 H    /*通过指向数组的指针来对二维数组的元素进行间接赋值*/3 O% R; o3 s6 z* ~$ Y/ Q6 _
    long (*pArray)[2] = NULL;
# g9 I$ F/ b# J- ]  p# P    olesaWrite.AccessData((void **)&pArray);, n$ {7 x. u, S/ u( ^
    memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));0 p5 i- x3 a$ x9 Y! }
. a. V& A9 R6 K
    /*释放指向数组的指针*/
# G+ q# q/ N( P" j( C    olesaWrite.UnaccessData();: o" B- r' c1 c
    pArray = NULL;! r. ~' A- ?0 n9 \1 n

$ W5 @1 k# V( M' n2 ]3 k    /*对二维数组的元素进行逐个赋值*/( \  s' d. B' J$ d4 l# F9 [
    long index[2] = {0, 0};
9 E) [$ j# v6 w4 x, J    long lFirstLBound = 0;
: l3 \8 x5 G, i: A6 D8 b/ }" R. ]) X    long lFirstUBound = 0;0 N* {# w. o- f' V# a2 N/ `4 m
    long lSecondLBound = 0;, I: R% T/ Z) p
    long lSecondUBound = 0;
0 T1 J/ a* J/ T) z9 P    olesaWrite.GetLBound(1, &lFirstLBound);* \% s( J( t, G- T; T1 t
    olesaWrite.GetUBound(1, &lFirstUBound);% o. G% ^+ C+ P# S+ \# F. L* g
    olesaWrite.GetLBound(2, &lSecondLBound);
7 z4 x1 e0 t* u' `    olesaWrite.GetUBound(2, &lSecondUBound);
7 B  m1 n/ m1 F% s% {    for (long i = lFirstLBound; i <= lFirstUBound; i++)4 G; E5 C- {5 K! e. T
    {: F0 v8 w) W) O, J; R. ?) s
        index[0] = i;0 W' _7 ]$ N/ s9 o) G) U
        for (long j = lSecondLBound; j <= lSecondUBound; j++)8 u0 A9 @7 e" I- H( N
        {
6 S2 T- E- t! ~" u; S1 r            index[1] = j;
6 o, e9 r" t- ?            long lElement = i * sabWrite[1].cElements + j; ! P- ~  b" o% z- e2 G2 ^2 b
            olesaWrite.PutElement(index, &lElement);; k5 x% w& i, Q* H
        }
2 s6 a- ]1 x7 B/ _% O1 U0 l    }
* n4 G) A# l& K3 }5 I9 `- x
4 p1 `2 ?& q: e    /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/0 B0 h# i: r$ t0 v. V
    VARIANT varWrite = (VARIANT)olesaWrite;2 _4 E0 a& o6 B% Y0 k
    range.put_Value2(varWrite);
' x, J6 B; l5 v1 C! H
& ?* W: y: A/ a  I3 a9 ^' Q    system("pause");
' p6 E! n6 ~* y8 ]( D/ j+ A# ]8 B$ B! _, V
    /*根据文件的后缀名选择保存文件的格式*/! s' M3 B& @1 Z. q7 |5 a4 `
     CString strSaveAsName = _T("C:\\new.xlsx");
1 ?5 Z2 }5 C* S! i7 [/ }    CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));
; M) Q  h+ w' |; C    XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;
0 X& X- k! R0 {4 ~    if (0 == strSuffix.CompareNoCase(_T(".xls")))
+ B% e4 g, K$ l, c9 Q2 ]( n    {4 r/ Y6 ~9 F5 r* G2 F( e) K. D
        NewFileFormat = xlExcel8;) x, u7 u+ n+ O5 z+ F3 b* }
    }. H# N0 M! ]1 e
    book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, 5 D4 \4 E+ D: m1 m: g9 r8 I
        vtMissing, 0, vtMissing, vtMissing, vtMissing, ! H( p! L/ Y" Q& s8 c  `4 }
        vtMissing, vtMissing);
$ u4 a: |! j6 M/ [0 V: e
9 B' R: {8 C2 F, _. K    system("pause");
1 C" O( E: g3 r8 J4 h5 n5 J
! T' P. h+ U4 }3 j" j+ W    /*读取Excel表中的多个单元格的值,在listctrl中显示*/' x1 C1 ~- ^( t0 C/ O9 h
    VARIANT varRead = range.get_Value2();
# }5 Q# C4 ~' q+ J5 ^# O7 i    COleSafeArray olesaRead(varRead);3 |) F  `" e+ k( q" X" R* q
2 s' ~* d" a8 {
    VARIANT varItem;  K: C$ w8 b% D
    CString strItem;
! F6 M: B7 M+ Y3 o# W6 l" M* K    lFirstLBound = 0;6 c# M/ c. S. w2 r; V& \, s
    lFirstUBound = 0;- b4 D) \/ ~7 b
    lSecondLBound = 0;
2 ^! j! _0 ]# M2 C; e    lSecondUBound = 0;
2 n6 b9 G$ u7 Z    olesaRead.GetLBound(1, &lFirstLBound);' P9 l3 {% D; t, j, ]& m& C* W
    olesaRead.GetUBound(1, &lFirstUBound);0 j( M/ |1 E$ l' q
    olesaRead.GetLBound(2, &lSecondLBound);
7 R, }# U' O! U. _- g    olesaRead.GetUBound(2, &lSecondUBound);, p/ D& z* C2 N2 w+ n
    memset(index, 0, 2 * sizeof(long));. o( O. R4 r% W7 _; Y
    m_ListCtrl.InsertColumn(0, _T(""), 0, 100);
- A) }6 b! Y3 x! k" V& C    for (long j = lSecondLBound; j<= lSecondUBound; j++)
: S# T) e& c: W/ G7 u* C. @    {
& x8 @1 J" _' w, n2 g        CString strColName = _T("");) [  D: S- D! a! z2 N# ^
        strColName.Format(_T("%d"), j);+ f3 q3 Y5 A/ T9 m
        m_ListCtrl.InsertColumn(j, strColName, 0, 100);' p/ `5 j1 q5 _& ^
    }
8 z% i4 B: r5 w% q1 d    for (long i = lFirstLBound; i <= lFirstUBound; i++)
5 g% j$ a$ U3 R5 z3 F' W    {
. \8 w; |- r: f- B0 b/ v) m9 _        CString strRowName = _T("");
2 O" s' L9 z; E. \, Q        strRowName.Format(_T("%d"), i);# [8 d6 z7 l4 f) x+ w2 s
        m_ListCtrl.InsertItem(i-1, strRowName);
- _9 o5 r) I2 W3 w  m5 o
! [# [2 v1 a7 t; f$ b9 p; c        index[0] = i;
; ~0 Q" I4 {* l$ o# M; X( v        for (long j = lSecondLBound; j <= lSecondUBound; j++)
% {# m' u7 x$ f2 \* n- w) z        {( F. G# L# ]4 Y% ~8 e% |7 y6 w2 x
            index[1] = j;
9 o- l2 G, H& ?9 M3 ~  X            olesaRead.GetElement(index, &varItem);$ `: y/ G' v5 \+ [; k2 w7 _

9 M# U/ f$ m6 h6 O2 f4 T+ e( Y            switch (varItem.vt)
9 y8 R2 S; i$ e' e. |            {
$ B9 H. g+ k( @            case VT_R8:- c1 a& ^8 ]; h% ~
                {( O$ d% H! }& y9 m
                    strItem.Format(_T("%d"), (int)varItem.dblVal);6 e& u) K5 ]( |/ p
                }
3 `% G  f0 k6 L* ^/ A& m/ a" a( W1 z" u/ z1 I0 i+ P; b
            case VT_BSTR:* l9 R8 m; _+ I/ d
                {
8 \$ q# P7 M7 n# G4 n2 Z- ]& o$ I                    strItem = varItem.bstrVal;
: j; z! _0 p( w. h/ k5 p                }
; ?, [2 R5 `- t' b# X
* K7 n& N0 F- W& s            case VT_I4:
& t0 m- U: X# ]                {! s4 P4 h  e7 i& f% ^* W* X
                    strItem.Format(_T("%ld"), (int)varItem.lVal);
$ f1 {6 @  ^: ^+ ~                }
  M8 }3 U1 [! @
( c  x: i& [1 \+ W$ H& L( m            default:- H8 W6 N! H. X' {
                {
4 Z2 I& v- F$ p$ [& s( f% M' R) D$ a( @1 I' F, I
                }. o' J' Q- V; N% c
            }# J: r- Y- Q' y, l/ \

2 V# L) W, g; C8 x5 n            m_ListCtrl.SetItemText(i-1, j, strItem);- D. b9 z( ^6 }3 a( y8 A% }$ ~3 n& _
        }6 S# y0 y' J# G+ `- n9 O
    }" S/ P9 a4 O6 n+ F5 X
& Y0 ?! C5 O/ n6 m) b5 \" w

  g9 Y- q: B! z7 w
* {* [6 @# d$ m, X    /*释放资源*/
( l: Q7 R% |# v+ X0 M    sheet.ReleaseDispatch();# P" }% [* T% @1 \
    sheets.ReleaseDispatch();
! U9 Q) I/ v7 p, h    book.ReleaseDispatch();' C1 z$ ?( S; ?2 L- ~( K" x
    books.ReleaseDispatch();
# s: W0 S2 s! f6 \% o& Q& @8 Z1 _1 V# U2 L    ExcelApp.Quit();
) K! q* H$ O  s1 P! e2 h# Z0 n2 R    ExcelApp.ReleaseDispatch();; Y) u4 m) m$ N

9 J, v7 {+ ?2 V" [! k
上海点团信息科技有限公司,承接UG NX,CATIA,CREO,Solidworks 等CAx软件,Teamcenter,3D Experience等PLM软件,工业4.0数字化软件的实施\二次开发\培训相关业务,详情QQ 939801026 Tel 18301858168 网址 www.diantuankj.com/ doTeam.tech
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 注册

返回列表 本版积分规则

  • 发布新帖

  • 在线客服

  • 微信

  • 客户端

  • 返回顶部

  • x
    温馨提示

    本网站(plmhome.com)为PLM之家工业软件学习官网站

    展示的视频材料全部免费,需要高清和特殊技术支持请联系 QQ: 939801026

    PLM之家NX CAM二次开发专题模块培训报名开始啦

    我知道了