|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
C# 或 c++ 不用安装操作 EXCEL的方法:c++ 对excel 的操作 非常不理想 要安装excel 而且读写速度也慢. t& m n) f/ R: @5 D, l+ {0 V
net 有很多 免费的开源库 比如 Npoi库 (Npoi库 支持c#、vb.net 等语言)
' ~/ ?$ b7 h' F) T# v这里我用c# 生成 com 组件 让 c++ 调 3 W0 C# f# I" p5 v
3 b' p9 n& O# K) r: c. Q8 C首先要学会 c++ 调 c# com组件的方法 (和com注册的方法)
" Y5 Y" f$ ?. g0 E+ r& Y7 |C++调用C#的COM组件(DLL)
6 e$ H, b+ U+ \" u# z1 F, u7 A" O; `$ j! Y+ t) {
下面我举个简单的小例子.我用的是Microsoft Visual Studio 2012,操作系统是Win 7.
6 D8 f7 l7 e' f$ J) E8 ]首先创建一个C# com组件.实现的功能很简单,就是返回两数相加的和.
7 F* s0 P9 L, R9 C7 {: O* q( J: H5 V
7 @& W+ Z3 D! b1.新建一个C#项目 ,类型就选 类库 .取名 MEI_AddCom2 U$ t5 J! D6 O0 t* }& K' V3 \
0 d+ B+ D! }& Z& ?) _
2.在项目中添加一个接口,取名MEI_COM.C++调用com组件中所有的功能只能通过接口来调用,不能直接调用类或函数
7 S. N' N0 ~' A: f( a
: R+ V j1 t6 U; p. \" t具体代码:
: [5 g x! |- v# O3 ]
0 y% e- s2 h7 z$ }5 {8 m: o% w. Susing System.Runtime.InteropServices; //记得加这个命名空间
% K3 Y7 T( w8 T( N- L- t$ i
9 z: N B# N, f2 a# p3 Pnamespace MEI_AddCom7 r$ s2 M7 q, @; w! X0 P" @. `
* c9 V v- v+ B5 t' E
{" A: h- O9 K; X) p* |/ c# E
5 L6 H$ d5 ? Y3 W
[Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的产生可以通过vs自带的工具.点菜单栏上的Tools ->Create GUID,然后选第4个选项.Registry Format.* j. _) O4 R' \
8 x9 s. g: O0 L
//点按钮New GUID,再点Copy.这样你就可以把产生的guid复制下来,然后粘贴到这个地方来.当然那个大括号得去掉.后面需要用到guid的地方也用这方式产生
$ x7 l9 P% N9 l) t" `) Q- j. x$ Y
[ComVisible(true)], Z) ~5 H4 |7 _# N& C. P8 j
* W( J9 K5 H) c! W v3 l( T, A$ k
public interface MEI_COM //记得用修饰符public
: d/ v3 [, R4 Y3 ^ G0 t, j0 T7 Y3 h" G
{) n# k6 ]* q% [
9 X% F" @" l# \% e0 \ [DispId(1)] //如果还要添加其他函数就继续来个[DispId(2)],[DispId(3)]加在函数前面
2 C+ A5 k Z* p! L2 m1 ^ ?1 b* \ n; I: N/ F: |2 y" I
int Plus(int one, int two);
0 D0 @" F H( Y% m" j
& ?# A6 x# v/ a8 k% S }
" |2 O0 P; d' H( R' H
6 @. X' S. J) L9 m}
* w5 o. ^ S1 ^0 z& x: q
$ J/ g( g) O, m+ w' E9 A2 V/ z; a! ?
7 V! H1 y" M. Z, k" h
, |7 y" m) a9 J' {/ u6 g3.添加一个类MEI_COM_T,继承接口MEI_COM,具体代码
6 h: ^4 N$ ?; k' G @* S4 C7 s' g7 L
using System.Runtime.InteropServices;
% G- j1 J! M; ~& U' L7 Q' M$ h& L3 g, M. {$ \3 D
namespace MEI_AddCom+ C% \9 L# w4 S! J2 T
# d" P4 b* M j9 i{
! [7 ~& h7 R! [) T+ u; Y2 g0 F5 a0 o- t
[Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]7 D, q0 {6 i! M+ f0 A7 H
! P* u. K, S/ ^' a# V6 [& F
[ClassInterface(ClassInterfaceType.None)]% F0 |0 v; V9 I
8 Q# t9 _& v0 f# e/ g4 {8 m2 e public class MEI_COM_T : MEI_COM
! l) H2 T8 s' X L4 t5 m* q8 A4 H. p. b# L4 u2 l$ B1 Y& q$ Z @( i
{
, S6 [4 x; A" d; H7 j) A1 X/ R( W% H y' {$ l: _7 {, m+ X' N
public int Plus(int a, int b)9 U+ Y* G/ c& j* N
# Z% \/ Q& c' U3 U6 U4 x! h
{
, f$ I- L& C* f$ I' A' T, J8 M8 R- D" l0 y1 C* f
return a + b ;
& D0 J% N, q8 K. Z; m! Z7 k% @2 H( e9 V) s" |
}
8 }. S% |0 R. }% k( L
# ?3 s" K$ V H/ G' n& Q8 _- U6 x }
* C; \$ p8 I, r+ Q# d( G
) T1 P3 C l, b' ?% ?3 R2 R4 v}+ S# W: B3 v) n) I
( s' @7 Z& V7 H
4 [6 ^" H( N( e! M0 F9 n# Z/ ^3 S
2 Q* Y( m2 @: f% j" X/ w/ C+ E4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)].2 H; a) [& ^0 k7 K! d. R
6 q$ t3 U( E+ n2 u
右击项目名打开属性窗口,在生成里,选中 为COM 互操作注册
; J( d+ Z/ l9 O1 O0 E
0 A- ]7 q3 V% c* U6 i
" d( s# P6 L; |/ k& o5. 生成->生成解决方案
, z, U* S/ f4 J3 c 注意 这个时候 生成 非常缓慢 # z+ J0 `. B! j) M7 `' N, U
直到 出现 成功 1 个,失败 0 个,为止才 操作一下面内容5 M9 N- t6 A2 F; I" y& s0 h
0 \+ U5 k& S0 F7 ?% U- U8 i) y. ^( s# }6 \3 e
---------------------------
) k k! V7 w- O7 N( m: ]: J8 T4 C
6 c3 z1 d; Z6 ]. [5 m# q) s6 F1.调用前要先把com组件注册才行. _$ i. z6 y5 q, N
+ g* K5 K) g, ~使用C#创建并注册COM组件 C#不能直接创建COM组件,因为其生成的DLL属于程序集,但可通过“使程序集COM可见”选项来支持COM。
* z) X$ K+ L) v以下说明如何通过C# 注册、注销COM组件。 7 ?5 Y6 y% F A$ x0 @5 ?
4 T! B' J8 A N5 P) g
为了能让生成的DLL能够进行COM注册,需要进行强名称签名; R, e3 D/ z5 `. ]4 d1 x
打开COMLib项目属性,选择签名,勾选为程序集签名,通过下拉列表选择新建,弹出创建强名称密钥窗口,输入名称,不勾选使用密码保护密钥文件。 X# P* C: x9 X7 }6 s, W1 h
创建完成后COMLib项目中将出现后缀为.snk的签名文件。) ?+ t- E- `- \8 M
最后,编译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文件。
1 @$ [9 [4 E+ |. |+ F) ?4 I卸载COM组件: 9 |& _, E6 m3 z- B& ~# R
与注册过程基本相同,只需将命令改为“RegAsm /u D:\ COMLib.dll /tlb: COMLib.tlb /codebase”。
- |- P k6 x. z: i+ K
" j5 D, M4 `1 V. w
; W, i$ e/ R8 r% Z. S. Q! x+ N; y- T2.注册完了就可以在代码中用了,先新建一个C++程序, 类型选 Win32 Console控制台应用程序
8 R$ a1 @8 y$ F% t
& _/ G# a4 }, V) t- j# T0 b9 F名字取MEI_UseCsharpCom,点完成
; Q7 z" I! n+ P6 I6 G' G; r. |! g5 [) _! i5 }& s1 Y; B) _2 A2 B; g
把MEI_AddCom.tlb文件拷贝到项目的任何目录下.我就放在D:\MEI_UseCsharpCom\MEI_UseCsharpCom.
- x& R) U% M7 M! W$ v
$ a r% H3 [+ U8 z- |0 _9 B我们会看到一个MEI_UseCsharpCom.cpp文件,双击打开把默认生成的代码全部删掉.敲入下面代码:
8 [4 f' |& S. Q5 z$ m0 P3 N% v
9 O2 J! }+ s+ b( t
! M! [' Z0 F) c2 I P [& R#include "stdafx.h"
% j/ O: \1 ]' o, U#include <windows.h>2 y# S3 X* j G! Z
#include <string.h>
# l( ?$ |- \, a- S* Q6 f/ G/ f+ N8 P7 H
#import "MEI_AddCom.tlb" named_guids raw_interfaces_only
( c' ` K' ?) z4 \9 g
" }, n0 R+ T8 ~4 A4 [char* WcharToChar(const wchar_t* wp) //wchar_t转char*
2 E" y# x" V3 p5 d0 @( a8 d4 h{
( J" f$ L. c7 T% b8 H; C char *m_char;
! ]/ W1 P. p) @0 H6 ^% }* _ int len= WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),NULL,0,NULL,NULL);
- Y' o ]5 X" V3 K( F. O m_char=new char[len+1];
7 t* z5 U7 M- Y: h, W WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),m_char,len,NULL,NULL); . F$ p4 m" j( t' }: `
m_char[len]='\0'; 4 g5 b$ m# b& |8 C. P' L
return m_char; , e& |+ X D3 M
}
, A/ h% ]0 m( D9 q; b- }wchar_t* CharToWchar(const char* c) //char*转wchar_t
! F( L+ g b% _0 a{
, T, a# O' p$ O$ ^+ p& p( [ wchar_t *m_wchar;
, H& d& X! N3 M2 E int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0);
2 Z) v, D4 G( o- R, [7 [/ X) R m_wchar=new wchar_t[len+1];
" } U- y/ D6 n( w2 y% A5 I MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len); # J+ l9 i* K& }
m_wchar[len]='\0'; 5 d8 X% r, Q) s" P5 i" b/ K
return m_wchar;
6 Z' N5 e! v# Q5 A l}
7 ~/ T+ j' c6 u( {& E" {" e: l3 Q
+ M- }! ~( i) l; Z( `/ }8 H5 Rvoid _tmain(int argc, _TCHAR* argv[])
, s9 O3 ], i: V$ d" f8 k0 T8 F z$ u" F$ K+ [
{
& y# F4 s$ q4 W( N8 T8 O+ g! U, g$ S3 f9 d2 Q: Z( d
CoInitialize(NULL);
2 D$ v! Q! j- W9 I+ C' k; l7 a( H
MEI_AddCom::MEI_COMPtr ptr; //类似明志一个指向接口的指针( o }7 w1 a3 @- w3 m, u( n
& d2 A% J2 H) g7 |
ptr.CreateInstance(MEI_AddCom::CLSID_MEI_COM_T); //实例化一个类 CLSID_ 类名
! {9 G( [9 _: O
& W6 n% K) w- {" v //这个地方有一点点奇怪我也还没弄懂.在C#中的函数是int Plus(int,int).但类型在这里都转成long了.另外就是我们不能直接
7 G( p" x @' X4 h& |$ h9 S% M5 V" l4 `
% W, C! I. h# k4 s& [7 |4 D) Z/ [ //来个long a = ptr->Plus(1,2);这样得不到a = 3,反正会出错.
4 k( e ^* [) r$ L( ~ //这里函数Plus的参数变成三个了long Plus(long,long,long *).其中最后一个指针得两数相加的结果
1 ]% I3 m0 @8 m+ y! C( j
! ]7 W! c3 n/ h* A4 f r- B long a = 1;
9 z: p2 p; m, w/ a% f
4 l1 X2 d7 o/ k; k+ l& h3 x& a. D long * lPtr = &a;" p4 e. L7 @" ~3 U
# H9 I/ U" l- ?' n/ I& u: b0 w# c# B
ptr->Plus(1,2,lPtr);% U: e* E0 p7 T% c
: d0 ~ H% M1 S" V char msg[132]="";
+ ? f' y2 v4 I( e1 l sprintf(msg, "%d",lPtr[0]);7 v5 i1 f4 P4 q l# R- p1 p2 y* g/ M5 Q
! g* v& u5 q, J; X! D LPCWSTR str=CharToWchar(msg);: j3 ^1 t9 e1 N- I& {+ M: u
' R, S" t& ^9 @' V- w MessageBox(NULL,str,_T("123"),MB_ICONWARNING);" B( o% t, Z0 W- _/ U9 U Z
z( }2 g) R) `! x7 K* w) p- t/ Y! U$ v5 G& V5 L
}
- ]0 _( P% E4 g5 p9 S; r/ W, Y V' D8 ~! \+ G# Q
此时就可以正确运行了.得到结果3
9 G* Y5 M& t: {, u4 m. O h( B" p$ W3 ], \$ `$ F
如果没有正常运行,则必须把dll文件拷贝到有MEI_UseCsharpCom.exe这个文件的目录下.
8 ^1 s" m8 h$ u# d+ o9 ]3 A4 ]! n& [/ n; K" }
2 v- `) o4 |& W: S8 J--------------------------------------------------------------$ P o, I- L* ]% W* t; b- _
C# Npoi库 操作excel 的代码网上很多% D% {' {% s( F- Y" K" Z
+ V( P" p, Q+ w9 c- g
// ----------------------------------------------------------------------% X2 X# j! L7 O' }) n; V. F
// 使用Npoi创建一个简单的xls文件,写内容
7 V2 V+ P0 v5 X* n2 s) W" Q: j# l' }; Z0 Q: B
using System;
6 @4 E$ {, M- f2 I, p" Eusing System.Collections.Generic;6 L+ o* H. p, ?" W2 x
using System.Linq;6 T$ r$ S$ Q/ d
using System.Text;' s) X- O% o0 M* `% N- x; x5 {6 k
using NPOI.SS.UserModel;9 S! x/ l+ a, J) b. {+ ?) i
using NPOI.XSSF.UserModel;
4 M% _7 J$ q( e. W# Jusing NPOI.HSSF.UserModel;
' C4 ^9 w2 v$ o$ E- x% Y7 lusing System.IO;2 H1 m: k+ M; [0 L, L2 A
using System.Data;" p0 ~* c% A# ?& B) i) ^$ ]
( n9 u7 j# y8 `0 v! Y
//using System.Windows.Forms;
! a; B" J, b, @. d- \& K, i, A/ F$ ]+ G. J
namespace CC' u4 t8 k- u8 n! P# A
{9 B& V' G8 a9 |! p2 }$ k! D- R! C- J
3 H! W- T' q, L' S1 o
class Program
! I3 K$ S4 A8 D {
9 C% U$ Y/ x" y" S) B4 z8 O6 N) V2 z2 d( T; S5 z x) R& j7 J8 q; ]
+ V8 v1 d( J; M% o static void Main(string[] args)" ~, m: f7 k8 y( y& w: ~
{
' m) C- }9 S4 q- W //创建工作薄% I, P( I T! Y- I
HSSFWorkbook wk = new HSSFWorkbook();
" C* V4 t. }6 i# Y- F //创建一个名称为mySheet的表
f) k0 S3 ^& j4 G9 i0 X& E2 h% ^ ISheet tb = wk.CreateSheet("mySheet"); f7 Y) k' ^! {4 `& p
//创建一行,此行为第二行/ P3 T4 Y& X7 u: M
IRow row = tb.CreateRow(1);
5 b" c; m- s+ O* ^0 j' N for (int i = 0; i < 20; i++)1 Z5 ~1 k s; E) ^1 r( }4 o/ K
{
" ]' ]7 J4 F) G" \: x( \ ICell cell = row.CreateCell(i); //在第二行中创建单元格
+ d, A1 T& K v. s" e/ Z4 V& p) c: D6 B cell.SetCellValue(i);//循环往第二行的单元格中添加数据' w5 ~$ [# e; b, @+ n
}( ?% t5 Y. ]/ o" r
using (FileStream fs = File.OpenWrite(@"c:/myxls.xls")) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!
- g, b* N/ T6 j5 I7 v9 p& U/ z2 j4 \ {
! h: ^ z9 V L1 t. z' c wk.Write(fs); //向打开的这个xls文件中写入mySheet表并保存。
5 o! a3 |- K# j3 C // MessageBox.Show("提示:创建成功!");+ Y' `1 N* A/ m; u7 N% z; E( L
}
D1 ?+ d9 A2 f* @4 P" S- l7 O2 `' c0 B- J! i
}
7 u) u+ B3 g: I0 x" _% {4 h. ^% @5 g2 _) \* ?. E# o, ^6 `# U
5 V5 B4 W' |& z9 h+ | }1 N9 U9 V$ Z9 }! q( ]
8 v( ~4 }" d9 ^9 E8 e. ^" O- C6 z4 \
( O8 a7 F8 H: n; R
}
: b; U! T: R5 }2 d+ p9 V0 M, O, k" o) x- v1 o) V# V
// ---------------------------------------------------------------------- G5 T# I* @$ C+ [/ r. t
// 使用Npoi读一个简单的xls文件4 \) R( _. Z& b$ i
1 ? l7 f4 E' L/ T; ~: `0 uusing System;
' A) P& b& ?8 i. P# X# y2 yusing System.Collections.Generic;: {; O2 c4 m2 ]8 g6 ^5 t
using System.Linq;
) y8 v* d$ `* } iusing System.Text;1 F! Y- F2 |) m+ W# ]8 }
using NPOI.SS.UserModel;- A3 b3 F; F# l
using NPOI.XSSF.UserModel;
+ |* M& I5 g% W6 ?using NPOI.HSSF.UserModel;1 Z5 K4 V T l- m2 g. E, H
using System.IO;2 S5 A" P8 ]2 _
using System.Data;
% N' I& n9 V M# H9 C# A3 V7 A
% T' x0 N5 e( k5 enamespace CC- c& J' _! z* E! s1 U
{& G3 K( C9 }! ~+ T0 W
; G2 E3 E8 E3 }0 ^6 b0 b
class Program1 ]: C# g: y1 Q4 y
{
4 N& z6 m3 U1 I) e
Z# P3 a. N7 G7 }7 F3 q1 q; q! h! J5 a0 z2 C$ g; X
static void Main(string[] args)& P c& i4 |3 A; E& F, v9 B
{
# ]7 _! I$ @! A StringBuilder sbr = new StringBuilder();/ c: T+ D# W' P( z: \' A7 }5 F
using (FileStream fs = File.OpenRead(@"c:/myxls.xls")) //打开myxls.xls文件
4 u9 W9 ^! [- H3 D- P {! {" P' e! s. v4 a6 a
HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的数据写入wk中
% ]8 b# z4 r$ N/ J/ k$ u- W7 r5 _ for (int i = 0; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数
0 w1 r. G& v7 g& \% h. l% L {
; \! G$ [1 K0 [( Y ISheet sheet = wk.GetSheetAt(i); //读取当前表数据/ K2 e! h9 }/ O5 _9 e
for (int j = 0; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数
# E7 R3 N& r( i3 Z1 [ {
5 b' S( I2 q/ Q( y% k IRow row = sheet.GetRow(j); //读取当前行数据0 _% K5 a5 g# u) | R, |: @
if (row != null)( X3 J% L, ?8 ?# O
{
9 V) T6 S8 C b3 F/ K$ o- v sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限1 Y/ V) g( A6 t! G
for (int k = 0; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数
5 [2 g8 ]! _' @: L0 r6 Q {: x- [& O0 a; x5 h8 j$ M
ICell cell = row.GetCell(k); //当前表格
( ~% r' `; b# ~3 j, s if (cell != null)
0 \, t0 J! I. m" X {
& x1 F) Q% w4 U% O: ]1 E) b* w sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型
1 E4 x+ K- P9 {9 Y8 ]& C1 ?. ]7 g; B }
4 }8 w' P- N; L# d% x; j: T }6 Q6 i8 y: V6 m: Z
}
5 l, X3 t5 b: @" Z8 A5 k6 h }
: I* C" `% X4 |$ y1 X/ _ }
: R3 e$ U7 q- c4 t0 u& Y }
( _" F3 w5 h8 l+ S. ^. L c2 C+ Y sbr.ToString();1 e. b& G# N$ S8 v
using (StreamWriter wr = new StreamWriter(new FileStream(@"c:/myText.txt", FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中; J# S% G3 ~, _2 Q' t" N# @
{
) _, o2 Q n4 d, v wr.Write(sbr.ToString());
C0 j; ~: _4 L; {. q wr.Flush();
! q( z) }2 F' n5 s, z }* W$ \0 |) z4 U0 P5 w
, `' j8 A( i' m' z& @! C2 Y8 t
& m+ I! V# _( ]8 t9 ^+ }% E
}; m( y9 R' a& d+ Q
/ T& m8 E: q2 r
) y0 M& l: Q( o2 R }' L. }6 S: b/ U. j" ?. ]! U
6 L; f- e8 G/ y
8 c+ q5 n7 i. ]: E' I: { i
; O8 V. M2 m1 z: G9 K, \
}+ f7 ^. Y6 @' a- w4 b' q
- K) l& g: N. M/ g# k
- c! u# ]8 M/ `+ T; L) d
然后 自己封装 给 c++用, J" ?) _8 z6 b2 v- \
7 \1 t1 F/ K5 w c
4 @+ B* g, y ^2 j/ I! W
# L! t, U2 r* A F4 [/ `/ A7 d2 S
% J R5 N; I, q
: t) q w/ F: j$ T h( V- Q$ Z4 L* q
( y! o1 I) j2 \2 b7 v
" a& G6 D% \/ I; w5 n+ @8 c
$ W, f, V# B- N, ~9 h* o w0 N- i4 _* ?# F+ o0 b9 c& b
3 b- U( [/ `% n% W) t9 T. ]9 T) _ o/ s
9 s; v8 ?6 P* D# N- K
" B5 |5 w( K# W# Z$ [( O& b6 ~4 v- a/ q$ u: J8 ]# G
6 q% j$ A( ?4 T' C7 W4 U) ?
5 S. G- @9 E6 ^( v ? y9 E, t5 N% s9 M/ |4 _; D- q
5 A9 ]% } y0 X5 W$ p( l7 q$ p* I
0 }' I, X- s& Z" |" y, z# N; N/ j
; ?& d9 n* f, F! `9 r9 |" C
: z: m; y1 p5 r# G |
|