|
|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
C# 或 c++ 不用安装操作 EXCEL的方法:c++ 对excel 的操作 非常不理想 要安装excel 而且读写速度也慢4 A1 N' \0 s, @5 u
net 有很多 免费的开源库 比如 Npoi库 (Npoi库 支持c#、vb.net 等语言)4 |8 z1 A4 G- Q+ Q: r
这里我用c# 生成 com 组件 让 c++ 调
& ]& e1 a% H2 f4 c5 H6 I! I- {4 y- M
, g5 Z! m5 _3 K首先要学会 c++ 调 c# com组件的方法 (和com注册的方法) g5 T+ g5 V3 x# u
C++调用C#的COM组件(DLL)/ p% L- I. W) r# w9 @# E/ f# m% Z
: a& g& R6 s5 x/ m [7 T下面我举个简单的小例子.我用的是Microsoft Visual Studio 2012,操作系统是Win 7.
* y6 {5 G: |4 n7 Q% M首先创建一个C# com组件.实现的功能很简单,就是返回两数相加的和.
. k* `1 `3 i1 F2 }1 y: Q( S! y5 y' l$ a& }4 [* l3 q
2 m! R, B M! l# F$ d9 Q! U6 m
1.新建一个C#项目 ,类型就选 类库 .取名 MEI_AddCom
" B2 ?% O: A' E9 W; u: _- \
8 a- l" g) _: x. M! l% R! X, I' @* N2.在项目中添加一个接口,取名MEI_COM.C++调用com组件中所有的功能只能通过接口来调用,不能直接调用类或函数
* h# c0 x: X- K! W0 L
5 ?) [1 Z! A6 R m" G% h" K具体代码:
0 F4 E8 H! Z& K6 ?6 M% K% \$ Q5 H8 a& U/ o9 U) c8 R
using System.Runtime.InteropServices; //记得加这个命名空间
' h2 O% f( W8 X- Z. E
& z1 h7 A7 _! J- i4 {namespace MEI_AddCom
+ R7 i; [$ Q6 q. c$ {/ p3 k' p$ X' a; k7 x/ h$ W# l
{- [# p' o& S7 a
" Q0 `- z. c0 t6 r7 e/ V [Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的产生可以通过vs自带的工具.点菜单栏上的Tools ->Create GUID,然后选第4个选项.Registry Format.! M3 P- ^+ x* T# K/ U- u: r
( Q( N+ k% W/ h& m! ^ //点按钮New GUID,再点Copy.这样你就可以把产生的guid复制下来,然后粘贴到这个地方来.当然那个大括号得去掉.后面需要用到guid的地方也用这方式产生
& U3 r% e( E% E& D. b- K& @7 P- _ ~3 [$ R D
[ComVisible(true)]
# Q+ ~7 E7 S! L+ ]6 S' C- m8 F# _2 R4 S' A/ F
public interface MEI_COM //记得用修饰符public
. @% z: K5 h) w& S* d) X" b) s
6 c/ F2 @) o& _ k {5 u1 x8 Q% D1 r5 {0 w* n% r
8 Y3 H0 a6 B! o/ s* u
[DispId(1)] //如果还要添加其他函数就继续来个[DispId(2)],[DispId(3)]加在函数前面8 V2 G3 t5 S# b o, F
# c" b1 s5 `2 e$ s9 p4 l int Plus(int one, int two);
2 ?4 \# f p" r q( j1 I! B& K
2 {+ S4 H2 _) b- R, U. j }
) x; ]3 I. s9 S8 j8 Z! x* F5 I" G# B( z$ j! o9 Z
}
' c3 S6 r1 z5 ], ]) d. O
# J Y3 N& g" H4 r; j+ l) J, g
5 O) o: W4 u6 B9 _+ @
3.添加一个类MEI_COM_T,继承接口MEI_COM,具体代码! e, w. A- {& X
6 P$ @$ G: m; b- Z6 \7 Xusing System.Runtime.InteropServices;+ R$ y6 |5 k% p
% V6 V: @0 M. g2 A, I, }
namespace MEI_AddCom
) i9 o( ~+ p% j" L: r* ?2 I4 c z2 ]' c
{
2 C) W7 w" \. F: K' g' a9 u
; g, \: W) c5 k [Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]% b. c2 G/ ~' P0 @
/ C# f- h, G0 f; ] w# Z
[ClassInterface(ClassInterfaceType.None)]& n' {. ?. o* L4 c0 o, ~
/ w- I" \9 C! C- p8 s# W4 u0 s$ F' w% \( b
public class MEI_COM_T : MEI_COM) u) a* \: Q+ \5 o
% }) T$ V1 ~. o- f6 k* T {
0 w5 n% ~3 P( q; G+ x* V6 @! M# N8 ~5 _1 q+ j
public int Plus(int a, int b)2 S0 u/ I- T3 _3 d3 r
% K x7 n1 Z: o {0 E* F7 a& N) K
' p6 @8 S" s# g* Z return a + b ;9 o7 T: O4 c5 ?& Z
; I% Z9 \2 d# x* Q3 ^' k }. n4 i% n) f. Q6 w$ J
- m, I: W* o: X3 d
}3 P% M" ]- G: A4 u* g
9 f. N$ L; X1 j) h w8 y% y0 W}$ i+ N) n, J7 \5 p" P
; j4 p X) ^. x# S' T% w+ n, D' ^
, c2 Z6 k" p2 O' P
; g4 i2 B* u% e: P2 k$ d4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)].8 ]& q& u5 [0 x2 a a
9 B% j# O6 s8 C$ p+ { m右击项目名打开属性窗口,在生成里,选中 为COM 互操作注册
) s9 ~( X. U1 B. k5 k
! f2 a$ B' V4 J3 T% C9 Q* O! I- k" V9 `% W1 M# A, e: h
5. 生成->生成解决方案1 A4 i+ U5 F6 c' y
注意 这个时候 生成 非常缓慢 + l4 x# b9 ?* {- w8 d
直到 出现 成功 1 个,失败 0 个,为止才 操作一下面内容+ l2 }) b' ]! w& c! H% E6 M
3 g% l$ c2 y( c6 b
8 i8 f4 o( r m7 C A, q---------------------------7 G+ a5 K- K1 i2 Z* K! T5 R# z6 `
: [; L+ Q- r: F5 S2 m+ V" z
1.调用前要先把com组件注册才行.: `- I, K) `9 `6 _
2 A& d6 {' G: E, {
使用C#创建并注册COM组件 C#不能直接创建COM组件,因为其生成的DLL属于程序集,但可通过“使程序集COM可见”选项来支持COM。" @' |' X _$ a! \* K! j
以下说明如何通过C# 注册、注销COM组件。 8 Y. R3 w& v) X* a" W+ X
; b6 l7 N4 M5 L) p6 C
为了能让生成的DLL能够进行COM注册,需要进行强名称签名
3 s6 z' _. K9 i) _; ?" }, d2 D! B8 \打开COMLib项目属性,选择签名,勾选为程序集签名,通过下拉列表选择新建,弹出创建强名称密钥窗口,输入名称,不勾选使用密码保护密钥文件。" T% W6 B; d) z0 ]( o% W
创建完成后COMLib项目中将出现后缀为.snk的签名文件。, L8 x) R* Z! h# k7 I, O
最后,编译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文件。
7 l3 ]* e/ s4 f7 S" f6 W卸载COM组件:
$ |; T1 T+ t4 ?$ |- j& I8 T0 {$ |- ~与注册过程基本相同,只需将命令改为“RegAsm /u D:\ COMLib.dll /tlb: COMLib.tlb /codebase”。+ {( Y+ ]' O) ^8 ` \" j/ Q7 U
) M/ z/ M! y1 U6 G0 I- V& l+ k
1 o. {- a" a/ |# C9 m( p) c2.注册完了就可以在代码中用了,先新建一个C++程序, 类型选 Win32 Console控制台应用程序
, ?- G' j; ^$ x. p' d1 n7 @6 R
6 I: h! ^0 T% i6 |名字取MEI_UseCsharpCom,点完成
! T6 v1 \; E. m U. O$ }" I- M7 ]$ `4 P& P! Z. `
把MEI_AddCom.tlb文件拷贝到项目的任何目录下.我就放在D:\MEI_UseCsharpCom\MEI_UseCsharpCom.
, b: ]5 ]8 p+ K9 Q( d% L! j' H& h6 \6 d& Z2 i. D5 e
我们会看到一个MEI_UseCsharpCom.cpp文件,双击打开把默认生成的代码全部删掉.敲入下面代码:
# r- S* X; Z- X2 z0 R! B: A, J) P+ ?* o( [. D5 Z5 Q2 ^
1 ?! i: a9 D6 R# T#include "stdafx.h"
* n: X- ~ z+ \. G9 I#include <windows.h>
' b: a9 |$ W! H#include <string.h>
% F: d& F* L( I' n% C7 ^4 _. n% y1 c
#import "MEI_AddCom.tlb" named_guids raw_interfaces_only
. ]" g4 N1 \3 }( ~* K, _
# x/ S% V1 M x( h! H! nchar* WcharToChar(const wchar_t* wp) //wchar_t转char*1 q0 q: I4 c/ s& y5 |% ^
{
! ^( ~& ^( P% x$ c3 q! V" Y$ F' `& \ char *m_char;
. C: w& g) x6 e int len= WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),NULL,0,NULL,NULL);
3 Q+ G: g; N( @; g$ k7 ~# _& P8 Z m_char=new char[len+1]; 9 K0 p* O5 ]- o
WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),m_char,len,NULL,NULL);
5 B/ Q% O! d9 R: Y) ^ m_char[len]='\0';
$ v0 o r+ h5 `1 ?) F return m_char; 4 B6 m. s: P$ g8 M
} 1 P, g& r( K( N% \ q& L0 T% q
wchar_t* CharToWchar(const char* c) //char*转wchar_t i9 `: m% S; `5 F, y
{
( x1 f7 T U6 ^ | wchar_t *m_wchar;
/ h# Z7 Z0 Y1 c5 _, }: ~9 N! P5 k int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0);
! c; K& F _+ C/ E+ U m_wchar=new wchar_t[len+1];
5 V9 z$ @5 J! M5 J* P) | MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len);
0 p$ {, Y J! v% L4 P m_wchar[len]='\0'; 6 W$ x; ~1 I2 @! t7 b% e% U$ Z
return m_wchar; 6 P6 y3 n; R4 K Q
} ; r8 a1 ^& h$ ?0 ?: L5 j
2 ?4 e1 [- D: |% r. E; h/ D% avoid _tmain(int argc, _TCHAR* argv[])
3 k, _) W9 a$ E/ h) W6 x* }7 ~6 v* Q3 _9 t2 F
{
' f1 P4 V5 d3 A0 q% D( ^ e* i
/ j; [% P1 Y; J0 q5 x R3 S CoInitialize(NULL);
: a$ I7 i5 ]: H6 {4 _" M$ }, R0 R4 j- Z* _& C) R9 ?( n
MEI_AddCom::MEI_COMPtr ptr; //类似明志一个指向接口的指针3 d/ X |; D" V$ g {
) `. q6 v+ r( Q
ptr.CreateInstance(MEI_AddCom::CLSID_MEI_COM_T); //实例化一个类 CLSID_ 类名! i; d) r+ p9 H4 E f- l$ z
5 j7 p- X! i5 g& L, A) S //这个地方有一点点奇怪我也还没弄懂.在C#中的函数是int Plus(int,int).但类型在这里都转成long了.另外就是我们不能直接5 X" P3 I7 O7 r6 E2 Z
. |- }2 z# g/ i: g. g: S5 K //来个long a = ptr->Plus(1,2);这样得不到a = 3,反正会出错. x! `0 A( G' s- w1 m/ D. r8 s z
//这里函数Plus的参数变成三个了long Plus(long,long,long *).其中最后一个指针得两数相加的结果( ?5 Q& {) ?- G7 n. I, p
- W8 M9 W2 H$ ]6 n$ g: k5 t
long a = 1;9 X5 W2 e. I7 e8 a6 L0 D3 Y
( l! [' L/ D7 h3 B [ d
long * lPtr = &a;9 d( U) Q5 C& |2 s) x$ R
v" ?- q8 a: H' _/ w0 e
ptr->Plus(1,2,lPtr);
/ W7 |, \4 ?! Z4 h0 \4 i9 {+ D9 O5 j8 w+ @
char msg[132]="";
/ N; \+ D* V9 W: e# I* a& m sprintf(msg, "%d",lPtr[0]);
: _4 r! D9 `9 C, e1 b' z( G% Y. K0 V% e# V* u4 ~, {& B
LPCWSTR str=CharToWchar(msg);0 l {' C( j* G/ u5 p7 v
9 o0 W' `* m/ ^0 E5 g4 Z7 E MessageBox(NULL,str,_T("123"),MB_ICONWARNING);
8 `3 ~- {; M4 G: b3 t( P( P3 n" |" \. [# {
# |: u* u* D" F3 r6 x/ W# d+ S
}# ?3 x0 v, O. T# v( d( b& z7 P
- p% E1 L( U; c此时就可以正确运行了.得到结果3
; ], y7 C5 S% M# A( P7 N7 Y4 l" j0 h' z- |+ }" H9 @% ]/ H
如果没有正常运行,则必须把dll文件拷贝到有MEI_UseCsharpCom.exe这个文件的目录下.0 } t. z% ^$ l" G: }8 N+ E" ~# i
* p% c4 t( n0 C2 P7 @/ M# k- d" k3 A+ i' i6 T
--------------------------------------------------------------
4 x/ }2 z( c% J; `8 B( NC# Npoi库 操作excel 的代码网上很多
0 h! Z' O; i# S( h. K( E
% O, s6 X) O& w* G% a! u// ----------------------------------------------------------------------
5 G% L! w* k5 s+ Z* p# R& `% x& }1 j// 使用Npoi创建一个简单的xls文件,写内容& y; J' q. [9 h" k- G7 ^3 ]
+ P4 R2 P4 O+ ^
using System;
4 V8 s9 U# o' J! q% t' Ausing System.Collections.Generic;+ c$ Y- `( P% g8 H5 k7 d
using System.Linq;
9 ?, X3 [4 m" M* j7 R0 [8 R$ Uusing System.Text;% y/ q' y/ G4 O( L$ J
using NPOI.SS.UserModel;
6 t4 V. q1 d8 D# Q& C* Yusing NPOI.XSSF.UserModel;
2 v: R& a$ w4 x/ P( ausing NPOI.HSSF.UserModel;+ K% t2 d' v* j
using System.IO;
3 T. E1 M+ E; W1 z0 D# Y. L$ @% }% Pusing System.Data;
" N1 {0 x% D/ X( u% U% H4 S% x* [& ?1 R
//using System.Windows.Forms; ' m: N% [: p/ }7 V6 K
# q* T2 v z; [/ k% y `# o4 ]namespace CC
' j& s4 T0 @7 x; H8 L{
' A) j; t9 `5 J$ f6 ~9 q5 m0 @. S3 q5 S
class Program3 O* G: n3 Q7 _9 _' s% ~3 K
{
, s+ l- c& h6 V# H! m
/ T h8 D3 e, N0 l/ k7 S0 e, o7 X' G3 p. r* N
static void Main(string[] args)9 i* s. X8 @' @+ l8 z% r, q% C
{
4 V1 Y: C6 Y6 B3 a. p" I //创建工作薄
+ j" }3 o* l# t; g5 w/ D& d$ J HSSFWorkbook wk = new HSSFWorkbook();
1 K/ p$ ~! o; }' @ //创建一个名称为mySheet的表' o1 E- A5 n9 u- `' E3 W2 H
ISheet tb = wk.CreateSheet("mySheet");/ s9 j" c; b% S
//创建一行,此行为第二行
$ r; o+ S O# g$ c7 W IRow row = tb.CreateRow(1);! j) ]! y0 O" l6 ~5 ]7 |
for (int i = 0; i < 20; i++)& l& A% m& ]$ B3 w5 e! b& ]
{5 m3 w8 H- ~* J* E/ B) W
ICell cell = row.CreateCell(i); //在第二行中创建单元格
: c, r1 y4 V3 z4 c: S" v6 f cell.SetCellValue(i);//循环往第二行的单元格中添加数据
, c. h* [8 L! i6 G+ _) } }
9 w$ n' W7 S+ I8 D5 X) u. Q using (FileStream fs = File.OpenWrite(@"c:/myxls.xls")) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!/ k9 ^* z' |0 e. F# y' e
{# j% p# k) L. G) k/ K: a c6 C
wk.Write(fs); //向打开的这个xls文件中写入mySheet表并保存。
; J7 U5 e# r3 i- s& o // MessageBox.Show("提示:创建成功!");
0 h# G# k$ F H+ a$ i }
: F; D4 u# U! g. n) ^: e
0 `# c% C3 o3 I }
' H; B+ d* U3 r+ i# |5 M H# l( D, g1 B4 w7 Z
; V9 M% k9 y- V6 h" J( x2 C/ R }
0 q% T3 r5 X' Q0 z4 P, G/ t* q4 U! P* N- G N1 C# m$ p
! o/ f* e( ]8 I+ e3 n! `
# E4 a j( L& m0 G$ g5 h% w$ K, j}1 b0 w5 z G% | z0 N+ F4 @
" J, _% C5 j6 G$ k' }
// ----------------------------------------------------------------------. Y0 M4 }. Q2 G% {8 B! }
// 使用Npoi读一个简单的xls文件- P+ @1 E- D; ^7 d, c, I1 F
0 p2 O8 j7 [" u
using System;
+ z* C) r! K" u/ Q. M Eusing System.Collections.Generic;
/ k$ ?: A2 w8 O; V# Zusing System.Linq;( F. N8 [, o: a
using System.Text;0 p# \: B; H" l
using NPOI.SS.UserModel;
. D' T3 X" C5 E% I1 r- \using NPOI.XSSF.UserModel;
* g# C) d- _2 z! @* }7 ~1 eusing NPOI.HSSF.UserModel;
@5 a4 \3 W; {' j- G* r" J/ j$ Iusing System.IO;
! }4 W k, b% `using System.Data;) F# U5 s+ W+ r3 O
/ B( v K- r8 v3 j3 h5 e( J- m' gnamespace CC
/ B$ `, \$ V: \3 k' t3 X, B{
0 l6 y' q Y( S q# b& a; _6 H% W% [1 |4 ]/ ?% n% A
class Program/ o, P- X4 J; `- A. o3 U; @6 A
{ {6 k% X5 R3 `. c. {# z) k/ T
( p7 A, b8 s9 s+ u( |$ i) r/ q
, S, k* \8 p' o9 L B static void Main(string[] args)& e2 l9 `1 n1 H+ D
{
0 K, r2 t+ S- T StringBuilder sbr = new StringBuilder();
( i) ~6 v [* Y' _' s# x# K8 I, q& X" N, b using (FileStream fs = File.OpenRead(@"c:/myxls.xls")) //打开myxls.xls文件/ I, Z& L+ |( p% o
{- }7 E0 X+ f3 e- F
HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的数据写入wk中! J" k9 T/ ?% a
for (int i = 0; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数: F4 y3 r- f# f! {. A' S, U4 A
{ U1 R0 s! q+ O/ o& j" k& `5 k- a, S1 u7 [
ISheet sheet = wk.GetSheetAt(i); //读取当前表数据
0 c7 C" s8 [5 _1 S$ p- i; q, P for (int j = 0; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数9 L& l/ W5 h6 ?
{
7 T7 X1 F Q( O* v6 H8 q9 J IRow row = sheet.GetRow(j); //读取当前行数据) B0 M; j" X) g( f
if (row != null)# Y' N' R6 g& ?, k4 c _
{
; T' U7 R+ L2 ] sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限
# G' M- ?8 P7 J. e for (int k = 0; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数
9 O& \* P4 ]' a/ R, W) a {
. s4 \( @9 X( I$ i4 _. l4 t ICell cell = row.GetCell(k); //当前表格# Y1 T% y Y6 r C) u$ V9 T
if (cell != null)
( b: R2 l6 t6 E: [ {; C; a6 s& q9 W Z" k6 f9 Y
sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型
0 K& |- g. V, S8 x! D- g d }
& X5 ^; ]7 Z7 Y4 {5 [/ N }7 ^$ r. l0 j% Q; I
}
. j1 G1 }2 s# }: R2 _1 H }& B" Z* I" G7 V( e( D/ L* B& v
}
& ^2 X' J+ l- D8 v }
4 |0 m- r4 o: F$ x sbr.ToString();
( J$ o5 ]5 l1 b; a- C using (StreamWriter wr = new StreamWriter(new FileStream(@"c:/myText.txt", FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中
# ^8 V7 T/ T" t' t! y5 s {* x5 p k+ i( Z, |. r( p5 {% M
wr.Write(sbr.ToString());, B# m7 I3 f2 s7 K
wr.Flush();8 l) o% g1 C- O; d7 y1 b
}
' J% z, G6 z) k# H
' d! C+ Z' o% g3 @2 `8 ~
$ v* e# d( g& E2 Q }
- f Y7 H) Z# Z% l! z+ A* ^" L: x" _0 e( j% p
) d3 ?6 t8 i, \ }
) _7 `6 {& I; x$ }8 v
M* C) S& u |$ v3 `- X( S- h, E* J x. W# ^' ?
7 u1 ?3 G r/ _: \' `
}8 ^2 k$ \% E2 K# N2 y5 x
3 g: \! F0 U5 n0 n" {/ y" Y/ @9 l# N! r) q0 l {
然后 自己封装 给 c++用
6 m& v" y6 }+ ]. K! o6 a! G
& j9 B" O$ q4 m3 H7 @3 ^ W, Q
# ~8 x, I7 h; x6 E: M( b `% {; r; V1 Y: h! S0 p9 [ `7 }( {
6 r( G1 G/ {+ }9 f" D3 G& L5 S3 P5 O9 ]1 S5 T' U* y9 } b
! X7 X& `' N" x" o( [
2 b' w$ a: r/ g9 t+ z9 E
" Z ^6 I: e" z2 H6 f' V5 T
5 V, K! x% E. Z
& ?& a5 p5 E9 C: M3 M# X7 o( ~& ~/ C( @) U- M% M
! ~# L$ e* v9 ~' b5 K# Y+ m4 B$ Q! N' U
( @# e9 w5 g- Q0 C/ K; c5 {
% G0 s+ M' |5 U8 x) y- Y6 a0 c- d- L) O8 q- [9 v6 `, C5 G [* B, ]
( p( q7 Q9 a5 ~ t9 A. W
' _# A; M* u7 S* F' i2 h$ b* p/ M# Q3 W3 E
6 z! e r! _: L" {8 \
$ ~) T# r, ]" `: B9 c7 _
" [- F! p% L1 p* J1 n2 }9 b; @# @ |
|