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

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

[复制链接]

2014-11-8 08:13:41 6710 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 o( Z! y0 V# L
  ' G9 ?2 m, \* h2 M
本文源码的应用环境说明:: u# m; x0 ?, H6 A2 a
Windows XP SP3
$ `. `: Y& `8 e1 ?. [' b9 EMicrosoft Visual Studio 20108 R/ z' {  @6 u; ]
Microsoft Office Excel 2007$ H0 W4 v' n/ a# O  D5 H
  
& k- C' S6 ]2 M8 i  d, V1、添加OLE/COM支持。; g# s# C5 ]. G8 }
首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。
7 k9 Z/ J  I0 P4 p本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。' l! K  q* D, a
通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。: e9 X% ^  g7 h, E  ~
#include <afxdisp.h>        // MFC 自动化类
* e. V, h0 \4 m$ u2 ^同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:, I+ E: y' i5 ~. M6 z
// 初始化 OLE 库
3 h7 g: N1 Z% V; d& J9 U  X" a0 oif (!AfxOleInit())
) [4 ?$ Y4 T$ }( K* l0 U& w. n; q* L{
. G/ @7 k4 g+ x. N1 v5 K+ rAfxMessageBox(IDP_OLE_INIT_FAILED);
; z4 A+ f8 U. e  t4 r% lreturn FALSE;- t. e9 z- @3 m6 E. R. I
}( p7 b# x6 E$ O& d
  2 ]  S# n0 s( {
2、导入并封装Excel中的接口
. m0 m/ o0 g- t' ~4 K% DExcel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。( e  S7 [$ L" l) p3 B. y
由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。8 |9 }) a3 H- R0 i7 {/ [
VS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择& D% B7 V6 `! s3 c! P
要导入的Excel类型库中的接口。0 n4 t+ o- n# `2 J  d% F
在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。8 S+ {) @3 N- ?
  3 }! ]' t* F1 J& y# L, K8 M3 X3 }3 o
