PLM之家PLMHome-工业软件与AI结合践行者

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

[复制链接]

2014-11-8 08:13:41 6746 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表格的操作。' R1 ^" I2 `3 }0 ?& X
  5 d0 ~" }8 O9 n' A4 Q
本文源码的应用环境说明:
, N: ~9 {- J( hWindows XP SP39 N3 \( E. k7 g' U, ~1 ~" P
Microsoft Visual Studio 2010/ V/ G" R2 c+ r- R- L
Microsoft Office Excel 2007
+ V( t- b5 k; a) a  8 {( J% j! _- D) }. w
1、添加OLE/COM支持。8 ]. S5 M( r0 o7 Y
首先,应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。6 {7 ~. h3 h$ R0 [
本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。
6 Y/ Q; T4 _: U& d通过查看源代码,可以知道在stdafx.h的头文件中,添加了OLE/COM很多类所需添加的头文件。
6 x7 L# G6 x) O3 M% u, E#include <afxdisp.h>        // MFC 自动化类' n! {# n0 P+ u+ ~
同时,在应用程序类的InitInstance函数中,添加了OLE/COM的初始化代码,如下所示:$ E+ [1 y# L: `+ e0 |+ A
// 初始化 OLE 库
0 p7 M9 O" h7 {7 x& m' sif (!AfxOleInit())% ?$ \' ?/ T  T3 d: g$ G9 `
{: f4 T2 I2 _4 l+ C. u
AfxMessageBox(IDP_OLE_INIT_FAILED);
: `4 X8 H# X4 w0 a( q/ ?+ ~7 {return FALSE;( v9 ]' a4 d. Y  K
}' W9 F5 U4 s  T
  3 D4 o( d  n* f/ R; t
2、导入并封装Excel中的接口
) i9 q4 C& a0 L; D1 \. dExcel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。3 {2 M$ H5 H8 m+ z$ b5 S( h
由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。
* R* v: @$ O( y* E! @VS2010导入OLE/COM组件的接口的步骤为:Project->Class Wizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择! Z7 z+ P; s+ @8 z1 [: h
要导入的Excel类型库中的接口。
2 X% y( D# ^: B/ p% n在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。
  h/ a6 W% z% f( h; Q  
) M8 Q+ \3 ?) P& F6 {- e本文所导入的接口对应的类和头文件的说明如下所示:
8 {$ \7 M8 S0 @4 X; D# z% C$ P  - [% _3 c4 e* b; \6 X/ Y) L. c- a
Excel接口
; |) K: f+ n, Q" G0 N- j导入类; [, I7 C/ O4 x9 P5 @
头文件
3 p9 s0 s8 b6 Y# g7 a3 V说明  I4 @+ Z' d+ G) E( Z/ N0 U
_Application# D& f) {0 \3 d1 w9 _$ V
CApplicaton
2 S$ o6 z- X% @* x% _! vApplication.h- I5 b* G1 b1 C9 l
Excel应用程序。1 I2 f( V8 w* }, }& V7 L
Workbooks
) F& Z5 [9 u: v. P$ S, ICWorkbooks" \; V) \$ C6 {
Workbooks.h
$ j1 ]+ h9 i& M' Y6 d5 Y2 k工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。" a0 v/ C6 G8 P) I. }7 z7 e* o9 h& M; _
_Workbook
8 i4 Z7 H: k# _& xCWorkbook
! O# J" Z7 ~6 j6 a8 J" H! y, oWorkbook.h3 k  g3 z- P$ @- a* v
单个工作簿。( s1 L- u: Y$ ?9 f
Worksheets
" S* M# S: j$ g" x/ ECWorksheets7 m+ O$ T6 a) q9 \3 R2 n
Worksheets.h5 x( D; B2 e/ x8 M
单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。
7 z  ~) p8 Z4 L_Worksheet; U! F& ~" s' {1 Z; C: o9 P
CWorksheet! G+ _. T+ n' ~3 [( S7 c2 r, U
Worksheet.h
! n. {% ?0 i  _/ W6 C% Z单个Sheet表格。3 E; h' ?# i" ?9 R0 U0 H  V% K
Range
: ]  B4 a: s% q6 k/ w$ ?CRange
. B0 b! D6 ^- ?+ ]- J1 }0 e6 GRange.h
, Y3 d6 c7 L4 Y一定数量的单元格,可对单元格进行单个或多个单元格进行操作。  ^8 c" [/ S; o: I3 J
  
$ [* I. x" ^9 t* q0 T: G) V3、导入Excel的整个类型库
- _' N5 n" _  W8 p接口对应类只是对接口的属性和方法进行了封装,而Excel中的数据类型,如枚举类型却并为并不能使用,因此,为了更方便的操作Excel,还需要导入Excel的数据类型。
: I. c% P; l6 G# e2 t通过查看导入接口对应的头文件可以发现,在所有导入接口的头文件中,都会有这么行:$ D( ^' X! P6 X- i, n
#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
; I1 ?" I( s& B) b- J这行代码的作用是导入Excel整个类型库到工程中。1 d' M( ?( H: X0 W0 m
由VS2010自动产生的导入代码存在以下几个问题:7 J2 A8 M$ T: `/ o5 @  A
(1)如果导入了多个接口,每个头文件都会把类型库导入一次,如果引用多个头文件,会导致类型库重复导入。
3 w1 e/ Q$ N4 a- l7 Z; I(2)Excel类型库中有些类型会跟MFC类库的某些类型冲突。
& _# B. X* r  Q& k(3)Excel类型库的某些类型跟其他Office和VB的某些库相关,如果不导入相关库,将导致这些类型无法使用。。7 b' f! T* c+ c5 x7 c- T" q! Q
以上三点问题的解决方法如下:
& E: W; f# m! ]2 ^! z(1)仅在_Application接口对应头文件中导入Excel类型库。9 {5 v! x4 _6 f- S
(2)对冲突的类型进行重命名。
0 Q- B: ]0 f. }, f, u(3)在导入Excel类型库之前,先导入Office和VB的相关库。
9 t4 C) G* D; h( f更改后的导入类型库的代码如下:
% x, X" o( D2 `: }  6 j3 A; x& l2 l
/*导入Office的类型库*/
4 B. _# e6 `) x3 x$ J, y& i: z: V#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \1 @! D$ E- k6 I  M  o. h% m
rename("RGB", "MSORGB") \
3 R% B$ ^. `8 ]$ [- H" m! k- vrename("DocumentProperties", "MSODocumentProperties"): ^7 b1 J; U; l5 |. J
using namespace Office;1 S0 W( b$ A4 ?2 B" `6 h+ x1 R. W9 P
  9 P+ R( G& e, ?3 F, I/ l  k1 i
/*导入VB的类型库*/
) y0 @8 v) {+ d8 H#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
) ]1 ~  z* w& G7 b6 qusing namespace VBIDE;7 H2 X* t2 e, }4 D7 l2 Q- a, J
  
1 Z. o/ o( N. u3 ]3 S7 K/*导入Excel的类型库*/
* {% x0 Y8 T7 ?& P2 C7 I8 y! V- j#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \8 `+ H: K# T, z
rename("DialogBox", "ExcelDialogBox") \" |, T+ i" _1 }8 ~3 N' c2 F
rename("RGB", "ExcelRGB") \. ~! {: K; Q& M. z
rename("CopyFile", "ExcelCopyFile") \4 h" U8 L/ Z* d- X
rename("ReplaceText", "ExcelReplaceText") \
. G: T) L+ v# a/ t* V% Uno_auto_exclude
5 R+ F, R: p* K, N; |1 U; qUsing namespace Excel;2 ~: K1 C! u' U
  
# u: S  f. W  y8 I; i编译程序后,会在DebUG或Release目录下生成三个文件mso.tlh、vbe6ext.tlh和excel.tlh。通过打开文件可知,该三个文件的命名空间分别是Office、VBIDE和Excel。导入了Excel的整个类型库后,就可以使用Excel中的所有类型了。4 h7 @" M5 @& `1 j6 ~
  8 T. u% d- v, O
4、操作Excel步骤/ Z9 `) d) k" l- E, r" ]" o) K
操作Excel的主要步骤如下:
0 z/ y% b5 J" _" F(1)创建一个Excel应用程序。
( w) `6 A+ X8 V0 f(2)得到Workbook的容器。
6 Z/ ?9 z4 u" @# O% ]' e(3)打开一个Workbook或者创建一个Workbook。
8 O/ F- q) z8 _8 C5 f3 B5 c(4)得到Workbook中的Worksheet的容器。4 q( K! N; |" A& }
(5)打开一个Worksheet或者创建一个WorkSheet。% d1 c3 q+ O6 }- J9 Y" X4 g  B
(6)通过Range对WorkSheet中的单元格进行读写操作。8 o3 C3 g1 [8 l& p
(7)保存Excel。
/ B% T3 X) u$ Q8 X; G(8)释放资源。7 I% y- Z5 C* o& K- X5 d) a; R6 W$ y' h
  1 a& m  a5 |) t! f$ ~6 j# ]) o' f- e! @+ B
