|
|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
C# 或 c++ 不用安装操作 EXCEL的方法:c++ 对excel 的操作 非常不理想 要安装excel 而且读写速度也慢: n5 g+ I% Q) W7 s7 a" [7 _
net 有很多 免费的开源库 比如 Npoi库 (Npoi库 支持c#、vb.net 等语言)5 b9 o% Y' F# u' c
这里我用c# 生成 com 组件 让 c++ 调
5 e! c, i& l0 q' A! R- ]5 b# S$ q8 N; V1 M6 p8 |- d. h# a8 d
首先要学会 c++ 调 c# com组件的方法 (和com注册的方法)
r! ~/ A: P0 c, N) oC++调用C#的COM组件(DLL)- P. }8 A, e L4 v
* c* I8 @' } w, |0 k6 `3 v
下面我举个简单的小例子.我用的是Microsoft Visual Studio 2012,操作系统是Win 7.
, c$ G1 X* ?' U6 T5 r7 e5 _首先创建一个C# com组件.实现的功能很简单,就是返回两数相加的和.8 E1 V9 e% L# P
; U3 H& h5 u$ i9 \: Z+ f7 M
0 {) i# R: c; W1 `3 G1.新建一个C#项目 ,类型就选 类库 .取名 MEI_AddCom7 o+ P5 z( L( Q- z! P2 O) B
+ t+ Y% d, k" l5 [! v5 M$ ^9 z2.在项目中添加一个接口,取名MEI_COM.C++调用com组件中所有的功能只能通过接口来调用,不能直接调用类或函数1 B! Y+ U+ @' X* R
; c* q- b- K2 r3 O9 m" B
具体代码:
- ?2 `4 H& g, u" k) ^$ i1 s' S# Q, i, J/ O
using System.Runtime.InteropServices; //记得加这个命名空间2 n0 ~, B4 e9 m
: v$ ?8 m0 ?+ g! z1 a
namespace MEI_AddCom
6 r( @9 F2 X/ j: W! E4 V
* @( E* o/ d2 F( n, m( C7 }9 K{
% A6 ]6 u2 ?' _. T5 N/ ~$ }7 c% p
' V+ B; `9 \: a' e [Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的产生可以通过vs自带的工具.点菜单栏上的Tools ->Create GUID,然后选第4个选项.Registry Format.
0 w( n. D7 s3 r/ n+ v$ u. y! k1 B, {) Y' L$ m( B6 E- S* _$ `
//点按钮New GUID,再点Copy.这样你就可以把产生的guid复制下来,然后粘贴到这个地方来.当然那个大括号得去掉.后面需要用到guid的地方也用这方式产生8 M7 r/ G1 h: t% H
! L5 l. c3 n& [9 ]& d
[ComVisible(true)]
6 W0 s. ~- o; W" Z* d: c* i+ I# i' F: W4 M& `
public interface MEI_COM //记得用修饰符public# P( R0 E. B* B( _/ z* l9 A p' W
E% W: Q& c5 L# T$ U3 V {0 l. j, E5 a( v- J/ [
8 c, X4 E, f0 G% S, D
[DispId(1)] //如果还要添加其他函数就继续来个[DispId(2)],[DispId(3)]加在函数前面8 _9 W4 W. l8 S. x5 a9 j+ }
8 B* r. D+ E( f* a: v8 r int Plus(int one, int two);
9 p2 o- o/ T$ N+ b+ c1 R1 v2 w. v) o9 m6 p6 k% V. }
}
6 O1 C) r& Z& k& F! {& d( p) q8 \6 S$ E6 g: s
}4 q- u8 b2 ?0 ~# O& I/ ]2 ^: w7 s4 f
4 s! d. v8 G: z( x0 L. @
/ B& ]; r; G5 o7 p' k# {8 t
6 O7 x8 B& v% U3.添加一个类MEI_COM_T,继承接口MEI_COM,具体代码
Z0 h8 w! f+ a2 S2 g2 x
9 ]4 l- f7 w; ~' X3 D* ]+ e* O* j Iusing System.Runtime.InteropServices;
/ j) b. p& K' w2 Z& v, L2 T3 P5 i/ a! i) ~9 l3 Y- T
namespace MEI_AddCom
, ~/ ]. ^& @6 |6 j o9 L1 N4 B" r, @* @9 V
{
) Y$ D- A6 M) t2 R* J3 l2 N& B0 {$ H/ y. N( x9 O: F/ D
[Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]3 V! M7 |7 G& U1 s7 |( G z
% ~# Q J% U% H1 |" P+ G [ClassInterface(ClassInterfaceType.None)]
y5 r/ m& Z- F) l$ v$ F* w
/ P7 `% F& t, J% e! K public class MEI_COM_T : MEI_COM% u2 e$ _6 n' C1 h/ `+ q2 s
/ ?) `% N$ d% g, p% H! H) x
{
* u- `* k/ K+ }) g! ^% t' R5 Y( C: y# W7 Z% {( J" ^
public int Plus(int a, int b). m/ t2 q- k& b9 q5 L8 B
* Y& F1 R* P% {4 U2 h1 j {
7 {. v: k8 e6 G: |
+ ?1 C" F$ D% `$ Q0 s" O return a + b ;3 Y7 `4 w) Z) O X, w
" w7 J( x, ] {, x' j! \7 F( P3 u: ` }
r! C9 d5 ? V
7 d: V' x Y6 S: ? }# J% L G# k/ w8 L
8 B1 W2 K6 A, Q& _}
Y6 X( M5 ?/ x! B. G+ d, T* T* `; T! t# ]6 L! W! m) o+ u
% L* M u/ J* Q5 I+ I& c0 _8 h9 q
; j- ?' L7 q5 |5 Y) v
4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)].6 i/ H: n& q! f6 Y1 @! r/ O
3 `; i- p M5 I- L9 Q
右击项目名打开属性窗口,在生成里,选中 为COM 互操作注册
/ u H* u) y1 A- `5 J% d! o2 a, ], o$ O3 g, D( Z: l2 `
) N+ z( q) ]( [0 W; ~: l5. 生成->生成解决方案
' B B6 e% `# U) h 注意 这个时候 生成 非常缓慢
; K" ~9 t$ T0 D& C. R5 [3 d 直到 出现 成功 1 个,失败 0 个,为止才 操作一下面内容
2 ]' w3 ?7 O, v2 w# L; _
+ c4 ~2 H6 |3 u8 T1 V+ t, H( {
$ J1 E8 J4 @$ L& C6 Q. c6 O& D---------------------------
8 f+ K4 q$ S, j C- i; E y5 j6 X8 b
$ S, N+ C) v+ v2 [1.调用前要先把com组件注册才行.
' j% n( X' i- Z, q9 D8 a ~
0 r( x+ ?2 m' P- l; r; |! h( k使用C#创建并注册COM组件 C#不能直接创建COM组件,因为其生成的DLL属于程序集,但可通过“使程序集COM可见”选项来支持COM。3 h% Z4 t+ B% N' O7 o( z- d
以下说明如何通过C# 注册、注销COM组件。
& r% h' z/ i5 v7 B9 l2 ~; M& k: n& ]7 w
为了能让生成的DLL能够进行COM注册,需要进行强名称签名6 ]- _8 `) [& N' X
打开COMLib项目属性,选择签名,勾选为程序集签名,通过下拉列表选择新建,弹出创建强名称密钥窗口,输入名称,不勾选使用密码保护密钥文件。
' i" s; Z8 R7 I/ D, y创建完成后COMLib项目中将出现后缀为.snk的签名文件。
( }) Y5 h3 @% X) o9 u% `2 ~! f最后,编译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 i g% t1 b4 D, C卸载COM组件: / R+ n' \2 q( s0 A8 g
与注册过程基本相同,只需将命令改为“RegAsm /u D:\ COMLib.dll /tlb: COMLib.tlb /codebase”。
2 \+ ~' ~2 ]/ X" `( G4 X5 {2 _! x
2 P- c' h. J7 y/ I8 o/ u2 {% u0 o4 V, e5 q) ~3 o# @
2.注册完了就可以在代码中用了,先新建一个C++程序, 类型选 Win32 Console控制台应用程序* P$ B! } L! Y$ I5 z& `8 R' z2 t
% g. p- r) }8 N! ^
名字取MEI_UseCsharpCom,点完成
1 Y. ~& `1 [( a' r' E; K/ L3 O$ Y6 Q& @
把MEI_AddCom.tlb文件拷贝到项目的任何目录下.我就放在D:\MEI_UseCsharpCom\MEI_UseCsharpCom.
& d/ x; i! p3 T
( [) P# R8 _* O% J& B' U; I我们会看到一个MEI_UseCsharpCom.cpp文件,双击打开把默认生成的代码全部删掉.敲入下面代码:
5 o8 T2 R$ R. x Q4 `. c
3 J) }8 R5 A7 K) v9 ]4 a: z% l7 [3 O- m# l" X
#include "stdafx.h". @# h1 \8 w- v
#include <windows.h>! a2 |: j2 D6 x- t q# I& h
#include <string.h>
7 x3 f+ e$ S/ _& C% N4 \5 B8 o
) ^' j0 r- a5 T9 ?: n4 g#import "MEI_AddCom.tlb" named_guids raw_interfaces_only
0 s1 l# Q5 U. D: i& B2 c6 k; @- Z0 t" b& t0 I3 }
char* WcharToChar(const wchar_t* wp) //wchar_t转char*
( h# F% y1 x+ ~- K3 p{ ^+ a# ~# z+ n( P- X3 K4 t5 L
char *m_char;
2 M# X9 H6 n c5 u) L- V" F int len= WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),NULL,0,NULL,NULL);
1 x+ C9 ?( t j2 W9 a- M. ~ m_char=new char[len+1];
1 O' d( `* d! k2 j3 S( E p, v WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),m_char,len,NULL,NULL); 8 `- M6 Y! h1 I4 P( ^
m_char[len]='\0'; ! v. U+ w' x6 s7 I* k9 `( w" D3 ?
return m_char; / Z1 \* a2 A3 d/ g q
}
' V' D0 O# r) n+ Z- Xwchar_t* CharToWchar(const char* c) //char*转wchar_t
8 j- v0 b- f- c{
, C7 R9 T" s; x( R4 Q' ~ wchar_t *m_wchar;
0 p+ o! t2 s Z; w int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0); 8 A4 V( N! F( S' C5 {
m_wchar=new wchar_t[len+1]; + u0 g( X. S, p8 X
MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len);
9 m7 R6 E1 c" m/ q; c/ R. c m_wchar[len]='\0'; j* x/ K& s5 i% i
return m_wchar; 2 P# N; _* w* q, u. U9 T
}
* [5 u# `! R* E! [/ ~4 I6 O S4 t$ @" G
void _tmain(int argc, _TCHAR* argv[]). X: b+ V" [# c0 m3 B, ^ E
5 i. l+ x1 f% J5 l7 C# }1 b: D
{+ s+ z& {; P$ `3 U( z
- ]2 y) h! c o2 R: }& R1 d
CoInitialize(NULL);, G+ A" r+ Z9 D4 t8 D \, I* D
- p- C4 O" i7 L( g MEI_AddCom::MEI_COMPtr ptr; //类似明志一个指向接口的指针0 r% E9 S, ]3 x4 p' e: q5 B; L
9 }. h4 M% ]6 g; i( _, ]; A" ~ ptr.CreateInstance(MEI_AddCom::CLSID_MEI_COM_T); //实例化一个类 CLSID_ 类名3 w$ w% C3 Y; D2 L
4 O5 t$ B/ \ G' s+ p' }9 U [
//这个地方有一点点奇怪我也还没弄懂.在C#中的函数是int Plus(int,int).但类型在这里都转成long了.另外就是我们不能直接
6 I! O+ g! \; V+ h$ K; {/ k7 c0 Z& \
//来个long a = ptr->Plus(1,2);这样得不到a = 3,反正会出错.3 t; v. }+ C/ U3 E$ X
//这里函数Plus的参数变成三个了long Plus(long,long,long *).其中最后一个指针得两数相加的结果2 s' {. }$ A( _0 S" b4 u: m
# s1 ?: V1 R7 r% g' E1 S
long a = 1;7 D3 S3 E. ?0 X; z0 f9 H
9 E# y+ w; r7 B9 A/ G6 o# [8 a long * lPtr = &a;
: x/ @* ?( g& x( w' w
. D9 O+ ]" K' J% M0 q! c ptr->Plus(1,2,lPtr);
2 X. ]( N5 [7 W0 K9 g& w
' s. _6 I' a! L1 g) h char msg[132]="";; Z, m) t3 D7 l
sprintf(msg, "%d",lPtr[0]);0 i7 `% O( v8 z% u
! o' c/ f E: a6 N% K% V
LPCWSTR str=CharToWchar(msg);2 W+ I6 N- M: B% R0 K
' E- @3 D3 T+ l' ^ MessageBox(NULL,str,_T("123"),MB_ICONWARNING);
& j% R7 N3 m8 E7 T1 n. D" M& M" u( z4 _
/ s: u. q- h: W9 @9 b2 c# J
}
' d+ n0 H+ Y. L2 T2 n# H
" t' m/ y, Y; O, ^此时就可以正确运行了.得到结果3
' K( D, R' f% } x' z
$ u) h) m7 p( t$ t如果没有正常运行,则必须把dll文件拷贝到有MEI_UseCsharpCom.exe这个文件的目录下.! i V; s6 u) q, t% B2 n
/ V) D! \; p0 `
# P. ]( F6 d" z4 a7 u$ r--------------------------------------------------------------8 I( T) U- D! q# M3 X4 j! h3 S" f
C# Npoi库 操作excel 的代码网上很多
" e6 u* i8 J* Z- b/ w5 n7 N
x! G$ I0 l- {- M5 k// ----------------------------------------------------------------------
: Z' J% b4 {, r1 e2 v// 使用Npoi创建一个简单的xls文件,写内容. n: U* Q2 J4 g+ k7 y
% H: ?/ @* c* _
using System;7 C6 [4 `; }. G0 k7 _
using System.Collections.Generic;
1 e7 g" s$ {5 l Kusing System.Linq;( }4 `9 C7 K$ {
using System.Text;
4 B9 ?% R& d3 ?& q) rusing NPOI.SS.UserModel;, {; T2 t9 h3 W
using NPOI.XSSF.UserModel;
) E5 N( N7 M$ k7 D( n- D3 V( {using NPOI.HSSF.UserModel;; H3 {; g9 ?7 u
using System.IO;9 X1 \" P1 h. v
using System.Data;+ N+ ]. g. t4 m! v$ u
+ J. W" P, Y) S0 x& N. |
//using System.Windows.Forms;
4 r* A& V, S9 @! h2 G4 H1 r- C% f9 S# Q5 r* ]6 Q2 g
namespace CC/ I$ I7 l2 P" P. X/ X8 D# h! d3 }
{
3 A; Y% Y7 g8 [7 F b; T+ ~7 B8 E5 D P, i3 `6 d3 D! |" }
class Program% q" \! m- u! l4 a: |3 |! {9 X2 }
{
+ B* Y( o* @0 V) k- M& L" ]' ~: _ @4 ^3 v( a
2 z. I3 w1 d2 F! f/ S5 E
static void Main(string[] args)# {9 P- ? n0 X; W$ C5 x5 X
{* H! R6 c& X5 w2 \( ?# Z' H
//创建工作薄
( j- S" b0 j' @ ~. \# \( t HSSFWorkbook wk = new HSSFWorkbook();
$ M) H4 o3 ~6 U //创建一个名称为mySheet的表
5 e |! b% O' s ISheet tb = wk.CreateSheet("mySheet");& R% p" Q! p- c6 E/ a$ O$ E: l X
//创建一行,此行为第二行* ^; y0 z, I1 h; y3 Y% V
IRow row = tb.CreateRow(1);/ P3 h* A- p2 i4 d8 F2 Z) Y$ m
for (int i = 0; i < 20; i++)
0 ?0 t( ?/ o7 E5 M; f {8 j+ r- F; k8 `, X; j
ICell cell = row.CreateCell(i); //在第二行中创建单元格
9 V* O+ ~" j7 S2 j2 s+ g cell.SetCellValue(i);//循环往第二行的单元格中添加数据5 \+ v1 v8 x# u/ r7 {4 p: u
}
0 g$ S, L4 Y; P- y( S3 i using (FileStream fs = File.OpenWrite(@"c:/myxls.xls")) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!
' B0 A( N! W+ U! B! c/ O {4 k5 K; k/ d" M
wk.Write(fs); //向打开的这个xls文件中写入mySheet表并保存。$ n; Y$ ^' d7 [" c5 s
// MessageBox.Show("提示:创建成功!");* |/ R+ E. F" a8 V& ~+ p$ ~
}
E% q. e* g6 L) C
5 \8 `5 w0 N" {5 O! e9 J0 d }
/ @+ ]$ _% ?" f$ } Q0 p, s, W: D, B2 T9 m' m
7 `8 }7 V5 m* S# t6 u1 y5 O7 K4 m
}) u8 U) J* j4 q% N+ B; X/ H
3 b7 H+ Y. Z) y* c
& H4 a8 z } V X8 J" K# l9 I# I: `' D6 C; I8 X
}5 H, B1 R. f& {2 z' ]8 z0 c* t
6 L! w U- g' d% M6 X1 ^0 M5 h* b# t// ----------------------------------------------------------------------
6 g3 U" v2 l u// 使用Npoi读一个简单的xls文件. `, }) p- u( y7 ^' y7 g8 F& M7 j
5 u4 I0 k! t, H% d$ Q1 y
using System;
3 Q% }/ Q9 X5 r# C8 Nusing System.Collections.Generic;
4 {3 N/ j K7 z7 Q3 }6 Z2 o- `using System.Linq;* M: o4 h# R6 a+ }% @- ^$ i. H6 M
using System.Text;
- g, q" S+ A3 @) n, _) }+ m( n* ausing NPOI.SS.UserModel;
1 M: F# b3 W5 I" E3 busing NPOI.XSSF.UserModel; _% h% O% Z: W( Q
using NPOI.HSSF.UserModel;
, b ]# B$ X) ?* W; pusing System.IO;; M. ^5 Q2 j6 d! n, N% E
using System.Data;
, p; a# ^2 h# Y; \" A9 M7 Z5 M$ O8 b
namespace CC% q% t" K1 l/ ^4 {$ m& ]
{2 w3 G0 R' L8 d" t7 z
6 P* u" [% Q* d
class Program
, Q2 n4 e8 v5 I1 m {# [( `( m! d9 U4 v9 v6 c# i
8 g( M' m N6 T4 P+ T
. b9 Z1 D* h+ {" \8 E; A' ^ static void Main(string[] args)
. q, q3 N; s3 ?) q Y* ]/ o {
" k2 @9 b+ r1 ~% a7 ~ StringBuilder sbr = new StringBuilder();
( {4 |' N2 ?# o using (FileStream fs = File.OpenRead(@"c:/myxls.xls")) //打开myxls.xls文件
) d0 F) T5 v6 [! k {
1 t' d' v. w. v& `" V i$ g HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的数据写入wk中# c0 _& S H- l
for (int i = 0; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数+ T' T8 S K" }9 H
{
/ N( K* V4 Z: f' H! s3 B- n# n ISheet sheet = wk.GetSheetAt(i); //读取当前表数据, _0 Y0 I, A8 `; v& @ f6 O
for (int j = 0; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数
7 ]; F' D( B) F: ]9 y {# t6 H% [ R. M! @4 M
IRow row = sheet.GetRow(j); //读取当前行数据+ k- | f' a8 f# t* @: f2 W
if (row != null)
- G9 Q" U3 i' X3 w' g- R% X0 M {1 z' D- D8 x; l+ U* I; O. ~
sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限, N; }% r0 f2 x6 j" G3 Z
for (int k = 0; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数
, r) B" w/ n! o* [' W* H {( e% [1 i' f% g0 n% t* ^
ICell cell = row.GetCell(k); //当前表格
5 |) {6 K# M0 j- O if (cell != null)
, C4 j; j! J2 r, K$ X9 V {
# a5 L$ p1 R; K' z2 q5 S) B# O) d sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型
7 b. ~: I: ^4 v- d" i# Y4 d }
; Z% _7 }) e+ L6 M- W0 b }
$ O: u( B& {& b6 J% o }+ h) x3 L" [, G/ v. q
}/ _, e) ]5 M% C$ J
}; y- v- F: F# o0 C) W
}5 W$ ^# \2 I' a( m6 }: v
sbr.ToString();
1 g8 ]4 B3 _% T+ B" t8 V& D4 d using (StreamWriter wr = new StreamWriter(new FileStream(@"c:/myText.txt", FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中
( i, X) a" y' V n {4 q( i, w" p7 x& V o
wr.Write(sbr.ToString());6 Z. g* z: U) C
wr.Flush();
% o, U' n0 D9 N/ W+ ~" `* B2 ~8 B }
% a( h6 b7 G, G: e' M" L$ ?" X& e/ s4 O6 `+ h0 X; d
, p, ?# b/ t! j7 A
}
! s* {! K' a# e& ^$ C, x3 g
3 L' ^: E4 Q+ e1 D( u4 }3 H9 C
5 X+ X0 y. ]4 Z) B0 p1 V4 x }* s* G" Y6 Z& F! n+ V8 C
/ k- c1 F4 B" w! z" _- {
/ |3 B: o5 \ D4 X% d2 x; S
. U% S7 }3 B. `# e$ ]
}2 E: k2 y% w7 G, z+ Z h5 f0 M/ u( K4 r
" D; F6 _: ]# I4 |
; M/ ]3 l; J# r& R" s m% t1 v然后 自己封装 给 c++用
) x4 ^. y: h1 d- J
5 g2 W' r j- K* B' C0 I1 A+ n: f' d8 z8 |0 O
0 a2 ], a M1 `' g& m9 q
1 D( z" P# `" T3 z) T4 c9 F; O" Y5 B( l! u5 e
$ {# s5 R1 \" D; P9 c( M3 Y }3 K" M) e; F; d: I
+ Z; o: @* u' N+ q1 d: i' Z! Y6 C+ \+ D! [
! }3 Z7 g; b1 n7 G2 u( r
$ `2 F- |5 h) L. C
. m/ A; Q X" T% l* H' Q/ i h+ p9 v8 D( }) `
+ F. i% g ?% @* @
. i! U$ A% h' c9 d! C4 f5 M$ g* c
( }* _: J6 O+ H+ v) L& d( e1 v
2 Q) a/ i0 `: ^& S+ a
! b3 v% @9 f" S1 `3 l. V+ ^- d
! S6 M, C+ H+ q2 w f* D( G9 ^. d9 r3 Z+ P* K% Z6 l- ]
2 l. X7 t7 o' `. k0 c4 e
3 m% R9 A4 F0 V) H* Y7 Y
|
|