|
|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
C# 或 c++ 不用安装操作 EXCEL的方法:c++ 对excel 的操作 非常不理想 要安装excel 而且读写速度也慢$ b$ {. {' z: Z8 s% ~
net 有很多 免费的开源库 比如 Npoi库 (Npoi库 支持c#、vb.net 等语言)7 E, l! g7 O0 n
这里我用c# 生成 com 组件 让 c++ 调
3 i& b& `# @0 t, h8 o4 r3 U, y
! q9 B- Z% X' Z2 i! Q3 [7 x5 D首先要学会 c++ 调 c# com组件的方法 (和com注册的方法)
& M3 p I3 X- w( y% W, bC++调用C#的COM组件(DLL), q; ~/ G: C1 D& F; s& F& C
* j" K4 \ X, O$ u9 E" b7 `下面我举个简单的小例子.我用的是Microsoft Visual Studio 2012,操作系统是Win 7.% v8 _) P( Q5 f$ D
首先创建一个C# com组件.实现的功能很简单,就是返回两数相加的和." j, a) k" c0 q8 \, }
# q5 o8 A! G" w( R2 g j" O5 r! N0 O- ]" v2 @# U# Y9 x$ n% F2 f, |
1.新建一个C#项目 ,类型就选 类库 .取名 MEI_AddCom$ V; Z/ P5 [1 P2 v
0 e* F# e( }: _' b
2.在项目中添加一个接口,取名MEI_COM.C++调用com组件中所有的功能只能通过接口来调用,不能直接调用类或函数
8 \. G7 s& ~+ u# ^* T: Z
9 k* y/ `; H H0 W9 \( ]具体代码:
5 t; Y9 z5 ?1 _0 N9 T8 R& N8 v4 M$ f: M K7 `+ Y( T
using System.Runtime.InteropServices; //记得加这个命名空间5 y" j6 b; M% ]# ^
; G& N! ~- B0 L, G' e! e) e' Z5 @
namespace MEI_AddCom
+ J/ @) {8 V' X' S5 ~6 k1 T3 {. g% x3 c+ ~3 O+ `9 w
{& n" X1 x/ }8 a! N# L E
. l- u& \3 `/ ` [Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的产生可以通过vs自带的工具.点菜单栏上的Tools ->Create GUID,然后选第4个选项.Registry Format.
- ^/ I2 Y+ ^% Y$ c" G; r& |6 M/ Z2 d+ j5 Q1 |
//点按钮New GUID,再点Copy.这样你就可以把产生的guid复制下来,然后粘贴到这个地方来.当然那个大括号得去掉.后面需要用到guid的地方也用这方式产生
+ _' l% e9 w' n. g' C7 D0 k
% o7 q4 u! ~$ p' b& Z3 _ [ComVisible(true)]
8 G( V% O' B. t- f+ P8 Z% g4 k2 X. R1 Z. f0 o) u
public interface MEI_COM //记得用修饰符public8 w% ?& Q: {/ a) y1 c7 E$ o$ m
, N( i6 B" J4 {) F# }! N {7 Y5 R; u/ x8 s+ j, S2 i
l$ w7 @. [2 a) ]8 u* E7 ?
[DispId(1)] //如果还要添加其他函数就继续来个[DispId(2)],[DispId(3)]加在函数前面
, t; Q" U( X3 `6 [
?( P8 Y0 R+ |+ B) {( r int Plus(int one, int two);
" n( p* f3 z' k3 {: z& p2 [+ p: N# @6 R" D0 _. ^. P
}
+ ]# [8 X/ d! P- v% T9 \% w3 r" k0 Q# O$ _$ L3 L; X
}
4 @# B. t$ y! d: @5 }6 k% d$ E8 }; H+ s% G1 e
& U0 I' q& P' H2 T& Z' u! Y
- v( A9 h0 X/ T" r3.添加一个类MEI_COM_T,继承接口MEI_COM,具体代码
% T0 ?$ o* Y, S0 A) T+ ^8 Y0 i0 H& V4 B+ ^; U. N
using System.Runtime.InteropServices;: R8 |# x1 _5 ]# L# `* h5 D1 H
- i8 n- t. F: a9 `& k& k/ X( tnamespace MEI_AddCom N! ?1 q4 Q: S' I% T% V- q
4 {! V' b: X& \0 z1 L{
4 Q; k. Q! T1 ~9 }5 V% _8 {; K% w& N" \: ?7 [% P" Z
[Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]
+ e% r" N( z* ?' l# _$ k
1 I* [: h7 A k( m+ D [ClassInterface(ClassInterfaceType.None)]
6 K$ y# O/ D9 w! m) _. J& u( V. ]) T, O% [: U" l
public class MEI_COM_T : MEI_COM
& i" g) F2 r; T/ ?1 a" ~& J
+ u# ~* ?# z( R& c4 B0 Q3 r {
. j% K- I T$ w! P& \8 h% ^( l0 w2 G+ k7 [
public int Plus(int a, int b)
3 m2 P! [; L+ L# U+ s7 h5 e% [8 A# ^$ J7 u( t1 A1 Q/ N+ P0 c8 B
{
0 v$ y( B F$ t( q1 R2 ?4 q
/ t$ s& x/ R! P8 f" u& s+ |6 ~/ W return a + b ;4 m2 U. G% J2 `- Z7 C
5 y7 I2 m* H# ^$ m7 G& l5 Y' d0 U7 ~
}
# c5 a0 A% ?' y: M4 j
& {. L* U+ m ^' J* y0 G& ] }& M+ C. [6 Z" d4 R Q9 u
, [* \5 o) m) p6 R$ m+ h
}
* F6 ?+ Q6 N: t( G+ U( k+ `1 T% f! q2 E
+ @: D# Q! k) l! Z
# V' ^3 G. J4 R% u2 B9 H6 A4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)].4 l. ? g- b% l% V( z* ^
% f/ }# Z: ?( L `+ l9 M6 W右击项目名打开属性窗口,在生成里,选中 为COM 互操作注册
7 q* c1 d2 U h' m8 _# }9 k7 v1 `9 Z
- @6 Z; A0 v. a) r! c3 ^# y6 P/ }# ^' ^7 q P
5. 生成->生成解决方案
2 F4 ]$ H* g5 r2 k 注意 这个时候 生成 非常缓慢
% A& j6 l2 O0 |4 m0 Q5 }* K$ ] 直到 出现 成功 1 个,失败 0 个,为止才 操作一下面内容
p+ G$ q8 M( u$ X- k7 o, q5 _! I" `1 f3 w& B
7 w' A& b" }" J/ N$ l---------------------------
+ ~" M& }6 ]# h* _3 H& y
( F% a9 K! B3 x0 u, Q1.调用前要先把com组件注册才行.7 o$ I( I7 b4 @4 R K. ^7 s7 F
# D6 g: I# t* O% K
使用C#创建并注册COM组件 C#不能直接创建COM组件,因为其生成的DLL属于程序集,但可通过“使程序集COM可见”选项来支持COM。
$ K7 ~* C6 N, ^2 a6 @! i/ B1 {6 c9 |1 T以下说明如何通过C# 注册、注销COM组件。
$ c: n) d) b6 f" e) _' f$ D# q6 F1 Y5 F9 W
为了能让生成的DLL能够进行COM注册,需要进行强名称签名
* @0 ` e* @/ q3 F. P- U打开COMLib项目属性,选择签名,勾选为程序集签名,通过下拉列表选择新建,弹出创建强名称密钥窗口,输入名称,不勾选使用密码保护密钥文件。
, _2 L, B0 J- h% Z9 n' h创建完成后COMLib项目中将出现后缀为.snk的签名文件。0 h8 R- M* ?" u9 s- u, E6 k Y
最后,编译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文件。
6 H5 t" z+ ^- H7 U# F9 a0 y. t0 r卸载COM组件:
7 B% Q6 F% m$ q1 ~" B \与注册过程基本相同,只需将命令改为“RegAsm /u D:\ COMLib.dll /tlb: COMLib.tlb /codebase”。
* [! T- w( @' ]9 \4 b& ?- m! n, G. w; g1 H. y9 ?
( G1 o, r6 t7 |% r9 `
2.注册完了就可以在代码中用了,先新建一个C++程序, 类型选 Win32 Console控制台应用程序
# k7 {' q- k7 x2 T$ U7 Z# t4 J9 U; H: H3 A, P
名字取MEI_UseCsharpCom,点完成
3 L3 B- X, j- g+ o' `/ W4 `4 h4 k$ U" s8 H! o, a) `
把MEI_AddCom.tlb文件拷贝到项目的任何目录下.我就放在D:\MEI_UseCsharpCom\MEI_UseCsharpCom./ T8 e5 @7 m c% \3 Y n9 a
2 U5 e6 b3 {9 r- z' e0 o
我们会看到一个MEI_UseCsharpCom.cpp文件,双击打开把默认生成的代码全部删掉.敲入下面代码:
3 m! X1 n; D: R( q
n8 n+ S6 T0 m+ q
1 J+ s( e$ X0 d7 L/ W( j& N9 c1 Y, L# [#include "stdafx.h"& O0 E4 V" @, X& V3 ~& k
#include <windows.h>
5 ?0 X) z P0 r: i5 s#include <string.h>8 Z& n% v1 |- L3 R# B, N
! U Z5 e, U ] z
#import "MEI_AddCom.tlb" named_guids raw_interfaces_only% A' z8 n' U0 l! A9 r7 s
! B# [6 w) J1 {) u r6 w2 wchar* WcharToChar(const wchar_t* wp) //wchar_t转char*
; S8 v. V( F% V{ 9 x" H1 |, c9 F2 ~) e
char *m_char; z7 A7 d9 o. @+ ~. T
int len= WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),NULL,0,NULL,NULL); 4 D9 O, ~: I( _) k: v/ E$ U
m_char=new char[len+1]; # \$ [, n/ R: N/ B( c ^
WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),m_char,len,NULL,NULL); & j7 M' {; k @$ y' [& Q
m_char[len]='\0';
: ~: Q6 D8 k% @7 s! I return m_char; 8 i& n$ E: c7 V, o8 E' R
} 0 Q0 P- V8 c, `/ e( T
wchar_t* CharToWchar(const char* c) //char*转wchar_t, x+ s' ]0 x/ Z+ f# ?- `) i
{ ! d5 B! z1 a" G, L0 y# U& f
wchar_t *m_wchar;
9 @ c1 f. {# C2 h: G \ int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0); - b: V, N3 s9 j" p
m_wchar=new wchar_t[len+1]; 8 q9 ]# W$ v, a. X- g
MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len); , \( ], I6 o. Y3 V+ ]6 p# h0 t! X
m_wchar[len]='\0'; & p1 a1 n9 U) h0 ?! o" N& N
return m_wchar; ( B3 v$ c8 v r8 D j# [
}
+ P/ G' s6 ^' K; A8 f& Q
- {2 N& L' {: t$ G/ L/ S6 xvoid _tmain(int argc, _TCHAR* argv[])4 t1 t1 k- F1 n$ |4 F6 U
. k( R: I# z/ m0 o! v
{
* n: ~- }4 z W
1 {: F/ D; w. `1 T: { CoInitialize(NULL);
7 V( B+ P0 P% p5 Z9 Y
* F/ f3 ?; a* ~- T+ d. G MEI_AddCom::MEI_COMPtr ptr; //类似明志一个指向接口的指针& u/ `& D: C0 M+ m4 T( m' ?
9 X- S5 Q9 [. T& B
ptr.CreateInstance(MEI_AddCom::CLSID_MEI_COM_T); //实例化一个类 CLSID_ 类名
2 p. M3 S' o& _2 Q4 q% W. T5 h- K) c+ y! h0 t$ h
//这个地方有一点点奇怪我也还没弄懂.在C#中的函数是int Plus(int,int).但类型在这里都转成long了.另外就是我们不能直接
: P/ c, s4 P" X. t" j8 k( i, @ \6 G5 Z
//来个long a = ptr->Plus(1,2);这样得不到a = 3,反正会出错.
/ @ R" J; m, @: M1 M" { //这里函数Plus的参数变成三个了long Plus(long,long,long *).其中最后一个指针得两数相加的结果
& z/ |0 u( l8 f: X$ Y" v- w1 ?+ C7 m" D0 i2 N
long a = 1;
9 H" Q3 ]2 w6 z' R: ?2 {: J
. V6 \' n. g" h" E! m; E( ^# z long * lPtr = &a;/ B: o; @7 @! s0 r9 {( [, b- Q( ~ M) k
: V& U( c! c# s* y ptr->Plus(1,2,lPtr);" X, v% m0 e* @" G( B
4 ?! @$ @8 {, H% w2 o
char msg[132]="";8 d/ \1 }. `1 v( L# v
sprintf(msg, "%d",lPtr[0]);
% a, f6 q1 ^ k0 [
" a2 k4 b- T" t/ A* D0 m LPCWSTR str=CharToWchar(msg);5 ^/ F V" n# J1 m8 w" D* B# V" \2 H8 ~
0 T" E1 Y1 U* S' ^. q8 R& k
MessageBox(NULL,str,_T("123"),MB_ICONWARNING);: S0 A9 o# [6 A) S+ X, m4 m
5 W4 j6 U& {2 ?: T* ?( n
! E n, ~0 s8 l8 B}; N& e2 u# A7 g' E* d
& G3 G% m+ D7 o2 E
此时就可以正确运行了.得到结果39 @1 \. i u$ X0 o* Z
$ Z# c9 T8 p% t* H: D; u如果没有正常运行,则必须把dll文件拷贝到有MEI_UseCsharpCom.exe这个文件的目录下.
8 [" l' n- \0 H7 T! c
0 t0 T+ n* ~' r! g' Z4 d6 k, ^$ @: _% B; ~( l. T
--------------------------------------------------------------" Z: s; g5 b$ l8 L; Y2 {4 I
C# Npoi库 操作excel 的代码网上很多, U( [7 I: x, E) u: V
/ l) x- F6 M' C4 }2 o
// ----------------------------------------------------------------------( g; B$ ~8 _, g1 \8 T8 s# \
// 使用Npoi创建一个简单的xls文件,写内容. \6 C5 `; h) [6 |# `
6 @7 b' K, W) k" `7 Uusing System;
' R+ M F: a3 D1 o4 F8 _! U' `9 \using System.Collections.Generic; h3 A( t* L1 w+ j' w
using System.Linq;) X8 [' Q; Y: X c4 K, z
using System.Text;
. Q( W& W& o" ?- U& T! Jusing NPOI.SS.UserModel;- K* B5 l8 _ X6 l1 g* ~" K
using NPOI.XSSF.UserModel;
% I; V( [- e! o2 Q) E- Q; H O( |6 Fusing NPOI.HSSF.UserModel;6 ?/ e; @# g% N. n3 C) N
using System.IO;6 B- J" Z! q$ Z1 X7 W
using System.Data;
) ~2 C h( z3 q+ t$ H' z- ~9 U0 U1 i3 N6 t% L; w- r4 t4 w- ]
//using System.Windows.Forms; ' ~3 I1 M9 P( F ]
3 a9 _6 C& s- `7 s
namespace CC
, ^. A! c, h! w. i{
6 w+ C y: P, _7 d
& ` H" A: n+ `1 y" o; ? class Program6 ^$ Z5 r! L' }2 C
{
( [& J. `" s/ ]6 F. y/ E
, o! M0 V3 P7 l3 A/ V8 \ d( l- P: P _" o5 U- c9 P0 N" ?) j% N$ f/ `
static void Main(string[] args)6 Z9 g/ R5 p2 G+ W5 w
{+ b5 ]3 O. Z! p, v) l8 j+ J9 ^
//创建工作薄7 S2 s2 ^ t9 O9 J
HSSFWorkbook wk = new HSSFWorkbook();# w- i+ N1 ~7 l& I: _0 _
//创建一个名称为mySheet的表& X: K9 V6 v* {1 k! B
ISheet tb = wk.CreateSheet("mySheet");6 m# Y+ i. A) ]& M. L
//创建一行,此行为第二行$ ^1 j6 k0 B! m" o4 A4 U1 k
IRow row = tb.CreateRow(1);
! E' C) d$ S1 A# V for (int i = 0; i < 20; i++)& @) `1 }. z6 Y! X& V" ~
{
% I* a% N$ ]# M( P0 h% h3 ] ICell cell = row.CreateCell(i); //在第二行中创建单元格
$ @2 k, Z( u& I& t, E' o5 `: S cell.SetCellValue(i);//循环往第二行的单元格中添加数据
+ T/ Q5 [1 B) r) A N+ S }
; w( B. ?1 z% g. I/ \' H: \ using (FileStream fs = File.OpenWrite(@"c:/myxls.xls")) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!
; O" J! u/ d/ T; m {
0 ?- J/ Y1 Z5 x wk.Write(fs); //向打开的这个xls文件中写入mySheet表并保存。
& A( ^$ x- p$ f; ` q# O // MessageBox.Show("提示:创建成功!");6 \( Z& Y2 f. s- p; H: l
}
N( @. E8 K$ @" l( K
! h! Z2 d/ d* L8 }8 U }2 g8 Q7 h3 X( Y& f1 w
% G. `& B1 k: r
4 F# u# l% u+ h! A: u% X
}
! _2 e. b7 s8 {8 U" [: x7 S1 i: x) R- `- J
+ j. U( P2 W! ?' F, }
% o3 d$ a5 t/ B( Z7 v3 C}* W: d6 X( Z% Z, a9 l1 K3 j
% @# F. O# F' S// ----------------------------------------------------------------------9 A& h1 P3 t3 j: g9 R
// 使用Npoi读一个简单的xls文件
0 q+ ?7 @: L4 I" N
+ O+ J4 D0 i8 @0 B! S9 wusing System;
' V$ s# K/ y$ O9 gusing System.Collections.Generic;0 K2 n+ M. v" D" J& V3 G" j
using System.Linq;
8 b! Z& C! n1 E) m) V; N. }! Rusing System.Text;+ E% b) c7 h7 S
using NPOI.SS.UserModel;
9 j' @+ v: y9 t! p8 `using NPOI.XSSF.UserModel;" @4 o9 O0 h3 J6 {+ S
using NPOI.HSSF.UserModel;
( l( n) N/ o2 ^4 Susing System.IO;/ `( p8 B1 L. r6 I
using System.Data;% U9 c5 w# Q5 C4 r
3 j! m- c$ q3 M7 F2 O
namespace CC3 X) W7 r, c# Z. D* o( R
{* }6 Q ]1 h) \) w( B( @
. H% d- Y- i5 {3 E c7 o
class Program
0 C. X- |7 [/ n {
3 V1 M9 J/ s, `. W7 L: @! i! s0 N
6 J7 q9 x2 q; w& y7 q1 |; J1 v
static void Main(string[] args)3 v- T* `+ m, G6 C; T5 q8 c
{
8 `3 _% D# B& |/ Y5 l1 c, q StringBuilder sbr = new StringBuilder();# l. \* o/ ]0 k% i( b9 C
using (FileStream fs = File.OpenRead(@"c:/myxls.xls")) //打开myxls.xls文件
1 ~ O8 K* k( X" Q1 R {! \6 h( |. \; o6 L7 @7 d5 X
HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的数据写入wk中
, n) \8 o, [' K; _7 d# P4 s+ A, j for (int i = 0; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数
& |5 d( i7 ]" t% w& [" ~' y {
1 E. ^1 A3 {+ V# J$ t ISheet sheet = wk.GetSheetAt(i); //读取当前表数据
; F2 i/ f. A$ I, q for (int j = 0; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数
) `( w3 ], q C- q( v- v u {
7 U( I/ y! j8 t7 F IRow row = sheet.GetRow(j); //读取当前行数据2 h' O+ ^ \9 X, Q' \
if (row != null)
- ^( p' J6 P/ l6 a+ e {# c( ~7 r* D# j+ P; I, D( M* b- t
sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限
7 g8 T9 f2 c) @ for (int k = 0; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数! s! N5 l' l# I* ?4 E v
{
1 W3 H, X( L% x# ~( w- l; l) [' j- s ICell cell = row.GetCell(k); //当前表格3 K) s a- s+ \# n5 \
if (cell != null)+ V" j& S+ l$ J, u5 `, ?: }
{
: R: o3 W c" I3 }4 E sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型
0 Z) ~# A d; M1 C/ D2 v" ]$ Y }* y, C9 g+ w9 ? k a
}
n2 X% v: e1 G }
( |2 D. q# ^. ]0 b8 J. R }
; M: C! a% Y9 p) T' u6 q" n }/ [" W' w# T4 g& b: |. B
} w- a1 n/ R+ k
sbr.ToString();
3 K8 g- l/ [/ f using (StreamWriter wr = new StreamWriter(new FileStream(@"c:/myText.txt", FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中' w5 F! I9 Z7 c: J6 _: @9 v
{
l) p" _7 m3 T* Z9 j$ \ wr.Write(sbr.ToString());8 R, R; N1 j, P* u a. |& F
wr.Flush();
9 s8 T9 m2 K/ A8 h4 r. P }& p3 m$ |+ O$ B" A2 _
; c: P& e5 q0 d( z9 r
v4 m9 l+ H8 _% o, q }# N4 x' T2 K$ j) b
3 z- c; p: @3 J* J5 _& a7 U$ c) [; C4 a4 o
}
+ g i6 q4 F9 q. ]9 Z/ d
* H: d" m; g r5 [+ Q
. E7 o$ N; R( N* n# x5 d$ q) h
/ K1 `! Y4 Y: h& _1 K0 t}
' A6 v. B/ I# v* S' ]4 F" k% a/ P" i6 {" b. a: X+ t
* n4 P' ~5 u( ^7 U( m# h
然后 自己封装 给 c++用
( t+ R$ Z& c3 x9 o
% r4 o i) N, P/ b( b! F
' o+ Y t z4 C' f8 y! l6 c( e/ C$ k( M0 o1 W
* N8 {7 ^. Q' T7 P
: B* G- c" N: w6 Z2 w
& K9 }; b1 J4 t8 r k# r
, P0 C/ a/ s7 q4 `) d8 n3 y( v" V
* Z* k! ]0 l2 d# N
. g, q* c3 A2 ?
( _, b) R" C- ~! g* p- k3 ^) \8 k) S0 u7 S$ { d
; u9 ]2 | `: s+ p8 t* O) g
; i n5 _% e7 r# u/ ^& G
$ Z9 y1 u/ o |6 Z* V) v) T8 l, m2 T8 i$ o
1 w- U, X$ k# c0 X- A$ `9 j( v) L
# ^5 Y3 o% Y8 u1 i7 {' B. [
% b. Y$ d1 O' { a( P
4 Z Q+ x+ C. z
# C$ ]: ~" F9 ~) w/ I7 @0 G$ |; K# n R F; g
7 z* v' |7 K8 F. V- n( X k
3 E: j4 k7 e+ o, [! N, H( v, r
|
|