如何让WORD在后台工作

chengjian 2003-10-17 02:48:00
我用DB中的BLOB字段保存WORD的文档.
如何取出其数据,对其进行一些操作后保存?(不需要出现WORD的界面,让WORD在后台工作)?
例如有下面的代码:
MyWordApp: OleVariant;
MyStream: TMemoryStream;

MyWordApp := CreateOleBbject('word.application');
MyStream:= TMemoryStream,Create();

(ADOQuery_File.FieldByName('ProFile_Data') as TBlobField).SaveToStream(MyStream);
MyStream.Position := 0;
取到MyStream后,用OLEContainter打开没有问题.如:OLEContainter.LoadFormStream(MyStream)

但是,如何在后台对MyStream的内容进行操作,再保存到数据库中?
MyWordApp.LoadFromStream()----没有这个方法,怎么办?
...全文
158 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
chwdong 2003-10-27
  • 打赏
  • 举报
回复
procedure tfrmlxxt.putout;
var
V:variant;
j,I:Integer;
s1,s2,s3,s4,s5,pd,sa,sb,sc : String;
begin
V:=createoleobject('word.application'); //创建WORD工程
v.documents.add; //加载文档
DM1.Cn1Query_tm.first;
v.Selection.TypeText(label22.Caption); //加入文字
v.Selection.TypeParagraph; //加入回车
v.Selection.TypeParagraph;
v.Selection.TypeParagraph;
sa:='';
sb:='';
sc:='';
while not DM1.Cn1Query_tm.Eof do
begin
DBRichEdit3.DataField:='';
DBRichEdit3.DataSource:=DM1.Cn1DS_tm;
DBRichEdit3.DataField:='a15';
sa:=inttostr(DM1.Cn1Query_tm.findfield('a13').asinteger);
if sa='11' then
begin
sc:='单选题:';
end
else
begin
if sa='18' then
begin
sc:='多选题:';
end
else
begin
if sa='12' then
begin
sc:='判断题';
end
else
begin
if sa='20' then
begin
sc:='简答题';
end
else
begin
if sa='21' then
sc:='分析题';
end;
end;
end;
end;
if sb<>sa then
begin
v.Selection.TypeText(sc);
v.Selection.TypeParagraph;
end;
v.Selection.TypeText(inttostr(DM1.Cn1Query_tm.RecNo)+'、');
DBRichEdit3.SelStart:=0;
DBRichEdit3.SelLength:=length(DBRichEdit3.Lines.Text);
DBRichEdit3.CopyToClipboard; //复制
v.selection.paste; //粘贴
v.Selection.TypeParagraph;
IF DM1.Cn1Query_tm.FieldByName('CSBS').AsString<>'' THEN
BEGIN
TRY
//AdvImage2.loadImage(ExtractFilePath(Application.ExeName)+DM1.Cn1Query_exam.FIELDBYNAME('CSBS').AsString);
V.SELECTION.InlineShapes.AddPicture(ExtractFilePath(Application.ExeName)+DM1.Cn1Query_tm.FIELDBYNAME('CSBS').AsString);
v.Selection.TypeParagraph;
EXCEPT
END;
END;
sb:=sa;
DM1.Cn1Query_tm.next;
end;

v.Selection.insertBreak;
DM1.Cn1Query_tm.first;
v.Selection.TypeText('答案');
v.Selection.TypeParagraph;
v.Selection.TypeParagraph;
v.Selection.TypeParagraph;
while not DM1.Cn1Query_tm.Eof do
begin
v.Selection.TypeText('第'+inttostr(DM1.Cn1Query_tm.RecNo)+'题');
v.Selection.TypeParagraph;
if DM1.Cn1Query_tm.findfield('a13').asinteger<=19 then
begin
pd:=DM1.Cn1Query_tm.fieldbyname('a2').AsString;
if dm1.Cn1Query_tm.FindField('a13').AsInteger<>12 then
begin
v.Selection.TypeText('试题答案:'+pd);
v.Selection.TypeParagraph;
end
else
begin
if pd='A' then pd:='正确';
IF PD='B' then pd:='错误';
v.Selection.TypeText('试题答案:'+pd);
v.Selection.TypeParagraph;
end;
end;
DM1.Cn1Query_tm.next;
end;
DM1.Cn1Query_tm.first;
ListBox1Click(Application);
v.Visible := TRUE; //文档可视
keybd_event(17, MapVirtualKey( 17, 0 ), 0 , 0 ); // win 键按下
keybd_event(36, MapVirtualKey( 36, 0 ), 0 , 0 ); // home 键按下
keybd_event(36, MapVirtualKey( 36, 0 ), KEYEVENTF_KEYUP , 0 ); // home 键抬起
keybd_event(17, MapVirtualKey( 17, 0 ), KEYEVENTF_KEYUP , 0 ); // win 键抬起
//文件回到文件头、标题位置
end;

