|
|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
C# 或 c++ 不用安装操作 EXCEL的方法:c++ 对excel 的操作 非常不理想 要安装excel 而且读写速度也慢
# w9 p- W6 y4 n2 J- k Z7 Pnet 有很多 免费的开源库 比如 Npoi库 (Npoi库 支持c#、vb.net 等语言)
* K6 {1 |: Z$ B7 M, @* \0 z这里我用c# 生成 com 组件 让 c++ 调
, d7 C, j2 j; {- O8 W1 K/ o: X" X. \6 b8 Z: g. K7 Y& c4 b, _
首先要学会 c++ 调 c# com组件的方法 (和com注册的方法)
0 j: b2 g9 i3 HC++调用C#的COM组件(DLL)
# `7 {4 `9 u$ A- `
. _; P0 v0 v6 d- _下面我举个简单的小例子.我用的是Microsoft Visual Studio 2012,操作系统是Win 7.
6 ~9 V$ B% u; L首先创建一个C# com组件.实现的功能很简单,就是返回两数相加的和.
! y! n/ F2 B8 s
$ W( t0 Q p' N1 q+ j4 k
, t# X7 I4 e4 V; s9 m/ h2 M1.新建一个C#项目 ,类型就选 类库 .取名 MEI_AddCom
, j$ m+ o6 E5 Z) ^
- @9 J7 @1 G: s& V0 H: H2.在项目中添加一个接口,取名MEI_COM.C++调用com组件中所有的功能只能通过接口来调用,不能直接调用类或函数( |$ x" b4 h3 `! Z# k
( j) f* }% y& m! \* z. D7 ?8 r具体代码:
5 L9 Q) f4 `" Z3 `
4 r; V$ m' o4 L1 [0 A! i9 ^using System.Runtime.InteropServices; //记得加这个命名空间
4 _: W" \4 \8 u& D$ l0 Y; t0 s1 I/ k! p$ r* n! A( m' G
namespace MEI_AddCom H! x) x6 H- g" b! }" Z
$ k; D4 f" X. x% Z* R{
9 {2 C. t5 j1 ~3 W2 T0 q6 r( A m1 \$ X8 n8 Q* t4 @6 w- l
[Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的产生可以通过vs自带的工具.点菜单栏上的Tools ->Create GUID,然后选第4个选项.Registry Format.
$ s3 d5 ]# E9 m- |+ }
; J+ C9 _9 ~7 d1 u, u //点按钮New GUID,再点Copy.这样你就可以把产生的guid复制下来,然后粘贴到这个地方来.当然那个大括号得去掉.后面需要用到guid的地方也用这方式产生
+ M1 u( [+ `& l/ P) _
8 B& B: e6 X% ?. ~! s [ComVisible(true)]
* S5 L* ^- P, G6 x' Y! k* c* }
7 K- K% R4 G5 I& F3 R# \8 d' \ public interface MEI_COM //记得用修饰符public! p+ t0 [) _$ `/ e; R( a K' w
1 J( i: P& |4 n2 R$ k0 J3 L
{
8 m- o2 h) O$ N8 G4 ~! ^# t. c& {3 U% m z0 R& d0 E
[DispId(1)] //如果还要添加其他函数就继续来个[DispId(2)],[DispId(3)]加在函数前面0 s2 r- f2 s" T# |, Z
+ B) W. X2 g$ p int Plus(int one, int two);
9 _0 F/ c: @ w. @6 S7 [3 p4 |: S6 M! S" a
}. g) ^2 z% [* o6 U0 j
! c* {0 g' k( g- H+ g- S}
}. V9 i& H, ]; k- l# d
( H# F V. g- D1 S$ I0 c A' _* l
5 W1 L; f* D- G- R5 P+ X# b2 P
8 s! q2 ~9 ^4 ~% l6 I( E7 h3.添加一个类MEI_COM_T,继承接口MEI_COM,具体代码
# k/ Y5 [4 ]2 e
1 O( u" Z9 P' K/ z, }using System.Runtime.InteropServices;
% |* @/ x- N# p) o+ c' B N- V2 C: f; n2 U0 B. K
namespace MEI_AddCom& H O6 c3 X; h
' W4 x. J& c) [5 ?5 d{# B1 `8 K* e( ~. \
& F3 Q% W' O8 S9 U4 g1 R; @ [Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]
- D3 {( E. u2 s" P1 M* l* W
( c: _- _: f& B- {* V [ClassInterface(ClassInterfaceType.None)]
0 i2 @! A2 Y/ l0 Z
$ o" K& y) O# K public class MEI_COM_T : MEI_COM
. j5 G3 p6 ?7 t7 J; _; R% c4 z
7 D* Z' G7 m+ E! [' e1 @; f {! {) C$ q/ R1 g$ x
; O% [" O8 U" g2 [1 e$ ~ public int Plus(int a, int b)/ @" n& {1 f+ P) z& j
6 K" N/ J* p/ t; y! o% z1 M
{
4 o" o: R S! O' H# b- [ |) a- j9 ?( M
return a + b ;' p9 N7 `. m/ z( N# F
% t0 P( C' j C( G- X8 _ }
+ I( J8 _9 \( L# [5 t' A
( [8 g# ]' `/ y }
- |5 r* x% ~, [3 }0 V; P* s: s9 V" V4 r6 E
}
# F6 v r! ^" f6 i* s4 J( U3 T% G% [/ t
3 P9 Z9 l6 l! F& g3 O2 t# ~+ p; T4 h# F
0 T+ J/ z) D9 I4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)].1 f2 Z- H0 d. u- l; P
- G' H# V/ A' }/ s* S* r4 h右击项目名打开属性窗口,在生成里,选中 为COM 互操作注册, A' V/ a( \- g
# e0 Z/ F) G1 u
3 H- x: T, t, F" }. u/ q5. 生成->生成解决方案
1 d6 u d+ e" o* E' q0 ? 注意 这个时候 生成 非常缓慢 ( l9 c6 ^: S( N% D% _
直到 出现 成功 1 个,失败 0 个,为止才 操作一下面内容
) p% W3 B# y& |/ s: u
& w! ^, l% _/ J5 L P1 t5 W- ^6 e* _6 r( @1 Q# u
---------------------------+ F/ q: V' E" }4 |; v
9 h I7 R4 j& H0 T* @7 I! N1.调用前要先把com组件注册才行.
5 a& ]' O; s5 s' x# t8 b6 r6 q+ A; O8 S$ _7 }; {
使用C#创建并注册COM组件 C#不能直接创建COM组件,因为其生成的DLL属于程序集,但可通过“使程序集COM可见”选项来支持COM。1 X% @. d; @. ?+ D
以下说明如何通过C# 注册、注销COM组件。
% X* ]" O1 T6 g$ q, n6 Q) X; ^$ g; I. Y$ q) s' M2 G& w8 M
为了能让生成的DLL能够进行COM注册,需要进行强名称签名
- g) |5 F. S9 G0 W9 ^打开COMLib项目属性,选择签名,勾选为程序集签名,通过下拉列表选择新建,弹出创建强名称密钥窗口,输入名称,不勾选使用密码保护密钥文件。
6 n3 |* T' f: `4 X; Y创建完成后COMLib项目中将出现后缀为.snk的签名文件。. R S, H6 A1 g1 r* S) V& p Y! X
最后,编译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文件。
, Q2 a8 e3 ^9 X, Y# X卸载COM组件:
. _0 m" z s9 T+ V2 e. h$ a8 J与注册过程基本相同,只需将命令改为“RegAsm /u D:\ COMLib.dll /tlb: COMLib.tlb /codebase”。
- m* T/ K9 P2 [) i' H3 |
# y4 G, ~ K/ J5 k3 f. b
. W2 f6 d- t0 O2.注册完了就可以在代码中用了,先新建一个C++程序, 类型选 Win32 Console控制台应用程序
4 s5 k2 ]% ]& P/ m( e; |; v; w0 t) U0 v: a6 k) ~
名字取MEI_UseCsharpCom,点完成
+ i- l) S( H9 Y. h
! z h0 g7 K- m2 }- A: f6 k4 b把MEI_AddCom.tlb文件拷贝到项目的任何目录下.我就放在D:\MEI_UseCsharpCom\MEI_UseCsharpCom.
) h7 I( ?' s8 E% t, x0 |; |0 J* i K+ f% B
我们会看到一个MEI_UseCsharpCom.cpp文件,双击打开把默认生成的代码全部删掉.敲入下面代码:% R0 G; r1 p+ p# c1 o
+ C- P# o% H5 i9 Y/ V: Z4 I6 A0 ]6 l8 `3 a9 T1 n8 c
#include "stdafx.h"9 l- j7 j" h+ F
#include <windows.h>
5 U, x X% o- u8 Z; w#include <string.h>' }+ _' C+ `/ _
5 G2 F1 ^; K8 ]( `7 B+ q
#import "MEI_AddCom.tlb" named_guids raw_interfaces_only l: k* [. X# C. X& e; b0 g
' P, [3 a- a( D& m) q
char* WcharToChar(const wchar_t* wp) //wchar_t转char*
! ?& _. Q% `# C/ s+ ?4 g7 C6 u{ 8 i/ ^/ E- K' b. }0 E1 D* ]) W
char *m_char;4 s" }; w4 p1 G! a
int len= WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),NULL,0,NULL,NULL); % D) q8 ]( T' E& S" ^8 m
m_char=new char[len+1];
, C1 v$ W3 H% H& v. y. a WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),m_char,len,NULL,NULL); % T9 a3 \, e3 ^ L/ M2 y$ w- G# N
m_char[len]='\0'; 4 q7 _4 U: j, |
return m_char; ; X. r: | ?8 `2 Z* z3 O F% e% n
}
( c7 G' I" M# p1 u3 t! ?wchar_t* CharToWchar(const char* c) //char*转wchar_t# Y% X4 n* h, F& b/ o$ R7 Q6 J
{ ) h. l0 q! M8 {3 X+ [% \$ R
wchar_t *m_wchar;6 b' i Y0 k! u# Z1 W0 ~
int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0);
b9 j8 G/ F5 g s+ p5 P3 { m_wchar=new wchar_t[len+1];
$ ]( G: i) j3 q0 Y MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len);
( i6 P% T8 t' ?' [- v- C! f4 ^, O m_wchar[len]='\0'; ) I( E. r6 N T. f f
return m_wchar;
2 J/ b- g5 F( m* V) }} % x* i5 a v3 D) W3 a
2 e8 p" o2 d: { e C1 C6 ~# ]void _tmain(int argc, _TCHAR* argv[]). X+ z( e+ H6 L0 s* }) a
/ d" W5 A* o7 l& }4 L
{
' w; {3 \, }/ D( r* z+ g& S
' s; n6 w- i6 O CoInitialize(NULL);
- j# D( ], n3 E0 ?
0 \' w+ [# k9 F MEI_AddCom::MEI_COMPtr ptr; //类似明志一个指向接口的指针
! X0 ?: \; d& D7 n/ ~, Y; b+ P5 Q+ I# o0 v; d4 l
ptr.CreateInstance(MEI_AddCom::CLSID_MEI_COM_T); //实例化一个类 CLSID_ 类名
3 S' O# c, }! N3 |* `: L% g5 I& X
//这个地方有一点点奇怪我也还没弄懂.在C#中的函数是int Plus(int,int).但类型在这里都转成long了.另外就是我们不能直接
0 O: g9 ?! w* a6 U# j, j1 e5 s5 S0 `; w a' D5 [
//来个long a = ptr->Plus(1,2);这样得不到a = 3,反正会出错.
4 u9 A8 b0 {: J0 }0 B, q. C& [- Y //这里函数Plus的参数变成三个了long Plus(long,long,long *).其中最后一个指针得两数相加的结果; c" N+ ~9 Z6 C# |
. D2 x7 v$ B) O, P long a = 1;
4 P/ q4 C# z- n* I/ p7 `6 U* @& l. S( W+ p" `! h8 o2 H3 f B* e) X
long * lPtr = &a;
7 U# g. p0 M/ ^/ W& K' P
0 }- y3 Y/ Q3 w# I7 D$ F ptr->Plus(1,2,lPtr);$ u1 j1 r7 T! X# w* w8 m0 H
. a. ?/ | v N/ p# s/ {3 f char msg[132]="";
+ c$ V* n1 F& S6 N$ @ sprintf(msg, "%d",lPtr[0]);) c% ?" v7 y1 s6 f9 _6 @/ C
8 z9 d+ U+ B3 k) z" N
LPCWSTR str=CharToWchar(msg);- j |7 L) W8 O5 x; c+ w+ u
9 x$ m, a9 Q8 e: R0 T3 T1 f
MessageBox(NULL,str,_T("123"),MB_ICONWARNING);0 J3 H# n; e' \6 `( M) U
5 V" `: B! a% G2 v& N' U7 m, H# Y* j
- a6 f4 w g* C& S0 @}* x2 D3 a4 R+ {' r6 |
% a/ D. B4 d) Q
此时就可以正确运行了.得到结果3
0 U ?/ r2 w" w# ~$ G! m( N+ r- h" W" N( N* G; Z( Z
如果没有正常运行,则必须把dll文件拷贝到有MEI_UseCsharpCom.exe这个文件的目录下.
: f0 U5 B( e) Z7 F3 ~! T8 L& ?+ q
# ]1 P. p/ `6 C6 F/ n--------------------------------------------------------------3 Q6 n z$ `& }3 q
C# Npoi库 操作excel 的代码网上很多
* v: Q' R* N, A' G
% X% t* ~( A. `( O; R. a; J4 x// ----------------------------------------------------------------------
) m0 o( t- Q) b7 Y* S- M+ v, }// 使用Npoi创建一个简单的xls文件,写内容3 `" v9 g' }3 L1 l6 z
; n' E1 d4 I8 D/ u/ Z
using System;
6 D/ w2 |2 r! s4 ~using System.Collections.Generic;4 `% e6 \/ B1 g' H; W
using System.Linq;9 r, ?7 ], j- D- n$ j
using System.Text; r$ l2 y4 x1 U' l
using NPOI.SS.UserModel;
/ A/ j( i% M0 ~9 zusing NPOI.XSSF.UserModel;
6 g# V b/ O' B) t+ k0 K5 Nusing NPOI.HSSF.UserModel;: T/ U0 F# t6 t& D5 s/ J
using System.IO;. ^( w& I3 f6 D' I, z% I, L5 I
using System.Data;6 y4 C, h. x9 [4 T! v8 [
; M$ D' A5 w5 g( {//using System.Windows.Forms; # k& m8 `3 `' W! g" \$ k& \! h' s& l
' ?+ G+ u5 L* h, D8 m" o2 d% n4 z
namespace CC
# H0 j* O! [2 q; j8 w, ?5 \7 u{+ D' T$ p |- C4 T2 |
9 |2 I+ O3 } i1 d* r class Program9 Y$ p; ` [' Q) ?: I& ?
{
! h+ J* t6 o3 Z+ _8 F3 T7 r6 L( c- R* C C p+ {3 I; s
! K6 h/ ]( m1 h0 t) t* ~6 f$ R
static void Main(string[] args)
) c# D9 A7 R8 i5 r: k! e7 e& _ {
; `3 e0 n9 ]& k- C7 O5 q" ] //创建工作薄1 Z. Q! t) }. y8 O6 h+ V9 S
HSSFWorkbook wk = new HSSFWorkbook();" S( u+ E5 G9 t: A5 W, ~
//创建一个名称为mySheet的表
0 W. A& D: W% h$ |4 X( \5 W T. ] ISheet tb = wk.CreateSheet("mySheet");
7 p. f" E- W8 X' t //创建一行,此行为第二行
) P" a* {& t. r IRow row = tb.CreateRow(1);! R6 K1 j' W, w
for (int i = 0; i < 20; i++), R @& ~$ g) w# d
{ V4 j! J% Y/ [1 r, v
ICell cell = row.CreateCell(i); //在第二行中创建单元格
6 k# m0 |0 j R* G cell.SetCellValue(i);//循环往第二行的单元格中添加数据4 Q) x: r8 s' s* F' n
}( B: G, b" t8 E- k+ N- |
using (FileStream fs = File.OpenWrite(@"c:/myxls.xls")) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!
: _4 X$ p7 F% G' k$ k5 ?0 F& c8 I5 @ {0 W5 b. M: x; i: X
wk.Write(fs); //向打开的这个xls文件中写入mySheet表并保存。8 G2 B8 X+ T! F9 M! L
// MessageBox.Show("提示:创建成功!");$ ]- g/ F) t+ `/ e; f7 L
} B( F7 {4 q) q& Y) }
. B1 l$ \) o* G1 f9 }4 k
}4 H8 q1 W9 J+ \( u" t+ V
' S3 B& d5 {) e4 S l
1 W" w: ]9 z8 S! w! F: S
}% d$ t& L( {6 r
8 h& ^ f8 H( T
3 h, W6 r+ T2 w! o. k6 Q: c
3 G6 g4 s `4 [5 ^& ]6 q& `}
# l1 d' w5 Q+ k' J# u: C- n# x
) R3 M& Q0 w6 c* s3 B// ----------------------------------------------------------------------
: x' V, E: M" W3 @2 D% h9 v4 s// 使用Npoi读一个简单的xls文件. T a4 H' c: y. J6 [7 I9 M: T$ {
# e5 M( x- ?0 U- @+ S3 \using System;
' n5 W( n7 e6 O5 [ lusing System.Collections.Generic;' o! p3 o4 f# L8 q; m! n! I
using System.Linq;
. N# z( E+ g: i/ A7 y+ M/ ^0 |using System.Text;
1 z3 T. {0 U$ dusing NPOI.SS.UserModel;
, u/ I% d3 t1 \using NPOI.XSSF.UserModel;1 G- V" Q' ?7 _! U) H( w- d/ B8 t# I
using NPOI.HSSF.UserModel;
. f/ @' |! B* b- r, eusing System.IO;+ ?% L: y, `' R r1 K$ ^5 d
using System.Data;
5 y" L D$ l0 G% A- O& X9 r9 ^$ V
7 f; l: u4 }" w6 |! I/ d5 k; N9 Mnamespace CC
$ t( R1 s7 t7 G% }. v8 X5 S$ Z{% k& _1 D. ?2 I+ V* `5 O
+ R4 o; x; v+ Z# [/ f4 s1 `
class Program
# z, }0 ^+ I$ Z" ^' k {
! p& a0 ?/ i! T7 i g! J0 f% \; `% t8 |6 j1 ~
# g6 o V# h. r) T$ u+ \
static void Main(string[] args)
. |/ o3 C' l6 ~9 a/ } {
+ c) F' _ X0 f" i StringBuilder sbr = new StringBuilder();
6 l' ^1 a8 q" E$ Y: }/ T using (FileStream fs = File.OpenRead(@"c:/myxls.xls")) //打开myxls.xls文件( @5 C; C/ D1 P# M
{
. f: s* R( { Y9 ^. E3 b HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的数据写入wk中1 {: C1 Z/ }5 Z7 T
for (int i = 0; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数
( U3 p; Y: I2 Y' R8 W* A {* K3 v6 k W6 }7 Q) u; { t
ISheet sheet = wk.GetSheetAt(i); //读取当前表数据
" q3 \/ K% W6 I' }, ]& ]5 e6 s for (int j = 0; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数
z! P4 t6 e+ |, X/ M7 d1 P' ?2 c" p {, q& `5 F2 Y6 s: i3 I; ?
IRow row = sheet.GetRow(j); //读取当前行数据
8 e; F7 F& P: Y% T0 \ if (row != null)
: i/ k; f0 N0 L3 A {
% W/ g. s$ X7 x; T9 _6 V) F9 j sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限
% K: p) C% \1 @1 W' p) w for (int k = 0; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数
! k' F, }/ q4 ^/ n {' g& B; D3 b, T5 `0 [' x
ICell cell = row.GetCell(k); //当前表格
* A8 T; b3 P$ |3 D if (cell != null)! ^" d7 v0 }' ?5 ?+ Y9 ~
{
# W/ a% e) E* m$ t4 N8 |3 r& r sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型6 n3 F. {, H+ H; J2 t
}
8 }" _" t3 {. v6 {6 n1 e, l/ A0 [ }7 v/ C5 Y" E/ y. A; F
}+ v: v2 R- `+ ^ V
}2 P3 W* U* Q; v5 h7 J; a# `
}2 H2 l" m; q9 W- x7 ]9 i" j
}
2 ]$ p2 w. \) C) q sbr.ToString();! @* Y% G- i: i* M
using (StreamWriter wr = new StreamWriter(new FileStream(@"c:/myText.txt", FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中
% g7 j( b! q Z5 U { L( J# |# V% C! x0 {8 Z' K3 [
wr.Write(sbr.ToString());
# H. h# T6 B* Y8 D9 }# _ wr.Flush();5 b# L: K9 F# [
}
z' b1 I$ m* D8 ?' n; A' d) ?9 C
3 S/ x, Q" P9 \8 p4 T1 w
2 f( m( M, c0 o. E, u }
4 R( a! E& ^# U- z5 W5 A1 i/ r7 Z8 v- j* v0 F( M
/ ^9 F* P) M+ u8 I+ B
}" B- y! O; W, C. W, O
. P! ]$ ~$ o5 v. K+ r( M6 P# C0 P' @2 i' P
7 @% w/ k" G8 X( k3 k2 {
}
. M1 ~! p0 T/ k: X$ M0 W. ^
) N, I6 |. q' N' u
* y* x. H6 s7 D8 j( u1 U; Y- w Z然后 自己封装 给 c++用
' e9 n/ ]* P: b. Z1 K6 u7 t1 x* ^+ Y% b* t
* P/ K0 ]' U5 S- K
% k) v8 a8 t3 x! a
- N+ L+ q! |) k! ^1 p- M
/ `8 W; Q4 M% c6 g
# r3 D& g; C/ u/ y. L% i( v2 L
{: ]$ X, ?. L' F7 Z3 |
3 M8 T! a' {* }" ]% J- c
: \ o5 B4 V* K2 S) w- C* s2 c: q
! P# n7 ^0 o* T, h8 W! t% ~) s5 H; Y3 L; M1 d2 a
* i& D5 Z" n6 N, B+ E( C, J+ o# |& _3 L* l8 R: w5 P* l/ x( n4 T
3 Z2 b) m; i( j; [% l; k" G
- J% {1 R4 q; p0 E& X/ P* K) g
: M( f- v* E+ t7 ] {2 a" J% c
/ y+ @% t2 r* A! n/ R
) R. v3 Z2 K! ?% s) Y5 `: m2 P
6 b. U9 w9 @5 B8 ~0 z. G
. s; M n: L, d* @7 y# f8 T$ O9 U. S* Q4 v3 X" k: D
& f$ S: L6 B& j" M6 ^0 `2 ^; K" a- \9 ^, p8 v0 @. J
|
|