5、批量处理Excel表格
- s; K  t) N# oVC通过OLE/COM操作Excel,是通过进程间的组件技术。因此,每次读写Excel中的单元格时,都要进行进程间的切换。当数据量大,如果一个单元格一个单元格的读取,主要的时间都花费在进程切换中。因此读取多个单元格,将可有效的提高程序的运行效率。3 ^3 O- E5 z9 c; l/ f
对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。
. ^- q7 Z4 H3 j/ ~8 JVARIANT get_Value2();! Z% E7 y/ j8 d. u% G
void put_Value2(VARIANT& newValue);$ R0 `# w' f3 r
其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。
  a; q; f3 D1 H+ F& i2 G  y9 Y3 g其中,VARIANT中实现二维数据的方法可参考
8 _5 K; k9 \3 B  Hhttp://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html
" ^4 d1 f+ N& [# K: k2 Q0 Y/ E' m当然,在对CRange类进行操作之前,要设置CRange类对应的单元格。
  }! b0 l9 G" R2 h  
7 C- k6 N. f  B& e/ [: G6、Excel表格的保存
% k( x; `6 y0 Z, F(1)如果要保存打开的工作簿,使用CWorkbook类的Save函数就可以保存工作簿,原文件将被覆盖。8 z( `$ E3 |* V; a. V, o% s. B0 |
(2)如果是新创建的工作簿,或者是要另存为,可使用CWorkbook类的SaveAs函数。
5 ^  J4 n$ w- Q1 b$ \) N$ ~SaveAs的参数比较多。其中,第1个参数是设置要保存文件的路径;第2个参数是设置文件的格式,可在MSDN中查看枚举类型XlFileFormat来了解Excel的文件格式。经过测试,在本文所用的测试环境中,Excel2003的文件格式是xlExcel8,Excel2007的文件格式是xlExcel4。# w' H& c  |( A! H+ t% P% e
  ( D; ?! z. c) A# q9 K# L
7、获取当前Excel的版本
5 Y7 _) z' P: a( v6 g可以通过CApplication的get_Version函数来获得Excel的版本,其中,Excel2007的主版本号是12,Excel2003的主版本号是11。7 S/ n! u' ^( _  j" k2 {2 h0 ?
  
% M4 E' _8 O: E  |& N8、示例源代码& o3 a! F9 K0 C% J6 T* V4 a
主要代码如下:
8 R6 m; Z) o( X; u5 Y  % V, A  P$ F4 T7 q
) H, C3 m* ]* @9 W2 t- l2 k

; z' _, P4 w. B* E    m_LisTCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);/ C, G/ u" c2 ?5 G, g
4 A1 }- n+ C% a( y' S' o4 p
    CApplication ExcelApp;7 {  g6 F. i7 G* R+ o( h
    CWorkbooks books;
% w/ t9 J8 U6 p  |2 p3 c    CWorkbook book;0 p  t4 f/ `) ~7 v
    CWorksheets sheets;+ j8 B9 r7 M3 Y7 \
    CWorksheet sheet;+ n. y: o! W4 W( i
    CRange range;
0 T9 E0 ?5 Y9 N& b/ c; o2 u# I, j    LPDISPATCH lpDisp = NULL;
. ~  @# w" x0 E$ Z
6 Q3 ?7 ]2 b' ^/ U3 z    //创建Excel 服务器(启动Excel)5 k, B. ~$ l" ]8 N; f$ t+ W
    if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))' U. f1 d+ P4 z: v& a2 M
    {7 Y5 g% T# I! t8 d4 T3 v- q+ H8 m
        AfxMessageBox(_T("启动Excel服务器失败!"));
3 b" V& i# f1 H# T6 q        return -1;
. @. r# K2 F. |; z7 J  C    }
' k2 t( h: B' U; \! C# G3 @) H
# |4 N5 C. I* O9 h: x" B% D    /*判断当前Excel的版本*/
3 z8 R9 p5 o. u    CString strExcelVersion = ExcelApp.get_Version();: A2 }+ g6 b/ G) X0 N# A' Z* |( G
    int iStart = 0;
