|
|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
×
C# 或 c++ 不用安装操作 EXCEL的方法:c++ 对excel 的操作 非常不理想 要安装excel 而且读写速度也慢
* E- H5 C, u; r1 X% _9 Rnet 有很多 免费的开源库 比如 Npoi库 (Npoi库 支持c#、vb.net 等语言)
' |- }$ z! p* }! v: r0 O这里我用c# 生成 com 组件 让 c++ 调
: K6 C) D# X3 n2 o3 ~- P; _& O; G! ~) J% N
首先要学会 c++ 调 c# com组件的方法 (和com注册的方法) _9 k+ ~# y9 y/ l! D5 S& `! y; k1 Z
C++调用C#的COM组件(DLL)
$ Q6 |. l/ p( [6 J% _2 O; @0 |# [$ ^& d* q4 I1 a6 ]! h" ~
下面我举个简单的小例子.我用的是Microsoft Visual Studio 2012,操作系统是Win 7.
+ s n, P, C5 s/ I首先创建一个C# com组件.实现的功能很简单,就是返回两数相加的和.6 n# S7 T% b$ H% `
$ l4 X" V' E; L7 x
* H* b7 I7 V( t2 M2 E
1.新建一个C#项目 ,类型就选 类库 .取名 MEI_AddCom
3 V/ @: F' S2 P$ a( B% d- L0 f( [& ]+ U6 h
2.在项目中添加一个接口,取名MEI_COM.C++调用com组件中所有的功能只能通过接口来调用,不能直接调用类或函数: @: K+ d% s; z2 m' ^% v) Z
* ]* M* W% i( @9 Y( B% B7 ]具体代码:
2 P! W: C; b' z* q
+ n# |- B4 v) I. Dusing System.Runtime.InteropServices; //记得加这个命名空间) z$ _9 u) v$ D- b$ C" t! v9 O3 D
7 T! p: M( N! o [3 ]4 Knamespace MEI_AddCom c- X6 j) E1 ?6 d
/ g# p; G }7 {2 v9 R: ]
{
( \8 b0 P- N4 [. e0 |/ ~3 S5 N9 _' L4 c7 @( S, B9 S! W( J0 Y7 u
[Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的产生可以通过vs自带的工具.点菜单栏上的Tools ->Create GUID,然后选第4个选项.Registry Format.
4 I+ m. t. v, i# U. T; f$ f8 b6 U! V$ m9 e, j) J( A' ~
//点按钮New GUID,再点Copy.这样你就可以把产生的guid复制下来,然后粘贴到这个地方来.当然那个大括号得去掉.后面需要用到guid的地方也用这方式产生4 J8 s$ t4 Q: N1 _
0 V, n2 Q4 r! B! G
[ComVisible(true)]7 u( d/ R+ }3 w: T; i" t+ Z
/ U# [, m3 T. z# J+ I
public interface MEI_COM //记得用修饰符public, b6 S% u2 b5 m" Q0 r0 U, X
* D0 M6 v4 y! y, x( C6 h
{9 ^, M, r" O% I# _: P- W
, z- r3 b, w; H' i8 X/ z6 C: G [DispId(1)] //如果还要添加其他函数就继续来个[DispId(2)],[DispId(3)]加在函数前面
- j' E4 k6 O: @! ^; P8 H6 T! G9 w6 D/ w$ ^
int Plus(int one, int two);
! o8 \. f h' N; ]5 x& R! C, H
( R @# D* U3 `: h8 U7 b w6 } }9 ~. i }; I& L4 G `$ r5 y9 f5 x
- D9 h" M2 X& v}& n/ N' w7 f- |& s2 M. d/ h: K
/ B4 N* A, e7 R3 V8 L+ l3 G1 \! y' T" F9 X6 b+ z
5 |) U& e: C1 X2 H3.添加一个类MEI_COM_T,继承接口MEI_COM,具体代码
1 e, @( F# }( |2 J: N+ G3 U2 l. y, h' [5 @* _7 ~ I
using System.Runtime.InteropServices;8 j8 \5 t4 O; d5 I# O
7 {! Q0 A+ ^7 m7 p
namespace MEI_AddCom) a( X* a3 b% G) Q9 h; Z: v
6 y* g I1 X5 K# W' ]{
2 o$ W1 U% M3 |0 Q+ p+ O. {/ U; a) C' c/ q3 B
[Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]8 \* H& W+ n* [1 a( a" e' x4 c$ V
1 U& j; k, U% o* H$ p
[ClassInterface(ClassInterfaceType.None)]7 f" j5 _8 k4 O1 g/ S7 f- Y* o9 a
: F5 O2 Y- a% O5 g: l0 E1 B public class MEI_COM_T : MEI_COM R+ F1 L8 r2 u' f
& {- D: Q+ C0 r; \+ H5 P
{+ b! f3 Y! E. ]8 j; f
8 @+ j4 f$ ~8 R4 N9 Z
public int Plus(int a, int b)) Q' E: i6 w! W) @4 G2 b7 A
4 B. ~! T9 r0 [7 @. y) Y, p) ~ {3 Y0 h6 Y1 s! _
2 w! h8 L1 |8 }( Q3 s2 x return a + b ;- p8 o0 g2 |: l3 o' }. G( V
( J e$ v* q. {9 W! N+ F
}
0 l; P, C0 X0 i; X' O/ e4 m' s: K+ a* F. k% k% b
}
) P1 e5 J5 r% U _" G1 Z4 T! z( t5 U% ~4 F' v6 A* f
}6 L) a0 B) Z; } H
. M3 l1 S: ^) f6 U: B5 ` m' A) }$ `1 Q
& g, @/ ~+ o) s4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)].+ \3 E6 w2 @) W
5 d4 K* k+ m3 v1 I
右击项目名打开属性窗口,在生成里,选中 为COM 互操作注册
/ z& K3 e' i. f% B7 o) g+ i( F( D0 ?: B' p* ?* p a+ s/ ?% K% @( w
3 @& [, O% F; A* d1 O5. 生成->生成解决方案
5 f- L( W+ D! {: @& R( i; p7 s 注意 这个时候 生成 非常缓慢
% @! V+ g z$ Y7 o* }' Z2 v 直到 出现 成功 1 个,失败 0 个,为止才 操作一下面内容2 U0 [. C. _ p4 E; l- A& {* x
' k0 i4 o( u" v- |
8 t" x0 ~( p8 H
---------------------------
( z4 k& M2 q l' s2 d3 a8 ^+ H& c; {! U$ j0 t- b
1.调用前要先把com组件注册才行.
4 f# D, Q- J4 [
% V6 R+ j/ g4 e( [* v使用C#创建并注册COM组件 C#不能直接创建COM组件,因为其生成的DLL属于程序集,但可通过“使程序集COM可见”选项来支持COM。
' Y3 {. Y% `7 B! f; p以下说明如何通过C# 注册、注销COM组件。 , E' [0 ~( a$ e- o; H8 P- s
7 h. h5 ?4 ~8 S! B' s5 q! D' K为了能让生成的DLL能够进行COM注册,需要进行强名称签名
3 Q4 j: |$ q; {' X; t打开COMLib项目属性,选择签名,勾选为程序集签名,通过下拉列表选择新建,弹出创建强名称密钥窗口,输入名称,不勾选使用密码保护密钥文件。
9 A% a$ T$ x6 b- h! {创建完成后COMLib项目中将出现后缀为.snk的签名文件。6 W; E" i, R: i6 ^+ L7 {
最后,编译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文件。
+ f) [1 c1 u( @* I* ~' j3 n. ~2 u6 q卸载COM组件:
" ^8 V% g8 N* H' W, H9 X与注册过程基本相同,只需将命令改为“RegAsm /u D:\ COMLib.dll /tlb: COMLib.tlb /codebase”。' P. P8 K% V/ C; j$ K- w
, x6 \) b! E' t" E' D2 u9 W! o+ X. |, B
2.注册完了就可以在代码中用了,先新建一个C++程序, 类型选 Win32 Console控制台应用程序
. V$ |7 n( V+ e
8 W8 z: Z3 b! E7 p) s1 e3 i名字取MEI_UseCsharpCom,点完成
( w, r; c+ R* A+ H* R
e5 z# _, y. T把MEI_AddCom.tlb文件拷贝到项目的任何目录下.我就放在D:\MEI_UseCsharpCom\MEI_UseCsharpCom.% U2 m, H/ Z, k7 X% q
% `- u' O& A8 H V6 v! L! V: N我们会看到一个MEI_UseCsharpCom.cpp文件,双击打开把默认生成的代码全部删掉.敲入下面代码:+ b$ `* {! S9 V4 q; @% o
% ~3 A9 J; o# q9 M4 d. i: V- T
( W% a/ d! e- A#include "stdafx.h"
- C' q% _7 a2 ]7 k+ z#include <windows.h>
6 [% D/ n* x8 ]4 h#include <string.h># V) h* J4 Y% t. C& f0 `; P3 _
) _; ~2 u& L; z. o
#import "MEI_AddCom.tlb" named_guids raw_interfaces_only8 G1 _+ c2 @7 ^8 j6 \" d
9 V" I, D) Y9 @' x
char* WcharToChar(const wchar_t* wp) //wchar_t转char*
; ]$ o3 ?+ j) Y/ b0 n# h{ 7 j/ S) ^. B# f& u
char *m_char;
$ D' R* H% H# }* _0 W int len= WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),NULL,0,NULL,NULL);
3 Z2 K, ~) Q/ r8 L' a# ^' E m_char=new char[len+1]; , I( W4 R' i0 L$ m7 m! P( c+ |
WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),m_char,len,NULL,NULL); 0 \+ {& ~6 W: o1 Z: Q
m_char[len]='\0';
* d! j% z9 A7 l$ J8 f* Y$ r return m_char; ' I2 E7 f- s7 M' k& P
}
9 S1 d& L# T2 ^5 x' l* xwchar_t* CharToWchar(const char* c) //char*转wchar_t: H1 a: g6 Z) p; i9 t& M; |
{ $ ~7 G, I8 v4 W' E; Q, A4 z7 Z5 ~+ `3 n
wchar_t *m_wchar;# y+ [7 Z. L$ z6 f9 B( R
int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0); - z; ~7 N. h: j& |3 @
m_wchar=new wchar_t[len+1];
. @2 v1 L4 H2 Y! L, ~ MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len);
8 \) S5 F6 _" Y, E m_wchar[len]='\0';
6 j- H0 e3 o' e8 \ return m_wchar;
& e( [8 m6 E$ N5 E}
1 f) x" x/ X7 u0 ?" `) L, j. L, M ^; ?$ Z9 d$ E8 L
void _tmain(int argc, _TCHAR* argv[])
4 ^& E7 M; D8 r; v) G5 Q' U, Z; x' d
{8 h' d) b, p4 s& }
, w8 n( J+ b# A9 E. l$ t CoInitialize(NULL);! x' l: ~6 Q! A% j
+ v1 {: I# V6 R' {; v I
MEI_AddCom::MEI_COMPtr ptr; //类似明志一个指向接口的指针
/ E0 b0 z6 s) k' \* |! l0 J$ f: X3 Z5 b
ptr.CreateInstance(MEI_AddCom::CLSID_MEI_COM_T); //实例化一个类 CLSID_ 类名
- ?4 @* u, Z$ m7 K8 x
! ~2 o" j" `0 n6 ^+ h/ H //这个地方有一点点奇怪我也还没弄懂.在C#中的函数是int Plus(int,int).但类型在这里都转成long了.另外就是我们不能直接
/ o& e3 ^' m7 F/ r* v
( y# \; f! C. p4 j- g" X/ J3 n //来个long a = ptr->Plus(1,2);这样得不到a = 3,反正会出错.) |2 j1 O9 i6 Q& d8 c$ {8 `# s0 X
//这里函数Plus的参数变成三个了long Plus(long,long,long *).其中最后一个指针得两数相加的结果
9 D' O! j3 ?: t# ~: `" C! F" k6 \( Z* s6 F1 _% p
long a = 1;
* Q, W! d3 N* p$ z+ y6 W; I( n1 k% W( O" |, ]
long * lPtr = &a;" @2 C1 s$ F/ u$ x$ f
2 Z& r: s T+ C% G* v. V ptr->Plus(1,2,lPtr);
; L& n& B( u; i0 j& q8 \: y p6 X
4 H: `/ C) t* |* E# _ char msg[132]="";
" Q- C, k$ n1 A5 J8 N" w sprintf(msg, "%d",lPtr[0]);
, \1 G: A3 x/ K% d( G# P2 T7 c+ Z
LPCWSTR str=CharToWchar(msg);/ b0 N2 |/ J2 u$ J
& U3 I2 v: i8 Q3 B2 z; C e
MessageBox(NULL,str,_T("123"),MB_ICONWARNING);# ?* F4 t0 U7 i. m$ T: w/ l
/ i/ X# X4 H2 ?0 t- e% A' @
" v( f6 X% X! @$ [# G
}/ n M1 f1 h/ Z
7 [' r/ g1 g; F! e) f4 a6 H6 H& w
此时就可以正确运行了.得到结果37 p* \& S9 d- Z, \
, ?! z q. u2 l7 q1 D7 O; w5 H
如果没有正常运行,则必须把dll文件拷贝到有MEI_UseCsharpCom.exe这个文件的目录下.
/ Y$ }* E( f9 j! N: I8 a' \! a4 k! N% T: k6 ~
9 ` Y) I- R, c) j+ N$ [' } g3 r--------------------------------------------------------------9 k6 _3 O3 n& O8 y
C# Npoi库 操作excel 的代码网上很多, v8 x. h8 a. [3 a, U& t7 |( C
4 H& K) Q( e6 o- ?// ----------------------------------------------------------------------
0 E% W" _2 O/ T9 a// 使用Npoi创建一个简单的xls文件,写内容
) j8 u/ T/ ~' |- C( k" R2 w
4 h0 ]+ E/ ]' _1 u" H2 ~using System;
0 [4 v9 ]# n7 v& P* Uusing System.Collections.Generic;! @8 L7 ]( a1 p8 B
using System.Linq;$ U. ^* U- C' p5 s& E
using System.Text;
' M( ?! M" r8 k3 `using NPOI.SS.UserModel;
5 i( s! ~8 D6 a Nusing NPOI.XSSF.UserModel;! c5 j3 c8 Y, E: }5 Y- n
using NPOI.HSSF.UserModel;2 } P& x m* ]5 W2 W9 y
using System.IO;2 u1 x/ R8 v* K4 q
using System.Data;4 K" u3 T) ^$ H3 i* B9 C
+ P" x% } j2 e, W% I9 X7 n* F//using System.Windows.Forms; $ t5 F4 L+ H6 v, e: a" k
, I( |9 |: A& t. l5 w! ?
namespace CC4 I g8 P* |. |7 b3 `1 ~
{, s# Q8 D& |1 B" Z# N
! |5 c W! M" F7 o3 w; d
class Program+ e( x2 ~8 H# f3 F4 {) e: S
{1 u& e: t) ^8 A+ L" P# }
& r9 l6 O- T" R$ p9 m5 z
0 Z: ]9 a! X W2 \9 i
static void Main(string[] args)
$ c; C( Z" J2 p6 U9 W {, M7 P, t. u7 s: }
//创建工作薄
2 K: b# C& g. u8 ?* B- l% N5 |* \1 [% S HSSFWorkbook wk = new HSSFWorkbook();3 L, b" W+ N: T' J9 r `1 r3 t/ w
//创建一个名称为mySheet的表
$ o9 s3 i3 |. a6 c5 i ISheet tb = wk.CreateSheet("mySheet");
; [, a) S! Z6 D; s' @ //创建一行,此行为第二行
; C8 d5 d0 {0 T5 B IRow row = tb.CreateRow(1);' {6 Y) k' Y7 _ S
for (int i = 0; i < 20; i++)+ e2 B, {6 L* }4 {/ C
{
' [: E X A1 m% ^6 {) x1 T ICell cell = row.CreateCell(i); //在第二行中创建单元格
, C0 c# |- A- \/ o! e cell.SetCellValue(i);//循环往第二行的单元格中添加数据
. p. Q, _* w9 c- {- Q0 ?! U; G }
6 a) v' \$ P; B! c using (FileStream fs = File.OpenWrite(@"c:/myxls.xls")) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!7 h, P% L* w: q. ^
{
3 M$ m; S) m5 E1 f5 L% [- H wk.Write(fs); //向打开的这个xls文件中写入mySheet表并保存。
+ M- I5 o, O/ s! H4 C' {+ g // MessageBox.Show("提示:创建成功!");
$ s, A* k0 `4 U) [ }
% p% Y3 o0 \( R" n# @' n
& b0 N6 O$ M" y+ q/ z }4 s, n, D* m1 P" m
6 X. A+ Q, R3 C0 Z/ C
% s. Q5 v0 c; D
}! H3 S, f9 U3 k: E" r( H0 h
U1 b! Y- e: f- W2 n( ]( k' s- v. e: Z9 M; _+ B
+ X4 [* v' a" t9 d! v( ^( F! Q}
H8 k% A* Z5 F( C( u' e2 y; B
6 D/ k% a2 c: U1 `5 X+ N) I// ----------------------------------------------------------------------
/ e* w( k0 |3 d5 {6 T9 Z4 Q// 使用Npoi读一个简单的xls文件2 Z* R* c" P# z
/ V( _+ b4 X; Y Q" qusing System;
$ r$ |. k+ A( E, x# S5 h' `using System.Collections.Generic;0 c# R, y* X$ z4 t3 w
using System.Linq;. G* O7 c; w3 P& W0 L% d2 Z
using System.Text;. G% q. [! v1 q% X/ e! e9 w5 i4 w
using NPOI.SS.UserModel;! ]: z* [' [2 L4 r
using NPOI.XSSF.UserModel;. q1 q0 u; w! a- F* b8 Z7 w) S
using NPOI.HSSF.UserModel;8 Z8 K; I& l2 M J5 `* I
using System.IO;9 J& ]6 U% q4 u$ E7 x0 S* o9 ]
using System.Data;
( h( [% A4 R d
0 b1 a" Y5 B& u) _ ynamespace CC
' [& ~$ z; X9 a{; {7 Z1 {; I3 {$ |
3 _* d/ D7 N% `! v" v class Program
; o: f5 a( c7 r {
" C% y/ s; R3 V- r8 S! x
3 q3 T, I/ D5 i
" M. z7 r$ W R( l8 q4 H) i4 h- K static void Main(string[] args)8 R0 l; Z* F0 v
{- f. H& I. U. C* B; J
StringBuilder sbr = new StringBuilder();1 a+ l$ [ V9 A! o2 v
using (FileStream fs = File.OpenRead(@"c:/myxls.xls")) //打开myxls.xls文件* j- s- {( S, b/ c& T/ g
{( E1 T \6 `, e9 |& c7 W
HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的数据写入wk中
& o- n) T8 @) Y7 w1 m for (int i = 0; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数% q- @8 I w! p- u5 ]2 {% k
{+ ^% @' V) ]. l5 c
ISheet sheet = wk.GetSheetAt(i); //读取当前表数据
8 Q U4 N: Q$ p: _ for (int j = 0; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数
/ z0 ]# A* q7 O {
/ X3 d2 Q v: ]# Q IRow row = sheet.GetRow(j); //读取当前行数据
! a# W n: m: ^$ X% T" |7 S( | if (row != null): u4 N% w; B2 J. |2 S
{
* Q2 `; r- y$ p sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限5 r+ r# A: Z9 `7 ]
for (int k = 0; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数: ?) x7 k6 {+ I" y% g7 b- a
{2 [7 N8 s+ e$ O% \4 C
ICell cell = row.GetCell(k); //当前表格" K" E' K0 O# }" O* e) H* a
if (cell != null)& E% k4 g: }% j
{, q2 e" \' |7 b d
sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型
& f0 h) L `$ z }
% U8 ^1 M [1 v7 ^& `, c }7 e* ^4 c# N ?7 ^, q
}4 l. X" ^2 N- ?6 G' V
}3 G- c' T# Y( q5 G2 h) M
}
$ {8 e( S9 `0 W& { }
. D6 [! G# |8 W1 M0 [4 h2 G sbr.ToString();4 ?' }; A1 d! b+ Q0 T. t( O/ n
using (StreamWriter wr = new StreamWriter(new FileStream(@"c:/myText.txt", FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中
: \( Y% D4 Y/ B, k% j, n: a {
' q9 P1 y+ }4 h w wr.Write(sbr.ToString());5 W3 Y1 V: M# Q" ^) L; q
wr.Flush();
7 G# ?& K% ?: {, i5 Q7 w4 `. S }7 B! X# D0 d1 {) C- {: H+ q
* e8 S$ X, h, H, B
; t; r2 H- w; }# r3 b* P }0 L {& O7 i/ J0 w, ~' q
# t0 E+ v' x$ M, n
; R) ~$ T" u* j U4 Y3 K m; S }7 e0 O! }6 A9 V; V0 I3 B
+ k" q( @! \" s+ S% X, P& x
, I# t- T9 j0 h
0 o: x3 j% r- J' }, k* q( h4 Q}. z1 N9 W+ a6 O! t9 D; K
: X. T* H& p' z* w: g1 {( ^
! J- w- b: y# ^* F7 r8 G3 z: o2 W* y然后 自己封装 给 c++用
z3 n& {2 q; u3 M- ~' ^
+ @4 W( _# D" e4 B& s4 t$ Y- g- d, I) ]8 r4 \
" D, t7 u; F" ?' m0 {* D9 h) a4 l6 j e; C! X
- z1 P8 |% r( x9 f1 u; M
! I+ ?5 J5 m7 E6 d h. b4 |: \9 X. U* c" X6 f' w" E8 U
4 [! V% o" n+ @
5 w& w" q7 B6 b4 a$ `' y: z/ X
: F8 B" n5 V' n4 S; `( q! _: o0 a* q
( v0 X! O. U6 g9 v9 W, J" R7 ^
/ M; y( M8 N$ x* w& d! O% U$ B- R/ O9 V1 A2 \3 `" n: F. a
0 k! f! z( u) j
% x( s# ~3 Z8 y0 N) L
1 N5 d* P M [3 _! }3 m: G' X
! z# C+ U, E* E8 O- u8 `6 C& F! K
& H2 n, b' d( |: Z. {" O2 q9 k" K( r) A0 E# T3 ~! t3 `; I
( g3 u7 [4 u/ h) I9 G8 v) K2 t! z
, M+ O$ A( P6 `3 j y+ k
1 u( F o( J0 H; n# B4 { |
|