本文所导入的接口对应的类和头文件的说明如下所示:
" D+ I( {9 Z) j% {! u( c( J4 j  ; c, j: [' F# K6 X3 ^# L! E9 L6 W/ f
Excel接口+ I" H. V9 U+ ^! Z  Z4 o
导入类
" u( n, P9 y$ X5 P: c2 D头文件
( L' D# y- t% A& G0 L9 g4 S1 k说明# q: E* t, W) O7 p
_Application
, ?; J- J4 D/ ^* S5 S0 XCApplicaton$ Q# t) T( p5 V: O8 M. m
Application.h2 s7 s0 ]1 l9 w, a7 g
Excel应用程序。3 ^4 T( b" \8 E' z" ~
Workbooks" ?1 x$ K- W+ n2 s+ i- V
CWorkbooks  V7 R7 S; P% p5 {: u7 P) o
Workbooks.h7 [2 @2 R9 x& i; j" D
工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。
4 S/ e5 a" ]0 |1 G* r( g_Workbook
5 L8 f2 O5 C& \$ \1 e$ sCWorkbook& M7 i+ Y% D% \- d
Workbook.h
* h  R# v- ?4 U' W  \单个工作簿。
: A. j1 i) R: Y2 Z3 K2 |7 h( }Worksheets- M3 i/ v- x7 k$ W2 ?7 h
CWorksheets
$ V5 ^. y/ ~, k( q% }4 mWorksheets.h# f, H& j1 Y6 `: k$ B
单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。1 A! n' r: E& \2 `9 i
_Worksheet
8 `5 r. b7 y; s0 p5 F$ ECWorksheet# }& d4 _2 u' n2 K
Worksheet.h4 l  |+ F1 ^# S$ @
单个Sheet表格。
' t/ `( |8 Y. M+ Z3 ?: U0 J5 r& BRange( @& Y0 C1 V" u' n) D4 q' [
CRange. w2 [4 ~% S: y2 f1 ~, O# E' a
Range.h- {7 n4 l# \' N7 C: Q
一定数量的单元格,可对单元格进行单个或多个单元格进行操作。
) w2 R1 ^3 Y" [6 r0 c  
, H% ]1 Z( g1 Q' y! C- E( T3、导入Excel的整个类型库
$ I, K! `# D! v9 T, a; {0 D接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。6 M3 y9 u0 U/ r, @
通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:* z; \2 ~+ z4 |$ l' g# {* r+ `
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace. [+ X3 s  m! G; G5 w
这行代码的作用是导入Excel整个类型库到工程中。
; P2 l) o! H- F7 @4 g由VS2010自动产生的导入代码存在以下几个问题:
8 r5 B9 M6 v/ M) V* M(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。
# m! r7 P) ~7 B8 `4 p9 C+ j(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。
* {8 }" X$ j. [(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。
4 [- z8 O* }  O" c9 m5 E+ Y以上三点问题的解决方法如下:
( Q6 \1 P% [4 o' B(1)仅在_Application接口对应头文件中导入Excel类型库。
# l  V6 l7 ?; ~* r% P+ k6 l(2)对冲突的类型进行重命名。9 t# G/ B0 u' {( W& c
(3)在导入Excel类型库之前,先导入Office和VB的相关库。
; D; e1 w4 b6 D7 c6 |更改后的导入类型库的代码如下:! {) T) w9 T1 F1 y) ?0 _; x* V1 B
  , |3 U: U$ s$ N& u4 ]. J
/*导入Office的类型库*/$ Y" {; i2 {; w8 z( z. c  q
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \
+ A' Y* i% `  Srename("RGB", "MSORGB") \
3 M8 G+ K7 m" `4 \rename("DocumentProperties", "MSODocumentProperties")
0 V) F" B- R, K1 v2 ]) U+ g/ busing namespace Office;3 i& d% \: x. {( I" D
  
4 S& K  u5 y) a( e" s( e/*导入VB的类型库*/0 V# b- {4 T( l( Y, ^. h1 H; i; m- Z
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"/ b1 d! n" w. w& I. \; P! \+ V
using namespace VBIDE;( L7 u! Z4 @( O, W, m$ s
  ' y) C* U* L- W9 W4 [- K4 I4 q
/*导入Excel的类型库*/- X" O% Q9 g. Q% C: x- p
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \
4 |* w$ W- Z; `: d8 [4 P( }7 Mrename("DialogBox", "ExcelDialogBox") \
! \  D% S4 f2 lrename("RGB", "ExcelRGB") \
$ i) e( y5 z+ hrename("CopyFile", "ExcelCopyFile") \9 d3 a& E5 N& y2 {2 u9 t
rename("ReplaceText", "ExcelReplaceText") \1 c5 {, ^8 d# [7 ^; a
no_auto_exclude  q* ^- H; c3 O2 W% b
Using namespace Excel;9 R+ p  R9 u2 u. c( J# ?- d) K! h
  
% c  a; `/ S9 Y& y% x编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。3 h$ K8 v- F# a1 f
  
! W( H8 M* h) c% R( k4 t  @4、操作Excel步骤
# H! G/ \6 D: m! v( H5 X0 U/ G5 ]操作Excel的主要步骤如下:7 `- u9 q( G; G8 ~0 j0 c0 k8 @
(1)创建一个Excel应用程序。
  f* }6 J9 U1 A: g1 B4 F9 c3 e(2)得到Workbook的容器。) _2 a4 i) s5 @  q
(3)打开一个Workbook或者创建一个Workbook。
9 R, r- g0 W( C/ B# k* g(4)得到Workbook中的Worksheet的容器。( z4 ]! {$ r! [& M& b
(5)打开一个Worksheet或者创建一个WorkSheet。0 V' _9 J+ i. z5 N9 B
(6)通过Range对WorkSheet中的单元格进行读写操作。
) E! ^% R8 O( z5 F% [$ U% Q  R(7)保存Excel。
- s' m2 K8 B6 }7 g  H* e% U4 x(8)释放资源。8 l8 r: I4 D& ^' K- I3 C7 d
  4 `1 D2 U# \0 |2 e) S; g5 b7 W* {
5、批量处理Excel表格! A6 k+ u% `: T& A6 w& o4 p7 s
VC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。2 G* ]( _$ e/ C* a, `& s) s
对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。
* F9 D4 L% r' j9 e) Q- gVARIANT get_Value2();7 n1 _* d8 @# t6 `  B1 E
void put_Value2(VARIANT& newValue);
7 v0 w7 ~* H( X- V' s$ C( e; q其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。
) L# C$ t! a' Q" |/ f/ Y: }; c( j其中,VARIANT中实现二维数据的方法可参考
/ @$ _; A# @; N3 [5 hhttp://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html, }# _  q4 d. q
当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。
, E* R- F8 e8 V  
1 K2 a+ z. n* e0 q9 w4 Z* v6、Excel表格的保存
/ e4 R. G% P2 J/ z" ]! D0 k" w/ U/ w# C( v(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。
& X" _: P; R. k) c+ a- r(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。; h- R3 \( L4 E8 |
SaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。% l0 L: H7 X+ [. K7 O4 m2 H' R
  & |- }% S) x* Q! ~
7、获取当前Excel的版本$ Q  U9 y# D9 [& V
可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。
, \( T6 S+ [6 T) c  
9 H- K  s4 O8 N. k8、示例源代码- x/ J, {& z  @0 d6 K! C' R: U
主要代码如下:5 S- x- l- j+ D$ J1 g+ O/ ^
  
1 O2 B' q) m8 ]. ^
+ c/ D: x' \! y7 u
) r  O7 w" \3 w9 y9 Z# F7 L6 X    m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);2 r4 h# n+ I3 C) \" R  R
  w2 \/ C: a5 {% o0 m
    CApplication ExcelApp;
- d% ?6 Y  e7 n8 g% ~- Z8 i0 n0 U! Z    CWorkbooks books;$ B7 n# U: W2 ~) E3 y
    CWorkbook book;
$ _/ q' E3 B/ N    CWorksheets sheets;
3 x1 I2 y$ W4 a# C2 x    CWorksheet sheet;! j- c% t& P, a# s( L; j
    CRange range;5 ^3 V) F, [4 x' B
    LPDISPATCH lpDisp = NULL;
- F/ }8 _. w, D" X9 S# w  l
+ D2 y# v6 d6 K0 K) Y4 P3 b, b4 S    //创建Excel 服务器(启动Excel)
, `- b  g/ b; q- }# _    if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))+ b1 Y6 C$ P4 ]4 `9 ]6 E
    {
2 @" l9 w* ^+ i2 U8 X, D8 ~) U9 x        AfxMessageBox(_T("启动Excel服务器失败!"));
/ P  }( Q0 ]" R5 Q7 E$ d% Q        return -1;
3 i# U% P( Z/ D) e    }+ `% n: w) n: G6 Z+ X& i
7 g0 C. l7 V' ~8 Y5 A" o7 r: x9 C' X
    /*判断当前Excel的版本*/: a7 f1 ?/ ?! v8 ^
    CString strExcelVersion = ExcelApp.get_Version();9 @  N2 w; T5 ]
    int iStart = 0;  B$ i( A& k  \0 S
    strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);
0 N/ Q" i/ m( _- f7 I    if (_T("11") == strExcelVersion)
: a9 y9 h3 p  r7 e    {
# ]- I2 ~3 b( ~- m        AfxMessageBox(_T("当前Excel的版本是2003。"));
3 v/ O5 `: B7 L8 x3 B/ e8 q& T    }& {% T( U# X1 U8 U; A$ O  [: q2 Y
    else if (_T("12") == strExcelVersion)2 d5 n( J% O3 W8 x2 ?/ U  S& K
    {3 c' g  v0 W# D& ]( F, C- g
        AfxMessageBox(_T("当前Excel的版本是2007。"));1 l( `" C7 X, {! r
    }6 [8 O  ~/ B' B" G* s% r* `
    else) E( A, |' b2 C0 O3 W
    {7 H; ^- W/ i0 e
        AfxMessageBox(_T("当前Excel的版本是其他版本。"));1 k: j2 R2 Z2 o- c( z1 F6 i
    }3 W/ Z1 a8 ^* G  q7 @

9 |$ V, o5 q) I' j    ExcelApp.put_Visible(TRUE);" C$ t; ^2 ]4 K1 x2 V0 d6 K8 A# s
    ExcelApp.put_UserControl(FALSE);- V5 @9 m$ Q- |; o. U0 e2 m$ }3 |, \: P
1 o/ K6 @( A! J# m$ ~. H
    /*得到工作簿容器*/
- v2 c* ?9 b9 ?7 q$ z1 M    books.AttachDispatch(ExcelApp.get_Workbooks());" ]8 ?  Y/ ~4 ~

3 T. [. |4 C4 n; N* \    /*打开一个工作簿,如不存在,则新增一个工作簿*/: F- e+ }& S; |- y8 }7 S0 o9 p9 c
    CString strBookPath = _T("C:\\tmp.xls");- g$ d7 q  W: b& U$ n5 M
    try! j( P1 y1 T# o) v
    {/ T4 U1 d9 i3 x/ I8 a  v
        /*打开一个工作簿*/$ ~# y3 C: ?, A; J
        lpDisp = books.Open(strBookPath,
& u, `) i7 }) F2 j( F/ |5 g" m            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
# J( e' E8 z. C# O5 t9 t            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, ' m7 l$ }0 ]- H+ s0 X1 ]# Y0 {- A
            vtMissing, vtMissing, vtMissing, vtMissing);
5 t5 k" y( j3 _& b        book.AttachDispatch(lpDisp);
& B# \( a8 Z/ T" B! Q- y, S/ R    }
0 d2 [/ ^2 D3 k+ x, E    catch(...)
9 w2 t/ z4 O6 m. o' _8 C) w* a    {% C. B+ G4 o4 z6 X9 M1 [
        /*增加一个新的工作簿*/
8 X" H8 o1 @5 |- E5 i        lpDisp = books.Add(vtMissing);+ C7 E/ [7 `# o, _$ g
        book.AttachDispatch(lpDisp);: U) l0 ^/ [6 u) F
    }
& r  |( i( C! `     - t0 `1 P1 t5 [5 M# i! E1 ^

6 ]: ?5 y2 k1 k. j1 j, g    /*得到工作簿中的Sheet的容器*/8 \' F# j+ m. T9 N
    sheets.AttachDispatch(book.get_Sheets());* _' [/ P& V3 {9 L& ~' t

4 p) X" d) S+ z2 P# b    /*打开一个Sheet,如不存在,就新增一个Sheet*/* d: h) e6 X/ c) J
    CString strSheetName = _T("NewSheet");) v# z" m2 O  e' c% g& [
    try
5 F' q- U( T# d( X: `    {* _" F7 n2 s% ^( U' [
        /*打开一个已有的Sheet*/
8 }9 g3 ~2 D/ g7 ^" g3 ]        lpDisp = sheets.get_Item(_variant_t(strSheetName));" \1 n! ^4 ?4 @/ T: J
        sheet.AttachDispatch(lpDisp);7 l* F% A, A- |, }; L0 N" M
    }! ]3 j) R/ O; Q1 O; g2 c8 _
    catch(...)