# a/ g- D& M4 C5 U8 J' r    strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);
& Z, f3 @7 q5 N/ {    if (_T("11") == strExcelVersion)
& K+ I+ O  [4 R. x& D- Z    {  X7 Q# t2 ?% t( k
        AfxMessageBox(_T("当前Excel的版本是2003。"));9 c3 I- {) J! l
    }9 `  B4 n" V  L: a
    else if (_T("12") == strExcelVersion)9 v9 y3 K3 \+ F6 a# Q- d! A. _
    {
  c4 a& I4 k6 ?/ e: }" z        AfxMessageBox(_T("当前Excel的版本是2007。"));
! Z. C3 q% r6 i    }
+ `7 D- G* k1 E    else5 D1 H2 E8 R1 s- q
    {
. t& t! J% H( ~  H8 H' m. v        AfxMessageBox(_T("当前Excel的版本是其他版本。"));
. U' H  m+ g! ?; T7 ]    }
7 X4 X) h9 S- Y% b4 p: h. r7 q
( l/ v& P/ v- ]) j" Z) h* b5 h- |    ExcelApp.put_Visible(TRUE);8 s! p. ?, I) [  m1 P  ~0 p, v3 C  E
    ExcelApp.put_UserControl(FALSE);5 h# R) E. y& \: T1 J4 _$ N
0 B. i3 P! z5 Y! `8 y( U' |
    /*得到工作簿容器*/9 }/ z  G/ M7 f0 ^0 ]
    books.AttachDispatch(ExcelApp.get_Workbooks());
* r2 Q) o- p. |' m9 j! c
+ C5 ^5 E& m: D* c- q    /*打开一个工作簿,如不存在,则新增一个工作簿*/, k1 K  ~+ Y, P/ @5 F; j) A( w* Z) u
    CString strBookPath = _T("C:\\tmp.xls");
9 J( K( a' \! {5 O8 i2 ?    try
# l) d8 L# l4 c* k3 R    {8 w& A# g6 ]. h
        /*打开一个工作簿*/& ^9 A0 h4 P7 Z9 L+ k, w; K
        lpDisp = books.Open(strBookPath,
  ?0 S/ `5 \, B8 `9 X9 t" ^8 R            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
6 [# B9 [3 W5 }% Y  ^            vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, ) I7 B5 l! K9 e" p/ N8 a6 P2 j
            vtMissing, vtMissing, vtMissing, vtMissing);
- j2 \( d! N! a4 d1 r; i! j6 L        book.AttachDispatch(lpDisp);
6 O* Y* q  `9 u% w, b* z$ A    }
- u6 g. _9 |% J* s9 N1 k) h    catch(...)2 e$ f7 E& X% O8 t+ |# p0 y
    {
* I; H1 J, S7 t' _! E2 t        /*增加一个新的工作簿*/, z' o  M: x# Z- h+ h
        lpDisp = books.Add(vtMissing);9 m0 N* _4 f* M  X9 |2 C0 }
        book.AttachDispatch(lpDisp);
