|
|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
C# 或 c++ 不用安装操作 EXCEL的方法:c++ 对excel 的操作 非常不理想 要安装excel 而且读写速度也慢" S$ p. W3 V! x9 x# t
net 有很多 免费的开源库 比如 Npoi库 (Npoi库 支持c#、vb.net 等语言)/ g: w i" Y6 d" Q) x/ z( S6 Y
这里我用c# 生成 com 组件 让 c++ 调 4 B0 l4 e3 ]) Y: H% Q; E
9 g1 V3 C4 @& g" W
首先要学会 c++ 调 c# com组件的方法 (和com注册的方法)
7 z7 }7 U8 I6 x8 R- x& a2 nC++调用C#的COM组件(DLL)! w: F' e0 y* K3 n7 Z1 ^, {; p9 N
# V7 {' p, N/ n' o" d: ?% l下面我举个简单的小例子.我用的是Microsoft Visual Studio 2012,操作系统是Win 7.
- Y2 F l8 v- E% n! T0 t. C; @首先创建一个C# com组件.实现的功能很简单,就是返回两数相加的和.
/ p. G/ E0 m' T$ O! c5 ], q6 }. x; B7 j' x- x! B- [
2 I2 O* B* v: P: D% i/ h% u1.新建一个C#项目 ,类型就选 类库 .取名 MEI_AddCom" {9 ]& ]8 r! J5 a( _
- X+ c! [# q0 h2.在项目中添加一个接口,取名MEI_COM.C++调用com组件中所有的功能只能通过接口来调用,不能直接调用类或函数3 A! ~- W4 w" ]( D, w) C
/ F6 q/ [$ w0 C/ t, a具体代码:
9 e, l! b2 A3 |% C7 e' ?7 S
) f. t( E* x0 }using System.Runtime.InteropServices; //记得加这个命名空间1 v% M# r: r) X9 |3 y, M X# g; w
2 t* ]2 s. W0 |, X) X0 E& dnamespace MEI_AddCom5 n B/ g2 K6 g
J0 o3 N9 I' v2 C$ K# p p. S8 Z
{
3 |: m9 f; [! ^8 ~# e" z: k9 c# s
# R- b5 K2 H0 ~: u4 Z- d! @: j" d, H [Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的产生可以通过vs自带的工具.点菜单栏上的Tools ->Create GUID,然后选第4个选项.Registry Format.
. L7 J, F# l, V5 y' L& p: O# m9 c) ~8 }( b9 F4 u' a
//点按钮New GUID,再点Copy.这样你就可以把产生的guid复制下来,然后粘贴到这个地方来.当然那个大括号得去掉.后面需要用到guid的地方也用这方式产生. ^, z5 z' z; M' c8 E
* R5 p% j0 j* {% y3 f [ComVisible(true)]
/ I; |7 ~3 x$ Z7 M3 z/ S! ^4 _9 q% h8 T C8 M& {$ z% _ z+ H, b+ |
public interface MEI_COM //记得用修饰符public
8 O8 C- k9 k5 _+ f' X6 t" b
% l1 A& B7 `5 M6 i! `1 i: F! s5 }" w {
. d- B$ X! n( b" y" h
7 f5 b- Q1 r h6 C; I [DispId(1)] //如果还要添加其他函数就继续来个[DispId(2)],[DispId(3)]加在函数前面
" R3 e% X8 k) G l) A
1 g" O/ \! p* b X* n int Plus(int one, int two);$ D( y B( X5 P5 o7 E
! U8 j3 H% }) q3 V4 p+ @ }: h" w0 z' {4 |! {- @1 B$ t
8 \# h( A. {! a}
1 E; C% K& @( V& @
9 p9 F6 f. i3 L J' V
# J; g: {8 ]* Z2 k' _( C/ I0 G6 E6 Q9 q
3.添加一个类MEI_COM_T,继承接口MEI_COM,具体代码
) U5 i1 Y0 {9 {
+ S2 J' o3 `# s' l% }using System.Runtime.InteropServices;
8 b" x N r" [- _$ ]
) y2 M U7 A! ?& c; Vnamespace MEI_AddCom
1 `% B k- z( u, y4 J k% }* W- m
{" u: f2 d6 ^# a% w. _3 c7 w9 x
. s- n( U* C' ^8 u7 Q* b [Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]
, C. }. K8 j: U4 \6 g
" Y ^- P( Y. Y* J# ?& q# y [ClassInterface(ClassInterfaceType.None)]
& P8 o5 a2 ^& [+ p
9 w- s( ], B/ V# b9 j1 O public class MEI_COM_T : MEI_COM
6 s! A6 A4 _0 g$ W+ n$ g9 a5 _3 d& F
{- M w6 e8 m9 I6 C. w
0 T& }6 \2 f5 X( F' _
public int Plus(int a, int b)
% L, L' p8 ^8 R( m& f6 w7 x/ m4 N; _1 v( _" y& p/ Z" D* N
{
0 F% a" l& Y' {
% k* S( w) q: J t* _ return a + b ;! Z w3 x) ]6 ?! y2 J8 J2 x1 P1 P
1 b% t% j2 Q$ O, v i
}
- g/ |0 m$ w! Y7 M: X
5 e/ k% B$ K3 s }' f$ l* B) j( L) }; h' H" Q0 v0 {0 H
/ g: t( F; l/ T( x8 W i/ N, y& p
}; O8 p4 @, N2 L' B/ n2 J4 i
" d3 ?% [* O# P# n6 D& s! ~3 l0 k0 P# z: a- S
$ Y( y) S( O8 R% y% ]9 x
4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)].' [# t( M$ u, A, T$ Z. E1 q; q
1 o1 L6 X+ J/ | ?. d* f右击项目名打开属性窗口,在生成里,选中 为COM 互操作注册6 O- p8 |% W/ G7 O; I
1 z% I( U+ ^% b+ Y7 p2 F5 }& C
1 p5 _4 h8 s# T5. 生成->生成解决方案
' w& s5 d! P. d# P 注意 这个时候 生成 非常缓慢 4 d; b( K' @4 K! C! P. l0 E7 C
直到 出现 成功 1 个,失败 0 个,为止才 操作一下面内容4 N' k- I- I3 T: G3 M) s
3 z" c* V' J, L6 @' F* F2 f
8 `! `' r3 u% S* p5 q2 R( j- H
---------------------------
4 b4 Y: n2 E8 ?, o! S( s
! v1 `; y$ o2 D/ j1.调用前要先把com组件注册才行.
- N {$ G% h7 Y7 R" ?' v H6 y# t7 y; J" z- S# _. T
使用C#创建并注册COM组件 C#不能直接创建COM组件,因为其生成的DLL属于程序集,但可通过“使程序集COM可见”选项来支持COM。 H8 o% D4 {! f! O8 H; p" c. G
以下说明如何通过C# 注册、注销COM组件。 ) A/ ^1 H6 W) ^- o+ J* d) {4 x$ X3 e
. I, A5 d* R8 N- J
为了能让生成的DLL能够进行COM注册,需要进行强名称签名7 |- M! h, r8 E- B
打开COMLib项目属性,选择签名,勾选为程序集签名,通过下拉列表选择新建,弹出创建强名称密钥窗口,输入名称,不勾选使用密码保护密钥文件。3 B# J4 i: \- T3 l
创建完成后COMLib项目中将出现后缀为.snk的签名文件。
" ]2 T v* C. B- J最后,编译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文件。
- n/ W* _* x% p o! N" x) f$ `卸载COM组件: & d8 W& M$ n s; e0 e, ^
与注册过程基本相同,只需将命令改为“RegAsm /u D:\ COMLib.dll /tlb: COMLib.tlb /codebase”。2 p: `. j1 o8 q; w
8 Z) C$ p3 r) v u! e4 C
- P- x5 k$ z3 D8 s4 w7 R
2.注册完了就可以在代码中用了,先新建一个C++程序, 类型选 Win32 Console控制台应用程序
- y; m3 [8 W- K0 F, y
7 g0 s; @$ x: D# l2 f名字取MEI_UseCsharpCom,点完成
0 y2 ?& }, ~8 b4 p; B5 l _1 f5 G' @* X7 r
把MEI_AddCom.tlb文件拷贝到项目的任何目录下.我就放在D:\MEI_UseCsharpCom\MEI_UseCsharpCom.
; o% }, J! s0 B5 w0 s( A, p: j$ W% {% D' l' l& g5 R1 s
我们会看到一个MEI_UseCsharpCom.cpp文件,双击打开把默认生成的代码全部删掉.敲入下面代码:- @' u3 A0 ~' Y8 C7 T; ~
1 f. |; t# v8 T7 }* w2 P
* c7 f. |( e; U% p% f$ P#include "stdafx.h", J' |0 ^8 r0 a9 T- c1 f- l: B
#include <windows.h>
8 `/ Q8 E ^5 B- J5 ^+ s#include <string.h>
: D2 ~7 _, y7 Z" ?+ C2 w. o0 Z- n8 D
#import "MEI_AddCom.tlb" named_guids raw_interfaces_only- Q8 U2 r# F# ]5 |& c+ n
& R. j+ ^, c& Q. w& K. fchar* WcharToChar(const wchar_t* wp) //wchar_t转char*% c( c" a) j& G9 \- x- q
{
' h8 _' P. Z$ d* Z0 @6 d char *m_char;8 E* U f1 r3 X2 @/ M: T* b
int len= WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),NULL,0,NULL,NULL); , i4 _) B, y' W7 y
m_char=new char[len+1];
' K; f& ? }6 r" A3 |3 x& I( f WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),m_char,len,NULL,NULL); " b7 p5 |5 r' I% L( J5 j# k
m_char[len]='\0';
* R% ?( t8 L J2 l( k! y/ ? return m_char; 0 \& G3 f0 `/ H+ |1 r$ i- j( l8 j
}
% a; t2 e ~1 L: i9 ~5 Cwchar_t* CharToWchar(const char* c) //char*转wchar_t
# E- p: }2 G9 y# p/ x) e/ H: v{ 2 U) N, P1 d, ]' y( E. X
wchar_t *m_wchar;
* S) y6 c5 L$ l2 C4 }) I7 Y5 I int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0);
8 U* y1 t. a3 R0 B& ~9 c- [$ u! C m_wchar=new wchar_t[len+1]; ! C; y+ w8 I- y7 [: @
MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len); 4 L$ w' W; z& X2 j4 k8 J- M1 v
m_wchar[len]='\0'; 4 e h% E% \0 D; P1 N
return m_wchar; $ x4 p% \2 G0 |6 k: w
} 0 D5 d7 t3 m" ?: @, T
; s2 F1 t0 f+ vvoid _tmain(int argc, _TCHAR* argv[])
: x* D) S# E* @% S y8 Y
( w# w# w9 [7 W* I/ U; w{: U, b0 @ L+ H! ?: _- `
1 C7 c! r9 J0 g% H8 H8 G { CoInitialize(NULL);
0 M; d2 b4 K. A0 T# k# Y
& f! ~. X( h" x; { MEI_AddCom::MEI_COMPtr ptr; //类似明志一个指向接口的指针) b R- V- K9 H8 m4 h
5 W/ x! A' s$ J( T- ?* t, @1 H
ptr.CreateInstance(MEI_AddCom::CLSID_MEI_COM_T); //实例化一个类 CLSID_ 类名
* h; a: D- Q# n5 M; c" Z* c3 q; F( S; _1 K
//这个地方有一点点奇怪我也还没弄懂.在C#中的函数是int Plus(int,int).但类型在这里都转成long了.另外就是我们不能直接5 @' ?+ {" c6 S9 E
1 x' y! D; t" K* g3 W, ]
//来个long a = ptr->Plus(1,2);这样得不到a = 3,反正会出错.; n( V* Q! _4 ~' h2 J9 Z& p
//这里函数Plus的参数变成三个了long Plus(long,long,long *).其中最后一个指针得两数相加的结果/ c" i; M0 ~8 w1 M, K" ?
6 A+ g/ m \# ?, ~0 Z0 Y
long a = 1;7 o6 u( J- ]0 Y: B1 X! R$ D
, X" c0 P& [; K9 b; D4 z
long * lPtr = &a;* ~2 g6 U6 A& x% G1 e3 m! ~
$ o. r7 @* m9 x5 O; `+ k, ^ ptr->Plus(1,2,lPtr);
4 Y( e% f8 o. ]3 x( l. m% _
6 \9 y4 Q6 s; { char msg[132]="";
8 ~6 ]) f. q- ~7 e) ~/ k9 l sprintf(msg, "%d",lPtr[0]);
! i2 O5 ~; O- [3 V2 C P7 `' x3 S, \+ f' `2 V8 t4 S6 A l& J9 X
LPCWSTR str=CharToWchar(msg);0 ~. u! A9 p& ]" Z+ e- C. K) t3 p
+ y7 W$ L! [. v% `: h& P" U
MessageBox(NULL,str,_T("123"),MB_ICONWARNING);9 }# G$ Z0 y; A
2 O6 l$ K: ?! B3 l" {. w
7 y/ \, ]+ {# `9 K* S6 O0 m( q}
& d- G$ |7 d# Q" p" N
3 o+ G4 F0 p. A0 O/ `( W此时就可以正确运行了.得到结果3
, @6 c, B; O5 a4 z. a3 V: S, Q8 N9 |6 L M. X8 S |$ }
如果没有正常运行,则必须把dll文件拷贝到有MEI_UseCsharpCom.exe这个文件的目录下.
* y& P/ v8 i* G7 w5 G$ Q8 c: q
+ T; o' b$ a: s5 J" \" T" B; y& L* ~ i: E! C x6 x% o% j0 {
--------------------------------------------------------------
7 I. K, A3 V' U# [' L$ nC# Npoi库 操作excel 的代码网上很多) b+ d: Q' B% @
1 e: |& |1 s4 d+ ? B: J; q
// ----------------------------------------------------------------------
6 f7 s: {% t7 b3 s// 使用Npoi创建一个简单的xls文件,写内容
0 P$ c) t+ X$ K$ J [1 K7 i
5 l" z# J; F) | t. P7 e" Eusing System;
2 y8 }. a" l, D- S! i2 m7 xusing System.Collections.Generic;
2 Q1 o) P. d1 I, Rusing System.Linq;" `- E n2 V& N3 M
using System.Text;$ P4 `% ^8 b+ z
using NPOI.SS.UserModel;) [, ^/ w, N4 W6 P+ n# u
using NPOI.XSSF.UserModel;2 Z- _5 E1 _ h( m) ]9 \
using NPOI.HSSF.UserModel;& D2 ~0 m' Z& I6 |' b
using System.IO;
; e- M9 y; l5 c' D: X5 z, i' f& ^3 F0 Q6 Jusing System.Data;
2 X7 Y' |1 s% a& B. R
1 {* p3 W, R" _$ r& B//using System.Windows.Forms; 4 W; A, G* I" A4 o
- E( ~0 R2 I1 T4 xnamespace CC
5 `5 y# P- M# F6 J{( p* E& v% K7 L8 [+ _
8 ?# k! ^7 h$ d6 g% p) m
class Program
7 Y; m1 j- o% E3 Z; ~) Y0 J: u {
- h [% S0 R" W2 m1 J( I: t- d% `
' X* |* ^( Q% B static void Main(string[] args)
' v0 g3 f: Z& L. p {& B7 @; L P1 i$ G) f( n. G+ D
//创建工作薄1 x" e7 D+ s3 F( b1 q
HSSFWorkbook wk = new HSSFWorkbook();7 _7 k' O4 C$ L$ c
//创建一个名称为mySheet的表
% Y! f3 l- }. t/ ^& G0 K6 y( p. { ISheet tb = wk.CreateSheet("mySheet");" [ r. I& d w- T
//创建一行,此行为第二行0 u* d. y6 u2 w, r- m x! [3 o+ y
IRow row = tb.CreateRow(1);* ~, _4 D& X- @9 {2 G% h
for (int i = 0; i < 20; i++)
, H! Z; P3 \* W1 l. v# H% ~5 G: B {. m" O* B* O" p( ]
ICell cell = row.CreateCell(i); //在第二行中创建单元格6 F& l# g# w( Z' D- H
cell.SetCellValue(i);//循环往第二行的单元格中添加数据
5 j) I1 N) C2 g2 A/ H9 D2 C' T }
5 L3 m4 I+ M4 S" z- A using (FileStream fs = File.OpenWrite(@"c:/myxls.xls")) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!
8 `! q7 [7 `, a+ _# p! e' g {
( E, G4 h+ `3 Y. o& `+ y wk.Write(fs); //向打开的这个xls文件中写入mySheet表并保存。
6 q$ D/ O& _1 P9 w // MessageBox.Show("提示:创建成功!");
$ T6 J K m/ b" W' G0 U }6 F8 L* w: f& ? ^
: h+ @! S: ?/ \0 e6 ]
}
6 G; k3 l- s( B# M u( u8 t4 a2 u3 C
; q. a: t) l! |; _6 w" b }0 {: r2 _! `& i1 {
- u9 g9 D# I! n. k1 H: d& A3 Z
5 n2 G$ Z) n* E6 v& Z9 t" k$ s1 L1 g" a" }! {; ?7 m
}
# A: c" M6 c7 D$ a
* s! h# L% ~+ q9 L// ----------------------------------------------------------------------. K) S4 @; ^ y7 e, A
// 使用Npoi读一个简单的xls文件1 X$ G& Q j) A6 F2 p |2 G
# L/ ~0 N* S) D: u* `& V" Jusing System;
* A7 v* e* v; rusing System.Collections.Generic;# K0 W4 b5 G1 @
using System.Linq;2 ^, X/ F* `1 A7 u
using System.Text;
; r U" F& b1 C5 x$ O2 |2 S7 |using NPOI.SS.UserModel;' r* c& R# X j* w. I% l
using NPOI.XSSF.UserModel;
" f4 @2 D; r" s% r6 [using NPOI.HSSF.UserModel;
# i1 P6 }6 U$ e% ]' ausing System.IO;
( r6 f0 ~8 q2 h" v9 k, i' D& n/ ~! Jusing System.Data;" C$ R2 ]8 L# p
. k6 b' m; _8 c7 [" \- I, m8 f) N5 dnamespace CC% g( c( R+ H; X6 {2 S' u4 |( ~
{$ p0 s% M5 ^, p4 w% F+ C% W
. M s: W' `0 E. \
class Program; C$ S# t3 z3 k4 g. P. ?; G
{
% |, L$ I) j8 e
9 b- r$ a4 v: _ k1 Y1 c( J) @" n
& s/ M4 U# o N' M static void Main(string[] args)8 }3 Y; z+ b8 X0 J2 x
{# @' k3 h' C/ K: G5 W7 ~- w
StringBuilder sbr = new StringBuilder();6 q6 U8 f% o2 {. q, y3 V: C
using (FileStream fs = File.OpenRead(@"c:/myxls.xls")) //打开myxls.xls文件
5 q- Q8 z- G+ C# x: s4 U/ ^) a {
* j( s2 _6 R* B! E" s HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的数据写入wk中
& a6 @' f3 h9 ] r9 H/ d7 I for (int i = 0; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数" ] E3 ]" ~$ t/ s( T
{4 y6 N% \0 O6 A3 ]* E ^
ISheet sheet = wk.GetSheetAt(i); //读取当前表数据; w: E: g; P/ F' ]/ }7 F
for (int j = 0; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数1 {8 O0 K& u, ~) E/ E
{0 U% S- I7 R; g5 w# ]2 c
IRow row = sheet.GetRow(j); //读取当前行数据
1 o2 S: ]( W9 `" s if (row != null)( Y. G; i9 ]3 Q
{
; m' `; ~7 H! }, i sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限
7 X6 t& L9 H' U7 J0 n. v for (int k = 0; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数
0 f! s& T* Z) e; A8 ` {
{: E3 ]2 b+ i" E6 [* T ICell cell = row.GetCell(k); //当前表格
4 Q8 x: v1 J% @5 s5 }* D p* P' Y if (cell != null)0 x; B, p, {+ j+ O
{
7 E' [, `0 s; A sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型# \( D- M* D' @1 x; p2 F
}: }$ l, O$ K6 n! j$ z& }9 S
}
! I/ o' W, z4 n5 H: c# P6 C6 x3 S }
" e' E: S7 T* H& v/ u2 G% S+ } } @. e* ]7 C$ I" d/ M, ]" F& z
}7 I2 m( I8 H7 y
}* Z* a; V/ I c; S; ~; V2 K% C2 |
sbr.ToString();
3 @& Q* W# D, c1 c using (StreamWriter wr = new StreamWriter(new FileStream(@"c:/myText.txt", FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中4 g R4 `3 ]! b' _% `2 W
{% x, C* i/ W8 ]2 G' P
wr.Write(sbr.ToString());
# J& K( S3 ~' {8 y wr.Flush();
5 s0 I8 o5 F) W/ w* |/ g }9 ?! i0 u$ H. N: l' W B
* |0 ~! s# ~: Q
" H+ M, n a+ x+ Z: t; j }1 i% u: v% r5 R+ ^' X0 {
9 `: f& h3 ^ ?* u7 K
( q! R' j. O, p: N+ [8 o4 j
}3 a+ v! a) x! q& Q% c5 q, h
e _9 d, @8 o% b
, J$ O6 A* N! N% X' h
5 n0 G$ H6 C. P+ ^& {
}$ O" Y) L _1 g' V0 y5 G: Q) E
" y# f6 T6 _2 S1 W$ G
. V6 w( M' E# y3 ?. }% S
然后 自己封装 给 c++用
* `' c- q: l& G$ e- ~
8 q3 G: ^ j+ y% d2 L" v
! R: S) B0 \2 D) ]" D
5 \3 d' q" }7 o2 w. y* D& W5 A6 {; a& J6 O
" A) Q, T# ~5 ~. D$ G8 u$ w4 \4 j, m7 z
# a5 W! e* ^" q# T9 L2 J) m& l. f/ g; S
% y0 [, q& H \
( P& D" a: ]* t$ Q) C! C$ @. c0 Z: {% r( v5 `
$ `, x% V8 }1 _% h
& z k& I/ J/ k" a3 N
- P& V0 P! W$ j9 k8 |5 s) w
4 c- S, S: l% a7 |2 N
0 `+ p# w2 V0 S' Y `# A" O. F; p- J9 O
" R4 e5 P+ P& \
2 F. X. G# t+ m: w+ ]+ J' g3 v! Z; F- b: N
) I; U; i. V9 b
; r" P: Z; `. B, O7 S6 R6 w$ E; U3 j2 C6 b+ |* u; h5 i
( ~" \; O; f* t! r! {, Z# w |
|