超级郁闷问题!都进来看看,不管你现在用不用得到,一定有帮助。。。请求版主帮忙置顶!!!

Comer 2006-01-05 09:49:23
由于要在PB下调用,所以封装了一个DLL,用于读EXCEL内容,读单个EXCEL文件(不管有多少SHEET页)都没问题,如果连续读多个excel文件,不管是PB调用还是在delphi下,某些(注意:不是全部,并且出乱码的单元格,每次都乱码)单元格会出现乱码(只有最后一个字是乱码)。

类似的方法,如果不用DLL,直接在delphi的应用程序里读excel文件的话,则不会出现乱码。
也是类似的方法,封装个COM+组件,在delphi,c#下调用都没问题,不会出现乱码。

郁闷至极,快一个月了,也没有解决,在网上找了些做DLL方面的资料,都只是强调string类型要用pchar之类的文章。

用到的第三方控件下载地址:http://www.axolot.com

我的DLL的代码:
library readExcel;

uses
XLSReadWriteII2,
ActiveX, Forms,
System,
SysUtils,
Classes,
Windows;

var
XlsRW: TXLSReadWriteII2;

{$R *.res}

//创建 XLSReadWriteII 对象
function XLSCreate: Integer; stdcall;
begin
try
Coinitialize(nil);

XlsRW := TXLSReadWriteII2.Create(Application);
Result := 1;
except
//创建对象失败
Result := -1;
Exit;
end;
end;

exports
XLSCreate;

//退出,释放变量
procedure XLSClose; stdcall;
begin
XlsRW.Free;
CoUnInitialize();
end;

exports
XLSClose;

//打开 Excel 文件
//openMode:1:新建文件(如果文件存在则覆盖原文件),0:打开现有文件
function XLSOpen(openMode: Integer; const SrcFile: PChar): Integer; stdcall;
begin
if UpperCase(ExtractFileExt(StrPas(SrcFile))) <> '.XLS' then
begin
//不是excel格式文件,不处理
Result := -100;
Exit;
end;

try
XlsRW.Filename := StrPas(SrcFile);

if ( openMode = 0 ) then
XlsRW.Read;
Result := 1;
except
//文件不存在
Result := 0;
end;
end;

exports
XLSOpen;

//保存
procedure XLSSave; stdcall;
begin
try
XlsRW.Write;
except
raise Exception.Create('Save To Excel File Failed.');
end;
end;

exports
XLSSave;

//取单元格的值,返回类型:PChar
function XLSGet_AsString(iSheet, iRow, iCol: Integer): PChar; stdcall;
var
ws: WideString;
s: String;
begin
try
ws := XlsRW.Sheets[iSheet - 1].AsString[iCol - 1, iRow - 1];

WideCharToStrVar(PWideChar(ws), s);
Result := Pchar(s);
except
raise Exception.Create('List index out of bounds (' + IntToStr(iSheet) + ')');
end;
end;

exports
XLSGet_AsString;

begin
end.
...全文
392 36 打赏 收藏 转发到动态 举报
写回复
用AI写文章
36 条回复
切换为时间正序
请发表友善的回复…
发表回复
Randomize 2006-01-09
  • 打赏
  • 举报
回复
學習了!CopyMemory方法用的恰當啊.
xili 2006-01-08
  • 打赏
  • 举报
回复
请问 免费下载的 TXLSReadWriteII2 有什么使用限制?
clasj 2006-01-08
  • 打赏
  • 举报
回复
正好赶上接分:)
Comer 2006-01-07
  • 打赏
  • 举报
回复
我的email: comerliang@163.com
QQ: 230043

欢迎交流

发信请把该贴地址复制过去
Comer 2006-01-07
  • 打赏
  • 举报
回复
DLL修改如下:
function XLSGet_AsString(iSheet, iRow, iCol: Integer; OutStr:PChar; aLen: integer): Integer; stdcall;
var
ws: WideString;
s: String;
begin
try
ws := XlsRW.Sheets[iSheet - 1].AsString[iCol - 1, iRow - 1];
WideCharToStrVar(PWideChar(ws), s);
Result := length(s);
if aLen = 0 then
exit;

if Result > aLen then
Result := aLen;
CopyMemory(OutStr, PChar(s), Result);
except
result := -1;
end;
end;

exports
XLSGet_AsString;

