|
|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
C# 或 c++ 不用安装操作 EXCEL的方法:c++ 对excel 的操作 非常不理想 要安装excel 而且读写速度也慢/ R% _/ R' a! C6 ^7 C
net 有很多 免费的开源库 比如 Npoi库 (Npoi库 支持c#、vb.net 等语言): P) v! K$ `3 j# \4 }+ {% X
这里我用c# 生成 com 组件 让 c++ 调 & _) j) v5 M# g8 Q1 Q
+ K* I. j& }+ \, V' S
首先要学会 c++ 调 c# com组件的方法 (和com注册的方法), P |6 h/ p2 v6 P$ R* y( b- Q
C++调用C#的COM组件(DLL)4 @9 q5 L% d/ _2 M) ^
# B# S9 N6 W" \2 T1 r4 i& U { y6 I
下面我举个简单的小例子.我用的是Microsoft Visual Studio 2012,操作系统是Win 7.( K9 q( r4 F- q4 Y9 q4 I
首先创建一个C# com组件.实现的功能很简单,就是返回两数相加的和.1 r4 c) |" V- v7 y
. n6 k4 S# ?" T& T1 v! }
. B5 v4 m4 h7 L7 D, ~ _1.新建一个C#项目 ,类型就选 类库 .取名 MEI_AddCom/ K* o' U- j: H; y
: O; a9 \8 @( }- v5 P
2.在项目中添加一个接口,取名MEI_COM.C++调用com组件中所有的功能只能通过接口来调用,不能直接调用类或函数
+ ]" l6 q1 n2 `$ g) `$ C1 d, k) ]5 V) H" |! \- p* x! Z
具体代码:
Q8 I; z" n& ?3 K
" f/ u8 ~" h4 X( l0 V3 b2 Susing System.Runtime.InteropServices; //记得加这个命名空间7 i5 ~/ l0 ~1 q7 H; J
% I: s; c# e2 x1 I" w; `
namespace MEI_AddCom
3 b, P1 H8 W' _! S( |8 c1 z: f6 h; X, k. C: m" Y1 a
{
3 O% u9 l1 }; v' E3 Q! }. E
. q5 { g- V- K( V8 z4 I; Q [Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的产生可以通过vs自带的工具.点菜单栏上的Tools ->Create GUID,然后选第4个选项.Registry Format.! C! c( z' c3 p0 F) [
, }' u% ]0 @) y3 j
//点按钮New GUID,再点Copy.这样你就可以把产生的guid复制下来,然后粘贴到这个地方来.当然那个大括号得去掉.后面需要用到guid的地方也用这方式产生
: Z& {/ ^5 j) B- A1 l+ k
- P E! a) A- X) w. B [ComVisible(true)]' g/ P8 }% D3 j0 p& R5 Z! b
& K" k0 k9 K _7 U3 M z public interface MEI_COM //记得用修饰符public9 _3 g& F, b. `
' |2 p2 |$ C+ r( Q$ G0 c {
. j! C. ]7 B; a* R; O, K- |+ [: g9 a
[DispId(1)] //如果还要添加其他函数就继续来个[DispId(2)],[DispId(3)]加在函数前面
9 E$ q. x! m- H" l6 ]5 b8 u% [( I3 K4 o2 _/ \' k
int Plus(int one, int two);
- e% D$ i/ s; g! ~9 `" f! `0 I, p0 w- z
}
$ C, P% s; T1 C0 o9 [6 {
9 F2 E' G% l; K- a4 U/ v+ H}
1 D, z7 z$ | a& g4 [
) Q9 v. R* B3 O/ x! x( {) t/ [& F7 ~+ `: v& z% h
# W3 V' x$ o- d; o
3.添加一个类MEI_COM_T,继承接口MEI_COM,具体代码
5 e0 x8 Z) p: q8 M# n3 W2 b* |4 D# Z- A7 Q5 m8 q5 N K
using System.Runtime.InteropServices;
- m+ ^+ u& l' c* _0 M% a2 T. o: Q# g' e [( ^
namespace MEI_AddCom
2 U- P; h( y! F6 D6 z' p* a, Z6 k. \% L9 X2 R
{
5 u4 L& Q, y8 k. X) Z8 F
# p8 u+ b+ E% |/ H' G8 j. y) I5 u [Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]0 a: E. x, c, ?3 Z2 ]
. @$ j7 U' j' ?" D! _ [ClassInterface(ClassInterfaceType.None)]0 F* Z0 m# f. o+ a, i- N% z
: v; x5 [ D8 Z& T Y7 P, y8 ? public class MEI_COM_T : MEI_COM
: j8 ^. r+ r' |2 z! j. H" f/ _8 @% \0 t0 |) _. J: Q: z) {5 i- x
{; O& x) J9 n' @6 D+ G
% G3 B9 s3 l3 ]2 k" n* ^ public int Plus(int a, int b)! l5 k: O" K& b9 B
8 S2 z( M5 B5 ^
{
' y8 Z8 |& Z; i, ]4 o3 k
. ?: M9 B( t& \4 T) L return a + b ;
1 {0 h# c) P0 [& A/ e& ?: ^8 u* _! n8 H. e
}% p l' a& x2 y8 y% b! c; b
2 E: E* h* l! t+ |5 { }
+ L8 T- O. `6 Z, g$ r: f9 @9 `% [. g: d. j: P) L4 S( l. n
}
3 F" B+ n3 V+ ?$ z- O2 o8 W3 z- @8 h* u- ^+ H# [4 b! y
7 o$ H h) N( y
8 c: H! Y9 c. \4 d* U: p. O/ ?
4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)]., T* L9 |2 B. [
- O% q' {/ K3 G) u# X/ r6 B9 m% j右击项目名打开属性窗口,在生成里,选中 为COM 互操作注册
+ v6 w. X* m$ ]0 \8 {0 L. L3 S6 |& K8 p2 G
8 w/ h1 }, f. W& r. A, v
5. 生成->生成解决方案
; |: s& j" R, X, Y& O; J3 g+ ^. k 注意 这个时候 生成 非常缓慢
3 s# t m5 G. } 直到 出现 成功 1 个,失败 0 个,为止才 操作一下面内容
& _$ C0 I! |$ L$ ]0 z& L% `! r+ O! n5 [/ q& ?$ O' k
8 O, [" {. k7 B8 H) Y---------------------------
9 {7 Z m* Q) V6 U& h+ c. @' B. m$ J
( v, C: w7 O0 j7 B) [* P8 |1.调用前要先把com组件注册才行.
* l# N& @! B9 [* s6 \# T9 |) T6 I( y# r' Y! e5 a6 }# @# F" L
使用C#创建并注册COM组件 C#不能直接创建COM组件,因为其生成的DLL属于程序集,但可通过“使程序集COM可见”选项来支持COM。
* K% Z: Z: @1 m4 u6 q, D& {! c# t, n$ q以下说明如何通过C# 注册、注销COM组件。 $ P/ k$ ?; Q" W% T' i
" U; b9 g8 {% u |) e& ?为了能让生成的DLL能够进行COM注册,需要进行强名称签名/ a# E9 ?5 A# `* a8 h( e0 U
打开COMLib项目属性,选择签名,勾选为程序集签名,通过下拉列表选择新建,弹出创建强名称密钥窗口,输入名称,不勾选使用密码保护密钥文件。( f7 z' l7 `0 {; c% W
创建完成后COMLib项目中将出现后缀为.snk的签名文件。$ F; P, ` d9 C3 l* c |4 q8 P" R
最后,编译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文件。
. U9 Y; h. J+ e& y0 K卸载COM组件: ; |) i; d" u. |+ X) f
与注册过程基本相同,只需将命令改为“RegAsm /u D:\ COMLib.dll /tlb: COMLib.tlb /codebase”。" |4 n4 b1 ]- S9 D5 I3 J7 k
2 E) H- J" @3 K$ o* X5 t- g& w
3 o& N" @7 Q; d2.注册完了就可以在代码中用了,先新建一个C++程序, 类型选 Win32 Console控制台应用程序/ O, O( s5 ^' [ ]2 f5 z
6 i9 @5 J( ]) x& v名字取MEI_UseCsharpCom,点完成4 _( `5 A. V% o
: n4 \# O1 e; h/ A- ?* }3 a X7 d6 ~把MEI_AddCom.tlb文件拷贝到项目的任何目录下.我就放在D:\MEI_UseCsharpCom\MEI_UseCsharpCom.3 h+ c! b0 t$ X6 `
1 C. P: b5 e1 E+ l! s2 o我们会看到一个MEI_UseCsharpCom.cpp文件,双击打开把默认生成的代码全部删掉.敲入下面代码:3 a/ H6 V2 D/ h% W. w
6 ]2 s# i" W+ m
6 {5 H* G5 I9 n1 N- A( o, A" g
#include "stdafx.h"3 H6 D% F! v0 K7 Q3 W0 E- C
#include <windows.h>
/ n, X6 g/ X+ c, A#include <string.h>
4 I! [0 j" \( @4 Y$ X. ?
6 P6 ~ O, B1 d4 X Z# D1 x+ ~& q#import "MEI_AddCom.tlb" named_guids raw_interfaces_only
# M" s- Z4 x% ^5 a ^1 _3 v) x% C2 @! ^4 Y. j/ c, p3 e
char* WcharToChar(const wchar_t* wp) //wchar_t转char*
- p: s# M, v9 H{
( P2 j3 r& j! W4 c# |) c. v char *m_char;
% B# X( S' L1 b n3 R int len= WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),NULL,0,NULL,NULL); / S7 t: n! u3 d5 V
m_char=new char[len+1];
% R3 l2 J- h2 r WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),m_char,len,NULL,NULL);
5 R3 p. ]3 _) e m_char[len]='\0';
: o5 l* f3 C0 _" A' Z2 a6 O5 y7 Q return m_char;
. f6 z, B9 N: N3 n}
0 k( z+ [4 e _' S7 j0 w3 ^wchar_t* CharToWchar(const char* c) //char*转wchar_t. C1 c1 i# @3 C' K
{ , d$ Q% R' c, i6 d, X, I% B& V. N
wchar_t *m_wchar;3 q1 k8 L, J$ u: }+ g' `7 w x
int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0);
T+ K+ K8 I; Z* |& j m_wchar=new wchar_t[len+1];
0 u, S' h G; a, \3 f0 h MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len);
' A) b7 Q/ _6 q m_wchar[len]='\0';
: G9 S. {5 Z" y) _! J return m_wchar; & ^& Y9 s: i! r2 ?( x$ S4 R8 [
} + w: Y2 h7 D4 h6 O
, h. L1 F" n4 @6 r
void _tmain(int argc, _TCHAR* argv[])
' g5 v" `* C# ^2 f
. ~, I7 u' V7 h0 Z9 l- A8 H{
! D, `3 H/ }; e/ a3 h. \7 u; v; X1 M6 O; g5 g N8 Q
CoInitialize(NULL);
: }: Z4 R. y8 p7 m8 ]" b0 ~! y- [0 u, m; W6 x6 k& A# j4 I; ]4 @
MEI_AddCom::MEI_COMPtr ptr; //类似明志一个指向接口的指针
& [$ {* w, \3 u! b9 ?2 ~5 c5 x! Y0 w4 M1 t
ptr.CreateInstance(MEI_AddCom::CLSID_MEI_COM_T); //实例化一个类 CLSID_ 类名$ ?' ]7 U: J! U8 ?- v- @: W
! U b4 Y& t& I7 n$ o
//这个地方有一点点奇怪我也还没弄懂.在C#中的函数是int Plus(int,int).但类型在这里都转成long了.另外就是我们不能直接
$ s, R. `$ s- }; E0 o6 _: _2 A1 |1 ]5 D3 Q9 V
//来个long a = ptr->Plus(1,2);这样得不到a = 3,反正会出错.9 P& G' _$ @, q9 s1 R3 c( I
//这里函数Plus的参数变成三个了long Plus(long,long,long *).其中最后一个指针得两数相加的结果4 p& c9 N: o; ]2 K0 [' b, e( u
" @! P! f: L6 }3 ?- f, y" u
long a = 1;$ H5 {- X! C: m* M
; P$ r* {; a+ X5 Z# w6 I; @ long * lPtr = &a;
^& x, y# d: Y9 i, T% U% L
8 `9 E r) F# P+ N- C/ B( `% {2 x ptr->Plus(1,2,lPtr);) z' L6 @9 N' Z' \1 [" H
* V7 R. s, ]8 h: V2 a6 M, m char msg[132]="";6 L1 s; B7 P; _; s# s4 O0 x, `) _
sprintf(msg, "%d",lPtr[0]);
+ W4 j/ _% g$ i
$ E8 n: F5 x- h+ ?$ { LPCWSTR str=CharToWchar(msg);
+ M4 ?: S! ]. W8 |8 ?0 F) s# x: t' j) H5 d
MessageBox(NULL,str,_T("123"),MB_ICONWARNING);
8 [0 a3 N5 F/ e. E& C9 ]- |; g" |) d, g: F% G6 t
! G6 _' B4 S* C1 b5 R
}
# e" `( r1 `( X0 r) o
7 q' S0 ~$ @" W# s此时就可以正确运行了.得到结果3
% a- q' z7 V' `- U, o# c; \& x3 t4 H$ t( G
如果没有正常运行,则必须把dll文件拷贝到有MEI_UseCsharpCom.exe这个文件的目录下.# \; r5 P& ]# d l1 {& d
4 c% R3 W) Y1 |" b- P
! A- o8 k8 O/ E( @+ U' L S1 c--------------------------------------------------------------
6 L1 ]5 R% v, k2 I I2 TC# Npoi库 操作excel 的代码网上很多: w: I, J3 Y7 d1 y3 b; Z
/ D& x' X2 T! u2 ]/ k; L' B6 e/ [
// ----------------------------------------------------------------------
* h6 o/ t8 N9 o, b* t' p3 [// 使用Npoi创建一个简单的xls文件,写内容1 }9 Z3 y! C8 j0 ^& O* T8 r
5 j' `; R) X( G) w5 ], {' n! Ausing System; D, G" j1 w& U
using System.Collections.Generic;
8 y6 e. I$ g$ t3 v$ w, Y6 {using System.Linq;
! o3 H( ~8 R2 I) X* gusing System.Text;% I# `. P/ t. u e/ e! ~# }. q5 ~
using NPOI.SS.UserModel;
+ o( f; T5 g3 l; U5 e+ c. `using NPOI.XSSF.UserModel;
1 H+ f' ` Y8 x" }: E; kusing NPOI.HSSF.UserModel;
' o) y. |7 j4 @% @ ~" Xusing System.IO;
7 Q3 O0 n( \) B$ g: vusing System.Data;
1 w" g3 F$ ?- w) l6 }8 p2 Q& ^
7 @* V3 V$ b4 o/ O6 A7 o' @//using System.Windows.Forms;
' R. \' W; m& k, v& ~/ b
) W7 I. {" Z. J1 W8 S) E* }# knamespace CC
" r @6 S& ~& S/ U9 k. l- H k, v9 `{
' E! p% b9 }; C. l
9 {1 R* O( R8 L class Program& D$ K1 ^$ H W: B0 v: m9 M6 u/ L
{6 d. T1 D9 c9 O# D8 S' |# P
' i# Q! L4 K# s& x0 o
) G' c. W9 N7 y2 }( l$ ~
static void Main(string[] args)
( K% ?5 |0 ^$ ]' c* I0 U6 V# @3 v' S {( {& G3 V/ S& V# V* w% [
//创建工作薄7 h% x/ P8 }0 \1 _( o
HSSFWorkbook wk = new HSSFWorkbook();
" d9 r- u. T9 A' N5 g3 g; |. r //创建一个名称为mySheet的表
7 w( R2 U" B7 u5 a# W# N) N+ g' i ISheet tb = wk.CreateSheet("mySheet");
U2 n( v* S \, w! {% C6 A //创建一行,此行为第二行5 q/ H, p/ Q7 s
IRow row = tb.CreateRow(1);
9 F' E6 ^0 h t6 M h( { for (int i = 0; i < 20; i++)' f/ z) l- m6 X! K3 ?" H/ r
{" R3 U' D5 z, E
ICell cell = row.CreateCell(i); //在第二行中创建单元格5 w j5 ]5 A, m# C3 R5 I7 B
cell.SetCellValue(i);//循环往第二行的单元格中添加数据# H& ^* D0 A( J% X! H
}1 a) \2 v1 ~ q1 L* R F
using (FileStream fs = File.OpenWrite(@"c:/myxls.xls")) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!
8 {+ ?& t: M3 b9 ? @9 Q {6 `" J: O2 @* r' }
wk.Write(fs); //向打开的这个xls文件中写入mySheet表并保存。4 M" y: x; Y( y+ v
// MessageBox.Show("提示:创建成功!");
. q. H& p7 Y* S9 f: N }( A) T8 t8 G+ [0 P- ?3 E
) x6 i- C$ S, n0 d1 u }
6 }2 T' l* \6 L4 y) y! _- W* d" |
3 Q; y7 e1 H. S* Z0 `2 x2 y }
6 A l* Y0 d7 W5 t
- _# c2 k* P& y5 h: ^
1 L; v) [8 j, P& }3 e }% ]! F$ D7 h7 ^7 U. \
}
( z. Q1 T0 v: @& D8 y! M/ O" w1 v- k$ S9 n' i8 j
// ----------------------------------------------------------------------
2 I+ f5 A/ f9 U; z0 {, n// 使用Npoi读一个简单的xls文件
, P& G. u" J" [3 U* Z
+ y, I0 i0 e0 O* U, l" tusing System; X4 m2 C& a9 c* R7 C
using System.Collections.Generic;" [1 H* k4 T j9 J4 D: s
using System.Linq;
) h& k( ^" }( |, R8 b9 V. }using System.Text;/ A' X% o( o3 L7 g- q: Z
using NPOI.SS.UserModel;: C+ ~6 N/ w& Z0 T5 \1 @
using NPOI.XSSF.UserModel;
. n- C. i g1 gusing NPOI.HSSF.UserModel;) y% D3 g# W, [: Y+ ` x
using System.IO; c4 h/ k, f, E& m
using System.Data;
) ~$ D/ g4 X6 d* h* [- s& b
! ?+ A. U( I6 [- [# F0 F( |namespace CC2 ]2 _/ l4 _% u( Y- D: H
{
, d" u4 C5 O# ~9 f, A3 D" M
' M3 `. U# ~2 H' Y class Program
# s8 H* y2 K6 R7 m {% z: a: E. w0 b) B7 Q
; ~1 d- k& i, h( f+ C* b5 V
) z- S2 i4 G* j) x static void Main(string[] args)
6 D. `9 V$ j9 l: B {
) I6 u2 C. i* w8 Z2 C StringBuilder sbr = new StringBuilder();
7 s5 }- R) y9 q. ^5 B using (FileStream fs = File.OpenRead(@"c:/myxls.xls")) //打开myxls.xls文件
- I% x- q Y4 J r. g' Y {' @5 h5 C" V( t, H% f
HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的数据写入wk中
' [- ]; I* G1 Y+ l9 O. I for (int i = 0; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数
0 O& k' o9 |9 A' A4 u9 A0 [: N {7 T( ~; k) z% o' D7 `7 T
ISheet sheet = wk.GetSheetAt(i); //读取当前表数据- l/ _1 | k2 T( c! [# c; Y" t
for (int j = 0; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数- y( m; P7 |9 o9 E. p- T8 Z2 y
{
% d$ N- j8 H! V3 o c- I3 ]& J IRow row = sheet.GetRow(j); //读取当前行数据
$ W2 i" X% Z: j E. C if (row != null) V" \& D8 c1 `% f1 m# \! e
{
# k0 d( f H. W sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限4 }& b* s5 H& _: y4 T7 t3 W
for (int k = 0; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数! Z h2 a' {- W; x- w+ ?
{% e3 W( U1 f: V
ICell cell = row.GetCell(k); //当前表格" T9 w) ]$ B, p# ?4 C2 h
if (cell != null): S6 f' a( [; [
{% G. n) v. @0 E) j7 M" b' w2 }5 g
sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型
" F! `+ H9 A7 q; R( z8 k1 C }
$ C7 H: S0 v6 R }1 E( x J) g/ t6 l& a& g" }! x
}
: G! s2 Y% }0 X0 |3 E" u2 ] }: n7 x# v# y) ^( V# M: A2 q& U
}" ]7 A3 [' N) E/ ]. H" m
}( k. @: m6 J& {1 M7 P! k# N
sbr.ToString();5 E+ z4 B1 ^: I7 g" w* [7 b
using (StreamWriter wr = new StreamWriter(new FileStream(@"c:/myText.txt", FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中* {+ ~' ]8 K. y: g3 y
{" D0 c |' a2 W7 M2 w
wr.Write(sbr.ToString());0 s1 T- c6 {' `& t
wr.Flush();
" R. f ], I6 k: a$ T }: g& F+ r5 }/ j( w, ~
7 b# o) S$ l: y- B8 r* R
' ~7 T: X( y7 @ }
7 U* l6 Z5 a6 a+ B4 U) ?
; J8 @- t( ~6 o% m
3 r; s' o6 E( l4 q: s, c }2 Z$ p& c/ y7 N5 G0 R7 I( ~( _
- [) y3 Z$ }. A" |1 I
- q# `# f" A0 V7 E) X; i2 ~& Z% w3 F) H- A; \' X
}
1 L& n- r/ f& ^, ~
5 W$ K' F: ?% ?3 o& I' j4 x! n8 C+ {5 q; F- ?
然后 自己封装 给 c++用/ c( D; v5 P% K) l* N- |/ \; V, t
! T$ l6 m. V5 i$ s: `/ |
6 j! s/ |+ t: d$ O0 I% p! k0 u' L; ^ ^$ J6 T. q" R3 A8 G0 W
" k! N( _8 ?# u) J8 X$ u6 o( |
4 B6 {) d3 r4 q) B' q; F
0 K$ T% S D$ k( _/ N6 |8 _) d) Z, D" R- }' k& O
. G+ n2 @ l0 V* W* D1 I8 F
; |) ^2 D. j* O* ], p7 z8 ^. d& o8 K# P4 E
9 ^# m9 t. G; v+ [
! o' M$ q' {- O
$ S. ?+ {/ l! m
" V+ I" {6 r+ K$ q9 _/ |& h7 x8 |/ \( Y2 ?, V7 r) j
8 Q) j0 {4 k* P/ M! y9 {/ P4 w# H d* \3 G8 n8 d( V( K. y
/ N ?* A8 `$ f1 i2 u! G
+ Y# z; b( Z* D9 e* n9 ~6 Q2 c+ c
" s# t$ `- G: @# e6 H% g
1 M ^7 E7 J% x# J, m
2 N* E. P o# a$ e2 ` |
|