读出word文档(100分)

  • 主题发起人 主题发起人 mhlang
  • 开始时间 开始时间
实在没有办法就这样吧,就是慢一点
使用流中的SaveTofile('c:/aaa.doc');
procedure Tdoccombin.BitBtn4Click(Sender: TObject);

var
msworda:variant;
i:integer;
namee:string;
begin
msworda:=createoleobject('word.application');
msworda.documents.open(filename:='c:/aaa.doc',readonly:=true);
msworda.visible:=1;
end;
 
以前我就是通过先存为文件,觉得它要不断地读写盘不太爽,
才想通过stream-->clipboard-->组成word文档,好让它快一点。
 
打开之前自己先建个临时文件,从数据库把数据读出来写进这个文件里
你要代码吗?好几个函数,贴不上来
 
先把文件存入库
tab_TB_JCWH_WDMB.Insert;
tab_TB_JCWH_WDMB.FieldByName('dcid').asstring:=fdcid;
tab_TB_JCWH_WDMB.FieldByName('wdlx').asstring:=fwdlx;
tab_TB_JCWH_WDMB.FieldByName('mbmc').asstring:=edit_mbmc.text;
tab_TB_JCWH_WDMB.FieldByName('zwhy').asstring:=edit_zwhy.text;
tab_TB_JCWH_WDMB.FieldByName('wjlj').asstring:=edit_wjlj.text;
tab_TB_JCWH_WDMB.FieldByName('bcsm').asstring:=memo1.text;
tab_TB_JCWH_WDMB.FieldByName('dylx').asstring:=copy(edit_wjlj.text,length(edit_wjlj.text)-3,4);
WriteDbStream(OpenDialog1.FileName,tab_TB_JCWH_WDMB.FieldByName('wdmb') as TBlobField);
tab_TB_JCWH_WDMB.ApplyUpdates;
tab_TB_JCWH_WDMB.CommitUpdates;
说明WriteDbStream
//Fname为文件名,BField为BLOB字段,成功反回true 否则为false
Function WriteDbStream(FName:string;BField: TBlobField):boolean;
var
MemSize: Integer;
Buffer: PChar;
BStream: TBlobStream;
FHandle:HFile;
num:DWord;
begin
result:=true;
if not FileExists(FName) then
begin
Application.MessageBox('文件不存在!','错误',MB_OKCANCEL+MB_ICONEXCLAMATION);
result:=false;
exit;
end;
try
FHandle:=_lopen(PChar(FName), OF_READ+OF_SHARE_DENY_NONE);
if (FHandle = INVALID_HANDLE_VALUE) then
begin
Application.MessageBox('打开文件失败!','错误',MB_OKCANCEL+MB_ICONEXCLAMATION);
result:=false;
exit;
end;
try
BStream := TBlobStream.Create(BField, bmWrite);
MemSize :=_llseek(FHandle,0,FILE_END);
//加一字节放NULL字符
//Inc(MemSize);
try
Buffer := AllocMem(MemSize);
except
FreeMem(Buffer,MemSize);
Application.MessageBox('分配内存失败!','错误',MB_OKCANCEL+MB_ICONEXCLAMATION);
result:=false;
exit;
end;
_llseek(FHandle,0,FILE_BEGIN);
_lread(FHandle,buffer,MemSize);
BStream.Seek(0, soFromBeginning);
//流指针位置放到最前
BStream.Write(Buffer^,MemSize);
finally
BStream.Free;
FreeMem(Buffer,MemSize);
end;
finally
_lclose(FHandle);
end;
end;
 
打开之前自己先建个临时文件,从数据库把数据读出来写进这个文件里
procedure Tsb_sbgl_wdmx.Button1Click(Sender: TObject);//文档信息按钮
var
fstr:string;
ldcid,lwdbm:string;
begin
if not DirectoryExists('c:/temp') then
MkDir('c:/temp');