da_yu 2003-10-27
  • 打赏
  • 举报
回复
关注!
chengjian 2003-10-23
  • 打赏
  • 举报
回复
我在数据库中保存的是OLECONTAILER.SAVETOSTREAM(MyStream)的数据.
在OLECONTAILER中打开没有问题.

现在如何在后台对MyStream的内容进行操作?即不要显示界面,只通过WORD对MyStream中的内容进行处理?
mengxiang5160 2003-10-18
  • 打赏
  • 举报
回复
delphi擅长做数据库类的mis开发,但对于oa就有点力不从心了。不过随着microsoft的com技术逐渐成熟,现在普通windows应用已经可以和office 97无缝结合了,尤其是在delphi 5中提供了一组servers组件,更是简化了程序开发。

最近接触了一个用户的案例,用delphi控制word做一个合同管理程序。办公人员先根据业务需要,写好合同的文字,但在用户名称、产品名称等变化的位置填写指定的标记字符串,然后通过delphi把数据库中的实际数据替换掉word中的文字,最后让word打印出合同。

delphi自带了一个简单的word例题,但功能太简单。通过查找vba的说明,再对照delphi的vcl,编写了如下代码,实现了基本的公文管理功能。

启动word时用如下代码:
begin
try
wordapplication.connect;
except
messagedlg('word may not be installed', mterror, [mbok], 0);
abort;
end;
wordapplication.visible := true;
wordapplication.caption := 'delphi automation';
end;

关闭word用如下代码。如果想保存doc文件,请修改savechanges变量的内容:
var
savechanges, originalformat, routedocument: olevariant;
begin
savechanges := wddonotsavechanges;
originalformat := unassigned;
routedocument := unassigned;
try
wordapplication.quit(savechanges, originalformat, routedocument);
wordapplication.disconnect;
except
on e: exception do
begin
showmessage(e.message);
wordapplication.disconnect;
end;
end;
end;

让word打开一个指定的文件,需要先放置opendialog,然后调用wordapplication.documents.open:
var
itemindex :olevariant;
filename, confirmconversions, readonly, addtorecentfiles,
passworddocument, passwordtemplate, revert,
writepassworddocument, writepasswordtemplate, format: olevariant;
begin
if not dlgopen.execute then
exit;

{open document}
filename := dlgopen.filename;
confirmconversions := false;
readonly := false;
addtorecentfiles := false;
passworddocument := '';
passwordtemplate := '';
revert := true;
writepassworddocument := '';
writepasswordtemplate := '';
format := wdopenformatdocument;

wordapplication.documents.open( filename, confirmconversions,
readonly, addtorecentfiles, passworddocument, passwordtemplate,
revert, writepassworddocument, writepasswordtemplate, format );

{assign worddocument component}
itemindex := 1;
worddocument.connectto(wordapplication.documents.item(itemindex));

{turn spell checking of because it takes a long time if enabled and slows down winword}
wordapplication.options.checkspellingasyoutype := false;
wordapplication.options.checkgrammarasyoutype := false;
end;

让word替换标记字符串要使用worddocument.range.find.execute,这里用delphi替换了< #name> :
var
findtext, matchcase, matchwholeword, matchwildcards, matchsoundslike,
matchallwordforms, forward, wrap, format, replacewith, replace: olevariant;
begin
findtext := '< #name> ';
matchcase := false;
matchwholeword := true;
matchwildcards := false;
matchsoundslike := false;
matchallwordforms := false;
forward := true;
wrap := wdfindcontinue;
format := false;
replacewith := 'delphi';
replace := true;

worddocument.range.find.execute( findtext, matchcase, matchwholeword,
matchwildcards, matchsoundslike, matchallwordforms, forward,
wrap, format, replacewith, replace );

end;

上面这4段代码完成了公文管理的基本功能,再把它和数据库结合起来,就可以开发一个与lotus notes类似的产品了。
mengxiang5160 2003-10-18
  • 打赏
  • 举报
回复
给你一个单元,可以控制向word的模板文件的任意位置写入指定的任意数据
注意,模板需要写入数据的地方需要用$$$_1之类的标志标明。


unit unAppWord;

interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, udbword, ADODB, DB;
//ComObj, Word2000,
type
TAppword = class(TdbWord)
private
dbWord: TdbWord;
// Protected
public
constructor Create();
destructor Destroy(); override;
//依据Word文件名和内容向文件写内容
procedure WriteDoc(sts: Tstrings; fn: string);
//提取模板文件并生成word文件
function PickDoc(DocTitle: string; Conn: TADOConnection): string;
{ Public declarations }
end;


