|
|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
×
C# 或 c++ 不用安装操作 EXCEL的方法:c++ 对excel 的操作 非常不理想 要安装excel 而且读写速度也慢
/ m9 W4 D- Q! n6 }; `net 有很多 免费的开源库 比如 Npoi库 (Npoi库 支持c#、vb.net 等语言)
7 m$ h0 g; I# n! i2 |这里我用c# 生成 com 组件 让 c++ 调 & A8 D6 K$ s& x+ C$ s
/ @5 d9 Z; x7 M2 h! k
首先要学会 c++ 调 c# com组件的方法 (和com注册的方法)
4 i* [9 x" v& v! MC++调用C#的COM组件(DLL)
# n" s- ^1 @" a" p) L. V" _$ C/ l1 W& u. A3 c( A
下面我举个简单的小例子.我用的是Microsoft Visual Studio 2012,操作系统是Win 7.
- m: o- `; T+ t0 i' \% Z首先创建一个C# com组件.实现的功能很简单,就是返回两数相加的和.: U; R/ u) L4 h! R; D$ B
2 x% ~& J. n* ~5 S: Q7 |. p
$ H1 u) [: n: G4 h4 q* R% u- v1.新建一个C#项目 ,类型就选 类库 .取名 MEI_AddCom/ N% A4 I! B- R
}$ R# y! |: s0 t
2.在项目中添加一个接口,取名MEI_COM.C++调用com组件中所有的功能只能通过接口来调用,不能直接调用类或函数2 c1 b' W2 Q: j# c C; i! W( G
$ x; }" ?. k" m: h# d5 b. o6 V具体代码:. p/ |+ g) O5 a% v/ M. ?* X
6 i' Z: r% l0 ousing System.Runtime.InteropServices; //记得加这个命名空间
) C! l. b2 f) I% W2 V' K
; `+ o* J3 X- X+ d5 z+ b& |# s1 M3 K8 Dnamespace MEI_AddCom
8 R, f9 F8 B% @9 _; k; w
3 S( k- b- ?+ E, X, L. |{& s x+ F- V9 S! A5 [" d
1 p7 x4 S z2 L& v; x! ^ [Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的产生可以通过vs自带的工具.点菜单栏上的Tools ->Create GUID,然后选第4个选项.Registry Format.
. Q* u% O' U8 J3 }6 n+ \2 ?. D/ B5 Z7 U) q7 ? T* U
//点按钮New GUID,再点Copy.这样你就可以把产生的guid复制下来,然后粘贴到这个地方来.当然那个大括号得去掉.后面需要用到guid的地方也用这方式产生$ O" Y9 \, d3 P* z
+ e7 i; l1 A3 n! M# G
[ComVisible(true)]
6 k0 Y m/ L4 Q& ]: ?2 t/ b- o" n
# Y3 `) S' z! z8 W3 Y% { public interface MEI_COM //记得用修饰符public* H( H- T9 g/ d0 F& p
; w k% P" ^ f C1 M
{
- P/ |3 o& b& _4 I! D
8 @$ W# ]7 d2 Q" @& a [DispId(1)] //如果还要添加其他函数就继续来个[DispId(2)],[DispId(3)]加在函数前面1 E/ e: X7 B+ w+ J8 D
" `0 e& a1 {+ L8 K" y! [) ]+ ^ int Plus(int one, int two);; M. D2 ~* l1 R
& W4 }; P) d% T9 Y
}
2 w% i& o3 Y3 o3 s8 r: \1 ]( ~4 q6 H
}2 s6 e, o! I* E8 [6 G5 F. V+ ?
$ i* x9 J! v6 L, ~
: _. k4 b! q7 r3 y/ y
) w: J4 {% m' y3.添加一个类MEI_COM_T,继承接口MEI_COM,具体代码; j- _8 X9 e" U
g z/ @; |8 U& i0 }4 G6 l2 ]1 eusing System.Runtime.InteropServices;1 C/ \3 L' ?! g# I
( D( S& ~$ s. w5 v
namespace MEI_AddCom* v" ^; I5 Y" p& U1 w. m. y
) |) b- f" y+ n" M8 t
{& D, v; I* t/ x8 V: d; V5 R
% n7 ~# T2 L1 `! @ [Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]5 b A6 y. k c. k5 W
/ E& ?& }1 F+ V0 z# R
[ClassInterface(ClassInterfaceType.None)]
4 ^7 W5 { I7 n1 a6 @) l& ]( S. N7 @. m8 o
public class MEI_COM_T : MEI_COM
, S U; K# ^5 w) l8 y+ d& E; C; f
{
. k% K% A2 Q/ P% n% a( v! c
& G" p$ k2 N9 |1 Z5 u9 C5 c8 X0 | public int Plus(int a, int b)3 k) ]9 J/ ]# t- \3 I# w
. m9 y& C8 `; k/ F7 a. d {- r! Q' H, Q# o0 g2 G% R
( L$ E8 b' h9 t( @& h
return a + b ;
) _: d9 o1 X7 B; C% p
4 Q& T8 I; o) \5 t3 y( A/ d }
( o) w0 C5 X K" O1 }
8 J% C" Y1 q2 _3 s E0 r9 x) P }
# I$ O& n$ h4 O# n' a: W0 \' J2 @ e7 ]
}
) o/ P! _: G/ D E$ Z, J" u. _' O b
! T' p3 P( a" `8 _( z& n
1 M8 I: H9 j5 R9 a+ ?4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)].6 Z5 {3 _: t% D5 o5 w, f$ z
+ o' l- ], ]$ S% Y3 \右击项目名打开属性窗口,在生成里,选中 为COM 互操作注册1 L4 E c7 |5 c, e
3 s! U' M2 T, r5 [0 Z' X o- T- Z6 W. t8 ?0 h. i: d2 E
5. 生成->生成解决方案
) L+ D9 x- k3 B0 b g7 e9 h& s 注意 这个时候 生成 非常缓慢 9 J/ v" l2 b! ?+ i& i' Q7 {# l: {
直到 出现 成功 1 个,失败 0 个,为止才 操作一下面内容* _/ t/ S# ^' G+ U7 Q' `6 I/ `
2 f% ] J% P+ j' Q8 I
4 x* D1 Z3 Q* D---------------------------
4 L& \7 J q6 C5 U. ^9 C2 D. W1 z* @, S2 g3 ^
1.调用前要先把com组件注册才行.$ Z1 E0 e" y# O4 R
+ E$ y/ ]9 `9 ?/ W' T+ s& a$ T( _2 `; o
使用C#创建并注册COM组件 C#不能直接创建COM组件,因为其生成的DLL属于程序集,但可通过“使程序集COM可见”选项来支持COM。 u ^3 h$ F8 s) ]; W& V$ w! r
以下说明如何通过C# 注册、注销COM组件。
9 A# C, u1 f1 h# N( |$ G% C u
1 O! l5 P/ [/ F: ~为了能让生成的DLL能够进行COM注册,需要进行强名称签名
2 _0 O4 v" j% d打开COMLib项目属性,选择签名,勾选为程序集签名,通过下拉列表选择新建,弹出创建强名称密钥窗口,输入名称,不勾选使用密码保护密钥文件。
N! U7 J5 l- M; }/ Q创建完成后COMLib项目中将出现后缀为.snk的签名文件。& u: _ K h3 n0 b' E9 \
最后,编译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文件。5 T$ M3 S& z1 R
卸载COM组件:
) K: @5 Z, q5 q* W与注册过程基本相同,只需将命令改为“RegAsm /u D:\ COMLib.dll /tlb: COMLib.tlb /codebase”。& T; A* u9 H6 u6 x7 x
2 k, ^, ]" g3 T
8 K7 `- i1 [# S5 x0 Y1 N. }2.注册完了就可以在代码中用了,先新建一个C++程序, 类型选 Win32 Console控制台应用程序
% O* W6 W& P R- `
+ a; o$ ^& l* P1 l名字取MEI_UseCsharpCom,点完成7 I/ L# a) _1 X' L0 B7 P
, f* ~/ k- c: v* ?5 k把MEI_AddCom.tlb文件拷贝到项目的任何目录下.我就放在D:\MEI_UseCsharpCom\MEI_UseCsharpCom.1 ?4 G `5 q5 T2 D H. q- A
; f& n' d( C4 y, e8 y+ H
我们会看到一个MEI_UseCsharpCom.cpp文件,双击打开把默认生成的代码全部删掉.敲入下面代码:
o8 S8 w( }+ L3 Q' V7 W( Z( C+ c4 r! x3 H7 o" L, ?, }
" W: E. n* |6 @5 _. Q% V* W3 L" l#include "stdafx.h"& b: _4 L8 @. b. W
#include <windows.h>8 @8 a% j3 H. v1 q
#include <string.h>
+ X/ }) ?( x6 X' A! m
; S2 m# J. X% J' l8 w- W#import "MEI_AddCom.tlb" named_guids raw_interfaces_only: k1 h3 n ~7 I+ E
3 S2 D/ z! ^% |" F! T) gchar* WcharToChar(const wchar_t* wp) //wchar_t转char*
h0 I e/ Y2 E% Z8 |{ 2 m! _# q; Z1 A( v" \
char *m_char;
& i8 G" K' M. A; R' [ int len= WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),NULL,0,NULL,NULL); " U5 ^. S7 V% p$ }) F) Z5 d
m_char=new char[len+1]; # t* ]+ j3 }9 L6 d* x; x5 f6 c
WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),m_char,len,NULL,NULL);
3 q+ p% C; d* s3 w5 L m_char[len]='\0'; / f! [# b# U% }0 {& R2 b: p2 V/ v, W
return m_char; : u1 \7 N5 w" Y8 q: x7 o. m( q4 p
}
8 }1 g, D7 E! m- a- B; d, `wchar_t* CharToWchar(const char* c) //char*转wchar_t
8 w+ S/ u8 W1 m1 c$ @5 h4 k, a{ 9 z: U4 `% n$ C1 T: L* a
wchar_t *m_wchar;" L& S7 y8 K ?6 B4 g3 D5 h9 x) w
int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0);
/ M; k% |8 q. w m_wchar=new wchar_t[len+1]; : J) \* m: R# T2 y9 x
MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len); 1 E* j" A# p7 k& ]9 `8 e' _ ?
m_wchar[len]='\0'; 6 E4 r6 C1 e" J/ L5 W
return m_wchar; : n( Z0 x* r5 m* I/ I/ z( J3 E0 A) \2 m
} + y H4 m! {6 f5 ^2 U( }
/ G! a9 J7 v% _5 h
void _tmain(int argc, _TCHAR* argv[])
4 z* A8 w; x4 q; n9 b; _ x0 p
+ G. D8 }3 y& N4 O. t{7 e5 v1 y, F% r" J) Y2 E
1 W/ ?1 ]$ h# U2 ]" c CoInitialize(NULL);
6 \- J7 v2 I$ d4 h. G
+ t" E& j# C7 l! G9 V- W8 }9 u MEI_AddCom::MEI_COMPtr ptr; //类似明志一个指向接口的指针2 t/ ^9 {7 h$ A( w! B1 W1 U3 l3 F* f
+ s) E6 x" @7 C7 O* b ptr.CreateInstance(MEI_AddCom::CLSID_MEI_COM_T); //实例化一个类 CLSID_ 类名
1 l5 m n" V2 ~' R
O" Y3 `5 d: m //这个地方有一点点奇怪我也还没弄懂.在C#中的函数是int Plus(int,int).但类型在这里都转成long了.另外就是我们不能直接% n) E' O+ Z# M1 q; O/ D3 L9 s
9 n# o8 c6 ^5 |3 ]* `; w //来个long a = ptr->Plus(1,2);这样得不到a = 3,反正会出错.
5 K9 s- `* R7 C% F //这里函数Plus的参数变成三个了long Plus(long,long,long *).其中最后一个指针得两数相加的结果+ z6 R3 y3 o5 ^2 F3 J
1 U% L( T: F# q2 C long a = 1;
1 ^" N; x% I, x' D$ K6 {$ g, Y( A8 z
long * lPtr = &a;0 |# W9 N, w( q# t! Z. O0 s- `6 }$ F( b
+ T \$ x# D6 A7 _# z5 q m
ptr->Plus(1,2,lPtr); C0 \0 y% M2 w
7 w5 a6 o( C: g- B5 Y9 Z
char msg[132]="";% x% |0 w$ _* e. P5 _+ q
sprintf(msg, "%d",lPtr[0]);9 F/ q' b/ }# k" Q5 y* L% O
" z! w. `3 `6 F! E3 c& a LPCWSTR str=CharToWchar(msg);
! j5 W2 K# c$ A% Z! Q
, Q6 t1 H( t4 m6 y2 e* Y d MessageBox(NULL,str,_T("123"),MB_ICONWARNING);
) X6 z% I7 c! r( a' O* a6 v. U% z: g2 ^
! F; n& N# i+ K" g}
# z/ i+ K4 m: |# }9 \0 ?: I$ I' C# z9 F% b
此时就可以正确运行了.得到结果31 U) ^% b' [7 X5 W" o
+ R" K6 L' N) [" i如果没有正常运行,则必须把dll文件拷贝到有MEI_UseCsharpCom.exe这个文件的目录下.
3 H# g; H; P/ d8 d% B) ^0 x+ j3 `, g" |, |1 Y( a% B( p1 j" n
& R0 y: Q% F5 t# q8 S--------------------------------------------------------------
, w+ e E- j! Y8 g3 Y. c: N5 zC# Npoi库 操作excel 的代码网上很多6 E" E& X& p: `) }: `' |
, A5 b! ?% l# h5 G
// ----------------------------------------------------------------------
6 W* i2 S& ]( G# S) S! i M7 _5 I- X// 使用Npoi创建一个简单的xls文件,写内容. ~) O+ ]2 ~) a
. o: q; k" K. z8 z! O6 j7 eusing System;
6 y1 l+ O' I# husing System.Collections.Generic;
0 k. J5 B$ Z: v Y Uusing System.Linq;- b0 n& p3 K3 O0 h, |& T9 x% \; n
using System.Text;# v q7 J) m8 `' G( m
using NPOI.SS.UserModel;
# _" `3 t: D' x K* dusing NPOI.XSSF.UserModel;# D5 Y' ^: L7 _* F+ s
using NPOI.HSSF.UserModel;
- g t. v, h% C! `7 Susing System.IO;" b& j; U4 R7 [" X d5 T
using System.Data;
+ R/ g" A' [: Y+ ]2 O/ n' G
" {! ~* E2 [% e5 R//using System.Windows.Forms;
$ e4 H v/ C& b/ D
( T; ^6 a A7 s" o) I$ z7 Bnamespace CC: y h! ]" S, R' t3 j8 U, `
{, [* v) {0 F V5 W E
m7 \, Y5 c0 |( j& L5 m9 p9 n& P' Q7 ^# w class Program
. V/ A: [1 h) P B0 E* z+ L {
: Q! ~, ^0 U9 j+ x% v; G% b' w$ v0 p! x
+ U7 |# U% g! d6 ` E3 m1 g) O static void Main(string[] args)( o2 E1 ]' O, }2 ~' Z9 n
{& d* a7 W) ~. o! L2 H6 R3 S
//创建工作薄7 [7 t. @, u4 z, ?7 Q5 o9 {; {
HSSFWorkbook wk = new HSSFWorkbook();1 i/ q2 P2 E2 M8 o- c5 g
//创建一个名称为mySheet的表/ ]' y5 w# A7 A" d8 i* |% u
ISheet tb = wk.CreateSheet("mySheet");
, O# d- Q! a# H y" h! H5 [2 | //创建一行,此行为第二行. d: |4 g6 N* z6 I- y* T* u4 |
IRow row = tb.CreateRow(1);2 o- N$ m [* |
for (int i = 0; i < 20; i++)
3 b7 n. B# i1 g# m {+ g8 `, v$ s2 ^4 T
ICell cell = row.CreateCell(i); //在第二行中创建单元格
5 L3 k2 a: D0 G cell.SetCellValue(i);//循环往第二行的单元格中添加数据4 q% r: t) q% @( C* C5 D
}! f: \% s2 _/ @$ M; h
using (FileStream fs = File.OpenWrite(@"c:/myxls.xls")) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!
B/ a0 {0 R0 X2 h8 o {
, U0 y# O9 Y/ d/ \# |7 V* _ wk.Write(fs); //向打开的这个xls文件中写入mySheet表并保存。
0 Q) u) p ^ q5 D( j2 } // MessageBox.Show("提示:创建成功!");
5 O8 v0 @. _$ A6 i( e$ z }
# U' e$ |- y+ m5 M! P. i/ [) C3 ?
4 ?; i' E+ s1 C/ d" ]( p }6 D/ z4 f' f: Y4 M" |
1 |! \2 ]- p" M% ?
* w2 |5 y- E1 M4 T6 x/ }: \7 V }* ?- R9 A( r* k: B+ ^
+ _$ e# D% U- _4 S' Z* |8 j+ l5 H+ R3 S
1 `" N% I/ a* T}4 s. Q# R" @! J* P- k
0 q# s k. i0 \2 g# ]! j8 ^" S5 X7 Q// ----------------------------------------------------------------------
" U- E- l4 c: w9 K, d8 s. W( t// 使用Npoi读一个简单的xls文件
! x: j B) m8 g3 U9 ^; T7 m8 t1 \
using System;1 X( S j, i: V9 N3 s
using System.Collections.Generic;* `7 V4 [2 E' ` D' n3 {* H
using System.Linq;
; V; i- j( x: K3 husing System.Text;0 D, {7 U8 k+ B# w: p" w( b
using NPOI.SS.UserModel;
- f2 W5 P+ q+ o; i: [- Qusing NPOI.XSSF.UserModel;
0 U9 M" Y) h5 q9 V4 ~) Rusing NPOI.HSSF.UserModel;
$ K4 [' z4 k( q; ~) lusing System.IO;
9 M& L) d7 b+ c- }using System.Data;) R h9 G% f; y5 _: |/ @- K" ^
4 J+ J* [( ^4 N1 anamespace CC
) ]; i& G- C* c# G4 j{
% @+ g/ r3 [# }4 |- D7 Y5 e) ~' P5 {, Q6 e* d+ H& H
class Program# _4 n+ `$ m+ a5 i+ f
{ @, J+ |/ c5 E3 `* W
[1 [2 G% b6 r/ F0 f
6 ?6 D' s3 u- ?$ X/ t static void Main(string[] args)* s- I/ n2 @& H, v
{8 e% f. f6 w" l; Q
StringBuilder sbr = new StringBuilder();* k# k8 Y: A2 ?# {5 K5 }+ g
using (FileStream fs = File.OpenRead(@"c:/myxls.xls")) //打开myxls.xls文件 T) c1 H e. O6 R& P& ]
{3 \9 }; A. D4 y2 y4 D* u5 a
HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的数据写入wk中) g+ _- _6 x" L! z7 }3 v1 P4 m( Y q
for (int i = 0; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数; P3 k1 j* s+ N+ L/ d" w+ |8 r( \% i
{
, m) T+ W1 H9 N5 k" L4 } ISheet sheet = wk.GetSheetAt(i); //读取当前表数据
6 Z8 x! ~+ X/ J- e9 } for (int j = 0; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数) [* H3 L: l4 ^* v a
{
g- y- b8 D% @* V9 Y o7 ` IRow row = sheet.GetRow(j); //读取当前行数据
: |9 F% D }5 W- u% W if (row != null)' g! g7 `5 p% V# f
{
& [! r6 U+ K. O- W7 Z. f2 K1 U' z sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限3 }" v- _) w# e* W5 v1 S
for (int k = 0; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数
" I9 k; C0 w2 O: O {0 H o' H7 ~9 B1 Z: t. C
ICell cell = row.GetCell(k); //当前表格
7 }% x/ _3 Y. a+ k+ O x if (cell != null)
; b! Q# T) B" `! I8 y {, ]. c9 W: Z1 y
sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型
2 E. Y* U" _7 p }
1 K( j9 j# O* u' N }
2 {7 {- M+ q7 K6 X, W }
: ]$ b! u/ X5 p: ~1 O( H4 x9 `$ z }
" T( ?5 h& i* {: A+ k }" [8 f; B' k2 H" a. W8 s
}5 S; ]2 Q. I, x; r- B/ w$ B
sbr.ToString();
1 p3 S' i+ W/ w% @4 @; g- u5 G using (StreamWriter wr = new StreamWriter(new FileStream(@"c:/myText.txt", FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中 ~* M$ {; L3 Y5 t0 I
{6 S7 m2 t! \; r
wr.Write(sbr.ToString());
6 r2 l; r9 n+ b; f: l0 j9 S$ \ wr.Flush();
$ D0 C7 R9 {! M$ m }
! e$ g/ z; g% f; b- E. s
. `+ h5 u. S1 j+ v. Y1 I
0 a3 @5 g4 }9 V! R! Q+ l }2 b- [( J! j) |7 L' @- ]( f
3 q# E4 U3 j% ]
0 R1 D. \- B8 [+ ]
}" }1 O: K: \: Q" y: ^! E
% ~! S* j% \% X g. Q; n" i. Z. [' i: u9 Q) I# y; @1 o3 O! D
3 A2 u: N/ `8 ]7 A% n5 f
}: g2 d3 [+ D7 Y; F7 Z) ^; I6 @' @/ O- w
/ N! {0 E/ A( W
( r+ c. o0 o& A2 e% q. @6 A
然后 自己封装 给 c++用
! U3 L' m' O* d& a5 X& `6 y* ~
) T, D! h3 v9 C0 G, v, |2 X2 [7 ]( ]5 Z* p) r+ V
+ X" F" L7 A9 \) o
' A0 M3 W& A8 o* N S/ u( C" e5 L+ }+ m0 f$ e
2 O5 L- v T2 r' O9 f
0 P: p5 c2 q7 s: \( |8 j5 l6 i3 }! g8 U. w
, |, t' b6 p/ k; a N6 V8 u( ]
; n, G. }& ^' s3 y& g
$ D( [ T2 C5 |5 D% D' r, w# H F
* p7 e2 N6 j( B+ m; _; u8 T
! I3 P- @! C; s+ F' Y8 o$ i1 I( B+ L% [' q1 m: s
! ~0 \, E. m& d, E* e; k2 L# d( V; ~. h! _
2 _" H1 D" G) P& a+ P& I+ h/ \+ t; `6 [$ p% |" A5 Y5 t
. A3 j! m% I e+ t( @ p2 e
/ }: t4 @( n s' [; J
. l% O% ?5 [% s, M* f9 V' G1 S& K- ~6 U; _" H E9 Q
|
|