|
|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
C# 或 c++ 不用安装操作 EXCEL的方法:c++ 对excel 的操作 非常不理想 要安装excel 而且读写速度也慢" p F: ^; h( p: I
net 有很多 免费的开源库 比如 Npoi库 (Npoi库 支持c#、vb.net 等语言)
" U% r: h' v; a" {+ t6 r7 p+ H这里我用c# 生成 com 组件 让 c++ 调
9 t& r# K! w& f' t9 s) \4 x3 @' d8 ?) A/ B% }
首先要学会 c++ 调 c# com组件的方法 (和com注册的方法): W b' T7 I5 a$ t2 d8 K& I, O
C++调用C#的COM组件(DLL)1 \$ z7 ^- y7 U% v& S$ ^& K% k
- A/ z3 x5 K9 V4 l& l/ u下面我举个简单的小例子.我用的是Microsoft Visual Studio 2012,操作系统是Win 7.6 x1 X: K0 F. X' y. B
首先创建一个C# com组件.实现的功能很简单,就是返回两数相加的和.
* l- i8 F h& \. |. |4 i' y
) ~3 J: V# H7 u s! @, V- E: {3 R6 w' ~3 V8 u9 {8 J
1.新建一个C#项目 ,类型就选 类库 .取名 MEI_AddCom) O7 x. d# R0 R( F# ^
+ b& O2 l* a8 g2.在项目中添加一个接口,取名MEI_COM.C++调用com组件中所有的功能只能通过接口来调用,不能直接调用类或函数* |( ~" M& u; T1 c& i6 f' k( ?- g- [
. l5 X! @9 G: }- Y' G1 k具体代码:
# h5 K5 [0 U7 b/ u3 @1 H6 F# m1 d3 L2 Z7 |; Y0 }9 j
using System.Runtime.InteropServices; //记得加这个命名空间" s6 a |5 |$ @0 B4 E
. H: p G! [! t( J' F& U4 J. o1 ?
namespace MEI_AddCom
4 G3 A5 G# ^/ J B. E" L# N
1 l& [) [( [! C5 u: T+ \* V5 n{% S7 t. c' Y" F# N$ F
. R) p1 z+ y7 i; H0 E) {# O8 y
[Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的产生可以通过vs自带的工具.点菜单栏上的Tools ->Create GUID,然后选第4个选项.Registry Format.
' f% K0 m5 v9 U( Q' Z5 N7 V4 s/ \ G2 I
//点按钮New GUID,再点Copy.这样你就可以把产生的guid复制下来,然后粘贴到这个地方来.当然那个大括号得去掉.后面需要用到guid的地方也用这方式产生6 L- q: g0 M/ ? H6 |6 }; `
0 k$ f% p1 P% d! A [ComVisible(true)]
4 E8 x' n S. X- R
0 R$ {( l6 l3 m/ A9 r public interface MEI_COM //记得用修饰符public# {* ?1 O; e Y1 u7 M; Z
% I3 w1 W# ^* E2 f5 S% O
{1 e2 Z* Y j+ I1 K
$ J3 r# N% ]" @
[DispId(1)] //如果还要添加其他函数就继续来个[DispId(2)],[DispId(3)]加在函数前面6 ?2 r$ `- k7 @; d) E
- C! B1 a6 L( B1 l int Plus(int one, int two);
# k* H5 i! k/ v, F7 ?! y; B
1 a3 m* p/ F6 c% K }
$ Y( w* o! t+ r, _( @+ d& r4 j- O& I' U+ x
}9 }9 Q3 K9 G4 h. L, F7 O; ?6 N9 c
1 ]5 C1 q$ u% y$ m, e$ {: A
8 m5 \4 N9 L' i/ {1 T8 U5 r
& B6 y5 |% l9 K* i3.添加一个类MEI_COM_T,继承接口MEI_COM,具体代码+ o; [; a' P- k( v' x; O2 \- i! w0 U
! a1 e! `% v% ? p+ l# s3 \9 \( J
using System.Runtime.InteropServices; A1 D3 Z7 A8 W6 `8 J
9 q- S: F9 I6 p6 d/ U0 u2 V8 Wnamespace MEI_AddCom
+ Q8 m$ O; `0 g G, i% T2 K* W4 q. o
{) l" _* K" d p. j
7 T% z5 B6 p n P1 d
[Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]
+ t ^& V/ q k5 |. {& @! G! G- [ r4 M/ F1 k# ~
[ClassInterface(ClassInterfaceType.None)]
4 a1 v& {1 S/ b0 `( S
' v' p/ z' k( ^6 U public class MEI_COM_T : MEI_COM
2 E5 d/ ]! o( S5 I; a! _ Y' t! p& s4 n4 g. X7 v' k- _
{" r' A. p0 V# H% \
% U5 l6 D$ q- r; O: o+ J n
public int Plus(int a, int b)% j4 M$ k: V! x7 _
" {. D. J0 ]& b9 D {
- }8 G6 G' M+ } b. k
8 `' V# o" l3 W* u( D0 r3 g return a + b ;! X) R! }5 q3 C2 Z u+ ^ U, t2 q
6 f x! t9 r ?) t$ o }- _2 O; Q* I5 V* E
! k6 p6 a3 g% K, u% k }' j8 j9 c. [, d$ s
( F0 N" I4 O. b; g" ?/ U}3 j( \( [( t4 f
! C Y- p4 r6 ]! g( v- V3 ~/ s( g4 v: {, J* b
+ Y. Z9 R( A4 [% O& y4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)].3 l* M: M( k: k6 C6 M2 K' O% N/ m
9 k4 c, `5 {9 X右击项目名打开属性窗口,在生成里,选中 为COM 互操作注册
9 f+ x+ d/ R9 j* W1 \$ i8 O8 u* W% I, ~- K, V
# S& n1 J2 t; @ n. j+ U& k
5. 生成->生成解决方案
) l" `* ~* N% K 注意 这个时候 生成 非常缓慢
. X. t. e I8 c1 ?; l! d% p 直到 出现 成功 1 个,失败 0 个,为止才 操作一下面内容6 @! d* q- o4 V( i) u5 H7 U
( o, K. a- ~( I0 j
8 a! H, l8 [3 q$ j. {# u0 j1 c
---------------------------; H" x* U9 V' A% U0 ]' G
' y7 } T* r3 y! I
1.调用前要先把com组件注册才行.
" D* [: W5 ?- Q; |! c7 B# A1 w
) z4 h4 F( K2 B* }( t' e使用C#创建并注册COM组件 C#不能直接创建COM组件,因为其生成的DLL属于程序集,但可通过“使程序集COM可见”选项来支持COM。
5 v! V! j b% I5 | r9 k以下说明如何通过C# 注册、注销COM组件。
% c1 S7 ~5 |2 x. }" D+ T# x% @8 ^) Y6 B6 M
为了能让生成的DLL能够进行COM注册,需要进行强名称签名6 d8 T4 t$ H4 _3 M; L) J4 @
打开COMLib项目属性,选择签名,勾选为程序集签名,通过下拉列表选择新建,弹出创建强名称密钥窗口,输入名称,不勾选使用密码保护密钥文件。
$ t9 X; N/ f6 B: V: C创建完成后COMLib项目中将出现后缀为.snk的签名文件。
! x8 q% x: t6 U$ s( Q- P6 |$ F3 X J; x最后,编译COMLib项目,生成COMLib.dll文件,完成COM组件的制作。 注册COM组件: 如将COMLib.dll放置D盘根目录下,以管理员身份运行CMD,提示符切换至C:\Windows\Microsoft.NET\Framework\v2.0.50727,输入“RegAsm D:\ COMLib.dll /tlb: COMLib.tlb /codebase”,回车后得到如下图所示结果,表明注册成功。同时D盘根目录还会生成COMLib.tlb文件。8 J& }3 s' d7 K" p5 s+ ~
卸载COM组件:
, I5 H' y2 Y: w% ]与注册过程基本相同,只需将命令改为“RegAsm /u D:\ COMLib.dll /tlb: COMLib.tlb /codebase”。6 R0 }+ P% B3 r" U- l2 e/ h
$ t+ s; ~/ G1 t6 P
; I; r$ l5 _9 y& i5 i
2.注册完了就可以在代码中用了,先新建一个C++程序, 类型选 Win32 Console控制台应用程序
1 p4 F6 U' E& `9 z# T6 c8 E+ u$ M i8 e) b7 n7 y* _' n& u
名字取MEI_UseCsharpCom,点完成/ ?7 u, H4 N3 }8 T5 N M
( k9 b: W6 y7 i7 A/ f4 `4 |
把MEI_AddCom.tlb文件拷贝到项目的任何目录下.我就放在D:\MEI_UseCsharpCom\MEI_UseCsharpCom.
: U* e" {- }: v5 A5 o3 X- ]2 x" y3 j
2 N$ b. e( r/ w1 }- T8 u% ~我们会看到一个MEI_UseCsharpCom.cpp文件,双击打开把默认生成的代码全部删掉.敲入下面代码:" G K- ^) ]) J; q5 K, ^
. u! J2 s! W; Q& w4 ~
2 a: N- k N' u
#include "stdafx.h"- i. Y1 \8 G3 ~6 P5 n
#include <windows.h>
; L+ A, m" \0 v: v# _- s2 H& X#include <string.h> t2 d4 E! W, ?7 R+ e o ?) j4 a
0 a; T i5 x- X7 a4 ~' l- Z1 M#import "MEI_AddCom.tlb" named_guids raw_interfaces_only
1 }2 g& r' T! Z2 u2 D- i/ C) F1 p" ]5 j# I( e7 `8 j0 u+ h% u. ~
char* WcharToChar(const wchar_t* wp) //wchar_t转char*1 t- T& L9 d& Q; s! c; c' Q+ M8 I
{
* `6 [* s# s2 }4 l: M char *m_char;
+ h# L# H+ {9 }1 e int len= WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),NULL,0,NULL,NULL);
; T$ r+ C1 ?/ I q) T2 _ m_char=new char[len+1];
' {# k- r0 s! P: {9 m8 } WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),m_char,len,NULL,NULL);
4 x7 o" ^6 g9 s" ] m_char[len]='\0'; _- d( C& v4 D# S) z
return m_char; $ o t9 K9 ?& h
} ' D1 u8 X+ ^+ u' J; }4 a) z4 O
wchar_t* CharToWchar(const char* c) //char*转wchar_t
) c% W: s- B6 F{ 5 M, d7 B% \3 L" d+ [; u$ L9 T
wchar_t *m_wchar;
& @3 o* r( }0 y4 [/ m2 C) [) o int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0); ( j* m2 L# H9 j5 x
m_wchar=new wchar_t[len+1];
5 N; t7 o t' N& [- H MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len); - Z+ z+ J2 K( m+ ~2 k" L' ]
m_wchar[len]='\0'; 8 q$ B3 R1 Y( N8 W% f/ Q8 p
return m_wchar;
) L! X; p& j( v; X}
% S+ b% m4 x9 y# l
& ]5 z+ E' x: t1 q: ]$ [void _tmain(int argc, _TCHAR* argv[])
% ]! F8 _. Z; ~: d) w" q& j1 {$ A3 B" f' h+ B* N3 J
{, V1 g7 T I9 d0 P% Z0 Z; u9 L
' \% ]. x" B7 ]7 s: J CoInitialize(NULL);
' @5 [) M. ^3 C7 N" A% X- O1 T! W+ h
MEI_AddCom::MEI_COMPtr ptr; //类似明志一个指向接口的指针
* c+ `$ o) t2 Y+ C
! A: i" }8 C. B0 \8 r, @8 b ptr.CreateInstance(MEI_AddCom::CLSID_MEI_COM_T); //实例化一个类 CLSID_ 类名
4 l1 y( W0 B3 v- c0 {7 k3 ~
! T$ C% _9 T; i5 b9 K //这个地方有一点点奇怪我也还没弄懂.在C#中的函数是int Plus(int,int).但类型在这里都转成long了.另外就是我们不能直接
/ A' S( L) x6 n9 W0 N5 ?% h! M
* u+ p4 i, u0 r6 d //来个long a = ptr->Plus(1,2);这样得不到a = 3,反正会出错.
" ^4 Y- K* W3 {6 A) V //这里函数Plus的参数变成三个了long Plus(long,long,long *).其中最后一个指针得两数相加的结果
3 e3 O+ V- s# s1 o% x0 ^6 A) k! j3 z. b5 _4 x) d
long a = 1;
$ E5 X3 k5 l2 C; E% E% s% B, b1 R |0 P. y% Y
long * lPtr = &a;& p7 x% V) ?, j0 C0 E$ _, N1 u
5 F/ h% l: m5 X! n/ w ptr->Plus(1,2,lPtr);/ x* Z1 |) ~* Z4 k8 K. S
6 p2 _* U) B7 P9 }5 X! `
char msg[132]="";
0 h/ H6 u# J- x sprintf(msg, "%d",lPtr[0]);' P$ H% W" G: D3 I
- G: X- M+ T ~7 ^- @: `
LPCWSTR str=CharToWchar(msg);# W/ z; s7 P$ D# r: ]: Z
& o4 ^' e3 m% g# O' \" l, o! [
MessageBox(NULL,str,_T("123"),MB_ICONWARNING);- J" i, h% j1 r+ T' r4 V
' y0 {0 ]6 P& n* M0 n# P' V: b/ T# q$ h1 t
}; w e& S2 @, t+ z
" C+ B/ m6 o# Z( _4 b- Y
此时就可以正确运行了.得到结果3
# M' c5 g9 [; |/ R3 `. W- t
4 ^7 Y# A% D3 C# y+ {如果没有正常运行,则必须把dll文件拷贝到有MEI_UseCsharpCom.exe这个文件的目录下.
7 p+ d- c: u, m2 x( P
' G2 N+ e T4 A& `
2 D3 s. `2 _8 K( }--------------------------------------------------------------
) Q! }" d6 [ F# W [' b) uC# Npoi库 操作excel 的代码网上很多
- \4 z3 M1 ]) K) a9 R$ Y6 {1 T# |) n7 n: q
// ----------------------------------------------------------------------$ b* d) j0 {8 O8 f
// 使用Npoi创建一个简单的xls文件,写内容
~/ b$ }! j$ I, b, h z. ?' G# e
+ F& k* B, ~* t% g6 Jusing System;3 r3 ^ c$ O5 {6 m
using System.Collections.Generic;8 Z. V2 F% X. l1 B
using System.Linq;
, [8 A5 K+ T& H8 W$ Nusing System.Text;
3 \& z) w1 Y! k) W+ k/ u2 uusing NPOI.SS.UserModel;
5 V' N1 Z3 J/ K. pusing NPOI.XSSF.UserModel;
; |# G. t. M6 e0 T: Dusing NPOI.HSSF.UserModel;
' N" h; c; K/ n7 W iusing System.IO;
/ S2 `9 }! W B, c, P+ _5 J! [! [" @using System.Data;' I7 y% B( @7 `5 y- B# ^4 c
V$ [7 K) `: x" d1 u6 `2 h( w4 J
//using System.Windows.Forms; * R8 R* q5 Z8 `2 u8 v% `
% Q7 G( D, J! Z. w3 h) y! [namespace CC8 n# I2 @5 k- R! ?# h
{
! V$ o2 t1 H. l& G9 E, P: m
* f4 v. v; _# C |. N/ `1 C7 L9 }# k class Program
. D' m' i* s4 A/ Y9 H: c( H* r1 q {% Q( C& w2 l7 ~/ I
4 |; [% A6 b. [2 |
' T: @; _$ m6 e0 l1 x2 T( X# q6 w
static void Main(string[] args)
1 ^( [/ r; l0 k, g {
+ U6 `) c+ F) X; S //创建工作薄; o# y; H! _! I( r3 F. }6 Q
HSSFWorkbook wk = new HSSFWorkbook();
5 U$ k) h/ ]6 l4 A ?1 r% \1 s //创建一个名称为mySheet的表
. O' k6 F' ]) Z( u5 T ISheet tb = wk.CreateSheet("mySheet");
# R9 Y1 b" f% a( Y //创建一行,此行为第二行9 ?7 Q0 y4 o( M3 z% P% q
IRow row = tb.CreateRow(1);: |' ?: r% h% F6 \# {8 V6 N. m
for (int i = 0; i < 20; i++)+ d7 c7 U% S: J, Y: o- k+ y+ O
{
, T: T( A' o1 h" }1 K, }& V ICell cell = row.CreateCell(i); //在第二行中创建单元格! J6 t& L7 X2 a! [. `7 h
cell.SetCellValue(i);//循环往第二行的单元格中添加数据
# `8 P7 s' @, }& s }; D' n# I5 s% i* x. f' J- U8 {/ `1 u
using (FileStream fs = File.OpenWrite(@"c:/myxls.xls")) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!
( J' o6 ]; R, h# m0 M0 }3 m/ Q6 t {
' ]+ f8 R2 W9 i' z" B wk.Write(fs); //向打开的这个xls文件中写入mySheet表并保存。
5 v) l/ b6 ~# v9 S // MessageBox.Show("提示:创建成功!");
' [2 }, O4 d+ F4 f _$ Q }6 |* z2 N+ I$ R9 j
8 g" `7 Y, }: h: g5 {0 h }# k/ ?; z, m5 o6 e; P! x
& l0 r, K# W' o3 X6 J4 k
$ t8 m% I4 z" R+ c6 s2 N @5 F" i( v
}
& d5 p' G' h5 d- Z$ d8 Q# s6 L. w$ p
' ~4 H: D( T+ j4 J* p8 |3 `
3 {% m: s" M& r7 x}/ G( ?$ K# B0 o5 S9 t
7 O5 |; i V0 A7 d// ----------------------------------------------------------------------; q% h5 O% K T/ j& y
// 使用Npoi读一个简单的xls文件
. C' n* O( G* ]9 @- r* f" x: X7 j, l
using System;
0 B3 {( _8 o; @# C/ H% ]using System.Collections.Generic;* p1 ?# `, j! n! r& r
using System.Linq;( ~9 u4 f2 j, \2 s# @" V) G) i8 h
using System.Text;& [1 Q( h, l5 q7 b" S3 j6 C
using NPOI.SS.UserModel;
$ }4 W% A1 O) I. t1 P0 Jusing NPOI.XSSF.UserModel;
8 t/ p# Y6 p; }6 E. ]1 Q4 Busing NPOI.HSSF.UserModel;% ?# H, L" j0 `3 \, w9 @ x9 b* V
using System.IO;
9 F, k( i$ H' Rusing System.Data;. @$ f1 }; g/ m- ?7 H" ?; L1 H! _
. x" f& F& l9 Q$ [0 b8 r' {
namespace CC, u5 F' a) U- t/ C+ x/ n# T
{0 P1 J( A6 K- ^2 H! q7 d+ u, P
& O( v& I; n! h, N" m" w; H+ i class Program
% b/ ]' C+ g! [7 d {, c Y/ L% K7 q
% C3 |, c6 E1 {* Q1 X/ a- s3 K
% [4 U: Y4 t0 z, e9 {: v static void Main(string[] args)
7 m' l$ K8 Y5 r8 l; ]9 K% m/ H6 k* q {
. ^3 L1 `! g( f7 H8 h7 s7 e StringBuilder sbr = new StringBuilder();
7 t; v* j) q, n) X- a using (FileStream fs = File.OpenRead(@"c:/myxls.xls")) //打开myxls.xls文件1 C, H2 y2 [! `/ @! D, B3 G
{6 [& h6 h/ {0 E
HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的数据写入wk中, s) p. u! A, N4 K
for (int i = 0; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数
0 Y* ]( H( N& f- [% W! H {0 ~9 `5 D8 w* a6 j6 e6 F3 ~
ISheet sheet = wk.GetSheetAt(i); //读取当前表数据
5 d5 E* g* R. I: i for (int j = 0; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数4 `! p$ k# b6 P
{2 M- _' [9 \- l- z3 v, U
IRow row = sheet.GetRow(j); //读取当前行数据
* E7 g! P) u. \" L1 ^# ^ if (row != null)
- ?5 Z' }+ ^' X& M3 X4 k' K" n* Z3 P {4 c' H% g* p3 V8 H7 U: Y
sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限" e# x0 U0 ^+ _5 i8 X# V
for (int k = 0; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数
* H5 k# ]$ ~: Q$ K h0 f: y {* V- @3 g; I+ ?" M" N5 j+ K6 Q0 Y
ICell cell = row.GetCell(k); //当前表格/ a! w( V3 [8 T t* ?! `
if (cell != null)
/ }7 h3 |7 s4 b {- W6 \* f- n- c/ C& w- n
sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型$ ~+ o. j$ U- m% x3 M
}' }7 o( J" K' f2 @ { I$ n2 V
}
5 N& }) k/ B; ]0 Q }* J9 J1 L, d' T
}
0 y3 t% s! }5 G' y o7 O% y }
8 m' s: _! {0 {7 y }% Z O( h% n% I
sbr.ToString();1 F/ ]! p. x4 d8 u5 F- C
using (StreamWriter wr = new StreamWriter(new FileStream(@"c:/myText.txt", FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中
5 B# I2 V* {" X6 v+ U {. e; ^9 v2 X# J/ G! S1 J
wr.Write(sbr.ToString());
3 o2 ^: o' T# e wr.Flush();) g* t# Q3 X( C7 Q/ u$ T7 L
}
- b" C% j6 P' B4 F8 L- h8 c
$ ~, _6 ]2 t' g5 r# _4 P# r8 L& C8 f! P
}5 f: ]" T# W- _/ Y1 n
" X T& J( U2 J8 o! Z! G
2 n. y+ e1 H3 x: B7 }
}' k1 }( W+ t! u' I7 M& M
; O) N$ _: E% K' d
; ^% }( v, H+ V/ T3 c1 l" v3 r% L, Y' W% h& e
}
+ t4 g4 l! R9 r) d4 o6 {" F* \1 u5 k+ ?+ k! j" P
/ z; l) o% v3 Z- X5 j
然后 自己封装 给 c++用8 D8 D; P" q$ v
$ i8 O( n0 D( R/ g: Y( Z& E
! A& m6 Q' H9 ~# @
2 A% F5 n0 M+ w7 T) c$ k% @1 M# u7 [+ T
$ L8 z6 V) P7 p l
4 }& V z( s( k# ~" x; T) ?9 \9 n. e8 V
8 w. f$ c0 d$ ^4 a1 t0 \0 h b. D/ K8 t- m/ @- G* E
3 u8 t! S0 d% t& S- t5 J
0 x' V- _/ q4 M- Z
. y. i* r N& r* A2 K: U
) D0 ^; j" F. T" e% K
# V7 m* N9 z# B6 `/ }+ |& V" l! V* @) D# Q2 y l) c g" R
8 L5 F$ ?! _4 Y' k6 y6 P
7 J0 U2 Z5 C! r! A$ t1 G2 ?! P# C; n: _( [
0 u' F) z( b6 o: }2 c) B" f
8 A2 ]* G A/ l& B$ j5 d1 N
! y, |7 i/ g0 a3 f$ q
7 d$ l5 M1 b* H8 | u8 E
' Z/ {/ y, L" d* ]; v1 i |
|