$ q+ g9 o3 d+ _% G/ K! q" F. `    {
* Z5 ]9 A9 H/ }- h+ |        /*创建一个新的Sheet*/! v+ L8 o7 x+ @3 s1 H' J2 o
        lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
  b: S6 x; ^; o% t! v6 s0 a) Y$ w        sheet.AttachDispatch(lpDisp);) I: N9 l9 m" _+ n; O
        sheet.put_Name(strSheetName);9 g6 `& P/ W$ u5 q( W* k5 C
    }
' A# l( b5 o' l0 I  H
7 }9 g* b: b3 G2 ?  A( B    system("pause");% z1 q' a/ I2 L6 k9 g; `
% x3 Y) C7 D/ i0 V
    /*向Sheet中写入多个单元格,规模为10*10 */7 H0 I1 V1 ?% P: O9 G
    lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));( x* I1 L! J% E
    range.AttachDispatch(lpDisp);
2 _- m# O" j: G- B8 V# k; s; @4 v- w1 p! u3 h! z( e3 ~
    VARTYPE vt = VT_I4; /*数组元素的类型,long*/
, v* g% ~2 H! _+ f5 E9 {( ^    SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/0 K. ~; e+ |% Z' p2 s# s
    sabWrite[0].cElements = 10;
7 e+ v' c9 b. X7 D6 O    sabWrite[0].lLbound = 0;
6 M3 A& z$ g% _7 E) e! I    sabWrite[1].cElements = 10;& I: I4 M5 ^; B$ C0 q; i4 n2 m
    sabWrite[1].lLbound = 0;
% T6 i8 W8 ?8 E) B' D* d4 g, x. p+ }
    COleSafeArray olesaWrite;
! J3 |7 p: ]! q& [0 s    olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);
$ q  L) J: \. W6 Y' w4 _- U$ Y, C& [
% k3 _9 l8 M% Z  q  y3 K    /*通过指向数组的指针来对二维数组的元素进行间接赋值*/
' ~! u. x$ d4 y4 U: N4 [) l! m    long (*pArray)[2] = NULL;
& N) E6 ?- Y& v; Z: v9 @    olesaWrite.AccessData((void **)&pArray);
/ ]4 |. j' y5 Z6 C    memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));' u1 S# N) [5 c$ ^- m6 b3 t/ w- j