implementation
const
ReplaceText = '$$$_';
constructor TAppWord.Create();

begin
inherited Create();
end;

destructor TAppWord.Destroy();
begin
inherited Destroy();
end;

procedure TAppWord.WriteDoc(sts: Tstrings; fn: string);
var
sCnt: string;
i: integer;
begin
if (fn = '') or (not Assigned(sts)) then exit;
try
dbword.OpenFile(fn);
for i := 0 to sts.Count - 1 do
begin
if sts.Strings[i] = '' then
begin
sCnt := ' ';
dbword.Replace(ReplaceText+IntToStr(i),sCnt);
end
else
begin
sCnt := sts.Strings[i];
dbword.Replace(ReplaceText+IntToStr(i),sCnt);
end;
end;
dbword.Save;
dbword.CloseDoc;
except
raise(Exception.Create('error'));
end;

end;

function TAppWord.PickDoc(DocTitle: string; Conn: TADOConnection): string;
var
AQuery: TAdoQuery;
sqlDoc: string;
SD: TSaveDialog;

begin
result := '';
if (Conn = nil) or (DocTitle = '') or (not conn.Connected) then exit;
try
AQuery := TAdoQuery.Create(nil);
AQuery.Connection := Conn;
if AQuery.Active then AQuery.Close;
AQuery.SQL.Clear;
sqlDoc := Format('select MB_DATA from tdly.MB_WDWJ where MB_NAME=''%s''', [DocTitle]);
AQuery.SQL.Add(sqlDoc);
AQuery.Open;
if AQuery.RecordCount < > 1 then
begin
Alert('无法提取'+ DocTitle +'模板文件');
exit;
end;
SD := TSaveDialog.Create(nil);
try
SD.Filter := 'WORD文件(*.DOC) |*.DOC';
sd.DefaultExt := '*.doc';
sd.Options := [ofPathMustExist, ofOverwritePrompt];
if not SD.Execute then exit;
result := Sd.FileName;
Tblobfield(AQuery.FieldByName('MB_DATA')).SaveToFile(Result);// .SaveToStream(memstr); //模板字段
finally
AQuery.Close;
AQuery.Free;
SD.Free;
end;
except
end;
end;


end.
procedure TFrmMain.BitBtn12Click(Sender: TObject);
var
//ItemIndex:OleVariant;
FileName,ConfirmConversions,ReadOnly,AddToRecentFiles,
PasswordDocument,PasswordTemplate, Revert,
WritePasswordDocument,WritePasswordTemplate,Format:OleVariant;
begin
WordApplication1.Connect;
FileName:='c:\ZhiD.doc';
ConfirmConversions:=False;
ReadOnly:=False;
AddToRecentFiles:=False;
PasswordDocument:='';
PasswordTemplate:='';
Revert:=True;
WritePasswordDocument:='';
WritePasswordTemplate:='';
Format:=wdOpenFormatDocument;
WordApplication1.Documents.Open(FileName,ConfirmConversions,ReadOnly,AddToRecentFiles,PasswordDocument,PasswordTemplate,Revert,WritePasswordDocument,WritePasswordTemplate,Format,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam);
WordApplication1.Visible:=true;
wweijie 2003-10-17
  • 打赏
  • 举报
回复
调用word有几种办法,我经常使用的是

a.使用Delphi提供的Servers控件调用Word,使用Word的属性
使用Delphi的Servers控件来操纵Word,在编程时Delphi能够实现代码提示,总体上看能够较好的实现Delphi对Word的控制,但是还有一些Word的功能不能在Delphi中调用(比如自己编写的VBA宏代码)。且实现功能时本来在VBA代码中可选则参数在Delphi调用的时候必须添加,否则,连编译都不能通过。

b.使用CreateOleObject将启动Word,然后以Ole方式对Word进行控制。本办法是使用以CreateOleObjects方式调用Word,实际上还是Ole,但是这种方式能够真正做到完全控制Word文件,能够使用Word的所有属性,包括自己编写的VBA宏代码。与Servers控件和com技术相比,本方法能够真正地使用Word的各种属性,和在VBA中编写自己的代码基本一样,可以缺省的代码也不需要使用。
本方式启动的Word与Delphi程序分属两个窗体。缺点是使用本方法没有Delphi代码提示,所有异常处理均需要自己编写,可能编写时探索性知识比较多。

如果不希望出现word界面只需要将其中的visible参数设为false

5,386

社区成员

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

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