|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
C# 或 c++ 不用安装操作 EXCEL的方法:c++ 对excel 的操作 非常不理想 要安装excel 而且读写速度也慢/ S2 j, h. m0 D0 T2 ?$ v
net 有很多 免费的开源库 比如 Npoi库 (Npoi库 支持c#、vb.net 等语言)0 I$ O* L. ~% V. L6 H
这里我用c# 生成 com 组件 让 c++ 调 7 i( t5 S+ c& y9 d8 ^; g m* U3 _
1 k4 q1 r0 }0 |0 Q. y$ P' O1 w首先要学会 c++ 调 c# com组件的方法 (和com注册的方法)) {# ]- J7 O6 {
C++调用C#的COM组件(DLL)- A% v, s3 V8 r R U
) {, E9 e/ c& \1 N
下面我举个简单的小例子.我用的是Microsoft Visual Studio 2012,操作系统是Win 7.
0 {7 ~; _# A& \5 X7 Y1 |0 s首先创建一个C# com组件.实现的功能很简单,就是返回两数相加的和.
7 U& N% S) Z, r* z
3 g3 ^- D9 ^3 R8 N+ M: b1 O
+ e. j3 |* r, m1 x Y7 i* P0 C6 e: j1.新建一个C#项目 ,类型就选 类库 .取名 MEI_AddCom
' q3 S6 f+ @/ }; s2 @/ E# a# c3 z. x5 ^" n4 m0 _
2.在项目中添加一个接口,取名MEI_COM.C++调用com组件中所有的功能只能通过接口来调用,不能直接调用类或函数2 R7 x: _& ~9 ^% P9 w
. t/ Z8 j; I2 z( j" I* X
具体代码:
1 J7 f6 a3 ^7 n8 Y" |9 a, l% G0 `, L9 r; a4 W1 ]' q
using System.Runtime.InteropServices; //记得加这个命名空间
9 k k4 f8 \; s" r% n( \- `, \ l( B' F1 o5 l6 p# Q% }# m
namespace MEI_AddCom, y5 e$ S9 J9 R. ]1 C' G5 D
8 g2 s/ _* h7 p Y7 H& ~{2 Q4 ]9 W3 z- M3 x2 K3 t
# P( S; b H, J1 p Q9 T# u+ \4 ~ [Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的产生可以通过vs自带的工具.点菜单栏上的Tools ->Create GUID,然后选第4个选项.Registry Format.6 Y! e9 f% ?( {1 [
) g& k: S" U O7 O- f
//点按钮New GUID,再点Copy.这样你就可以把产生的guid复制下来,然后粘贴到这个地方来.当然那个大括号得去掉.后面需要用到guid的地方也用这方式产生; ]" R0 A {8 u1 P
' j7 [+ H6 p7 m) h
[ComVisible(true)]
4 |! H( i& `7 ?( t2 y' ~5 ^& _
, K; X7 T! I z0 J _ public interface MEI_COM //记得用修饰符public! x _" G5 D8 g/ `" v; @1 N3 V8 |
, p" ~6 D' u8 O" ] {
$ b# S# f( ]2 J; S* y' r" h
1 b6 n& |* k4 K2 i' T h [DispId(1)] //如果还要添加其他函数就继续来个[DispId(2)],[DispId(3)]加在函数前面
+ C5 m& s0 D' z* o, e4 s: c3 d! }4 Q4 Q0 q& t4 V2 B
int Plus(int one, int two);
& ?" ~8 |4 I+ f @. B7 n* H8 |+ y a# L0 |
}( |* w5 N; Q5 s
O, g: N" _6 t% L7 m* b}# v+ P! V i Z! X$ ]+ F
3 z# D' [$ B7 X3 \# ]& C
3 g% ^" U4 J$ r) c8 R2 q8 v
. s3 w5 ]% T9 k. M- B" S3.添加一个类MEI_COM_T,继承接口MEI_COM,具体代码. n0 @/ @9 h% {; P) }$ `) D
( z% k" {) A+ H
using System.Runtime.InteropServices;
( s+ k) ~+ n* e( x! m
" \5 z2 R% ?' R4 R. Y Znamespace MEI_AddCom t: ~7 z. {# n, a8 `) S" D) o
( V5 u# i( o! Y9 [+ G1 r{; s# H& V# x+ q$ A! H- m1 I6 w
, \: F' V+ f5 F. W( }( t. G) t4 g [Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]# ^7 K; ]. Y$ ?
6 I( Z7 B# Q8 m, a- Y2 O" P [ClassInterface(ClassInterfaceType.None)]
7 l# w3 U2 a, H+ p+ e9 S; Z" Z2 j* k/ N, U2 z; @
public class MEI_COM_T : MEI_COM+ M# l% G% X" C" Y( A/ @. d0 t* F
' E0 X% M+ C( [$ J* l, e
{
; |# a- W3 B' t. i, e% \! d u3 S0 U& s/ H3 H
public int Plus(int a, int b)- K! ~( N) }7 l5 G; C8 u( g
. X( h" ~0 n( T0 ]) A" h {
/ B3 Q4 J5 u2 t* L: X' V# }" x( E. E }8 F, {
return a + b ;0 M( p2 Q+ K% I3 ~4 b( u# ~
6 d- n$ T* ~% E$ g2 c" u7 R- r, d }2 y# o4 ?" L( s' [4 C9 j# q
( V) Z/ T1 i0 f% F% V }* S! d3 j% V9 ?9 u4 P8 D2 a& F
& L, t2 ]# w2 J) w; l' V3 s}# H9 l9 x7 f/ @: x) e* C
# }. l3 q- p+ |# ?; Q# M
! X6 x) Y3 E9 P c8 v- w, p
2 ?0 y6 ~8 K ~4 X8 P! q- S
4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)].- x+ U. D) d U1 L' l! }7 e# x
2 Q+ M6 {* G4 p
右击项目名打开属性窗口,在生成里,选中 为COM 互操作注册
" \% h" G- }/ W2 d* S$ O1 g' X* @
4 H. H5 b/ U- L$ h8 _$ B5 K& M+ v/ ?$ O0 e6 N" v, _
5. 生成->生成解决方案
! B% [0 ~1 Z' O; Q3 ~ 注意 这个时候 生成 非常缓慢
. B0 \ \: q) r 直到 出现 成功 1 个,失败 0 个,为止才 操作一下面内容
1 v& Q) t3 [6 w) ?( n. x3 a
6 G1 Y7 _+ t4 y" c0 w) v
5 R1 A" P1 x" c" P. ~, d0 g5 V---------------------------5 W/ ?% H, U. K& M1 Q
- H$ A7 U8 {# p# j! g8 O, a1.调用前要先把com组件注册才行.
' W6 @* C# F0 ]2 \
" _3 @8 w' O# }+ k4 i( L0 M/ _! ]使用C#创建并注册COM组件 C#不能直接创建COM组件,因为其生成的DLL属于程序集,但可通过“使程序集COM可见”选项来支持COM。
9 \2 V/ e* {0 f2 Y* L) M以下说明如何通过C# 注册、注销COM组件。 % V6 Y' B& w4 u; X6 }, f, z+ ? y
+ M% k. M! X) G7 u) C, i
为了能让生成的DLL能够进行COM注册,需要进行强名称签名% d. g, R4 [+ e+ A$ W+ L7 o% k2 y
打开COMLib项目属性,选择签名,勾选为程序集签名,通过下拉列表选择新建,弹出创建强名称密钥窗口,输入名称,不勾选使用密码保护密钥文件。' S" ]* L. x" Q, d
创建完成后COMLib项目中将出现后缀为.snk的签名文件。# w7 s; A, I4 r- v
最后,编译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文件。
/ b; d5 {+ I# C8 i% _3 d# p% [卸载COM组件:
" L9 g1 E7 P- z% l与注册过程基本相同,只需将命令改为“RegAsm /u D:\ COMLib.dll /tlb: COMLib.tlb /codebase”。) K/ x4 z, r( i! z8 u4 E; u
2 c* p$ v' w( i2 k9 H/ [ P& U8 [7 u/ _3 N2 Y: z/ T
2.注册完了就可以在代码中用了,先新建一个C++程序, 类型选 Win32 Console控制台应用程序3 ]/ @/ |0 o6 z4 w6 t" v7 S C
$ m, ]( J: Q- t9 w; F4 M% |* j+ }名字取MEI_UseCsharpCom,点完成1 S1 C5 F2 j, O1 E H) Y
6 ?# @- T0 t8 t把MEI_AddCom.tlb文件拷贝到项目的任何目录下.我就放在D:\MEI_UseCsharpCom\MEI_UseCsharpCom. U! ^$ T$ ]9 ?" b& w' J
1 c- v, z9 x7 C' D
我们会看到一个MEI_UseCsharpCom.cpp文件,双击打开把默认生成的代码全部删掉.敲入下面代码:
6 G0 Q+ C3 f7 k( e& M2 E
% G$ K2 E) M0 X; Z6 D8 p
4 ^; i, c! i. q, m#include "stdafx.h"
9 _5 [+ b% x" J+ @#include <windows.h>" l! g7 @7 n7 X% x, Z
#include <string.h>3 Q: k* k5 I% O/ H- y( X7 H7 n1 ?* q
6 g ^7 k" ?# h3 j- W3 a
#import "MEI_AddCom.tlb" named_guids raw_interfaces_only5 i; N) Q) C" F8 v" P, k& \7 Y
# T% r: m* U; F: V. G- Gchar* WcharToChar(const wchar_t* wp) //wchar_t转char*# ^% W. g$ W, t. Y8 i0 M3 m: F. R
{ . l# w8 i! U) X. K; n
char *m_char;
1 ^6 c( K0 z. B* Y5 F3 S int len= WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),NULL,0,NULL,NULL);
# J2 X' ~( ?3 j8 {% M m_char=new char[len+1]; ; r+ J) ~7 r5 {: b( F
WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),m_char,len,NULL,NULL); * G" ]# I6 s3 y. U% |
m_char[len]='\0'; * y6 t# [* {6 H$ h5 ^
return m_char; * q, Z! f, \9 n9 a
} " f5 }" q& z$ L" s- U y! j& x
wchar_t* CharToWchar(const char* c) //char*转wchar_t
2 t/ U6 @( y/ Z% M5 I{ 3 R' A; F9 e+ B9 Z5 }& p/ q6 G
wchar_t *m_wchar;
* c- t5 h6 i1 H int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0);
! n/ n( d G( }7 `& \4 A m_wchar=new wchar_t[len+1]; + X; ~) a3 u( Y* E" N# ^6 Z% P
MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len); 8 j4 X6 C! e- |) j1 X" H: P
m_wchar[len]='\0'; K: T! {! V+ ^8 O
return m_wchar; ( S+ K* t+ T; Y' k- m
}
8 n6 h! w3 S+ k: P# }5 o
. R! z2 U% x0 X, Z( H. w1 ?6 A6 wvoid _tmain(int argc, _TCHAR* argv[])# i* Y& Q2 U, ?$ m4 S" Q' F
; z I& K2 b1 Z, v
{
: ?: M7 J/ W7 ^5 d: p( \8 l; ~0 x0 v$ i$ ?
CoInitialize(NULL);
; @; r. _. Y% \# S6 t: q, r% l8 y( f* K) t, l7 E+ k
MEI_AddCom::MEI_COMPtr ptr; //类似明志一个指向接口的指针
, f, i3 E5 Q; v3 ]8 u1 A
' ~3 S) E% o2 R& q6 ~ R: j ptr.CreateInstance(MEI_AddCom::CLSID_MEI_COM_T); //实例化一个类 CLSID_ 类名$ K- r8 y+ Z- e% F t- H; v
, Y" {6 M2 ?9 y2 L. @* G8 `& y //这个地方有一点点奇怪我也还没弄懂.在C#中的函数是int Plus(int,int).但类型在这里都转成long了.另外就是我们不能直接; R9 p4 P2 R4 N/ N. S/ z
4 e3 R+ q# G1 B) V+ P9 x
//来个long a = ptr->Plus(1,2);这样得不到a = 3,反正会出错.8 u$ B8 b& A) w2 C/ w+ u$ V
//这里函数Plus的参数变成三个了long Plus(long,long,long *).其中最后一个指针得两数相加的结果
# K+ K% J, Q& D* j2 {
. w3 j3 I, B: h long a = 1;
8 `" C# D6 w; Q8 m& X( M- G8 O$ \1 B% C; x
long * lPtr = &a;; e2 Z j0 ?1 s' `/ Q
% J# u2 Z4 G( H0 A/ W! B" @
ptr->Plus(1,2,lPtr);! z' f: l. V/ t- ~4 s; i( Z
/ k. m$ [* S! n% d1 g
char msg[132]="";1 ~1 E% K" ^) ~* T/ W
sprintf(msg, "%d",lPtr[0]);
$ k6 H% n \9 X) H! H9 B1 P6 y7 Q( q5 _1 X
LPCWSTR str=CharToWchar(msg);
, I" j. Y7 u+ F3 c* P
7 W9 L9 K2 k1 r+ \ S1 y$ ] MessageBox(NULL,str,_T("123"),MB_ICONWARNING);3 _0 B q% |6 N# h9 J8 d
5 _0 h8 q% q! p7 m ^, u: z8 S# K. |8 J- i! }# c) ?
}
9 z% }' e O M |; A* ~) g# J' m6 D c1 k
此时就可以正确运行了.得到结果3
' I: x8 f7 k' A W$ ]# W1 V/ @+ T
5 o A, E' z! n+ C如果没有正常运行,则必须把dll文件拷贝到有MEI_UseCsharpCom.exe这个文件的目录下.. `( r- ]1 r$ V0 k4 X R$ k
3 ?7 B7 }. I3 ?' J. H
7 t6 F8 k( `5 c* J( M8 P--------------------------------------------------------------
& G0 b! W, z# [. }. H2 w! v. H. sC# Npoi库 操作excel 的代码网上很多
2 L) w5 b4 _0 d" c, m
b4 L1 s. b7 N3 |% p5 z// ----------------------------------------------------------------------
* P; y( f$ `' p E// 使用Npoi创建一个简单的xls文件,写内容
7 g5 @& L' U9 ]8 ]$ \" Y* T w5 ^& a( V9 U$ G
using System;1 l& x" N N3 L3 m: m7 l; i& D( _
using System.Collections.Generic;1 J" f! o5 @7 g2 z% N: V( v* `
using System.Linq;" D# I5 G8 I3 e [% Z* j2 b
using System.Text;
" E5 h. n/ d( }3 U. g* ^4 jusing NPOI.SS.UserModel;0 a! F2 F# K2 E( K7 Q
using NPOI.XSSF.UserModel;
' J* L3 i; ^; C% y6 qusing NPOI.HSSF.UserModel;
3 m& E( u9 O- b: e* ^ a! Pusing System.IO;* y: |+ p; R$ P0 O" ?
using System.Data;
( r/ ^! k3 R& l9 S. g6 t( r E: U- [; `+ K6 _
//using System.Windows.Forms;
# r q; b0 y3 L, p+ [8 o/ j3 c+ c! _9 z( U5 v3 l1 P6 O
namespace CC3 \) a( P( J0 K
{7 s9 c. [1 n" z4 ?( g
/ C/ a! ]% G5 {* Q+ u class Program
* D& i- N {9 Z& G2 O4 s$ o {# P/ v6 k, m) I9 F. K. s/ v+ }
' Z1 u# T' e8 Q' u6 c, V8 d' r
7 g( u9 a1 i l2 o3 ]5 N: Y- c static void Main(string[] args)
( M% v, ?* K0 y& i" e; L6 A1 f {7 [/ J' h; i9 z! e/ B
//创建工作薄
, U2 N4 R) q$ E9 G( j2 V7 b. ]* a HSSFWorkbook wk = new HSSFWorkbook();1 S' N' n: G* u. v# {
//创建一个名称为mySheet的表% {7 ~* U- {' d' o9 w
ISheet tb = wk.CreateSheet("mySheet");
- U. }0 a" G( U% h1 O6 ~$ } //创建一行,此行为第二行# `/ D7 {$ `4 S5 J. c
IRow row = tb.CreateRow(1);
7 ?* y8 e5 \. R! O! z K6 Q# b for (int i = 0; i < 20; i++)2 J' ~2 z: X) V v7 f
{
( Y! Y( }0 s" h9 ] ICell cell = row.CreateCell(i); //在第二行中创建单元格
) N% s' o; W9 ^- I" t) w cell.SetCellValue(i);//循环往第二行的单元格中添加数据) X0 y: R3 o) [" Y2 i* F. h/ I9 J
}2 w0 I% s; M& q) J
using (FileStream fs = File.OpenWrite(@"c:/myxls.xls")) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!
, g1 O0 s8 Q$ d {- w6 Q5 e6 |7 r; N& j7 y
wk.Write(fs); //向打开的这个xls文件中写入mySheet表并保存。
2 k% \$ N9 @4 H$ M { // MessageBox.Show("提示:创建成功!");
* A% {, Q' ?, k3 k' _+ a }
3 R9 n0 e5 G# o) K( l; x
! J1 H$ v0 q" P+ [ } E" f* u' a% J: Y1 n
4 ?) l- Z; b+ K6 g3 J; G, N7 f3 q5 |$ a
/ B4 M$ {2 e/ \# j& j }: u! B* M8 I7 Y0 a( r @
* U# i! e; K; N! f
+ {! S) @2 p% F* x D
6 i+ @) ?4 r' b& \/ ?& R} X: E) |+ m5 v+ O& f5 E
& Z1 ^$ h' K7 B/ m- ]% w5 }
// ----------------------------------------------------------------------" I0 Y, V9 {0 }
// 使用Npoi读一个简单的xls文件
) ^. g. I. [7 y" p3 r1 |$ p9 f4 `$ e
using System;4 t1 x1 ~9 I6 v3 m4 _; F/ \* c3 J {
using System.Collections.Generic;1 q5 P0 k+ c5 }% f
using System.Linq;
8 K& C4 E4 _, R9 rusing System.Text;* d6 `; C& ~. U- T( j# I
using NPOI.SS.UserModel;- m3 t( ^+ v3 ^( V
using NPOI.XSSF.UserModel;
' Y4 a) q9 D3 zusing NPOI.HSSF.UserModel;: N. ^- J+ o, `8 a
using System.IO;2 c& |9 O: ^" W' ^
using System.Data;
6 Y9 D+ f" [4 @$ X4 D. R0 ]6 p: v7 f2 F6 j; Q4 p
namespace CC
8 y w( F2 E& {* M* v{
/ V& Z4 i2 F6 {$ H- i! R! i4 u
" b+ t/ F. |0 a1 k class Program! [8 M" m0 W* }# ]( E) W! J' k
{+ W1 ] x# Y( W _ A; H
6 N: H# E0 C, x( a% U( U- {' a% C9 ^9 T8 f, G: K) H9 ?7 j
static void Main(string[] args)
% j+ `/ m* {5 w! K5 t- h" {( Z {
0 s$ S. E- V. J+ ?/ v& X StringBuilder sbr = new StringBuilder();
! B6 ?7 B$ H' C( c! v" n using (FileStream fs = File.OpenRead(@"c:/myxls.xls")) //打开myxls.xls文件9 r* p& z8 q2 t8 O( P2 @
{
, O, n# Y) b" H; [, X HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的数据写入wk中& f2 R2 b# e3 u/ l- d
for (int i = 0; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数+ t" r& b: k* b' U [1 F
{
/ r: Y; A. j8 r1 i7 C7 W' B. D ISheet sheet = wk.GetSheetAt(i); //读取当前表数据8 d3 m+ Y6 X8 U- n2 J
for (int j = 0; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数
# C9 N- u2 P7 M, {0 R {
+ `* @9 g4 q; ~# e IRow row = sheet.GetRow(j); //读取当前行数据
+ T/ @$ D" I3 G/ F' E1 o9 ~& c& Y9 u if (row != null)
! y! U& ^* a3 p' [& h) o2 s {
/ I" _& f) g; L7 l+ o& v2 ] f' C sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限* S- Q5 I' g7 ~/ [" o' F, P, g/ N
for (int k = 0; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数
4 H, N2 p7 j. f# S1 L3 j {
/ ?( f7 O- C: q/ W7 |3 a8 z8 _5 |) `, s ICell cell = row.GetCell(k); //当前表格; y! s& {2 I" R4 q; X9 L
if (cell != null)2 h6 B( \- i! ?$ e4 l+ i" W
{: b6 @# l4 G+ N( r' d$ t+ d
sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型0 h: [) ^0 v, }% Z
}
; s! Z' d; A" i* } }8 X$ t$ U f# [' E% b
}' L$ v* Y# b, e" x! K' b
}
/ T) M2 b6 r# l2 W0 ]- t- @8 t N }# j' r8 D7 Q9 s
}' b# q7 z/ S9 N4 f5 f
sbr.ToString();+ ?0 X' M, m& d
using (StreamWriter wr = new StreamWriter(new FileStream(@"c:/myText.txt", FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中
t; q$ L$ U5 q {
& Y* P1 W# E( u) s+ j8 N# @ wr.Write(sbr.ToString());
+ L( M( a+ l2 W) ?& M wr.Flush();, n8 C B5 H7 j0 N9 ]
}
5 m6 V* C2 H6 |3 X$ T. l( K" J3 m) N! o: A6 A
" L( W u* }( S: n7 x6 C7 F3 B }; W! F: a8 k" I2 N( I
L9 U( i. v, `# d9 b
% Q3 H# ]$ }0 L# R7 j1 A. H }
! u6 }7 v$ v3 f3 V& n
( |1 Q3 Y. C' ?- \: a& j4 l2 M* C& ]# p
, ^$ G4 o# n2 k7 V1 J1 I1 j
}
7 G7 [. q' a# ~' \# S
* [8 M' u3 o) W4 y+ H' G
1 P6 ~- _% g: s1 w' J8 Y" f然后 自己封装 给 c++用
* l9 i' J j- W. A1 Z% ^' z" @1 N
5 F O8 t0 q# e7 ^( P
" i' H3 E; g' |/ F+ v$ N
8 P/ r% U3 ]" w2 P' O x4 W+ ?
7 u& _; ]7 E4 G/ \* U% n
, t( I3 E. b' n4 i
+ R. S, V7 Q5 Z* Y4 J
/ ?; E c, P3 r4 Z4 m {$ P0 x( p0 Z9 x# c
% E/ ~5 O2 a% s* b7 k! y
& A: _! z, f' m; c. M7 x; S8 B8 u
+ g8 Y' Z5 @' T$ l$ H9 @5 n' n% z) X4 I
- U7 F" R, x/ w, _
9 e# z) H; Z0 f
# s" B: ^1 ^/ p$ b* t# t
' j$ q8 ?8 c( N6 b4 q) H A, Y- a, g9 |
# n K# g. k0 U% c
( a9 N) {: L" {) M' M+ V# S3 B {
, M6 a% g- g: k
* b3 e4 R5 n% ?" s
' ]/ m& ^8 H# U1 F j
|
|