$ M/ Z) P% F1 r& ]% f9 O    }; O. Z# [' s8 z% ~( m
     
  ~' ?, d' t1 E. L1 ^
3 x) @8 L2 b2 Y: Y7 J    /*得到工作簿中的Sheet的容器*/1 @/ q; C. V* Y6 r7 O9 ^
    sheets.AttachDispatch(book.get_Sheets());( }  N* n9 a. T2 Q

  n; k: N: _& x+ q* l    /*打开一个Sheet,如不存在,就新增一个Sheet*/
  a; S) c/ P3 b# N: t    CString strSheetName = _T("NewSheet");" W4 T) I, U. u6 \
    try$ Z' I( ~2 c3 K1 c* x
    {# |* z  s% Y# @) Q% Z
        /*打开一个已有的Sheet*/
7 B+ @5 ^' S& U9 O' u* y% c* q        lpDisp = sheets.get_Item(_variant_t(strSheetName));  `' P% Q; b! c- s) |/ y: F
        sheet.AttachDispatch(lpDisp);
$ d4 X) V. U8 [    }; y1 I3 m. p! D; b
    catch(...)$ ^- P3 W. M+ w) s- E) w' t2 c6 L
    {
) i1 V+ Z. e, o( t        /*创建一个新的Sheet*/
% ]5 ]5 t, G: L* P5 \* u        lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);9 L5 x! y: a: }( E
        sheet.AttachDispatch(lpDisp);* m! N% {( S" ~3 P2 g" K, L9 t5 D
        sheet.put_Name(strSheetName);
1 V' e/ ~2 o8 E( V    }4 `5 M% G9 F+ e$ V/ d! E- P' `( Z( |

) Y. n" |/ \, w2 Z4 J# K    system("pause");
( U8 a, o! u, w7 K3 A) [% z0 I, A: z" a% `2 c
    /*向Sheet中写入多个单元格,规模为10*10 */
5 _2 o2 @8 K: l8 W$ v    lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));+ C/ {: a# T! P& c+ t( C
    range.AttachDispatch(lpDisp);9 \4 D" u# E! T& Q
$ M* y) `  w, H/ H; N( [& y
    VARTYPE vt = VT_I4; /*数组元素的类型,long*/
) \# I' ]" y* ?$ b9 K- a! T    SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/
, k0 H! {: I6 B    sabWrite[0].cElements = 10;2 o9 ~/ d- u! ^1 ^
    sabWrite[0].lLbound = 0;
) M+ |. @. Y* c' g& O    sabWrite[1].cElements = 10;! J0 |2 ?5 @' S; M, I
    sabWrite[1].lLbound = 0;
5 T4 h1 ]1 d+ X9 H6 L% w2 D. h6 H! F6 V" c8 w( U$ y1 p
    COleSafeArray olesaWrite;/ k4 p$ T0 H5 x* b7 z  t" v5 S5 k
    olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);9 q0 `6 \: H/ E
) [! K& ^- M. M+ Y* \" v5 q0 e
    /*通过指向数组的指针来对二维数组的元素进行间接赋值*/
  @- }% @6 s! y+ |7 ?    long (*pArray)[2] = NULL;