fstr:='c:/temp/HDBFS_QWJS'+fdylx;//fdylx入库时对应的文件的后缀
ldcid:=fdcid;
lwdbm:=fwdbm;
try
tab_tb_wdgl_wdmx.open;
except
exit;
end;
if not tab_tb_wdgl_wdmx.Locate('dcid;wtbm',VarArrayOf([lDCID,lWDBM]),[]) then
exit;
ReadDbStream(fstr,tab_tb_wdgl_wdmx.FieldByName('wdmx') as TBlobField);
OpenTypeFile(fdylx,fstr);
end;
说明ReadDbStream
//Fname为文件名,BField为BLOB字段,成功反回true 否则为false
Function ReadDbStream(FName:string;BField: TBlobField):Boolean;
var
MemSize: Integer;
Buffer: PChar;
BStream: TBlobStream;
FHandle:HFile;
num:DWord;
FDir:string;
begin
//如果文件存在则先删除
result:=true;
//判断路径
FDir:=copy(FName,0,GetPos('/',FName) - 1);
if not DirectoryExists(FDir) then
begin
//如果路径不存在,则创建C:/TEMP,文件名则相应改变
FDir:='c:/temp';
FName:=FDir + Copy(FName,GetPos('/',FName),length(FName) - GetPos('/',FName) + 1);
if not DirectoryExists(FDir) then
begin
if not ForceDirectories(FDir) then
begin
result:=false;
exit;
end;
end;
end;
if FileExists(FName) then DeleteFile(FName);
try
FHandle:=_lcreat(PChar(FName),0);
if (FHandle =INVALID_HANDLE_VALUE) then
begin
Application.MessageBox('创建文件失败!','错误',MB_OKCANCEL+MB_ICONEXCLAMATION);
result:=false;
exit;
end;
try
BStream:=TBlobStream.Create(BField, bmRead);
MemSize := BStream.Size;
//加一字节放NULL字符
//Inc(MemSize);
try
Buffer := AllocMem(MemSize);
except
FreeMem(Buffer,MemSize);
Application.MessageBox('分配内存失败!','错误',MB_OKCANCEL+MB_ICONEXCLAMATION);
result:=false;
exit;
end;
BStream.Read(Buffer^,MemSize);
_llseek(FHandle,0,FILE_BEGIN);
_lwrite(FHandle,Buffer,MemSize);
finally
BStream.Free;
FreeMem(Buffer,MemSize);
end;
finally
_lclose(FHandle);
end;
end;
说明OpenTypeFile
//***extname后缀名,**************filename文件名
procedure OpenTypeFile(extname,filename:string);
function GetOpenFileCommand(ls_ext:string):string;
function GetCommand(ext,subkey:string):string;
var Reg:TRegistry;
str:string;
begin
if ext[1]<>'.' then ext:='.'+ext;
try
Reg:=TRegistry.Create;
Reg.RootKey:= HKEY_CLASSES_ROOT;
Reg.OpenKey(ext, True);
//读取类型值
str:=Reg.ReadString('');
Reg.CloseKey;
str:= str+subkey;
Reg.OpenKey(str, True);
//读取打开文件的程序
str:=Reg.ReadString('');
Reg.CloseKey;
finally
Reg.Free;
end;
result:=str;
end;
var str:string;
position:integer;
dir:Array[1..512] of char;
begin
str:=GetCommand(ls_ext,'/shell/Open/command');
if str = '' then
begin
str:=GetCommand(ls_ext,'/DefaultIcon');
end;
str:=string(StrUpper(pchar(str)));
position:=pos('%SYSTEMROOT%',str);
if position > 0 then
begin
FillChar(dir,512,32);
GetwindowsDirectory(@dir,512);
Delete(str,position,12);
insert(trim(string(dir)),str,position);
end;
position:=pos('.',str);
str:=copy(str,1,position+3);
position:=pos('"',str);
if position>0 then
begin
Delete(str,position,1);
end;
result:=str;
end;
var ls_command:string;
FDir:string;
begin
if extname = '' then
begin
Application.MessageBox('该文件类型不存在!','错误',MB_OKCANCEL+MB_ICONEXCLAMATION);
exit;
end;
ls_command:=GetOpenFileCommand(extname);
if not FileExists(ls_command) then
begin
Application.MessageBox('打开该类型文件的应用程序不存在!','错误',MB_OKCANCEL+MB_ICONEXCLAMATION);
exit;
end;
//判断路径
FDir:=copy(FileName,0,GetPos('/',FileName) - 1);
if not DirectoryExists(FDir) then
begin
//如果路径不存在,则创建C:/TEMP,文件名则相应改变
FDir:='c:/temp';
FileName:=FDir + Copy(FileName,GetPos('/',FileName),length(FileName) - GetPos('/',FileName) + 1);
if not DirectoryExists(FDir) then
begin
if not ForceDirectories(FDir) then
exit;
end;
end;
if not FileExists(FileName) then
begin
Application.MessageBox('要打开的文件不存在!','错误',MB_OKCANCEL+MB_ICONEXCLAMATION);
exit;
end;
winexec(pchar('"'+ls_command + '" "' + filename+'"' ),SW_SHOWNORMAL);
end;

