|
|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
C# 或 c++ 不用安装操作 EXCEL的方法:c++ 对excel 的操作 非常不理想 要安装excel 而且读写速度也慢5 o2 t# F, f0 ^6 m# n
net 有很多 免费的开源库 比如 Npoi库 (Npoi库 支持c#、vb.net 等语言)7 q" f: Z5 _+ b6 n- v" d$ I
这里我用c# 生成 com 组件 让 c++ 调
* Q8 Z/ S2 ?" ~
/ ]1 a* b+ l/ I( _0 P2 u; i- x5 J首先要学会 c++ 调 c# com组件的方法 (和com注册的方法)
( \/ }0 `: I1 J2 |: FC++调用C#的COM组件(DLL)
- }5 P% t; [: d1 B s! A& b2 a: Q9 N5 n" ~5 [
下面我举个简单的小例子.我用的是Microsoft Visual Studio 2012,操作系统是Win 7.
$ n6 Z- e4 G! O$ U% {) K$ m首先创建一个C# com组件.实现的功能很简单,就是返回两数相加的和.9 I2 p! j8 m4 e" C2 o- R
+ ^8 A0 x! B$ k5 ~: ]" l
5 q! k' O; ]: d+ y/ d! F
1.新建一个C#项目 ,类型就选 类库 .取名 MEI_AddCom- o) v+ ^, \. ^ X6 u3 ~, A
8 m% t2 O8 L) Y) C ^& _
2.在项目中添加一个接口,取名MEI_COM.C++调用com组件中所有的功能只能通过接口来调用,不能直接调用类或函数
- j; Z) p2 K# q
0 a7 ?* Z* {2 f. i具体代码:/ V* ]- F( `* i( W2 C4 v: U( c! u1 k8 X
& l( Z0 n# Z) ?
using System.Runtime.InteropServices; //记得加这个命名空间
: v; H6 [9 U: O3 ]1 c4 ^
/ T5 b2 j% H0 n5 F nnamespace MEI_AddCom
/ a, c$ E' D* d6 H* k& h8 {( _2 C: L m( O4 Q1 S- k9 T* ]# n
{
, R' j: C- t& ^1 \& u% X
" Z O$ }9 @+ P [Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的产生可以通过vs自带的工具.点菜单栏上的Tools ->Create GUID,然后选第4个选项.Registry Format." q" d6 ^! ?6 D
( t' P6 p7 Y2 q; c //点按钮New GUID,再点Copy.这样你就可以把产生的guid复制下来,然后粘贴到这个地方来.当然那个大括号得去掉.后面需要用到guid的地方也用这方式产生
. p& {; b4 m0 ~* S% R0 g9 R, H7 a7 {; u0 J2 Q( E
[ComVisible(true)]
9 n" k D% g0 ]6 u
# _% K9 ~% D) B public interface MEI_COM //记得用修饰符public* X# ^- y( D/ F6 r$ f; F
( Z0 g" J; N- u% a. e& _* x ~4 g
{* ^& w7 J+ O+ d! f1 U# b1 o
6 I, W8 ?/ s6 s0 x* w [DispId(1)] //如果还要添加其他函数就继续来个[DispId(2)],[DispId(3)]加在函数前面
# d: b4 O; _: [7 k, ]6 D5 q: \8 Y, F
+ _0 b2 h2 l; Z: k' L! e int Plus(int one, int two);
+ P% B% i# Y# q/ c" K! q( s& g0 {" n- k g3 ^2 R# U& V' c
}) B' d- t/ I- o( t
' g/ `7 E0 V! T9 r}" O: N3 m/ ]' ]$ N% G
3 u) p* l- s# D9 ]" Y7 s
: t$ K K6 m6 t, U
1 U, X% T. }$ E8 ]* G3.添加一个类MEI_COM_T,继承接口MEI_COM,具体代码$ S ], g6 ~9 N6 v, F7 B* S
6 U2 @; V1 C: y1 C9 Q
using System.Runtime.InteropServices;- J$ v. p! i. f! G6 i( @) E5 p# S6 J
% K7 ~' {2 i" N7 Znamespace MEI_AddCom p) _- z* V1 v" S
; P' j! Q d8 \) T{! i& b" r6 [" f+ k+ K1 ^ d
0 b4 L* y3 P8 o2 p* `5 {0 J2 f
[Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]
, X9 U1 M1 P9 N6 q$ e4 f; W) ]) c
% O$ G' { n6 U& _" x- E9 n [ClassInterface(ClassInterfaceType.None)]
8 a- `2 i: T" i
5 k) g$ S B5 k( }0 T" U2 E public class MEI_COM_T : MEI_COM
1 x) F! o2 z. N `# b% I4 W) B# {" l' D' }- K/ ~5 A, }
{
) V3 L {4 M y. D$ u& c `
: T! ?' H" d& [" ^+ ]: f: f public int Plus(int a, int b)3 ^5 t5 ]( V9 l3 L. _ X* Z
, E2 O4 b- O3 z; ?9 \
{1 }9 W3 r. I8 p, \
4 \ ~0 n+ C7 a- {; I d return a + b ;
+ c' d2 G" \1 \. o
, i o* A+ s4 C) m+ o }
. }& f8 x8 F. s# j F8 ~
+ Q$ s- Y$ _+ t, b) U7 F7 s }
" o9 p `$ M. T9 c( F
3 x+ C9 T9 t+ \# S$ { ]5 s7 T}
; n; X1 e9 ]' R/ _& u: o% W8 |
) q$ ?4 Q0 | A Y; {" j+ K3 X4 R$ n7 B% G5 e! E& D4 g) {3 b* c
+ H- v3 B% X+ B/ d$ m! \% c" w4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)].* c: h% D" x, U. S& k# Z8 T. x8 R
0 s9 z/ Q$ G. [) o& |* W右击项目名打开属性窗口,在生成里,选中 为COM 互操作注册
0 L) h8 x, N* b* Q, ^- I, Q) Z) l% D' ^" X6 H1 `0 T5 J: y. }
% j2 l" Z+ |$ i; W, \; r! b5. 生成->生成解决方案
, q. ?% B1 x, a, `) S 注意 这个时候 生成 非常缓慢 9 F, B: c" O/ R: B7 t! U. s& W
直到 出现 成功 1 个,失败 0 个,为止才 操作一下面内容1 T0 r' J6 D# D5 c
& A* K9 d1 C3 C6 ]& ]
) V8 X$ H% @2 i% L* {- u, n' B0 A---------------------------! E' A" _! x! ]$ q% N
1 k8 } Z* o- a/ O e2 E1.调用前要先把com组件注册才行.5 b: M7 F4 Q' o5 ~1 m# M" |5 W
: J% ^. L. ^* t5 s使用C#创建并注册COM组件 C#不能直接创建COM组件,因为其生成的DLL属于程序集,但可通过“使程序集COM可见”选项来支持COM。. u% h) s) p( y5 _) K% j" `: D9 K
以下说明如何通过C# 注册、注销COM组件。
1 I$ L8 l( v* }
& s+ X1 G; ]: H: n, ^. T. m为了能让生成的DLL能够进行COM注册,需要进行强名称签名$ a) _9 ~/ |) G7 c4 n' c9 h3 Y
打开COMLib项目属性,选择签名,勾选为程序集签名,通过下拉列表选择新建,弹出创建强名称密钥窗口,输入名称,不勾选使用密码保护密钥文件。+ N9 ^2 a. P- N5 ^# _9 Z7 O! v# W
创建完成后COMLib项目中将出现后缀为.snk的签名文件。
( A$ ]1 S8 I& M最后,编译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文件。
8 f! E% T" o E' W卸载COM组件: ; G" K# C) {1 m# V) C6 J" J
与注册过程基本相同,只需将命令改为“RegAsm /u D:\ COMLib.dll /tlb: COMLib.tlb /codebase”。 j. I, m6 l( o1 o8 r
. p+ W+ x! H) l4 T5 {
5 p) I8 b* Y* U0 E2.注册完了就可以在代码中用了,先新建一个C++程序, 类型选 Win32 Console控制台应用程序# P! C) S6 e% |5 W0 O
0 J. u3 e; i) C
名字取MEI_UseCsharpCom,点完成
' p4 Z# L3 `% e" x1 U3 ]& a" g' a D5 j
把MEI_AddCom.tlb文件拷贝到项目的任何目录下.我就放在D:\MEI_UseCsharpCom\MEI_UseCsharpCom.5 N* g, x- d: C, U3 g4 J# h4 r
8 w- N ]7 i- x8 f4 T* ~: G0 b8 w我们会看到一个MEI_UseCsharpCom.cpp文件,双击打开把默认生成的代码全部删掉.敲入下面代码:0 r1 W8 n0 D3 m# x+ C" q! u
* P8 B& p& ~( J) i( `7 @' w2 `4 L1 S# A
#include "stdafx.h"
+ U$ I* J1 D# B3 a, _#include <windows.h>
$ ~; |2 B2 B0 E8 _$ W9 Q0 m#include <string.h>
" C# o; b0 K* @& v {: h
& |/ w1 E: `* F% [#import "MEI_AddCom.tlb" named_guids raw_interfaces_only4 A/ L! R* I% _) I! W
; \- f' h% E$ Z; h
char* WcharToChar(const wchar_t* wp) //wchar_t转char*
, V4 ?$ p- R$ N$ k& V @{ ( I2 f: n$ A' |" U
char *m_char;
5 q' m$ U2 f" v8 o9 Q int len= WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),NULL,0,NULL,NULL);
4 D/ N D* W' @1 D/ m* L, p( G m_char=new char[len+1]; 7 ]- o( L1 M/ g/ ^2 d
WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),m_char,len,NULL,NULL);
$ N; ^6 V' u M Z# t, d7 V% {6 H m_char[len]='\0';
, h9 \& z4 x( i7 ~* M$ R6 K8 L2 S return m_char;
2 u; e9 B( n$ \0 V, l} / G9 `- }/ Q% L0 t8 [1 A8 m0 H* c
wchar_t* CharToWchar(const char* c) //char*转wchar_t
; ]3 n$ }0 `7 C2 T5 B `{ , U$ S* _" f; y% C
wchar_t *m_wchar;+ `* u# U6 a7 p
int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0);
1 A# `, b# l. h! d8 o+ S. g m_wchar=new wchar_t[len+1];
- @( w+ \* S* c+ u T/ C+ p MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len);
& H2 q9 G. E6 y! k7 N" A$ ^ m_wchar[len]='\0';
: c* ]& A! v: m' M, ^4 F4 x return m_wchar; 2 E1 u5 N# n' |. {! e' {
}
6 u8 [7 h) ?# `) R8 j4 _: i& B2 Z- `
8 N7 l5 ?0 o" o: `void _tmain(int argc, _TCHAR* argv[])
* u: N8 B7 k7 \; Q- ?, v. w# ^3 r
{$ F3 ~$ w, [: M7 }* g
9 a$ f* D: L; O CoInitialize(NULL);
1 f4 }% g2 p. ]) ? V
8 e6 ?- P2 v- z p! n! D/ Y* u MEI_AddCom::MEI_COMPtr ptr; //类似明志一个指向接口的指针+ ` R2 D2 T# S, b& a: d
Y: N/ D' J l( u ptr.CreateInstance(MEI_AddCom::CLSID_MEI_COM_T); //实例化一个类 CLSID_ 类名
& w# x1 e. v: J7 k: y8 {4 S3 F- l9 g
//这个地方有一点点奇怪我也还没弄懂.在C#中的函数是int Plus(int,int).但类型在这里都转成long了.另外就是我们不能直接
8 k. z( V& R1 @2 P) G
& D' Q+ _; G6 S //来个long a = ptr->Plus(1,2);这样得不到a = 3,反正会出错.
8 I$ h/ ?, A' J8 N. \( t1 W6 p3 Z( Q //这里函数Plus的参数变成三个了long Plus(long,long,long *).其中最后一个指针得两数相加的结果' M* @' c0 s6 G' }6 T2 X
* J' s& ^- x) o5 x/ V- [7 p long a = 1;
/ h! ? Y% E9 D+ q' D3 U. W1 |
! B' K b- n8 C! P. M9 v( M: v: f6 ~ long * lPtr = &a;8 }" \+ U; c: a. p
+ l& w. X) O6 G0 D: K( `$ O0 Y
ptr->Plus(1,2,lPtr);
& o% ?& _* X8 d* g" E2 h: A! L: o; X @! r
char msg[132]="";, m4 c$ F4 I* `' \ w
sprintf(msg, "%d",lPtr[0]);- F9 u4 m- c1 T0 A
/ W& [- ~6 b* l; Z6 D; P
LPCWSTR str=CharToWchar(msg);
: f- Q! V+ m8 r. T: m: F" N. m: z8 B
MessageBox(NULL,str,_T("123"),MB_ICONWARNING);% H, q' j- I* X) x* o
7 U6 u6 D: f1 V ~2 b, a) {- x% Y) Q! K8 j
}
4 E& s+ m, O9 R
/ P% ^; K3 x; ` [1 I& _/ P. Y此时就可以正确运行了.得到结果3
2 }, y" f' B$ D+ P6 `
% z7 ?. u8 g: B, Q6 t如果没有正常运行,则必须把dll文件拷贝到有MEI_UseCsharpCom.exe这个文件的目录下.0 t8 e- E$ ^# Z# H
) _6 G6 S4 W0 ]0 R$ h' s" N; m, f
8 s" O8 p& l, e6 f' V( A--------------------------------------------------------------, c7 v, f, q$ N2 A3 E! H
C# Npoi库 操作excel 的代码网上很多
4 o' D' ], k1 m! m! |
: W8 r1 O% l7 v/ j5 I// ----------------------------------------------------------------------+ ~% z7 M- J# @ [1 J9 Z2 r# q$ W' e
// 使用Npoi创建一个简单的xls文件,写内容( k- T- ?6 _# S/ c, K- C# N
5 y; a- k! _5 Z" l% A" B. }using System;1 b* Z% n) `! n- V" |
using System.Collections.Generic;; Z. l: K* N( {+ ~; p
using System.Linq;2 d1 }! \8 T/ L) M
using System.Text;3 E/ B0 \! e8 W8 B; t
using NPOI.SS.UserModel;8 _7 X3 b% E& U% H% b0 D( b: Y
using NPOI.XSSF.UserModel;* G9 [) r9 u" C
using NPOI.HSSF.UserModel;
4 g2 b: L- z4 C Dusing System.IO;/ J: a! W& A& m& ~, Q$ ?1 U
using System.Data;
. E3 f! h2 t# ^* b3 w% r: y* E! G
//using System.Windows.Forms;
5 k* y" ]' H: {8 U2 z! \% _% ?. U1 ?# R7 q4 ]/ Y
namespace CC% _, G! Q% B3 J0 \. b+ {2 q/ m
{" l6 K0 F+ e) @
; j, m6 ~9 ~6 Z5 J1 W# r
class Program# ~$ A L) k, D2 G' q8 P1 j9 Y
{
$ Q6 ~& N, O& x' {
0 A4 [) S# O4 ?4 m/ |
: ]8 p) m$ q: W- r" W G* c static void Main(string[] args) V* R( z; x) d
{
* q7 L: B/ R( @/ w //创建工作薄
' D9 J3 E) j" `1 ~! |3 |, \0 q! I9 U8 q) N HSSFWorkbook wk = new HSSFWorkbook();9 D0 J6 S) v6 H2 g7 `0 m! }. n! Y T
//创建一个名称为mySheet的表, u+ R% {8 @3 F ^* ?: F3 r- G
ISheet tb = wk.CreateSheet("mySheet");0 \/ Z) n5 m! u; ^" r9 V& z
//创建一行,此行为第二行
; a- J! N6 G( _* |7 L IRow row = tb.CreateRow(1);
" R7 k" R9 k A/ p2 e4 x% [ l3 K7 i for (int i = 0; i < 20; i++)
: O- E6 M% }0 J0 \3 q1 {$ o# F {* ]& @+ @- N( v. R
ICell cell = row.CreateCell(i); //在第二行中创建单元格
" e. Z5 _& N" J8 k! m" E cell.SetCellValue(i);//循环往第二行的单元格中添加数据% A) _+ e) n& V/ x( l
}
' _1 z. _+ o, c using (FileStream fs = File.OpenWrite(@"c:/myxls.xls")) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!
0 p, k* i; {) J" X: P" | {! M6 n) R' T' Z4 m0 u' t7 D
wk.Write(fs); //向打开的这个xls文件中写入mySheet表并保存。; b) f- ]9 ?! Q5 ~$ }4 r* j& f
// MessageBox.Show("提示:创建成功!");
8 P4 {) a+ R l2 L9 S }
: t3 w. @4 w: L) o h! A6 M. q& y, ^% n9 U6 ~
}: H; ^( I/ F$ A5 f9 t2 \
! ~! H0 d, E2 C9 ^6 f% y
( l; z" ~9 {+ l8 h$ S2 F4 Y
}
, `9 s7 Y! m4 v7 M! U
" t+ D F4 \3 y; T. M* h5 W4 f$ d+ F( d/ U- D- o! Z8 |
3 [! n6 I z6 L}* Q Z# \" k, i6 v
% h% {1 y, C5 r. g
// ----------------------------------------------------------------------/ I7 \$ Z1 @' j# b7 @
// 使用Npoi读一个简单的xls文件
) l$ R8 g; S5 j0 t5 a" o# |: u- o5 I; N1 e- _2 {* O$ g
using System;
, m" ]0 r v2 C& Y/ L/ Cusing System.Collections.Generic;
, ]; r- N. n; G# I8 W. `2 f- xusing System.Linq;
4 w3 `/ Y* `5 @& L" z; M, Z- yusing System.Text;5 m u. q, T: s7 b' ~6 L
using NPOI.SS.UserModel; Y* N8 O- v: _; u E! C
using NPOI.XSSF.UserModel;3 M! Q5 L+ M& X! L- {
using NPOI.HSSF.UserModel;2 P* ?8 N' R; T$ o' x/ M
using System.IO;
, H3 ?+ S" @ @, p! e* `using System.Data;# m1 t3 T. |3 \# s; [2 q
6 v! ?4 q* p% d* c# _( ~namespace CC4 {- R8 X; W, j: u6 X0 `' l
{# w5 { C. R8 Y, E/ z% @0 M
1 O% p8 c1 v. U" z. B5 q, t
class Program
( n, a1 S& b$ m3 r, c% t4 J: f% z {
- d; Z4 A4 U5 G+ X: |& @
$ W/ w# k7 U2 @$ D$ z
; K4 W- m' `. } static void Main(string[] args)! N5 ^3 I8 t9 z+ }% [4 x
{. i; R3 L6 u+ M2 d
StringBuilder sbr = new StringBuilder();/ d$ _% C% [# q. v9 H8 H
using (FileStream fs = File.OpenRead(@"c:/myxls.xls")) //打开myxls.xls文件
* \. M# h5 l0 k: ~8 r# S, [ {
2 _) m5 o! w5 Z. I HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的数据写入wk中
' |. j6 z2 c$ ^. e' `: ? for (int i = 0; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数6 k# M( ~/ d$ M L: w
{, f) s; j. L e$ `# t v
ISheet sheet = wk.GetSheetAt(i); //读取当前表数据
: ]5 p) P# ]; @7 T* }& \8 m0 e8 c for (int j = 0; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数1 E) L4 n2 B& ^4 W4 B4 l( I4 ^* `
{! M; r. a% Y2 e$ r: x
IRow row = sheet.GetRow(j); //读取当前行数据
: H8 q; {; {. D: a3 K" d7 [# N5 ? if (row != null)
7 T m- t) {& {0 o4 J4 t {) Y. n/ @& f+ v' n7 J
sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限
; }% |6 z' b: C0 w for (int k = 0; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数, u2 h+ {: Y5 e; H
{* M+ u+ |+ m5 p# z
ICell cell = row.GetCell(k); //当前表格5 L8 E$ g# Y" q2 S. h
if (cell != null)
( I' ]! X9 a) U( @ {/ o/ g4 E e+ w$ j' E+ y
sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型
( Z" H$ n* K# \1 A6 D( D }
" Z0 I4 y9 Z( X: e/ b' _1 [0 m7 ^( Y2 d }
2 Z# Z# X5 X/ B+ u- W' s }
~7 D( [0 s8 p. B% N }
, x* i0 T6 `* |- @! h1 N! {1 J }( t j) U* P$ U9 t C! |9 V$ {8 j
}
. e4 G. e( t7 A) D sbr.ToString();/ [0 K5 k9 i9 B3 R v# E
using (StreamWriter wr = new StreamWriter(new FileStream(@"c:/myText.txt", FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中+ z; F# J6 [3 T
{: I" r+ t, c( D
wr.Write(sbr.ToString());+ _3 o: Q, A5 C1 Y! u- A: x
wr.Flush();
, J9 K9 |0 i. ]( q }
3 S0 [: i9 x' J- O9 T9 m6 @* C A$ w5 t# r
3 E7 P! K# O7 J9 H
}5 T; Q% I0 y1 ^- W1 |' `
& o, j8 p( t0 T) a& h! }9 A
& @* }% }& ]0 k# _8 r! X& E }& j' p! k( J6 g1 f, y% Y
V# }! E' J# K7 O
; c# P' X0 A' [9 _ X
' A3 H0 B# f! M, b" \3 i$ J}0 d# @& ?! a: f/ ?. r$ T& e
; K8 k ^3 y# A: A6 F
' a5 y6 h/ g8 q( ]6 g6 O
然后 自己封装 给 c++用
( w$ z7 h x) Z: v" d; j2 z6 g9 k1 W$ _; C+ g
$ W/ @4 p' ~, y+ x. k- [4 X
- z5 |* d, }6 d7 }
! w! s+ W ~8 x6 }2 s! x* P
/ z" f& H6 E1 c) y2 A+ | e; Z
3 ]8 n" P% N( x+ ]4 T2 o8 m' Y% l$ ^& _" y2 l0 E9 V1 G: q
. s, l. v% \2 G5 b* q/ @
2 V7 J) l0 S% W( j Z# j1 [+ A0 a
8 u. P) T: q0 t1 y: _+ }: W% } e* x. |: { u) r
0 j" `4 g, }8 l' p, O q" Z
3 W2 S+ N' B; f5 X0 r& o
; {% K5 y& S% m4 W$ K
- e2 M) W" ?2 z2 X: n2 R6 M) t" X R% X# K4 p
4 D& B0 d* Z8 d. u2 W
* u- N% L7 Q* L+ B- U4 \* A9 d4 Z' o, O% O/ c+ q1 x
( g, b+ J0 W% `" ]
2 c4 m$ t' t2 ]- |
) F$ C% L0 \* r2 J- \/ ~4 C2 ?% `( _4 ~
|
|