|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
C# 或 c++ 不用安装操作 EXCEL的方法:c++ 对excel 的操作 非常不理想 要安装excel 而且读写速度也慢+ s6 @" {/ V4 a2 [ K2 [
net 有很多 免费的开源库 比如 Npoi库 (Npoi库 支持c#、vb.net 等语言)
' i9 ~5 [. }5 s% t& E8 m8 C这里我用c# 生成 com 组件 让 c++ 调 / l7 E7 ^' N9 _& U- z! T
0 u' z- [8 P4 {9 |1 [; e首先要学会 c++ 调 c# com组件的方法 (和com注册的方法)6 u- Q* I9 n! W7 q
C++调用C#的COM组件(DLL)
6 ]( L+ M, H( `
; @, b. g1 U0 j" o1 \7 w下面我举个简单的小例子.我用的是Microsoft Visual Studio 2012,操作系统是Win 7.
+ Y. y$ q/ P# X6 b8 U首先创建一个C# com组件.实现的功能很简单,就是返回两数相加的和.
* C, _/ B/ G2 G9 N+ W2 g# U2 D$ L9 M: E- \. c+ y
) V5 k$ C& E, k7 ^( R1.新建一个C#项目 ,类型就选 类库 .取名 MEI_AddCom
+ Y4 m9 R: O5 T& p( |
, H7 h o! V0 J2.在项目中添加一个接口,取名MEI_COM.C++调用com组件中所有的功能只能通过接口来调用,不能直接调用类或函数
9 F1 f& U6 V* f( O& V: R: F: M% a2 e' k
具体代码:( `$ b4 F: h5 S3 ^
% s# A. D" Q+ @! Z" S' _using System.Runtime.InteropServices; //记得加这个命名空间
/ x/ ]& N1 F9 N U2 ~/ z1 @: M) c3 t0 P X% ]7 }, M/ i- @
namespace MEI_AddCom5 w0 j) Y) I K0 F. H1 j9 `! s6 g
4 b# s( ~/ g; m9 n! `3 t{; v0 N# d# Q2 @# a( t
3 t" h/ [1 L+ A/ r3 [' [6 [
[Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的产生可以通过vs自带的工具.点菜单栏上的Tools ->Create GUID,然后选第4个选项.Registry Format.
6 p7 P9 H. d l7 y) S: S3 j* ?7 d! X/ u
//点按钮New GUID,再点Copy.这样你就可以把产生的guid复制下来,然后粘贴到这个地方来.当然那个大括号得去掉.后面需要用到guid的地方也用这方式产生1 u1 T7 |) `' U8 R+ D0 r5 Y- ]! x
& `, `& |( o5 G/ u% A! i- s
[ComVisible(true)]
f& d/ Y. f+ `! [% t& g4 x f; j
; P1 s" K1 R% r( A) s( R* b; L public interface MEI_COM //记得用修饰符public5 w1 l( D$ u9 B# k
& t8 R3 p4 X& N2 j8 e3 z {, x$ J( Z/ l2 F1 @6 b5 g! \$ [. X) n
- b6 n6 q+ Q* V6 n+ T0 r5 O
[DispId(1)] //如果还要添加其他函数就继续来个[DispId(2)],[DispId(3)]加在函数前面
; Z- K# \* X8 ]+ m4 U4 E6 B3 d9 g0 K3 h" l9 s5 }. _6 ^
int Plus(int one, int two);0 u1 U/ B) K6 d
) F0 v E N3 l$ E3 q; Q& n p5 A) L }: p5 L! z. y* ]6 X
$ g" c, T/ l% H
}! k& A) q2 G7 G" p4 O
: p% y* ?% H# c h8 k* K) ]$ q
4 B6 M: s; q8 I: t$ ?3 T
) ]$ _$ F3 K6 V1 @8 G7 A/ M5 u3.添加一个类MEI_COM_T,继承接口MEI_COM,具体代码* m5 N8 x/ `. y4 {3 z& ~
4 L& r: \4 ]3 f' X0 E2 ^% iusing System.Runtime.InteropServices;
( ?' J& o$ e- X5 ?
( o7 @! {- m @4 K" [ Cnamespace MEI_AddCom
5 A: O f# A' w5 o; J4 v5 D6 K7 q' J, c* C0 \5 n3 S0 \8 e# _7 @0 i
{
" {" X' h( ~ X0 P) @5 `0 v+ L
6 G6 d: S X4 b$ B9 G' d, d; X3 n2 e, y [Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]
& a* R8 T7 F+ O$ S: ?* t8 O) M! E2 y' M }' D
[ClassInterface(ClassInterfaceType.None)]; C H& H1 Y9 Q
( i f( |# O2 X7 ^! u: A% ^- V
public class MEI_COM_T : MEI_COM4 o* D" C: J: y
2 j# X9 i1 ^- P, d {
2 E: Y% ?7 h% I3 {
9 w* n# S5 U; O* C2 K4 d public int Plus(int a, int b)+ U! m- _3 v! I; `$ M+ P" J
1 q: w, p- t) C1 W4 l {
* t/ l; _1 i$ D
& A' z S6 M& R# C# @7 r ~ return a + b ;
( m x6 r5 Y! q& Y4 n0 H- D
* \% L O6 T, ]5 s4 U }7 L' j Q5 ~8 q. u: p' `
0 `/ [' K3 w- d8 o. f& U" t8 ?, i; e
}" M+ v) v+ j: g5 r4 R; e0 g
( s" ^1 i2 M. _; I. y' p5 w* r& N, z7 d
}
+ Q2 s8 x% p/ `) f
0 K4 B, k6 ~3 y. s# |4 u8 e
Y' K: j+ G' V! @9 c9 E8 e0 {- F5 g
; ?2 c8 S$ i+ r8 e4 {2 ?/ ]* ^4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)].3 d" n# s3 ^6 {) Z0 Y' N* M
6 q$ Y6 Q) c+ P) S0 U; M+ }: g
右击项目名打开属性窗口,在生成里,选中 为COM 互操作注册" O, R# p0 y% Y8 e$ t3 G6 }7 y. x5 b
1 ?7 s& I x$ X( ]( ]9 `2 I
- F3 {( h( h4 ~1 L, y6 B
5. 生成->生成解决方案
2 \) o& M B' H4 L7 V* \ 注意 这个时候 生成 非常缓慢 3 S3 E- S' J7 P
直到 出现 成功 1 个,失败 0 个,为止才 操作一下面内容2 F& p: m8 D, V( p, h9 e& |1 _* t
1 ^- t$ ^* \ p. K3 [7 |0 |) S
/ L! Y# D6 `2 u# u' n4 s5 i---------------------------! J$ `' y# C5 n& _8 W
b, M( M4 b$ q' ?1 w
1.调用前要先把com组件注册才行.$ H4 w9 I3 x) q: M O5 v( g
# R: G- P$ }. _* q: V使用C#创建并注册COM组件 C#不能直接创建COM组件,因为其生成的DLL属于程序集,但可通过“使程序集COM可见”选项来支持COM。! O" o8 {3 A9 I9 R) _
以下说明如何通过C# 注册、注销COM组件。 * @1 f2 Y+ I% |" ~6 o: R
) e, g* V0 j5 V; {
为了能让生成的DLL能够进行COM注册,需要进行强名称签名
! n1 Q- W; t+ w+ l3 ^% } `打开COMLib项目属性,选择签名,勾选为程序集签名,通过下拉列表选择新建,弹出创建强名称密钥窗口,输入名称,不勾选使用密码保护密钥文件。
& ?. V( S/ j' y创建完成后COMLib项目中将出现后缀为.snk的签名文件。
0 c& e' o6 w& Z3 \, ^% H B最后,编译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文件。
$ X, U0 c) i* {8 e- e卸载COM组件: 7 F8 I' ?5 \$ ^" f" c& g
与注册过程基本相同,只需将命令改为“RegAsm /u D:\ COMLib.dll /tlb: COMLib.tlb /codebase”。" A/ ^6 Z+ n# @
" U4 j- K9 H9 \& T3 ~) O; J" h
8 t" W/ @* m3 l) G4 q3 F2.注册完了就可以在代码中用了,先新建一个C++程序, 类型选 Win32 Console控制台应用程序$ Q1 I5 E6 t3 e, m( Y9 v1 z
$ `5 u& C" B6 V6 v2 c
名字取MEI_UseCsharpCom,点完成
4 V. ]* o/ t0 @& v+ k `! _1 Q! m4 E! _; {% ?- T6 P
把MEI_AddCom.tlb文件拷贝到项目的任何目录下.我就放在D:\MEI_UseCsharpCom\MEI_UseCsharpCom.& X# {5 F4 I: h* {4 w7 Y
+ ?" ]- o& P" x8 E8 h) W我们会看到一个MEI_UseCsharpCom.cpp文件,双击打开把默认生成的代码全部删掉.敲入下面代码:3 D* W1 e2 ^( E! C
8 D/ w6 g& n8 G' g( ]9 [6 T2 P4 y" b& P9 L) ?/ f
#include "stdafx.h", v/ C+ |$ F6 o
#include <windows.h>) v( W1 u: [( V" }7 _: V
#include <string.h>
7 c$ ?& D7 |' [! K3 t4 @: s/ n
#import "MEI_AddCom.tlb" named_guids raw_interfaces_only J. {. A, P! p
: i' H# c& R! a- M: lchar* WcharToChar(const wchar_t* wp) //wchar_t转char*7 }2 N5 g/ A5 o; u: r* v
{
W: |4 a$ @9 U) t1 {9 A b4 F char *m_char;" d0 ~$ `% ~: y$ C0 f
int len= WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),NULL,0,NULL,NULL); ) N2 Q3 S* }8 H; T; J; o o) h
m_char=new char[len+1];
9 F1 V1 ]0 r9 L WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),m_char,len,NULL,NULL); : `7 g8 `2 z2 j6 [! ?6 P6 T( R2 A
m_char[len]='\0';
" y- s; Y2 r+ r/ S$ h$ o1 C* F return m_char; ) g. K1 Q6 o S8 P/ }- X1 T
}
9 m: Z$ _. v% n( @; R. q' }' |3 @wchar_t* CharToWchar(const char* c) //char*转wchar_t
5 g, [' _$ t8 p! _% p _, V7 }5 B8 }{
3 y! O- j- ^( u wchar_t *m_wchar;
9 T, B3 m9 I' `) C# o+ M: n int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0);
! F6 T8 @5 x6 V, y4 L$ ^ m_wchar=new wchar_t[len+1];
' X1 D1 ]$ W' O0 H+ w; o8 x& G MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len);
( Y2 ?/ `: J; X+ J) r m_wchar[len]='\0';
) g. I( k! ]; M0 q return m_wchar;
3 b: L- Y& N. K2 K$ t}
7 H) T# a# } z9 y8 a' E' t" i; ~
$ g( x+ i. @% d: q0 ~void _tmain(int argc, _TCHAR* argv[])
/ E z0 V" z( U/ S" p4 ?) x0 E/ _" P# d( F6 ^+ x6 W
{/ t& T; x2 E6 E+ _ ~: v
, o- e1 O7 m/ S* Y CoInitialize(NULL);
/ p& N, K: P# C
, `# O' j3 ?' |$ x: J MEI_AddCom::MEI_COMPtr ptr; //类似明志一个指向接口的指针, |8 I$ I! @" O M
5 N5 j ]( ]6 K: U) f6 u
ptr.CreateInstance(MEI_AddCom::CLSID_MEI_COM_T); //实例化一个类 CLSID_ 类名; [) t2 E% p: ^( Z. [
( ^7 c# }9 A( K$ R6 ~
//这个地方有一点点奇怪我也还没弄懂.在C#中的函数是int Plus(int,int).但类型在这里都转成long了.另外就是我们不能直接' S0 [+ i" e' r$ H8 `4 E. e7 ]+ p4 h
; y' n% [+ l- `/ R0 t2 \- W* K$ K/ y //来个long a = ptr->Plus(1,2);这样得不到a = 3,反正会出错.- \- H: ^: R8 W" F: l& ~9 Z$ X \# D
//这里函数Plus的参数变成三个了long Plus(long,long,long *).其中最后一个指针得两数相加的结果
% V! J* i. {3 V, g8 n
# X3 `0 v s3 Y6 F- x* ~ long a = 1;% v5 X9 Q U, ]4 D& m- z. X
( D* b* z: W1 M" R long * lPtr = &a;
- ^: |. W0 R9 W: p. u P% |5 Q# N% k5 I! e8 Q7 `. ~" g
ptr->Plus(1,2,lPtr);
a8 R( o& |/ C! P) ?& f6 E' |9 Y0 y2 z
char msg[132]="";
& a. x, ?! M X: ^/ u sprintf(msg, "%d",lPtr[0]);$ k8 s. T" y. y+ v8 S
3 A8 }/ C5 f$ h4 O( D" x* v LPCWSTR str=CharToWchar(msg);
( o7 p" m$ j- q/ Q4 s3 @8 b! l
! T d O0 D2 A0 l$ T% r MessageBox(NULL,str,_T("123"),MB_ICONWARNING);
. Z) C& _9 Q+ w& T1 f% u& U3 p! M6 P, Y. e9 n
% W' U* a$ a, w
}
1 k$ O q4 J# Z
5 O- y4 z6 c' y% L+ \; S此时就可以正确运行了.得到结果3
. A- _5 r$ G4 J, R ^ r! U; I* i8 B8 h& s6 b2 X
如果没有正常运行,则必须把dll文件拷贝到有MEI_UseCsharpCom.exe这个文件的目录下.
K4 i1 g% ?, D% q3 h9 T' R5 M, m' G% G {
! L& |8 N, y, Z. R3 L. U--------------------------------------------------------------2 V% E1 p( N0 j7 O/ D
C# Npoi库 操作excel 的代码网上很多
8 t3 q/ I2 {$ \! p' K& ~4 U( t9 F4 N% C W
// ----------------------------------------------------------------------
5 ]9 H5 \3 k0 p# P3 }3 _// 使用Npoi创建一个简单的xls文件,写内容
; l' y* W9 Y6 ~; X1 s# U" v& a* m- R' U0 ]3 Q
using System;
# X; _5 P8 h8 \% y4 wusing System.Collections.Generic;
+ m* F, d: R& W( Jusing System.Linq;
0 i. d6 r) Q1 C- f7 Susing System.Text;
) |+ c1 l( V6 \3 q1 z& q8 m3 C1 Q" rusing NPOI.SS.UserModel;4 a6 t+ N1 t! O! G( m
using NPOI.XSSF.UserModel;# ~% @( A5 d0 I
using NPOI.HSSF.UserModel;
" J" f- f" X0 b0 x6 b3 v+ wusing System.IO;' r$ a8 N9 x7 c2 v w8 V- A. ^0 y4 F
using System.Data;
- l0 i/ ?+ s6 ~& _2 |7 }7 N$ M1 B/ J0 X" Z; s4 a
//using System.Windows.Forms; 8 s: q4 Q+ d: ^6 F" y9 ^5 i
% n$ W+ y! R: k8 r7 U2 mnamespace CC, M. X6 M3 a/ C& D; U3 B
{
+ ^0 z1 i$ F% ]5 w; T! T1 I7 T9 w6 L
class Program2 ^* Z2 {) P: A- s) G8 p: j
{( K3 {0 g0 \7 k7 k% V1 D1 ]0 u
3 I* p9 ^0 E; p8 j# b; f/ q
) R! `+ w; m5 w# x
static void Main(string[] args); h( W/ c# R; a0 z! g
{" I2 e' d+ @5 x! e5 ^7 A# E
//创建工作薄
' d) h7 u" `/ L- ?$ z HSSFWorkbook wk = new HSSFWorkbook();
+ a2 ]1 u1 K1 [( L+ ^' H& v4 K //创建一个名称为mySheet的表) g: Q! t9 b9 J5 Q3 ~
ISheet tb = wk.CreateSheet("mySheet");. t3 e$ w4 k* ?# W$ O. n
//创建一行,此行为第二行& i' U; u, {, H
IRow row = tb.CreateRow(1);
4 E4 V& {/ p. B4 K% ~ for (int i = 0; i < 20; i++)( m# v' J! j" M& n8 X; R
{
3 h# G: C% `2 d& G! [/ Q7 ]/ c: L ICell cell = row.CreateCell(i); //在第二行中创建单元格
6 j! a& u& I/ G# B cell.SetCellValue(i);//循环往第二行的单元格中添加数据
( {' F: g+ U$ f+ s4 X5 | }3 {% m; L1 ]! ^: f. ^
using (FileStream fs = File.OpenWrite(@"c:/myxls.xls")) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!9 X6 Y1 b6 L# n' O% v) {
{. a* t0 Z b5 i
wk.Write(fs); //向打开的这个xls文件中写入mySheet表并保存。
% T- O# y2 [' A( A, E // MessageBox.Show("提示:创建成功!");% O& [1 T% [+ ?( y. i: O2 O; Z
}
& d6 c' o I* [& H! M# c: |( z. [2 z* {% O7 \$ [
}9 M x& E* \/ U3 q% p% m6 i
& {( u- r3 a$ m$ [6 {1 r
2 p3 s* q. l+ u6 J1 t9 y5 W; k }
; C/ _! ^' F I% }& E& T7 _1 y7 f& ~2 N% f. n' q
; o! P5 p, H/ O0 w# U: h3 ]; s/ x0 j$ C5 s2 ^& \: b
}
2 `! M) t7 p; B2 k" c2 y( R8 M3 c5 q/ H
// ----------------------------------------------------------------------
7 a: d+ x$ {+ V# m* E& u0 g// 使用Npoi读一个简单的xls文件
* h' Y. K8 [, V6 \5 C# G2 a' X9 y D" V; p" Y
using System;
2 d" u8 G9 H G4 n5 p! S9 I# a& n1 kusing System.Collections.Generic;# K9 l! r) d2 M0 g( f @/ g2 T0 t
using System.Linq;
& J. G+ N4 F7 N( e0 m5 m0 b# Wusing System.Text;
0 q) X7 T8 ]0 a" P- B8 Tusing NPOI.SS.UserModel;
7 i m8 Q# x+ f; w4 E5 p7 M" ^using NPOI.XSSF.UserModel;
9 i" f/ g9 ]) Y' |# Vusing NPOI.HSSF.UserModel;
" _5 S8 L) L$ r9 Cusing System.IO;
4 |. R& Q$ e' L/ ^, }using System.Data;
@5 E6 h& I7 R4 b d9 R S) l9 \5 Z6 X
6 N' B Q% Q; K& w( h f# Enamespace CC0 D5 Q7 U6 Y$ ^' u& f
{8 ^% }; v9 h4 l
3 T$ d! q" N0 m$ ` Q5 P
class Program( E( Y. I0 C) ]( I1 `0 d
{) f9 s7 X: o4 S
. ?7 b p, F, x7 ]! g( N- f
( H* ]/ t3 K5 J+ I
static void Main(string[] args)$ T, f! S/ |' Y0 T
{0 w6 I" Q1 c# X9 d9 b0 H' ^
StringBuilder sbr = new StringBuilder();, E) {5 h. T& @; x, f t
using (FileStream fs = File.OpenRead(@"c:/myxls.xls")) //打开myxls.xls文件
$ x8 m/ S7 p7 n$ M0 e! d' ]7 P {9 e1 P! o+ t5 X* h5 |9 X a5 f
HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的数据写入wk中
* G+ c8 m5 b2 e% }: I6 s8 R: { for (int i = 0; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数
8 M9 Y2 T6 C- l {0 B+ P! I0 D9 j, z4 {0 k
ISheet sheet = wk.GetSheetAt(i); //读取当前表数据
1 ]' N" v8 q8 u for (int j = 0; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数; N6 D& u5 w% J7 o3 N ~- J3 R
{
, p) J @" v9 T, S& N( Q IRow row = sheet.GetRow(j); //读取当前行数据
/ j* ] \# H4 R+ f1 o if (row != null)( N2 M- v& s; K$ J! U
{$ X( p- C+ s4 A8 i/ U. y# |
sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限
3 S4 X! k* n* f. D2 [ for (int k = 0; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数 b/ A( I E4 s9 W% _0 H
{. s) w. j* F( T3 X$ J, P/ G
ICell cell = row.GetCell(k); //当前表格$ k$ [; G. c7 P% n$ b3 w
if (cell != null)5 S, \) z1 ]: N& D
{8 j- t6 H0 ^. Z) u
sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型* |( q1 l; m) l. X' ~
}
' F* t! C3 }% m# \, v# j: U# K }0 r. |4 j! a6 b+ Q. E
}
* R, p5 W; i) {8 c1 S }- {1 y7 N2 J6 R# w5 P
}0 p7 S* }: Q: A" V+ t2 W
}4 N% y/ _- o0 v3 u9 A% j
sbr.ToString();
, \) ^1 Z8 t9 d using (StreamWriter wr = new StreamWriter(new FileStream(@"c:/myText.txt", FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中
- v6 G7 ~. ~8 _ {% F" @% T* J+ ~2 ~+ W" C" h6 A
wr.Write(sbr.ToString());
6 |" f2 W; }; Z( E$ @ wr.Flush();
6 Z- j# X: w1 `; b }- H+ l$ V$ R) k# i" u/ J9 Z2 w% Y# S
) u7 N3 W; i' u! R
# z J' D. R( u& S# X
}% ?: V) R' [2 X! q) m9 J# L8 ^
' }$ p7 M1 g0 v6 l! n; k4 X3 [% L$ J& `* @( ]. `' X
}! b, ~' i. ]: I: \
3 Z- y( \5 K, _& f
9 X9 f! ~; A. r2 l
3 o O) x) |' X" E}
7 ^* y* F% {5 I! e
# d* |4 T# P- ^0 W- ?4 c0 P1 t. G0 e U
然后 自己封装 给 c++用" R0 a+ Q: x+ P7 _3 ~
( k' T1 v8 [* O
/ Q/ B6 ^+ M5 c$ _' w/ q
! ]. `$ l" M' X
1 B$ Z% B9 r# P/ H4 l1 m7 ~
, X D5 E" ]: V$ p/ r* f0 x
# T% m' G c9 G! I4 s J3 q$ A8 ?* T3 u* I" L& h9 C8 a
$ ?1 F0 E' k/ x3 g/ }5 V# X. B, Q
" J% M' }4 S; T! A* ?5 y) X/ r
3 X6 g" i2 O9 T
2 x! }4 j7 ]& |9 V! D& r. o& w0 C7 n6 y' Z8 H
7 V0 V/ m6 f9 v1 Z4 e( n, {( r% }+ _
, P S' U1 p% C
% _: L( P0 U6 j
1 R% i* A u+ e9 m; q( t3 U' D3 e q/ X/ v
3 V+ B7 h, T; ?8 ^/ x% I4 C4 s. L
) d- i; H9 t9 l% Z f" D5 X
) r7 r# g. U+ ^$ w5 |7 i1 [ C$ V; x0 A) l/ v, I8 i) H) t
6 k& B" c! t; d% B5 F |
|