|
请使用QQ关联注册PLM之家,学习更多关于内容,更多精彩原创视频供你学习!
您需要 登录 才可以下载或查看,没有账号?注册
x
C# 或 c++ 不用安装操作 EXCEL的方法:c++ 对excel 的操作 非常不理想 要安装excel 而且读写速度也慢
, E# T- k7 e4 {6 d( x/ J A5 Qnet 有很多 免费的开源库 比如 Npoi库 (Npoi库 支持c#、vb.net 等语言)
, Z; I$ _. J) u这里我用c# 生成 com 组件 让 c++ 调 $ B, {7 _4 `: a
9 B& Z' w# Y* p- @5 e9 G
首先要学会 c++ 调 c# com组件的方法 (和com注册的方法)
7 Z! p- M2 H3 cC++调用C#的COM组件(DLL)
- C$ P. ]# Y9 ^& N! W( g, c, h7 n5 A6 x9 y6 g% v4 w
下面我举个简单的小例子.我用的是Microsoft Visual Studio 2012,操作系统是Win 7.0 }8 a3 p" C O# v* Y* m: a+ y
首先创建一个C# com组件.实现的功能很简单,就是返回两数相加的和.- {" z/ \ Z7 M5 n, F
1 d9 {. j; V. W# o, a! k$ c7 ~1 g& {5 ^5 b
1.新建一个C#项目 ,类型就选 类库 .取名 MEI_AddCom+ i9 w4 X2 ]( x$ I
( {" Z0 C9 e9 I1 R- f2.在项目中添加一个接口,取名MEI_COM.C++调用com组件中所有的功能只能通过接口来调用,不能直接调用类或函数5 O: _* p$ d* R1 e$ y
3 g' G. ]6 F8 T6 X) J8 b( s2 [$ H2 _具体代码:4 O0 V7 W+ p+ W9 Q4 W8 B7 p7 e
- ^# J6 J) a6 I& G4 I5 u" G7 ^7 c
using System.Runtime.InteropServices; //记得加这个命名空间
" Y. @/ [" w7 D2 v9 x7 \7 V* k3 @- M( X/ \9 t) [- X0 \
namespace MEI_AddCom! j# ^6 n! v9 g. @3 V, d+ Q8 s" j
1 C" M3 N$ l' f{
. ~- Q' ^9 n [" O5 F6 e$ c/ |$ m: ~2 @( `
[Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的产生可以通过vs自带的工具.点菜单栏上的Tools ->Create GUID,然后选第4个选项.Registry Format.
/ ~1 w2 k! M2 l$ k; J; f6 s! d4 m
//点按钮New GUID,再点Copy.这样你就可以把产生的guid复制下来,然后粘贴到这个地方来.当然那个大括号得去掉.后面需要用到guid的地方也用这方式产生0 `8 i V' B4 Z: L$ h1 v
5 s8 i+ Q" {' W3 H3 A+ ~
[ComVisible(true)]) `5 u. }* A! E* f
# f7 a9 L; ?3 H) \* B8 l public interface MEI_COM //记得用修饰符public
: ~' g7 m0 H. ~$ u
' g& `* q4 E6 e% e% v2 Q- \ {
: l) }2 Z0 G2 }: ^0 L3 S( L' d* t7 ~
; F: I* v2 ?( z( ` [DispId(1)] //如果还要添加其他函数就继续来个[DispId(2)],[DispId(3)]加在函数前面
" f N4 O! o) g: @8 j2 e4 K/ G
$ C. B7 i X | int Plus(int one, int two);, f* ~0 e$ N. J( {% w
1 o( C$ q) ?7 Z; M( N }$ b- u! a1 @# r/ E
7 n% o- G5 a0 l
}
: E/ Z5 S4 ]9 {1 s1 M# w' F, |, U) W# O% z9 J7 ?/ ?. J! G
) }+ ^% ~( e) Q& U7 {# x0 u
7 I+ |' I' r4 i( c8 `1 E7 |
3.添加一个类MEI_COM_T,继承接口MEI_COM,具体代码1 [+ b( Q! y1 |4 K& W. b8 @' d
& Z% n5 S& o6 C+ W y
using System.Runtime.InteropServices;( I% T$ h- I4 c1 ?# S3 y
. S# u0 u4 y/ Z N9 M8 c+ j3 pnamespace MEI_AddCom
9 e9 S9 w$ m3 K2 |* {/ _$ E4 w+ J0 R5 O- u x
{* j2 D, i8 V. y! R6 i+ q9 R
+ F8 C/ S: l* F! V- A7 B5 N2 W
[Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]
% T/ [8 r6 W' u, w' s, n0 F/ O, }$ B
[ClassInterface(ClassInterfaceType.None)]
2 D: ^ c J1 Z) ?, X5 C4 Q7 H) {( g9 _6 V( {* A
public class MEI_COM_T : MEI_COM
# \4 K+ m; o' {% e$ q9 K' T0 h3 x8 j4 D8 }0 v/ v
{
( W2 _7 _0 ~4 A% Y0 i+ x) B+ g; w( v t
public int Plus(int a, int b)- T3 ]" z/ b9 ~/ }
2 ^' N a) c! m o( i. e$ [ {
# q8 M9 S7 ?3 N% O( s7 _6 d- a8 I% `( |
return a + b ;1 r5 o0 E6 i# f9 Y) t2 r
9 N: q, J/ p: ?, [5 M. G. l }
/ P, B# g# B7 t3 i A @# x+ i6 [
/ i* E. {; M+ r }
4 H/ a' \' j! B9 [, Y" A3 D2 \5 a2 ?/ T6 t' d
}
) H- V( k; v ^- ]* \1 D
F. {( t! ]9 C4 W
" ]" c2 Q7 m- J3 l2 D+ H
6 {1 {1 R. _% S Z5 v( S, L7 s4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)].. O' o1 q' ?5 `. c
' G4 h6 [- G5 b/ A. g( |# k
右击项目名打开属性窗口,在生成里,选中 为COM 互操作注册
) S9 T7 g$ p; _$ K
, O r# R2 t" z L: g% V& y; q
: n- u: J0 m% k- E9 F5. 生成->生成解决方案- d9 r. c, N( H% i0 ~
注意 这个时候 生成 非常缓慢
5 h7 P+ O- N2 v1 G 直到 出现 成功 1 个,失败 0 个,为止才 操作一下面内容0 e3 J/ E( x1 p( r: E% d
! G& \2 f& F* e$ T! K* R% |# e
7 `: `9 W" p9 F+ c5 r3 Z1 J$ j---------------------------& ]- B3 v% {& [# U: j6 v5 ?
, ]8 s- @( U+ y6 L g1.调用前要先把com组件注册才行.- b9 z! \/ _: A8 g- `( L( e' l
: _8 x1 G: W" m, A3 f$ `
使用C#创建并注册COM组件 C#不能直接创建COM组件,因为其生成的DLL属于程序集,但可通过“使程序集COM可见”选项来支持COM。0 ~, Q' d# d& V' A y) b0 ?
以下说明如何通过C# 注册、注销COM组件。 7 J0 t" \$ Q. r# T# {
& W6 }8 h# U7 U. `# K8 Y* H1 [, _; Q
为了能让生成的DLL能够进行COM注册,需要进行强名称签名! g C% R, j9 d6 ~3 j E, d t
打开COMLib项目属性,选择签名,勾选为程序集签名,通过下拉列表选择新建,弹出创建强名称密钥窗口,输入名称,不勾选使用密码保护密钥文件。1 I0 K9 J/ t6 X- w
创建完成后COMLib项目中将出现后缀为.snk的签名文件。$ {. b; _' d* _; s- f, 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文件。: X, e! r# v: o7 b/ _
卸载COM组件: - @- Y, o H9 b% P" X9 g
与注册过程基本相同,只需将命令改为“RegAsm /u D:\ COMLib.dll /tlb: COMLib.tlb /codebase”。( s, g% D4 K' ^- s% S$ t
7 U/ | _1 n5 P7 H1 v3 s2 [3 Q. ?8 `8 z9 Y6 N. P$ i
2.注册完了就可以在代码中用了,先新建一个C++程序, 类型选 Win32 Console控制台应用程序
: d% x' V. H( x1 i2 t# T4 r" a
' W$ Y" @. ?! e! d/ E名字取MEI_UseCsharpCom,点完成
" c' ^9 ~& ^+ _+ X) K/ A, H1 x4 {( e/ _; v% L
把MEI_AddCom.tlb文件拷贝到项目的任何目录下.我就放在D:\MEI_UseCsharpCom\MEI_UseCsharpCom.6 _# i& R: A) [1 [
4 a s' B0 K6 l1 W* ^; l3 G我们会看到一个MEI_UseCsharpCom.cpp文件,双击打开把默认生成的代码全部删掉.敲入下面代码:
% ?" _$ \' L1 U4 C6 ^
- Y0 Y5 O) @5 W0 q; |& \; g8 J4 p! T& K
#include "stdafx.h"% |; E! z. T3 R4 [ u
#include <windows.h>/ Z4 w2 s/ o! ?& U9 u) b( s& l5 d
#include <string.h>
4 w. c8 x3 a# e( Z, ~" A/ _6 F% u. ?' `
#import "MEI_AddCom.tlb" named_guids raw_interfaces_only; P0 X, c8 }% O. m4 }! s
7 T2 F9 w. U& |. H; ~
char* WcharToChar(const wchar_t* wp) //wchar_t转char*. \0 C" A @4 y0 _9 |- e3 ?
{ 2 x* Z/ P. `( T$ v
char *m_char;
1 ]- l5 L3 `' |/ s) y4 i int len= WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),NULL,0,NULL,NULL); / a) Z: R! i9 u1 p2 U! ]% X
m_char=new char[len+1]; ) e8 y* v+ N$ V% g3 ~
WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),m_char,len,NULL,NULL); 2 z0 Q: p8 O0 Z Y
m_char[len]='\0';
% j* A5 ^$ E4 _) _9 R' r! U# N return m_char;
4 d6 W) z% B' c6 |} - w4 g0 C* \9 J, J1 G, p/ k
wchar_t* CharToWchar(const char* c) //char*转wchar_t1 e* V$ p; S0 g! d4 O; {
{
, d' Y; ` B9 F( {0 V! Y$ ]: r wchar_t *m_wchar;1 [# e0 l% M. ^9 B4 ?7 J
int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0); . B( H% c$ A0 p2 }* q9 }
m_wchar=new wchar_t[len+1]; 4 W) y6 B v7 V
MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len);
; x, J' d4 k$ t& g, O z5 F, q m_wchar[len]='\0';
+ C( w" ^9 `' [; h return m_wchar; 9 d2 _% i' h3 c* U: h
}
# q/ o& p1 d8 R1 ~- K% z. Z0 ?2 J% l& J0 P
void _tmain(int argc, _TCHAR* argv[])% u5 Z0 L" z) {/ u0 K
8 X: u1 E, y5 \" u{
0 x3 l$ d; j* ~6 j' ?/ L' ~3 N( B: ?! _. z) V# v- a* j
CoInitialize(NULL);
$ B, i; X0 p1 U* x
0 |" a9 u$ g0 ~' I MEI_AddCom::MEI_COMPtr ptr; //类似明志一个指向接口的指针
% E" [: X" C% o) |
% b9 o; t* f) Z: U ptr.CreateInstance(MEI_AddCom::CLSID_MEI_COM_T); //实例化一个类 CLSID_ 类名. O: f/ F8 C6 C; T3 p, C4 w
. X" b2 B3 j; A: L+ H
//这个地方有一点点奇怪我也还没弄懂.在C#中的函数是int Plus(int,int).但类型在这里都转成long了.另外就是我们不能直接' y2 Q4 K# B4 o
H4 E) M# `- j2 r2 ^ //来个long a = ptr->Plus(1,2);这样得不到a = 3,反正会出错.
+ p6 G6 J- B6 b+ F //这里函数Plus的参数变成三个了long Plus(long,long,long *).其中最后一个指针得两数相加的结果& a! c1 J/ i. Q
0 i T( E* q6 J long a = 1;
% l5 D: u( ~6 w; ^; R! u1 i- H/ N$ X9 O' m; U1 O
long * lPtr = &a;, ? r7 K, C8 p; y4 L3 G
% p" f. } r. V! {- x8 ^
ptr->Plus(1,2,lPtr);
# z# o0 `* U5 V; E v
+ }) w( L) {. a' r+ O; G# M char msg[132]="";( E. S# w1 |9 f2 [ S/ x2 G _
sprintf(msg, "%d",lPtr[0]);" Z; Q( |5 ~) O# R- `+ N1 B8 @. f
9 n7 K% H X7 U' l/ N
LPCWSTR str=CharToWchar(msg);2 S0 n8 w1 \4 W3 [8 I! U% {
5 z. E( R& u: {8 F; i' I
MessageBox(NULL,str,_T("123"),MB_ICONWARNING);
. m+ c8 l6 s0 W9 _; y
/ @, q1 [7 d; v. Q! R" x0 ^: v3 _! Z3 H3 ?% U+ _ \
}2 O1 k2 |) [% R [; {7 V g
& V2 g, Z* |. y. j: O: R0 k此时就可以正确运行了.得到结果3+ X+ r+ u F3 I( m7 T
1 [) @. D! L3 I如果没有正常运行,则必须把dll文件拷贝到有MEI_UseCsharpCom.exe这个文件的目录下. I$ r3 {. u, ]1 r* w) ]
% T2 A2 _2 Q( ]7 o0 I
3 X/ g: ]& t6 y8 A5 S2 \3 j
-------------------------------------------------------------- ]5 f8 n2 J" f- |3 U) B
C# Npoi库 操作excel 的代码网上很多. Q V# o" x" p* [
& S& r9 T6 T1 D @// ----------------------------------------------------------------------7 e& Z3 \" w" I9 }0 `/ q
// 使用Npoi创建一个简单的xls文件,写内容
1 W# n4 p, p K* @) \6 j! R( z! _4 L7 w7 ^# M0 C
using System;
; i% T) H1 C0 q0 M! I0 I& ~$ Y- @: W5 kusing System.Collections.Generic;9 |' b9 Q% B. @8 T( [9 Y
using System.Linq;3 Z/ I" B% o6 V: A' ?- b) C
using System.Text;0 h2 Q# y2 c8 O3 u/ h
using NPOI.SS.UserModel;
4 N8 Z6 B1 S4 Z: W* N. V" Gusing NPOI.XSSF.UserModel;
. I+ m i0 s: B/ e; eusing NPOI.HSSF.UserModel;
& e) X# f7 b9 z; G S/ ]2 P Ousing System.IO;
8 O" [1 Q7 ^( I% n, uusing System.Data;* g3 y% }, `$ W1 K+ c4 D6 m
- f% @! v, Y; u W. p; h( S: {7 O//using System.Windows.Forms;
8 X, W7 K2 r. N$ S
+ \: ]6 m$ C% Q9 ynamespace CC
1 b/ n' e! a+ y$ R{# z1 ~, |; e7 Z4 Y+ p# R0 K
9 ~" E3 r: M; s' G0 j- J
class Program
% y, L5 G) f' ~7 D {
& m2 |# n0 f1 q; _/ e8 w( i/ U. O! S- g- v1 }0 W3 }" h
7 c! n: }' Y2 z% z/ [( } static void Main(string[] args)" F# K( f* n6 _# T, e
{
. n' D1 B( B- O6 \2 ~( T* X& e //创建工作薄
; L! R0 [: f$ n! E# ` HSSFWorkbook wk = new HSSFWorkbook();8 D: ^5 v6 f% T3 l" ?
//创建一个名称为mySheet的表
7 ~! s8 i( V& w$ K+ S ISheet tb = wk.CreateSheet("mySheet");% _; e0 e3 b( o3 l/ w+ S
//创建一行,此行为第二行
9 g4 Y' l* F6 r' o2 X IRow row = tb.CreateRow(1);
# { W- K( ~' {9 n) D for (int i = 0; i < 20; i++)
+ A& ~9 J5 ?& j6 k' y9 O {
7 z* |$ w' `% `7 W3 Q7 C ICell cell = row.CreateCell(i); //在第二行中创建单元格/ q) T9 i. n& X( m; q+ I& i
cell.SetCellValue(i);//循环往第二行的单元格中添加数据! s; I! j% p) G ^
}
6 E: G8 ?) u: Y2 k! i& w9 h+ F& b using (FileStream fs = File.OpenWrite(@"c:/myxls.xls")) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!. a5 U2 R1 P3 s' @- j, E$ D3 c
{4 L( y9 C2 u* H+ q. u7 [
wk.Write(fs); //向打开的这个xls文件中写入mySheet表并保存。8 f, y* V3 T) g" y. X. I0 A
// MessageBox.Show("提示:创建成功!");0 q4 @/ `1 S1 Z$ P( i- }' a6 r
}
# q7 T: {- v# G" G
. E$ @2 H4 r+ o6 Y, i3 L4 y }2 }/ q. Y7 ^- ?5 ^3 E; X4 Y# O0 d
& ^5 W( ? A4 C X& K7 `; j0 ]
1 ]& e. |! r0 O- w0 p5 l }
2 M$ K* E6 Z! ?5 l2 A. T2 C. c4 `) ~. p8 N0 h- x9 a
$ ^0 q- h. t' @7 z3 n$ A1 Z. O
6 o& V" E. F8 N: c& v/ y+ D
}1 m: C y6 ^ ~& K A
, s8 p6 y2 v' c% @% r( J
// ----------------------------------------------------------------------3 \; w' g2 Y8 X" i6 X
// 使用Npoi读一个简单的xls文件" l3 E1 k0 ~8 W- u* T# c! W8 `/ v
# J Q, c& j0 f/ p" ^5 @
using System;; @* p8 ]2 p& _0 s- n9 |, c- z; a
using System.Collections.Generic;
% [6 v6 K- Q$ Y, z; {& tusing System.Linq;
/ I2 M9 u6 F: @( c7 qusing System.Text;
3 S. q0 T& Q; r2 lusing NPOI.SS.UserModel;
) w! u) K/ L1 Y/ `# ~' q0 Yusing NPOI.XSSF.UserModel;" c& V: z! w- p$ M
using NPOI.HSSF.UserModel;8 ~5 L) K" v& }' s* o( Y5 F
using System.IO;0 i4 D+ M) G( D1 G2 Z0 Q
using System.Data;1 g1 F' q- R% O1 d" d
1 i ^$ t; p. t. C* \" |namespace CC
5 q V9 U% s, e* M) K{
) g( C3 Z+ v [6 y0 V
* H$ n0 b# N1 _2 D class Program! U N6 U: l/ r" i( v# S
{4 Y) L9 w, X+ T2 U# o, }; {
" g0 f O8 z3 D0 X. l
) i/ d* _" Q: ~
static void Main(string[] args)' ?5 J& O- a- m1 t0 J! r; U
{1 m4 v" i$ L" s& F3 C
StringBuilder sbr = new StringBuilder();' \0 x0 _& Z( O7 M* h: S
using (FileStream fs = File.OpenRead(@"c:/myxls.xls")) //打开myxls.xls文件
0 m& p1 _ U' s% P {
5 ^9 t" b3 Z: I9 I4 {1 c6 H' T HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的数据写入wk中
. ]' i3 [, K% g5 c' r, B for (int i = 0; i < wk.NumberOfSheets; i++) //NumberOfSheets是myxls.xls中总共的表数
! H- T9 _+ ^2 j! n, p; J {
0 E0 L# V' L4 ?1 M# n ISheet sheet = wk.GetSheetAt(i); //读取当前表数据
6 K6 b" B% E1 Q3 z! s: A for (int j = 0; j <= sheet.LastRowNum; j++) //LastRowNum 是当前表的总行数) B' t; A0 l# x5 ~: W' C' J
{
3 y% u" ?/ x6 v IRow row = sheet.GetRow(j); //读取当前行数据8 Y) Z1 h% J9 H- w' H+ K
if (row != null). Z1 G. `+ L1 h: L5 M2 ^1 }
{
& ~& p: G0 G" B7 ~- g sbr.Append("-------------------------------------\r\n"); //读取行与行之间的提示界限
6 ?% X- P T! ] for (int k = 0; k <= row.LastCellNum; k++) //LastCellNum 是当前行的总列数! m* x( r! E' B% c {6 t4 k T
{% o0 S+ A% W2 K* P
ICell cell = row.GetCell(k); //当前表格9 L; N! D$ J- l. {6 n3 |2 b
if (cell != null)2 @, a. B) p+ q+ b6 f8 _
{( |+ Q% n* _8 |& s3 k# u
sbr.Append(cell.ToString()); //获取表格中的数据并转换为字符串类型( f3 _: c9 \" Z# i# k' C' `
}# D0 C; _9 y6 ]
}4 r8 r8 p. y. z, P
}% i. J" }& F( S
}
" O j) `8 A! M& R6 V }; P5 U" ]! J& L* h3 _1 B
}
0 d& ~0 E+ T: O" t& u sbr.ToString();2 C" W9 I( K) a. \ S) `8 P
using (StreamWriter wr = new StreamWriter(new FileStream(@"c:/myText.txt", FileMode.Append))) //把读取xls文件的数据写入myText.txt文件中
6 Y: L" X g2 |0 X {' k9 T1 N3 C4 l* ?5 M0 j( K4 l* f2 D6 J
wr.Write(sbr.ToString());
! S6 R U/ z" u; h% p wr.Flush();
" s' a& \' n: h5 \/ M5 l$ K* T }
5 M, ~, b; Y4 |7 a" F7 d
: w6 E! w4 L# Q% ?: j
* U7 o$ g' | }( P, ?7 S8 Y }, t. s8 _0 p, o; R$ L
5 ~. N6 r$ t$ @3 } F$ g* Q7 A% ?+ [& e3 Z+ p1 k/ Y7 L
}
2 l6 u# a5 B% A5 W8 M4 U. `
! h5 \* n8 r% I0 ^/ D5 o1 e& v! }6 U) B n7 r6 ]$ [+ m' T
. w0 F4 T+ k$ @$ G" o; \) J: ^7 `
}) E, d" e3 k( v. R" R+ u, J
' T7 ?; r" H. X, E
: K7 d5 d* e$ X" r然后 自己封装 给 c++用
) e; b9 m6 M" A: R
" [, ^5 y4 E; k* t. C* p" N9 p: i ~! r/ Y0 R, ]. m
5 y+ A& ~# H9 n6 d' V# w8 K; C5 @3 L
; I2 d0 j# [3 T1 c6 N. Q" K+ `, S+ |
; o+ d0 U/ Q- x% d; N/ ~
/ k- U+ G6 ^$ d% h
! g: U; ]3 P' T" k2 p
& J4 M8 m2 [1 e; m3 E. m" C9 x2 G+ ^3 E% @; m
( X+ v+ z( E$ j) @) j, ?6 T1 W, y5 A- Z! ?2 b U" E
% x3 c) p' B- P: ]! I& d5 D2 y; X" T; S' s2 a$ @& y3 b# }% h
, z! N: p7 m7 q' u0 g; x: r
) k7 d6 p3 A2 B3 t2 i
! i! T. y; w7 t B
0 @, B$ R2 ~6 B. B8 k: ~6 y9 W. P5 Z& B4 U" O. C2 w& c/ L9 ]
v) n1 @# F( y5 n) D: z" _. {5 D
% E, w5 K& d E9 i* j2 w# I9 d% B& E1 y$ V( Z- h
|
|