9 W4 w6 \5 g- y9 N% g6 i7 f) |    /*释放指向数组的指针*/
9 L+ C$ V8 {, g% s' O, J; c7 F    olesaWrite.UnaccessData();2 i$ w* o6 u. @6 j6 l+ `- I
    pArray = NULL;
9 t% a9 w! V) S8 N) P8 m+ G7 ]' y7 o* [3 L, ~& Z
    /*对二维数组的元素进行逐个赋值*/
, V' @1 U! `# h. i    long index[2] = {0, 0};* @( X, _3 z7 i  }4 X
    long lFirstLBound = 0;
3 g) n5 E/ u* b, `, w- H# g- o1 t: ]/ M    long lFirstUBound = 0;
) q# o8 K" F' {3 b, Q    long lSecondLBound = 0;! _7 K8 ]7 J8 Y4 c$ Z
    long lSecondUBound = 0;3 _8 e7 U+ u9 D
    olesaWrite.GetLBound(1, &lFirstLBound);! [6 v" P3 P% K& l( {$ P
    olesaWrite.GetUBound(1, &lFirstUBound);
, m9 p* g5 H" E/ @% B3 d    olesaWrite.GetLBound(2, &lSecondLBound);
! p0 C/ i  m" O2 Q1 i3 s    olesaWrite.GetUBound(2, &lSecondUBound);
0 M/ M- t- T9 B! V! Q$ {    for (long i = lFirstLBound; i <= lFirstUBound; i++)
! e  V+ F: c3 X8 P. S    {
! u. V) N, u* o        index[0] = i;
. \7 j- b# a. g; x        for (long j = lSecondLBound; j <= lSecondUBound; j++)# V( m) l2 A! d1 ^' W
        {
4 H+ M% L: M6 R: B/ ^) R! Q# H            index[1] = j;$ m, i  H0 Y: s) n) ?# f
            long lElement = i * sabWrite[1].cElements + j;
3 q, P) S# u: }4 V/ E. O% h, Q            olesaWrite.PutElement(index, &lElement);
& G* x, q$ |; ]! r, \2 z        }
% i' L" s* L. m# t1 O- L' n    }
& }' e. T% f/ l5 _1 O" Z
) b4 u$ ?2 I- e2 ]4 a' G# h/ S3 v    /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/+ G$ A' n: W; g  G+ u% k6 B0 e
    VARIANT varWrite = (VARIANT)olesaWrite;
, `7 B7 z/ q4 c' ]* W- Y5 p    range.put_Value2(varWrite);
, Z, W' A4 `3 S6 P/ r9 S3 M
8 l7 Z6 O- O  _- w6 n    system("pause");- k; n8 d+ ^# R  g/ K2 ?2 ~% p
/ l5 G: b% o8 L  K" {& u0 {' |/ _" f+ L
    /*根据文件的后缀名选择保存文件的格式*/