delphi下的调用就不用说了吧,说说PB下调用:
int i
string s
i = XLSGet_AsString(1, 1, 1, s, 0)
s = space(i)
XLSGet_AsString(1, 1, 1, s , i)

搞定
ztenv 2006-01-07
  • 打赏
  • 举报
回复
顶一下...
xili 2006-01-06
  • 打赏
  • 举报
回复
请问 控件 TXLSReadWriteII2 是不是免费?
harryduan 2006-01-06
  • 打赏
  • 举报
回复
很明显,你的pb调用代码写的不对,^_^
柯本 2006-01-06
  • 打赏
  • 举报
回复
我也一直用TXLSReadWriteII2;虽然没有碰到楼主的问题(我不用PB),但也希望楼主能贴出解决方案,谢谢!
Mr_Yang 2006-01-06
  • 打赏
  • 举报
回复
学习。
才子鸣 2006-01-06
  • 打赏
  • 举报
回复
UP楼上的
summersky204608 2006-01-06
  • 打赏
  • 举报
回复
学习下!
hthunter 2006-01-06
  • 打赏
  • 举报
回复
不厚道,解决了也不说说方法
Comer 2006-01-06
  • 打赏
  • 举报
回复
自己搞定了,爽

居然成了热门贴,那就下周在揭帖吧!!!
ysai 2006-01-05
  • 打赏
  • 举报
回复
那你查查取得的值与函数的返回值的二进制数据看看是否一样的再确实原因在哪,在DLL中的值写到A文件中,EXE中函数调用的返回值写到B文件中,用UEDIT对比一下
swimming8243 2006-01-05
  • 打赏
  • 举报
回复
只能说borland不是ms啊~么办法了
Comer 2006-01-05
  • 打赏
  • 举报
回复
to ysai(所有真的都是假的真,所有假的都是真的假) :
刚刚试过了,还是不行,读出来的内容:

资 产 负 债 表奂剖?
内 部 现 金 流 量 抵 销 资 料 表?
快乐老猫 2006-01-05
  • 打赏
  • 举报
回复
1.不可以在DLL里面分配字符串空间给调用函数,字符串空间必须在外部分配。
2.不可以将字符串作为返回值,你看见那个WIN API有字符串返回值了。
3.一般都要传递给函数PCHAR的空间长度,避免字符串空间不足。
4.XlsRW.Sheets[iSheet - 1].AsString[iCol - 1, iRow - 1]; 返回的应该是string吧,应该没必要用WIDESTRING变量。

常见写法

fun xxx(ps: pchar; ilen: integer): integer
var
s: string;
begin
s := 'abc';
result := length(s);
if ilen = 0 then
exit;
if result > ilen then
result := ilen ;
CopyMemory(ps, PChar(s), result);
end;

var
ss: string;
i: integer;
begin
i := xxx(PChar(ss), 0);
SetLength(ss, i);
i := xxx(pChar(ss), i);
end;
Comer 2006-01-05
  • 打赏
  • 举报
回复
to aiirii(ari-http://spaces.msn.com/members/aiirii/) :
转化前,转化后都没有问题,我在DLL里用showmessage测试过,正确


to ysai(所有真的都是假的真,所有假的都是真的假) :
--还是老实参照API的做法,谁分配谁释放.
试过了,只是没用使用过这句:
CopyMemory(OutStr, PChar(s), l);

我试试看,解决马上揭帖!!!
ysai 2006-01-05
  • 打赏
  • 举报
回复
function XLSGet_AsString(iSheet, iRow, iCol: Integer; OutStr:PChar;AMaxCount:integer): boolean; stdcall;
var
ws: WideString;
s : String;
l : integer;
begin
try
ws := XlsRW.Sheets[iSheet - 1].AsString[iCol - 1, iRow - 1];
WideCharToStrVar(PWideChar(ws), s);
l := length(s);
if l > AMaxCount then
l := AMaxCount;
CopyMemory(OutStr, PChar(s), l);
Result := true;
except
result := false;
end;
end;

procedure TForm1.Button18Click(Sender: TObject);
var
p : array[0..MAXBYTE] of char;
begin
FillMemory(@p[0], MAXBYTE + 1, 0);
XLSGet_AsString(1, 1, 1, p, MAXBYTE);
caption := p;
end;

明显是最后半个汉字,也就是最后一个字符没取出来
我连函数返回值都不用PChar,因为内在是在DLL中分配的,还是老实参照API的做法,谁分配谁释放.
加载更多回复(16)

5,391

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