|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
C# 或 c++ 不用安装操作 EXCEL的方法:c++ 对excel 的操作 非常不理想 要安装excel 而且读写速度也慢- T8 q2 v4 q$ \5 q$ f. Q( `; z
net 有很多 免费的开源库 比如 Npoi库 (Npoi库 支持c#、vb.net 等语言)
: U- T* L; M0 R* Y V4 c; }& n这里我用c# 生成 com 组件 让 c++ 调 9 ^- L3 ^* ]) J0 Y
$ m+ z7 |& b% L首先要学会 c++ 调 c# com组件的方法 (和com注册的方法)$ p- y+ X7 _# {: w2 F. F
C++调用C#的COM组件(DLL); C1 z( i/ s# d6 r n O
0 I) Q+ B9 c1 O, \! r
下面我举个简单的小例子.我用的是Microsoft Visual Studio 2012,操作系统是Win 7.
# @+ D7 S. Z2 w8 s6 h首先创建一个C# com组件.实现的功能很简单,就是返回两数相加的和.7 H5 k. r$ W1 h; ^' `( J
& H( o! _) V+ K4 q
1 ], x$ j# l" r) Q' l
1.新建一个C#项目 ,类型就选 类库 .取名 MEI_AddCom" ^" \& A6 m+ I2 n4 m
- U$ _- N$ ~, h2.在项目中添加一个接口,取名MEI_COM.C++调用com组件中所有的功能只能通过接口来调用,不能直接调用类或函数+ n; {' o7 |: p; m! @1 U3 f
4 d- N# v& g; g1 Y8 Z6 j" R" s具体代码:
- k% N" A+ v( n6 u" h9 w8 u" W) z3 P m4 T) P G
using System.Runtime.InteropServices; //记得加这个命名空间+ F' t4 @3 u( _$ b
G7 \$ e8 b1 V" C, g+ q$ i
namespace MEI_AddCom' Q* ]! V. O2 D. v4 |
4 r* w, N/ D L- U# B, Z# p
{, Q* i. T: b9 ~7 L/ M: f# }: R
6 X9 `9 [1 b6 V+ Y! |& {
[Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的产生可以通过vs自带的工具.点菜单栏上的Tools ->Create GUID,然后选第4个选项.Registry Format.
" d6 I! ?/ ~- d7 X7 Z$ \ N( c0 x+ F) @5 C6 ?/ J6 G5 U. W
//点按钮New GUID,再点Copy.这样你就可以把产生的guid复制下来,然后粘贴到这个地方来.当然那个大括号得去掉.后面需要用到guid的地方也用这方式产生
/ a R0 r6 T: q9 W; {
" A! g% @8 Z1 J5 E* B3 C [ComVisible(true)]1 m% x- { ~; v
7 q* g N; _: M8 N8 U
public interface MEI_COM //记得用修饰符public9 A1 ^ J8 q/ t% {0 w
2 r- U! T; l# [+ \
{
- I& C e) g$ U+ X( a, l; _4 Y, g2 c7 ~: m2 J9 [$ a" |% D
[DispId(1)] //如果还要添加其他函数就继续来个[DispId(2)],[DispId(3)]加在函数前面; O( D4 K; J8 w: f* K9 s
" x3 G, Z% h1 m; [' ^: y0 e& ~: A
int Plus(int one, int two);0 d, K9 M9 n" {. l0 ~
) J0 f% P$ I) j, t; s }' k: G1 G( m% t" c( h; @; ?) @5 o
/ ^9 K2 `9 }. I1 o* T}
0 W7 b2 \/ z! m
* y, Q3 a' c, U" N5 {! s( W4 M: ^! V/ Q: l& u k: g
' A. ?; H, S4 r @1 K; a
3.添加一个类MEI_COM_T,继承接口MEI_COM,具体代码
' G. a8 H( J( Z0 e
0 `, r0 T' l. T0 p: e8 X5 }using System.Runtime.InteropServices;$ U; Y- t; T! | G7 n
, v7 G3 _- W0 A' K2 u) u% m3 bnamespace MEI_AddCom
. ^6 r" G, Q1 l9 C% J% D
2 ~& B1 z; J4 O+ y0 ]4 h% a{
/ b4 b4 c* ~ t0 L: _/ {
5 y! Y- ~. ^6 Z4 W; t [Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]
7 w3 m: P0 i$ m7 G6 H2 W
! c, d% h3 f% p& ?$ n7 e [ClassInterface(ClassInterfaceType.None)]
1 I8 _0 T! v- ]+ d5 M- Q
! F8 E4 |( s% { public class MEI_COM_T : MEI_COM @1 A$ T4 w( N4 e' v
$ z+ F' m3 R- M5 R; w: E" ?
{" U, A. M4 O) M! Y. a# i- S, F
' N9 e, C2 _% h public int Plus(int a, int b)
: { Z9 G4 y' B* M$ {6 q4 J
- [. C7 h+ \" ~# E2 O |' c B {
6 K I4 Q K X
% q, c9 \5 S' R' e4 X# w9 q- s return a + b ;, [5 B5 n( x* d
, V' t9 z ^- T/ [# i w( [ u
}, w/ i. F5 k7 O: {4 }# k
% A% u. U( N1 x- \1 _4 ?0 e
}2 Y) _) I2 D$ m- B& ?: x' C
( D$ [+ r3 y- e
}5 x& {' H% |9 ^5 G" m" A
3 b) l" |0 ?: o3 Y* c
: Q8 m" g1 U1 I7 V* h
# G% n% Y8 g+ }( G4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)].: H. Y) H0 z/ N* W! h! a6 W5 a
3 |0 ?7 `5 G @0 w
右击项目名打开属性窗口,在生成里,选中 为COM 互操作注册
. X+ u8 j; Z7 ^5 M, F( n
- N: a G' a! b' r% A# s9 l
5 j+ H! f) U/ C+ v8 u5. 生成->生成解决方案
* L. ~5 q7 n# a6 K 注意 这个时候 生成 非常缓慢
- N' h8 A7 x" l1 J+ N/ t9 @) l' [4 \ 直到 出现 成功 1 个,失败 0 个,为止才 操作一下面内容
9 D0 ]. U \0 v" d" X5 Y( K" G8 T; p5 L# L
) `0 m; h( H/ N
---------------------------
9 L0 q# g7 u' f+ P
0 X2 M1 T/ o9 n% m0 T3 Y1.调用前要先把com组件注册才行.
6 D- \0 k# b, u9 i& P# G3 U9 _: E( T7 P; b+ L7 s3 l$ X9 q" Z
使用C#创建并注册COM组件 C#不能直接创建COM组件,因为其生成的DLL属于程序集,但可通过“使程序集COM可见”选项来支持COM。
9 l- |$ u2 K# T2 D$ w以下说明如何通过C# 注册、注销COM组件。 ( ~. }, Y; J) q$ E
! l; q* g: a7 M) f5 [' E2 E
为了能让生成的DLL能够进行COM注册,需要进行强名称签名
2 X' Y# J. ^! e5 Z; f打开COMLib项目属性,选择签名,勾选为程序集签名,通过下拉列表选择新建,弹出创建强名称密钥窗口,输入名称,不勾选使用密码保护密钥文件。
. ?0 t* ]2 ~, ?创建完成后COMLib项目中将出现后缀为.snk的签名文件。
5 S' `6 S8 U$ X! e& E0 i5 Q" k. 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文件。8 ]% ]( m8 T% r) y
卸载COM组件:
2 M& N- ^* I% S* `与注册过程基本相同,只需将命令改为“RegAsm /u D:\ COMLib.dll /tlb: COMLib.tlb /codebase”。
7 C% R* h0 Y. K& T
; |; _. W3 B$ h* @
4 g I; o/ h/ X& c2.注册完了就可以在代码中用了,先新建一个C++程序, 类型选 Win32 Console控制台应用程序
8 i# d/ Z8 n, k v( ]. p2 [# c
]$ N- r5 r" V j* m" R名字取MEI_UseCsharpCom,点完成3 @+ v! O7 f: }! V/ P' ^. A' F
% q2 {' ? m' W: l- Y把MEI_AddCom.tlb文件拷贝到项目的任何目录下.我就放在D:\MEI_UseCsharpCom\MEI_UseCsharpCom.
; ?1 a: w8 S* D/ a" ~' L/ N% }( x7 ^4 k m/ O7 y( d
我们会看到一个MEI_UseCsharpCom.cpp文件,双击打开把默认生成的代码全部删掉.敲入下面代码:
6 u9 }0 q8 |, ~4 Q) q }6 Q; C- w
$ I3 c2 y0 A4 u$ r: i+ d) o" T( B0 j; d: y" u
#include "stdafx.h"* Y6 s, i& E) K/ w2 X" U. G
#include <windows.h>& v1 E( V& y* n Z
#include <string.h>
t7 C. k: d9 v; _
+ l/ S1 Q# U& J/ l# H2 P ~#import "MEI_AddCom.tlb" named_guids raw_interfaces_only
/ v4 [# g u. B) X3 y/ X. d8 U9 X q4 W( y1 h( v
char* WcharToChar(const wchar_t* wp) //wchar_t转char*
0 t% ~+ h8 ~$ q. e- @7 u{
H" a" g3 {$ f7 g char *m_char;
) t! m: Q ^& R1 U! r( a% ? int len= WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),NULL,0,NULL,NULL); ) K9 r' z0 v& a. z/ E8 P4 ]
m_char=new char[len+1]; - n$ p/ F* @3 q* q
WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),m_char,len,NULL,NULL); . }$ u+ l8 p9 Z6 \0 s2 p. @
m_char[len]='\0';
4 K! b H0 X% D4 |: I5 T/ P return m_char;
- \4 _% `- r, @5 `0 A; ]} 6 p9 r) i. |+ {( D c3 {
wchar_t* CharToWchar(const char* c) //char*转wchar_t3 _$ n+ U! g, s# y; y8 s# i
{
+ L6 `1 C4 R$ g s- ]* F F wchar_t *m_wchar;0 H$ J2 g4 W7 S6 p# a: q
int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0); 8 @/ A2 ]& F4 V) p) y
m_wchar=new wchar_t[len+1]; " ^: U4 L7 h" g8 V0 `5 C: l. ?5 {2 F
MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len); " _" p6 U5 v' j) L2 \
m_wchar[len]='\0';
8 D$ o. @- O/ |* ]% d+ g return m_wchar;
6 _# T5 [+ T- N5 j4 E( @}
. L8 ?2 r9 I Z, J1 k5 l U+ R2 @! V% `3 ?
void _tmain(int argc, _TCHAR* argv[])1 f# d7 {( K0 R! c+ D, K
9 j3 P: f# z6 I+ H
{0 w! a& K S* t8 Q( S- a5 J" ~
" c$ `( b1 d$ B9 M8 H
CoInitialize(NULL);% p/ E- c# L2 r& k
' g* j! A7 u! m. r" a3 Q/ s MEI_AddCom::MEI_COMPtr ptr; //类似明志一个指向接口的指针
# G8 u4 c4 o O8 s% {' {
3 e5 M3 W7 J& @1 d ptr.CreateInstance(MEI_AddCom::CLSID_MEI_COM_T); //实例化一个类 CLSID_ 类名# h1 \! D5 E' e
% \% @* \) ]2 _) K! L
//这个地方有一点点奇怪我也还没弄懂.在C#中的函数是int Plus(int,int).但类型在这里都转成long了.另外就是我们不能直接
- l8 r* S* H0 w8 c6 u a! a1 W5 r8 N8 ?/ e1 H# N8 ^
//来个long a = ptr->Plus(1,2);这样得不到a = 3,反正会出错.) a% c( ^- {& U
//这里函数Plus的参数变成三个了long Plus(long,long,long *).其中最后一个指针得两数相加的结果0 e1 J3 l$ e+ t4 ^
2 k) \* |6 L6 e. {7 J3 t! ` long a = 1;
3 V5 y1 f5 ^1 F! F& r5 C
0 |. C& H3 D: r1 o5 \$ k" e long * lPtr = &a;
$ Q' L9 ~$ y0 }8 O
3 a: m/ a+ F+ O1 [ ptr->Plus(1,2,lPtr);
( M; E+ K$ e3 ~$ |3 M4 w8 @+ d& N2 r# _8 ]+ p) h
char msg[132]="";
- [. |3 _7 w# L8 G* `/ q sprintf(msg, "%d",lPtr[0]);
" ?# y% _; K# n8 Z0 ~. l, P. v5 D5 H& I0 z
LPCWSTR str=CharToWchar(msg);7 v* J- h, S9 g/ W/ v
. n! |- M0 R8 c+ @ g MessageBox(NULL,str,_T("123"),MB_ICONWARNING);% r1 S9 q, h6 q" b( C4 E w( P
6 _6 a, p/ m; c& x6 O* A
$ t, e) n: _1 U/ c
}' S) y' X( ~- s" h W
% \( T8 Q# \& B2 L O此时就可以正确运行了.得到结果3
' V" V/ T5 p |( o% {/ z5 ~8 {+ `8 N' l' S/ B/ q! d% {
如果没有正常运行,则必须把dll文件拷贝到有MEI_UseCsharpCom.exe这个文件的目录下.
0 C+ O4 j% |2 t7 B7 s' A8 b* C4 M' z: s) I; C3 w) r' T2 Y
& r* i% p5 S* p+ z8 K; k) M2 m* z( l
--------------------------------------------------------------
/ h: S/ j7 @0 NC# Npoi库 操作excel 的代码网上很多
! b1 d/ _* ^' k' _; W3 K1 U
$ p" } y7 w' f; e+ v' K8 {// ----------------------------------------------------------------------
; z" H8 S& |$ N3 B. Y) o5 T// 使用Npoi创建一个简单的xls文件,写内容
2 p+ @, e# G3 ^. Q: l. b; L. m9 b" n+ H/ ]. ~! M. P% X
using System;
+ o D0 [2 V7 M0 b; J* Dusing System.Collections.Generic;1 g3 V, `( ^, Y9 h* \' _$ y
using System.Linq;
6 J0 Q" }7 R1 X9 ?- S, Jusing System.Text;" [9 _' A2 R" u: q$ ~% x4 N: s
using NPOI.SS.UserModel;7 X2 I( l6 a: V
using NPOI.XSSF.UserModel;
0 a. ^& Y1 ?3 A& f0 G. |using NPOI.HSSF.UserModel;
- m& K' b) r6 P, ]2 Yusing System.IO;* O* k; K. F2 f! S
using System.Data;- u! D1 r& V; N2 \3 n `# `# i! j
: n6 K7 Z& A/ x+ f: p2 N8 N& V
//using System.Windows.Forms; 4 w* b. Q) p D. D& M3 V, x$ _
. u- X/ f' Z" C3 p; O3 ~- y; Vnamespace CC3 ?) N5 O6 M9 u! r% q- E }
{
5 _2 {4 a& W& a/ P* n8 Q- I2 V; D1 X3 n
class Program
3 e% w- ]- ?5 k% a' A; W# z. e" p {0 s$ t* o5 f6 D0 z- b- x
: D& A- j9 |. J5 B" O9 H8 w O
0 D. B9 e/ D7 T
static void Main(string[] args)& [$ ?9 H7 z( Y" Q8 l
{
0 Q, }) C6 S5 h1 h6 e //创建工作薄
9 I% B7 X& U5 K! } r HSSFWorkbook wk = new HSSFWorkbook();! ^" `; r9 O' T1 U( f
//创建一个名称为mySheet的表3 a5 R; O% W0 U# H4 s' m# d
ISheet tb = wk.CreateSheet("mySheet");. b4 X! E+ _9 [6 X) ?+ ~# D F" V1 q
//创建一行,此行为第二行( O% m4 `) W: q3 E
IRow row = tb.CreateRow(1);; U. l9 V% ^+ K5 B, T8 e( [0 `4 \3 }
for (int i = 0; i < 20; i++)
/ Y% o0 B* [6 q# C {
" s1 ~; S$ _5 ~- T A ICell cell = row.CreateCell(i); //在第二行中创建单元格
8 f5 T9 m$ O; b$ z) ?! L cell.SetCellValue(i);//循环往第二行的单元格中添加数据
, ?1 L: _7 k m- v# m }5 Y! W6 `% F6 e0 c. G+ Q
using (FileStream fs = File.OpenWrite(@"c:/myxls.xls")) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!
# j' Y" @# E2 C& J7 @; X$ h0 K {
0 J; S. D" J- R- n* E# Q wk.Write(fs); //向打开的这个xls文件中写入mySheet表并保存。
/ s* s! |' p: _! p! u$ k // MessageBox.Show("提示:创建成功!");
% s. W$ l% `9 q! R }- L( d* v, ~" a3 i2 A
0 o; J W' l" n: u% Q }
3 z- q+ N; A: x$ G7 V- [2 ]2 E& J0 ~# {4 H- a7 O3 z
: E8 w% U2 N$ T
}
- O! m# \* P+ C5 g6 l4 d( J6 Z0 _5 C: x6 H) F! c8 ~! v, G
9 f) u+ e. V8 a/ z" e! q
2 C/ q0 g3 {) e2 J4 y# L- {
}
5 J# d* K3 ?% T
, m; H6 |3 q% i4 L( p/ Y// ----------------------------------------------------------------------! S! [3 N) Z$ c6 B6 S @7 P+ ^
// 使用Npoi读一个简单的xls文件
" A" y4 ?- q L# }
3 h5 V& R! F* W9 o' @* ~$ l3 Z/ susing System;
* F: S7 X) G9 h- J& s& Dusing System.Collections.Generic;
! j; ]4 E# H; F" r- i! ~, pusing System.Linq;
2 J+ V$ @; T; `% n5 Tusing System.Text;3 p+ l: v) p& \+ A; Z) A
using NPOI.SS.UserModel;9 q5 }& J# u/ k+ W1 P
using NPOI.XSSF.UserModel;% X" Y7 X% x8 V Z. w8 ^
using NPOI.HSSF.UserModel; |: }+ t3 q' I0 Q$ V1 L
using System.IO;
, f4 x% p# x) s+ h) ausing System.Data;
2 W# x1 a. c7 T5 w, U/ i! ^2 {- W- n: e
namespace CC) s7 @" ^- t) e+ M. V4 I, Q4 i
{
9 c/ `! I) A9 p6 m8 |
. p8 b S3 e H& J/ a class Program" u0 ^- m' ]5 M1 ]' H' x
{
, q$ s5 |3 \; A/ B6 y S
7 B" I. ], E4 O
]$ Y$ _& j& S6 Z9 |3 f' j6 i static void Main(string[] args) W! V' n1 J* X/ |6 q) |) D {8 I
{
2 D* B5 u8 l7 x+ _! s$ } StringBuilder sbr = new StringBuilder();) I8 N, G% c# j. U1 W
using (FileStream fs = File.OpenRead(@"c:/myxls.xls")) //打开myxls.xls文件
4 z6 N/ v1 ^) R8 w$ ?) Q9 x {
6 _% \0 O5 v/ B' J' i D& i HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的数据写入wk中/ J; F t0 r0 @3 r+ d6 q2 S
for (int i = 0; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数0 w" ?; V& r) m4 T. z
{1 \$ L4 `2 I @
ISheet sheet = wk.GetSheetAt(i); //读取当前表数据5 O7 ]' Y; x( H$ C: N9 X
for (int j = 0; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数
8 S6 r/ F1 `+ m5 Z {% S3 P% H/ T$ q$ _* g
IRow row = sheet.GetRow(j); //读取当前行数据4 f' D2 s9 T8 F
if (row != null)
4 w8 w" ?$ E6 \* L- P8 E {
' W G. F, B* ?+ b5 ` sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限
1 ?. l' P3 k# g# Y5 e7 h& ~" E for (int k = 0; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数' d. k5 k9 n1 w$ [! P" u- p
{( h( R: {% Z4 k& p( h* d
ICell cell = row.GetCell(k); //当前表格
. O% O, C' g* \1 ]. ~2 Y if (cell != null)
7 C- W" J# d" F8 z7 q {2 _" e; H( k) a% a: l0 o) }
sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型5 w: j7 h: |. Q* `4 O* a& V5 t
}$ A6 d* O+ M) Y* o9 |: o
}
) L9 L- ~! w5 i, s }5 y! L" F% z# S& r+ g' {
} d- j# Q4 C; Q% Z, I
}) E/ \! a/ o: b8 G% U* u
}. `6 ]3 O2 ~/ _) H
sbr.ToString();
- G4 k6 ^# R$ R$ }% }4 b3 \ using (StreamWriter wr = new StreamWriter(new FileStream(@"c:/myText.txt", FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中
4 D/ Y4 j0 O( u! |& L2 K {% Z7 T6 b* W7 @2 V
wr.Write(sbr.ToString());& k* K$ N( i7 b$ `) P! @; f
wr.Flush();
; Q+ B4 ] A5 C- C/ x9 E }
6 [4 L j1 \, S. N$ F
, B" b% w. y1 ^# ~8 s9 [$ T( i2 O& @+ _
}6 R, V6 b4 C( T% G5 H
/ B% X- p' ?& l5 ^3 ]* c, f2 z
7 } I9 V: J. }* i0 u
}
- p+ D, h( B$ f6 W
- P& C2 r! ?8 ^( f; f" B+ {4 r% ^2 \8 X! a& a5 t7 a$ W
. }5 q8 S7 w. i
}5 ?; w& E' C3 g; P; @$ {# d1 X
( Z6 b* f0 e9 D' x: _) v& w+ S" X# u# O: \
然后 自己封装 给 c++用7 H; [1 p8 T$ E! L# W/ s, l6 z
; A& K: y8 s4 w# x! u
, f$ @) r5 [9 a, U
3 H& ~4 r, a$ K- j# L' R t8 n
7 z1 O: G E g; B4 Q) g2 O8 n
2 i% F; F/ V! F8 E t! U
* L+ w$ w' ~$ ?2 a' {$ _" v3 f7 }& ?3 ]
9 W# @! i9 y, `' d7 Q2 s/ G- P" J) S/ r8 `8 F8 M# p1 C
$ v' `+ N$ M" t1 j" j1 y* t v
4 l1 y0 n0 e2 y. r1 y, g7 q! F! w
" K- G4 j# |6 a; F& ]; g. ?1 S4 L5 i: X' ~; g1 E% G: y
! f) X2 ?. V$ {+ }5 u0 U
, j$ Q+ @! z+ C" |0 R+ U2 {9 P% m! }* Y& \1 q
% a! F4 ]0 j# m/ A% B: l1 e5 \, U. D' }8 E5 [3 f( A! x
- D T: w5 t' q2 B
$ Z/ N' a+ X0 S8 A; v ], v& b2 B
% `2 A5 ~" c y; R) U% E5 E+ D* R% N! g
" M/ i0 _4 H, I ~; B7 _ |
|