* a6 E( O( L4 n4 a     CString strSaveAsName = _T("C:\\new.xlsx");
5 m6 p8 a, L& k0 ]/ u7 q    CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));
+ s1 B) @  C8 `% ~& e4 e    XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;& W3 R9 T/ Q  M: O) E6 m
    if (0 == strSuffix.CompareNoCase(_T(".xls")))! n5 D3 ?( c, }" X4 Y8 X
    {
! x, m  F7 n0 @        NewFileFormat = xlExcel8;
7 b' q# Q/ k7 [5 \1 v1 _. o; ^    }
# K& M/ f; T  C/ ^# k. p$ _    book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing,
2 @" @1 F+ |, q. f  j        vtMissing, 0, vtMissing, vtMissing, vtMissing, , N/ Y& T3 ]8 _7 S
        vtMissing, vtMissing);& h! q0 k- j$ C4 `5 ~
# M# ~; ?+ r* r7 `. h; t* K
    system("pause");
: H0 _# l) h7 ~% o+ {
3 |5 a; d* ^$ _    /*读取Excel表中的多个单元格的值,在listctrl中显示*/: e; a, [6 Q  r; }
    VARIANT varRead = range.get_Value2();
0 ]; A) ^* i# M# K& D% t1 r# t    COleSafeArray olesaRead(varRead);
6 s* g0 i9 N. d" f: _3 g: T" h8 f9 \3 f' n! N$ Q7 M9 T
    VARIANT varItem;; z! g; y/ s) l3 g2 u
    CString strItem;9 ]1 \& M# }/ H1 O% d0 P
    lFirstLBound = 0;
