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