申明 tab_TB_JCWH_WDMB.FieldByName('dylx').asstring:=copy(edit_wjlj.text,length(edit_wjlj.text)-3,4);
有问题,我只是对与word
取文件的后缀,就是调用类型。要查找‘.'你自己看看。
实际上我这个函数是用来对多媒体信息的,当然包括word
 
我认为你的stream-->clipboard-->组成word文档不太可能成功。

关键在于你一开始将word文档存入stream,也就是blob字段的方式,
如果是单纯的用流读文件到blob字段的话,你的word文档的合并在
合并后一定会什么都不是。用word你会打不开该文档,而且即使打开
也只会显示No.1的内容。

我说的我想是不会错的。
合理的方式是用将字段内容保存为临时的doc文档,然后用VBA的合并或
拷贝命令合成文档。
顺序应该是File ->Blob->Stream->ActiveFile->ClipBoard->File或
File ->Blob->Stream->ActiveFile->VBA->File或
ActiveFile->ClipBoard->Blob->Stream->ClipBoard->File
 
建议你采用最后一种方式。

可以以不可见的方式打开Word文档,并读到字段中,这样可以剔除doc文档的文件头部分
(如版本,长度等信息,不可能通过流合并的原因就在这里)
 
谢谢楼上两位朋友的详细解答,特别是zqs10597249。我初学,也看懂个大概了。
我想把我已经做过的说清楚:
写入blob字段是这样的:先拖入一个ole容器:olecontainer1,其中插入word对象,
编辑好一段word文档,然后append,再调用以下过程存入blob字段:
procedure oletoblobfield(var olename:Tolecontainer;fieldname:Tblobfield);
var bs:TADOBlobStream;
begin
bs:=TADOBlobStream.Create(fieldname,bmwrite);
olename.SaveToStream (bs);
bs.Free ;
end;
post后成功了。浏览时调用以下过程:
procedure blobfieldtoole(var fieldname:Tblobfield; olename:Tolecontainer);
var bs:TADOBlobStream;
begin
bs:=TADOBlobStream.Create(fieldname,bmread);
olename.LoadFromStream(bs);
bs.Free;
end;
那么在olecontainer容器中也能顺利看到它了。
这就是我存入blob字段的过程和方式。
至于说“选定了其中一些记录,现在想把选定记录的field1字段中的word文档逐个读出,
并逐个写入一个新的word文档如“temp.doc””的作法,我试了以后再说吧。我只是不希望
不断地读写盘。
 
我最后通过临时文件解决了,感谢各位,平分了吧
 
多人接受答案了。
 
后退
顶部