|
|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
C# 或 c++ 不用安装操作 EXCEL的方法:c++ 对excel 的操作 非常不理想 要安装excel 而且读写速度也慢. T) O8 ~/ z( H$ v! ?2 i1 P3 ^
net 有很多 免费的开源库 比如 Npoi库 (Npoi库 支持c#、vb.net 等语言)
) U( u6 f, {5 c( I6 V这里我用c# 生成 com 组件 让 c++ 调
% x' h2 N7 b& Z4 x3 |6 v* A, {2 y3 M# L" [3 z& k
首先要学会 c++ 调 c# com组件的方法 (和com注册的方法)9 ^/ D# u. L$ O/ U( V$ c& ~
C++调用C#的COM组件(DLL)
& L+ ~5 B3 @( S* G; l, t
: X9 `+ F3 V3 T8 U5 b: g下面我举个简单的小例子.我用的是Microsoft Visual Studio 2012,操作系统是Win 7.0 O+ p5 y7 ~2 K. L5 r1 D
首先创建一个C# com组件.实现的功能很简单,就是返回两数相加的和.
9 d1 g2 T1 u- m* {; U- G' J" k) N) ~/ Z$ y/ s$ ]0 X
$ j5 |3 [1 K) V% x$ K1.新建一个C#项目 ,类型就选 类库 .取名 MEI_AddCom
! r9 w$ e6 u4 h1 C2 M6 n+ ?( G; E5 d: B! N& I3 T$ \
2.在项目中添加一个接口,取名MEI_COM.C++调用com组件中所有的功能只能通过接口来调用,不能直接调用类或函数
3 }1 n5 c' |( l% X5 }7 T: V w9 s) ^* F# U2 E- r7 E/ \- S: |* d
具体代码:
' k& O4 k" z$ i. m. m4 U+ Z
( E G1 _9 ]7 H" uusing System.Runtime.InteropServices; //记得加这个命名空间
) s2 k9 V( V, F4 H; J1 l
T8 h. Z' @7 z2 S9 P' D7 J& Onamespace MEI_AddCom
; p5 F' T$ z. S- B4 ^0 b2 \
5 W7 o$ A# d6 g4 L7 [ x{
8 y* t7 q/ {3 Z- H; @, `- e' }' u8 C7 V. \0 W( {" k4 o9 n1 b# U+ w* \2 S
[Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的产生可以通过vs自带的工具.点菜单栏上的Tools ->Create GUID,然后选第4个选项.Registry Format.
; o" Z$ `$ k; S9 m% ?
3 E+ J6 P, w9 `6 ^% A9 V3 s //点按钮New GUID,再点Copy.这样你就可以把产生的guid复制下来,然后粘贴到这个地方来.当然那个大括号得去掉.后面需要用到guid的地方也用这方式产生; E! z$ t4 @9 y6 t+ t; I
$ c/ l% K5 A" H& d/ g
[ComVisible(true)]
1 u2 ?, {* V+ Q4 y/ P) I& C. ?- y5 t( z4 ^- S5 v" ?
public interface MEI_COM //记得用修饰符public7 N6 f6 y* F$ D' S3 D
- B/ G( s; m8 y0 k- u$ D
{
2 K0 M2 K' J8 d) A; `1 S9 M1 F2 o* J- F) R- I$ d! R
[DispId(1)] //如果还要添加其他函数就继续来个[DispId(2)],[DispId(3)]加在函数前面2 ~& J& B& r8 X/ m, F/ a
2 L1 j# o$ d! e" C: W& @ int Plus(int one, int two);
6 i* V% W! k0 R% ?; T5 e! _3 H2 F
" p! b" Q9 v9 D% D( v7 m# Y }
/ _* h3 @8 M4 _; u* E% J2 f* y J1 Y2 d5 k; J$ d: [ [" T
}% Z( s+ l& M0 G8 [) |% W
2 |0 m! u* W% O( k" k) Q9 _
2 ^& s/ P2 `, R; _
3 l, f& ]( L; o& n. p. m3.添加一个类MEI_COM_T,继承接口MEI_COM,具体代码
4 h: L# A) o$ P+ W" [5 Y' N8 G* [/ K! C! H2 d S3 r" I% J5 f+ s/ M
using System.Runtime.InteropServices;
2 h; ~& x6 o6 \7 `% C: B: q* N% O
6 j8 R4 @ p, t) F& anamespace MEI_AddCom
$ }+ p2 e* [ E$ O+ Q0 ~% P
; \7 z+ {+ I+ q9 T8 K4 _2 M{3 v2 A0 \0 M7 u
" }& A1 l8 u G
[Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]
+ [4 a+ y+ V! r2 l) K- E5 d% }5 D2 J: o8 d7 k
[ClassInterface(ClassInterfaceType.None)]8 B. C4 w4 |2 R/ |8 l
3 ~5 a! a: _) G. S public class MEI_COM_T : MEI_COM
+ U- d/ l3 v% P$ @2 B* c6 K1 `9 O9 a. T$ u0 g
{0 o R ?- W) f9 `( F& T5 b
/ {1 u _" P7 v9 A3 U public int Plus(int a, int b) L6 \! ?% j! b: O! u
, ~! B1 u$ |+ J: G3 p2 b5 d3 U. b. o
{2 ]9 u6 I/ t8 W) K' A
4 ~! I: k3 B% B5 h* O2 f) a- l. ] return a + b ;
2 r' e9 l- b/ b' U Q. r
! C8 g& i: i4 I- ?: j }5 \5 p3 S, U4 F1 A
2 D& l6 T' d) @3 C: l5 i
}
! H! O3 H3 Z2 x( O y- D' T
V2 f5 s/ J7 D$ f$ N" t$ Y}1 U+ f5 H5 t( V* f
5 M; }6 k( b8 t) t r
+ I* S( G! K3 v; L, C1 N
+ H& m# ^4 }: c ~
4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)].( _ q2 K5 A( I+ u
! c* o) a" G; K+ a右击项目名打开属性窗口,在生成里,选中 为COM 互操作注册
- k% k4 L4 y4 w) Q& w0 Y8 G+ ~9 e% ^
5 T% N" C2 v0 v: h3 i4 e; a7 x, k- I- h% u
5. 生成->生成解决方案
; b- m( a0 B6 \3 c; T4 V0 b 注意 这个时候 生成 非常缓慢
) ^' n( E6 F. F6 Y, q" m3 U 直到 出现 成功 1 个,失败 0 个,为止才 操作一下面内容
8 g. O" Z$ C; q9 ?/ \, a4 n l) r3 _+ J2 T2 i
3 m, R8 M) H; C; G' @. H! v9 S---------------------------
: K7 b+ N) Y# D/ v3 Y+ @, ?) J( z4 z* c8 \% J: s0 D! I3 c& b
1.调用前要先把com组件注册才行.7 i# ?3 H- r T8 N6 ], v8 A3 L+ o2 M
0 k' H( j- _3 P5 k+ x& Y5 x9 G" r% ?使用C#创建并注册COM组件 C#不能直接创建COM组件,因为其生成的DLL属于程序集,但可通过“使程序集COM可见”选项来支持COM。
8 u6 A) k8 P) ^+ }以下说明如何通过C# 注册、注销COM组件。 8 X+ L+ J' U1 o! }# O
' P( R: {/ n& o1 C6 X: [9 p为了能让生成的DLL能够进行COM注册,需要进行强名称签名9 u) s0 _6 D; `* M' c& c7 h( O
打开COMLib项目属性,选择签名,勾选为程序集签名,通过下拉列表选择新建,弹出创建强名称密钥窗口,输入名称,不勾选使用密码保护密钥文件。
W7 R7 i# j4 n9 o" M$ f& [: e+ b创建完成后COMLib项目中将出现后缀为.snk的签名文件。
6 }, {( p1 ^' j2 g# ^最后,编译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文件。
# D l( q8 t: D( W; L! ^6 C卸载COM组件:
; j2 f N. k7 g1 h; f9 {7 N与注册过程基本相同,只需将命令改为“RegAsm /u D:\ COMLib.dll /tlb: COMLib.tlb /codebase”。
; x1 w c5 i# ?( |; V, v; f% w
' X' r3 p9 @+ f$ k: h8 N
, A0 {3 ]* ], k4 Y$ T6 J2.注册完了就可以在代码中用了,先新建一个C++程序, 类型选 Win32 Console控制台应用程序3 {9 [: r7 P0 u/ S) W2 Z
% E- d u4 R/ w& K/ V
名字取MEI_UseCsharpCom,点完成
/ C. i/ N1 m5 t: e0 \ n; F
9 q% ~+ {" o) {. ^1 l3 F把MEI_AddCom.tlb文件拷贝到项目的任何目录下.我就放在D:\MEI_UseCsharpCom\MEI_UseCsharpCom.
, u& E) Y [+ ^$ p; l# G' z: b3 T! m |; j* p
我们会看到一个MEI_UseCsharpCom.cpp文件,双击打开把默认生成的代码全部删掉.敲入下面代码:
4 q) j) |! o) a
$ u9 g+ K: b5 h" p& L
/ p. @$ b" N+ m. K#include "stdafx.h"
, U& f4 c8 A, @. G1 s$ o- m# s: f7 I#include <windows.h>
+ l3 g" x. R3 Q0 S% M#include <string.h>
$ ]2 P& Z. v& u% q+ {3 e d; z& |7 T0 P
#import "MEI_AddCom.tlb" named_guids raw_interfaces_only! k: R; ?/ `; q+ w0 p
) T) u9 G; m! }- p6 Hchar* WcharToChar(const wchar_t* wp) //wchar_t转char*
# J5 ?3 {" k# L{
. F) X, F$ ~9 Y- H: U$ [, I/ _" L char *m_char;: v- d) d% l, e$ I: @' I
int len= WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),NULL,0,NULL,NULL);
& z% P) |+ m2 Q% _" q, {- b m_char=new char[len+1]; 7 X$ q$ i0 i3 |7 D: v4 c
WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),m_char,len,NULL,NULL);
/ X9 `* Q: W7 } q& v) P m_char[len]='\0'; $ b1 m9 @7 E1 j* d% k! v
return m_char;
5 Q& K/ n7 }0 s8 N% F} , M4 r E: C# ~
wchar_t* CharToWchar(const char* c) //char*转wchar_t
. l0 @# H% Q& k4 U! S3 K2 [$ ^{ , L; D P* M! W6 M
wchar_t *m_wchar;9 N& F! b. ^; Y- ^2 m9 @# S) Z; R
int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0); : b/ e/ P! @* l/ K; r; |5 u' Q
m_wchar=new wchar_t[len+1]; # ?% u) O0 l. h. ^
MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len); " S1 r- u: r) ~! G; U
m_wchar[len]='\0'; 2 E- Z* |& ~. V, n/ ^8 S
return m_wchar; ) {/ D9 D6 G7 v9 O* M C: G7 J
} * q# Y" U- f% y: `; N% u
7 n) Q, r( J G& B
void _tmain(int argc, _TCHAR* argv[])) @' f: _ g7 t) c
2 |0 O" E( j. E ^2 Y
{) b9 F) z. G9 k- q( R4 m& d" u0 R
* _- ^0 L( ^3 u; N
CoInitialize(NULL);* k' e* M; r3 i
7 o: Z: i$ b* k) |2 s8 [ MEI_AddCom::MEI_COMPtr ptr; //类似明志一个指向接口的指针0 b5 F4 G6 P' G
5 ^8 a5 |! G/ i8 o% @' X i# T
ptr.CreateInstance(MEI_AddCom::CLSID_MEI_COM_T); //实例化一个类 CLSID_ 类名, ?2 [; J- V- X7 [( m) \3 s. z
9 S. Z* I, Q$ b3 Y% \& R' j //这个地方有一点点奇怪我也还没弄懂.在C#中的函数是int Plus(int,int).但类型在这里都转成long了.另外就是我们不能直接 w7 b" T) j2 X' G0 @- U: a
3 j5 q, C/ B0 D' v9 ?) x //来个long a = ptr->Plus(1,2);这样得不到a = 3,反正会出错.
. M7 S& ?* U# e7 P, f //这里函数Plus的参数变成三个了long Plus(long,long,long *).其中最后一个指针得两数相加的结果8 K! b% X3 r# y; r8 T$ h
2 K8 w9 L% `$ A; o2 z
long a = 1;: U# ]& ?4 x# m0 F+ w4 E5 E
; C( a6 x8 J: k; n
long * lPtr = &a;, Q. l2 c$ C; M- G
9 j: Y$ f0 s6 v* C. H' `
ptr->Plus(1,2,lPtr);! e& G! d; R3 ]8 U7 |( P
1 U( m, [% [# A& f: J$ J. F char msg[132]="";$ _& K' v/ I" }, q4 H4 ]
sprintf(msg, "%d",lPtr[0]);
: Z9 V6 R9 e/ M- Z. I {% k) N* I" V) m7 W" @
LPCWSTR str=CharToWchar(msg);. o9 I) n- X1 x1 U% W# z8 b
v3 w/ z& V" k MessageBox(NULL,str,_T("123"),MB_ICONWARNING);
4 U" Q, Q) h+ s8 B( |1 y+ X4 y7 s& C& V6 t. T2 k( u/ [4 y$ V6 g
) c: ?/ h) T2 N. k; V3 N}7 \0 U: z+ Q& a' R
1 L; u! q* Z6 K此时就可以正确运行了.得到结果3* Z" e" A! a! r1 D3 t: U
* C9 \: a$ |4 d) Q6 N& c% D
如果没有正常运行,则必须把dll文件拷贝到有MEI_UseCsharpCom.exe这个文件的目录下.# s, {7 S( T9 c2 q
* t9 E% R# S( l& L; a! y; R
) d$ n; l8 c- b/ t9 S--------------------------------------------------------------% r6 p# C0 y' f" [
C# Npoi库 操作excel 的代码网上很多
+ i. d$ M; E0 {1 c3 i, w4 X0 V3 `8 ]" K1 P. z4 a
// ----------------------------------------------------------------------
0 q1 M5 H7 |* B1 M( W3 h// 使用Npoi创建一个简单的xls文件,写内容& q( v# B. b& ~) W0 s) H# e0 x, F
; |8 I! K$ Q1 w) L! {$ k2 {- u8 L
using System;
! \, r% n% l. h$ a: _( busing System.Collections.Generic;' a- ` f! y% h' z
using System.Linq;
$ F7 [; `3 m- Y; j# ousing System.Text;. n3 v9 M" E, P, l
using NPOI.SS.UserModel;; |3 A. n1 V/ g6 G
using NPOI.XSSF.UserModel;1 f; e7 D2 X: l5 u0 K
using NPOI.HSSF.UserModel;
* k" e; K, H$ y5 `" y# K% k2 jusing System.IO;* }% b! G. b/ z; P
using System.Data;
7 @1 |( j: M$ W
" |7 B. I- T8 [! g3 G4 K//using System.Windows.Forms;
, P/ G R- e3 v) z. g# Q+ o) ]% C2 @+ U, g
namespace CC
7 {+ U" P& Q: w. @' V{) f2 O1 y) X; i: z( M
* e# y5 J* N/ { y, u class Program1 ^9 z9 A4 R8 C, L; o3 S. t4 @
{) w; h$ p6 ~( z7 k$ ~- M
2 |0 j- Y# G: H J& b! O9 N8 P
s& k. V$ b' j6 k0 b: U: | static void Main(string[] args)
4 o2 V7 X% R1 n/ I) S0 O {
9 c9 h: ^7 g( s //创建工作薄3 c+ |+ H3 o9 g( Y2 H
HSSFWorkbook wk = new HSSFWorkbook();: H& q9 v1 n) i( d) B1 D
//创建一个名称为mySheet的表' L% ^( E: o4 e: H( q
ISheet tb = wk.CreateSheet("mySheet");
) N. F. u m7 A# p //创建一行,此行为第二行0 ^ F5 ~$ x+ `/ s+ ~4 N1 D
IRow row = tb.CreateRow(1);
1 n& G" J9 W) S3 `, n+ q& K for (int i = 0; i < 20; i++)# X# j/ ^$ ^9 i1 {2 f. ?% V
{( Y+ T$ ?# R u, d- A
ICell cell = row.CreateCell(i); //在第二行中创建单元格
J, b' n; b8 U; R/ i+ [" X5 u' r cell.SetCellValue(i);//循环往第二行的单元格中添加数据6 O, y$ d6 s6 _! W( @- ^! O, Z
}' I/ k$ k* `5 _2 O6 i, s
using (FileStream fs = File.OpenWrite(@"c:/myxls.xls")) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!
* S/ |7 P1 J, R {8 ]$ M$ d1 G" f2 ?0 D5 \# V
wk.Write(fs); //向打开的这个xls文件中写入mySheet表并保存。1 o4 i- c) J3 ~" m' v! h0 h
// MessageBox.Show("提示:创建成功!");1 u3 Y/ }6 O! Z
}4 a. v5 C, v! e
4 x: p; U6 h# @6 r6 D }2 R6 J1 D; Y4 `- w, i8 [
5 `8 V1 b# n9 P2 r
- l! K& t: M, F+ u# G; p }
( }" o, A: G4 ~ {. R0 a7 ^ P; x- u
& J; Q) g4 s O- z* @
# V: B. d2 o p w. M. ?; H7 _}; ]& A3 o `" e/ ]# ^: n% k
4 ~7 B# ]* `# o( c: c, F
// ----------------------------------------------------------------------9 H% r, G0 H9 Q8 b4 B0 E" p3 e1 P
// 使用Npoi读一个简单的xls文件7 l+ F2 a' E' N7 V1 Q7 g+ ^* R. _
7 {+ L4 _/ }& V# w! R9 q, a) fusing System;9 _3 y5 H" Q Y/ C
using System.Collections.Generic;
; P* m1 s! B6 ^0 jusing System.Linq;' h c# o# ], t; ~: |9 l# C
using System.Text;& ]$ b a6 [1 ]" w% `( ^4 O3 g+ n
using NPOI.SS.UserModel;
4 V. x- w% p% Z0 S0 ^( wusing NPOI.XSSF.UserModel;
$ d: U! d. @8 P" l" Xusing NPOI.HSSF.UserModel;
2 A; {3 Q# a8 \0 W S9 V8 n* Jusing System.IO;* a0 d5 d( u# v- A$ r
using System.Data;
+ O* l' \ x' Y, n; f7 k
7 b' ~; c2 ?4 D6 F! O( pnamespace CC
: v( {" h G6 R* C/ Y{. {( }" v/ @' E" B
+ W% g) H C% Z: E0 E' [$ u2 H5 W
class Program: S% h {3 o8 W" K
{7 Y% H. o6 N( i, Z
! t; g* r$ g* r! j5 U8 d1 `
& l: b6 }- H! U, O# F static void Main(string[] args)- z5 G0 K" X8 T
{
4 D) a' H" a2 W% e2 C$ Q StringBuilder sbr = new StringBuilder();
$ l7 R: B# m9 w, l D, |, b using (FileStream fs = File.OpenRead(@"c:/myxls.xls")) //打开myxls.xls文件# B! A# E. c& z$ t2 C" I0 D
{
- H8 c' v% y: V8 H8 I HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的数据写入wk中8 E% M: T) K& ?6 v/ W8 `
for (int i = 0; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数
0 B- L3 K a3 Q1 W+ N' ^0 ~ {
: ~* B- c. q/ W4 R5 X0 { ISheet sheet = wk.GetSheetAt(i); //读取当前表数据. ]4 K8 F+ t) U8 V3 b; u' u# i
for (int j = 0; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数
! J7 C. L( Z9 S9 O {- H3 E7 c. b" {, F: D) S8 I
IRow row = sheet.GetRow(j); //读取当前行数据
4 e1 }$ o+ h# O1 W1 k if (row != null)
# D# M- Y1 F' f6 T1 } {; J8 E' L( {" B( {) I7 h' Y' {
sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限
; u0 a+ P/ d' @ h( j2 h% w% l for (int k = 0; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数+ s% V, n% N+ m" W" q
{8 D0 u3 B# `: I6 w% x
ICell cell = row.GetCell(k); //当前表格
y z+ G0 L/ ~7 m' D: n if (cell != null)) e/ v: c4 s9 c: M0 o
{
( i, o1 g4 J, F0 N sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型
( p& e% I B2 e8 V2 E }
3 Y$ `4 A' Q+ ?& a% K' X$ m9 n }
; U" Z/ M* z0 ^- ^( S" e }
% T( u6 B! J# J0 X+ c }$ e; r) i; h0 q- E
}
2 K5 @/ q& C% @" d }) l; T2 \# Y1 Z$ }
sbr.ToString();) `/ b0 l' R4 w& x2 H: J
using (StreamWriter wr = new StreamWriter(new FileStream(@"c:/myText.txt", FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中
1 F! I6 {/ \4 J( G H, Q9 F {
/ P# \" z/ A4 ?+ p# o wr.Write(sbr.ToString());
* K& ^5 n: p7 J8 C, U* h' H wr.Flush();
0 i+ g$ D: o: a" q. Q1 W) _ }) J8 X: r5 a" {- ]$ s7 M
; A# K* w' Q' k) ~, K8 X) x7 D$ J9 ?8 c! J9 Y; \
}- ~8 `6 w- h" q# ]+ a' x6 Y, `- x
6 L; v& V5 `/ [7 V' R6 Q
! Y/ i9 b4 O L& H# _0 K }
) I. |7 b* l/ C a, ~
' W h$ D- z+ d5 u7 v
! L; \+ M9 ^2 j1 V7 Y/ P3 K* ~$ V4 k% P c% k" q% {$ I$ k
}
9 Z) P. K2 L6 l2 x: g8 Q( p
5 m% j2 y6 p" I( ?8 ]) N6 A+ Q! f! n1 @/ H T9 v! a# f: k
然后 自己封装 给 c++用
" |+ e+ C4 |% O, E- d3 ~
: i! {$ `2 x. |; P2 A% Q0 n2 ~4 G" I9 r4 e
. B( B) f W" E: J) S
& Z5 r7 K! O' H) ~
& N7 j3 ^# {6 U2 S1 x2 y/ U3 N) c' _# W N* U
# c3 j9 ?. s( X" P) t
8 A% z: _* ]3 I" E1 s
$ b U4 H4 {: F' S# R
. i8 _3 q8 X. y0 V: P) p( \) w9 U
/ g' h! B! f& M4 D5 ?! R* X( b
0 a" I; r" O& k! M, `4 j2 A, i' F& D% _% ^2 b
3 f. a' |& h6 C7 \+ N# l
' {. U# i3 M# N
8 E1 x, i6 M) `$ U2 X- C
- Y V& d9 O) | p% O4 {- s% t0 K1 Y! l) q2 O# p
# @* `1 _. U1 C' v& R5 t
& ?, W8 q7 o1 i# P+ m! s& Q$ U9 ?) f4 N7 L' D1 m( t
+ u2 r6 W$ m* m
" r- X% Z. t$ s% Y, C2 \ |
|