8 Q. Q1 m0 l# N& j    lFirstUBound = 0;
( f& w4 }  I& i9 t! {1 W5 W/ `/ |    lSecondLBound = 0;
$ a8 g) J7 m# R' S    lSecondUBound = 0;
) b+ d+ d' W9 Q" b' \# b. j8 E    olesaRead.GetLBound(1, &lFirstLBound);$ ~9 D; U) B: S, n% w, J! z( m
    olesaRead.GetUBound(1, &lFirstUBound);
6 U5 K4 w4 ?( l. ^; C7 Y5 M    olesaRead.GetLBound(2, &lSecondLBound);
/ Q, u4 j% J; \% g7 T4 l" a    olesaRead.GetUBound(2, &lSecondUBound);
- S+ i/ S, v- C9 {/ Y) p    memset(index, 0, 2 * sizeof(long));& _" ]$ _1 k  a) m9 ~, a
    m_ListCtrl.InsertColumn(0, _T(""), 0, 100);* D0 n  D2 B8 n0 }
    for (long j = lSecondLBound; j<= lSecondUBound; j++): L$ M" d; `5 D6 ~# M
    {
! |, @, h3 z: _        CString strColName = _T("");5 W( S) L+ r* b* {- P
        strColName.Format(_T("%d"), j);
7 w/ j5 x$ x% e) I( C6 O        m_ListCtrl.InsertColumn(j, strColName, 0, 100);
1 O+ X5 G( s' X% S    }
7 R$ |: L, G0 [. a    for (long i = lFirstLBound; i <= lFirstUBound; i++)
. a  Y9 {/ G' R0 A" O1 i% Y    {; W4 T+ T* l7 d9 ~( X1 k0 j! h( a
        CString strRowName = _T("");0 C" ~4 B  E# z* _$ z; g/ J
        strRowName.Format(_T("%d"), i);* N* ]' |0 }3 L
        m_ListCtrl.InsertItem(i-1, strRowName);: p5 B. E6 n2 |# l

/ y, O2 u" ~. ?! Y        index[0] = i;
. }* Z+ T+ t7 d: ]9 q        for (long j = lSecondLBound; j <= lSecondUBound; j++)
# x. B- f* a/ a/ e. {/ p; `( Z        {3 ]1 \$ j3 L7 e/ E: Y  v6 X. Y$ m
            index[1] = j;
2 o3 O% x2 d' x! O6 B+ L$ I1 M, C# G            olesaRead.GetElement(index, &varItem);- F4 ]" c9 m5 Y2 Z8 }/ F$ G

4 p  J1 B8 w2 W  N# B            switch (varItem.vt)/ d7 H4 Y6 A2 C
            {
6 s. E2 A3 V# O7 \2 N. H0 u            case VT_R8:7 m' W& D2 |- s2 y# \. C* \
                {
# J5 {- W+ O9 n- V0 e! L                    strItem.Format(_T("%d"), (int)varItem.dblVal);
  f* f) C0 x5 }& C7 R                }
3 g" r7 L2 Q- t1 K  H, w8 j! x
# X% B" H" Z" y            case VT_BSTR:, g; j2 m3 i& r3 Y3 K' q
                {
' f1 Z# y0 A8 s& ?# A, k* k                    strItem = varItem.bstrVal;! V6 q4 k$ E( U. }+ n# L
                }5 W& w! }, _: o1 {
1 p0 Y" ?3 F# Q- }
            case VT_I4:, ~4 _$ ?% ?; K9 |+ t
                {
$ h2 \! Q' h7 M# ~) q                    strItem.Format(_T("%ld"), (int)varItem.lVal);  I# z) `3 C3 @! k* e& D0 t
                }3 {% V  B- J4 _6 J4 x% i8 P8 Q7 L  ~

& M2 D% N% g3 }( Z8 {1 T3 V            default:1 n; v6 e  E- K$ X7 O' [
                {
" t9 R" v7 k% `( L/ C$ R5 K8 F9 t5 P/ K
                }
' ~& r* w3 M8 O            }
- a' m! X) K8 o, H7 q- ?/ _8 a
$ ~6 {/ B9 _, M+ A7 |- ^1 `+ m  R            m_ListCtrl.SetItemText(i-1, j, strItem);
, W3 S- m9 M% W        }6 I3 o$ ^4 j+ T8 v5 m  _8 g
    }: v5 x3 a: F# C
' I  E5 f$ y2 O5 @
) U$ C5 l0 |8 G

& s3 V+ Q( ?' G9 \& h    /*释放资源*/
' d" V4 c6 y4 U  \$ Y. r4 A    sheet.ReleaseDispatch();9 l( q: ^2 n& k# V: N% [
    sheets.ReleaseDispatch();
1 |' A! B+ J$ i! Y& D- Z( x    book.ReleaseDispatch();
9 H" j$ l1 F1 d* g    books.ReleaseDispatch();; h+ m6 Y4 h+ b" y" i) _  @
    ExcelApp.Quit();. z) K2 o% L4 m0 ?0 ~# n3 S
    ExcelApp.ReleaseDispatch();" @* ~6 f, C2 ]! d2 |
- V' O: q3 S) k8 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二次开发专题模块培训报名开始啦

    我知道了