6 o6 y( \% z3 O! Y9 G$ u    olesaWrite.AccessData((void **)&pArray);) }0 j# K6 j# T2 ~3 {5 O9 [
    memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));
2 d1 Z& _2 t1 p; f/ E. s; j  @5 w4 F
    /*释放指向数组的指针*/
6 r! o3 E9 w) k+ J  h, `    olesaWrite.UnaccessData();$ `/ P* [: ~) t! J6 g
    pArray = NULL;
2 x0 Q- Q  N, u. K0 [1 B
7 J6 B: K' T% l' }! `7 D' k    /*对二维数组的元素进行逐个赋值*/; u+ |: q# P( u; M" x
    long index[2] = {0, 0};3 _  H/ V* B" L
    long lFirstLBound = 0;
" f* Q: j( {6 k* R% z# r9 s- t1 `    long lFirstUBound = 0;
5 Y( ?5 \' z9 s- y2 y    long lSecondLBound = 0;
& _: s! e* m1 G    long lSecondUBound = 0;
* R  X2 H: @# k    olesaWrite.GetLBound(1, &lFirstLBound);
/ ^' B; m# R$ h: o) c6 N& m$ _: |/ K    olesaWrite.GetUBound(1, &lFirstUBound);
% Z# A; P. {; I' ?3 T( C9 O    olesaWrite.GetLBound(2, &lSecondLBound);) r8 p8 H! e% R8 l' i( r  l. K, b
    olesaWrite.GetUBound(2, &lSecondUBound);# k* A# c/ ^. v  y
    for (long i = lFirstLBound; i <= lFirstUBound; i++): W5 R+ q$ `  N% j
    {* G4 c6 S* O% K2 P+ O$ N
        index[0] = i;
$ X4 ], k) b* G9 h4 p        for (long j = lSecondLBound; j <= lSecondUBound; j++)
. S- d% ]' s: ]% O& K        {
" v; T; K+ u& r! z. v6 C  i' S& @- n            index[1] = j;, _( S- z7 N! W1 ?0 c, C# i# ~) c
            long lElement = i * sabWrite[1].cElements + j;
( Z- _$ f( S, j3 G$ w' @5 S/ J            olesaWrite.PutElement(index, &lElement);, q4 R6 j: i) D" @  E
        }/ `. i( {- M/ n5 P% a9 M( W
    }
  p) e1 P8 Q9 @* N; t: a' i3 K# K  t  c6 b  ^
    /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/
$ e1 A! \" l8 S+ o3 E    VARIANT varWrite = (VARIANT)olesaWrite;2 Z) M1 v; {! w  C$ `- o6 z! y( h
    range.put_Value2(varWrite);, }  N2 n8 d7 P3 a

' }) u% u: z7 s! z. a    system("pause");: w" z! M* a4 @

# I5 X# b5 Y' y    /*根据文件的后缀名选择保存文件的格式*/
5 h! S8 C: G+ N: `* N     CString strSaveAsName = _T("C:\\new.xlsx");+ ]1 v6 y% A8 f0 \+ x
    CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T('.')));
, h9 `0 g% y) R, _( b4 o8 \& f$ [    XlFileFormat NewFileFormat = xlOpeNXMLWorkbook;* u' ^( S% q% `* b1 b
    if (0 == strSuffix.CompareNoCase(_T(".xls")))
* r$ O% p1 H) @9 H1 b" Z    {
" C9 c8 G) [: ~. y. ]4 h+ f1 [        NewFileFormat = xlExcel8;
/ }9 P0 _8 u0 j! ~3 R5 d3 l8 K    }
! Z8 Z8 U. B& }) @  ~    book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing,
& G, R0 l' v: @2 N        vtMissing, 0, vtMissing, vtMissing, vtMissing, 4 s( i- h* l4 O
        vtMissing, vtMissing);
  ]! ?: x- O9 _* [+ r# P& [$ P; O& n* \" c4 }
    system("pause");
8 Y* \/ d+ Q# c) \8 T' t' u# N! P: H6 U! M% y5 s3 a! e
    /*读取Excel表中的多个单元格的值,在listctrl中显示*/
' R9 H1 J/ X' a: u3 Z9 P+ g    VARIANT varRead = range.get_Value2();
+ G: `" ]4 X* p: d4 `    COleSafeArray olesaRead(varRead);
$ D& j$ q: i4 ?% t1 Z5 C! t1 H
# @. J# Q+ R. j4 n* u' i    VARIANT varItem;
% g  k+ `) t! s$ F+ N) |2 O) W( {    CString strItem;
$ ]. T3 _% d# P  n    lFirstLBound = 0;
! F) q4 V% u2 N( F4 }    lFirstUBound = 0;
$ c, X$ I- k, j6 ^    lSecondLBound = 0;
! d6 w# k6 a4 n  d5 Q$ p1 F    lSecondUBound = 0;
; V* F( _& d" o' P' t    olesaRead.GetLBound(1, &lFirstLBound);
! n1 |. N7 G- R3 F7 }    olesaRead.GetUBound(1, &lFirstUBound);) c$ g1 T% W+ S3 e- c4 Q
    olesaRead.GetLBound(2, &lSecondLBound);8 Z9 U1 E1 |2 ^" u+ {9 J8 H8 f
    olesaRead.GetUBound(2, &lSecondUBound);4 p( p  C0 N$ o
    memset(index, 0, 2 * sizeof(long));
) I0 [$ G6 X' N    m_ListCtrl.InsertColumn(0, _T(""), 0, 100);
  h& {7 I. v( `% J9 Q% H5 k: B    for (long j = lSecondLBound; j<= lSecondUBound; j++)
( w  V; [3 E1 L. Y  @* G2 [9 [    {* M- {3 p* g1 T6 U6 K
        CString strColName = _T("");
! ~) q- e" y. f% B" p$ Q        strColName.Format(_T("%d"), j);
- _. F  X8 l4 {# {. `6 g        m_ListCtrl.InsertColumn(j, strColName, 0, 100);
0 K( z. @6 Q! b% y6 g4 r! a( \    }
# I% s* U% M/ L* I, Y    for (long i = lFirstLBound; i <= lFirstUBound; i++)
$ b4 f4 I1 _8 d    {
; j" x  @: ~2 w2 f! S  r+ c  I        CString strRowName = _T("");# r5 q: a6 J1 ^; {9 G" ^* G6 K; B
        strRowName.Format(_T("%d"), i);
4 K  @8 A0 W- J# E        m_ListCtrl.InsertItem(i-1, strRowName);7 S' ~' Q- e. h$ m
/ b0 y  B) E1 U0 e; Y4 J
        index[0] = i;
4 b5 R# |& |9 n" ]% Y        for (long j = lSecondLBound; j <= lSecondUBound; j++)* f# b8 }4 D* \2 B0 Q
        {' q, Z' O: ^: `$ R' p7 p, \
            index[1] = j;6 }+ M) a/ ]" B! ^! I
            olesaRead.GetElement(index, &varItem);
, C, Y$ B4 [- o/ T& C3 m8 s8 n
+ a0 U* D& h2 G            switch (varItem.vt)% X, y2 I9 x, X, ~4 |9 M% s
            {& x6 L. v& A3 E. R+ o& J3 S
            case VT_R8:
$ G. q6 {$ ]( e8 c1 W                {
5 m* S/ L6 V  \& @* F6 P! {                    strItem.Format(_T("%d"), (int)varItem.dblVal);
  Q/ j4 H: l, ]- B: |                }
/ K) Z" M# f" O" E1 k9 I/ r$ X
9 o2 I0 h$ b* y- ]- P- X            case VT_BSTR:2 ~" `) F8 `& o5 Z
                {* e8 M( l' n" s1 \
                    strItem = varItem.bstrVal;
. U1 V; Z: Z& C, s# G" H                }/ w) [) I% e8 p9 i* U9 E" I
" {% B/ h/ R, y; t
            case VT_I4:6 D2 v0 @) M  d: M
                {! z  V! B, t) U% i& K0 Q
                    strItem.Format(_T("%ld"), (int)varItem.lVal);$ G! c& u. Y& S: a% r$ K' i
                }
5 y( ?: P3 ]& S. ~$ q% W3 {: e8 R$ ?  Q; n
            default:$ g" W! c; u! `( W! V, q3 w
                {. h, S% w  u- ~- [
- I$ @, @0 S" \) t0 T* S& d2 E
                }7 m: w: [: m" i9 {9 S) f
            }
$ Z- M' s3 t1 U* T* L" t/ _7 V
            m_ListCtrl.SetItemText(i-1, j, strItem);) Q7 ^; V8 t  x: ~7 G
        }) u: t' A! I* O
    }9 A: ~7 @$ P* A$ ^) \- R- x
3 k( K; z3 x& _  `

6 t/ F8 x2 g. p) {9 N- L/ K' t* n; ~: C1 Y% v! {! [$ F
    /*释放资源*/; ^3 D- A! G' U: S
    sheet.ReleaseDispatch();7 ]- {' m2 M- w5 w
    sheets.ReleaseDispatch();
* u- N- o! g1 q/ u) x8 D- F    book.ReleaseDispatch();6 B, ]: i  J) u3 f, r
    books.ReleaseDispatch();
8 h) ]5 E) M$ B! _3 t( A3 A+ N2 q8 \    ExcelApp.Quit();
- ^  b0 V/ K; S" y4 J3 \) _    ExcelApp.ReleaseDispatch();
" @  b. x; [1 y) P
5 y2 d: J! O# i1 v2 K! e
上海点团信息科技有限公司,承接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二次开发专题模块培训报名开始啦

    我知道了