多线程处理word问题(高手帮忙啊)!(100分)

  • 主题发起人 主题发起人 aiqikong
  • 开始时间 开始时间
A

aiqikong

Unregistered / Unconfirmed
GUEST, unregistred user!
我的word 是这样生成的!
根据用户选择的模块,每个模块根据各模块的word模板从数据库中调出数据放置到相应的位置上,以模块名命名各自存为一个word文件,最后把用户选择生成的各word文件合并生成一个完成的word文件。因为模块有20-30个,整个过程有3-4分钟。 我希望用多线程解决这个时间过长的问题!
我的代码如下:
unit UBuildWord;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,word2000, WordXP, OleServer,ComObj, CheckLst, DB, ADODB,
ComCtrls, ExtCtrls;
type
TFrmBuildWord = class(TForm)
''''''
private
{ Private declarations }
public
folderName :string;
templateName: string;
NO,Rid,zl:String;
{ Public declarations }
end;
var
FrmBuildWord: TFrmBuildWord;
implementation
uses
UDataCon, UDataMDB, UDataMDR,UReManage;
{$R *.dfm}
procedure fenxiword(str_id:string;str_tablename:string;str_filename:string;folderName:string;templateName:string);
//综合评述 调用该过程生成word
var
vWord,vDoc: Variant;
ItemIndex: OleVariant;
x,z,i,h,y:Integer;
begin
vWord := CreateOleObject('Word.Application') ;//创建Word线程
try
vDoc := vWord.Documents.Open(folderName+str_filename+'.doc');
with DataCon.ADOQuery1do
begin
close;
sql.Clear;
sql.Add('select * from B对比评述 where CrediteyesNO='+''''+str_id+'''');
open;
end;
vDoc.Bookmarks.Item('m').Range.InsertAfter(DataCon.ADOQuery1.Fields[1].AsString);
vDoc.Bookmarks.Item('mm').Range.InsertAfter(DataCon.ADOQuery1.Fields[2].AsString);
vDoc.Bookmarks.Item('mmm').Range.InsertAfter(DataCon.ADOQuery1.Fields[3].AsString);
vDoc.Bookmarks.Item('mmmm').Range.InsertAfter(DataCon.ADOQuery1.Fields[4].AsString);
ItemIndex:=2;
with DataCon.ADOQuery1do
begin
close;
sql.Clear;
sql.Add('select * from B对比结果 where CrediteyesNO='+''''+str_id+'''');
open;
x:=RecordCount;
h:=Fields.Count;
end;
vdoc.tables.Add(vDoc.Bookmarks.Item('mmmmm').Range,x+1,h-1,100);
for i:=1 to h-1do
begin
vDoc.Tables.Item(2).Cell(1,i).range.text:=DataCon.ADOQuery1.Fields.FieldName;
end;
with DataCon.ADOQuery1do
begin
z:=1;
First ;
while not Eofdo
begin
z := z + 1 ;
for y := 1 to h-1do
vDoc.Tables.Item(2).Cell(z,y).Range.
InsertAfter(DataCon.ADOQuery1.Fields[y].Asstring);
Next;
end;
end;

vWord.Selection.Font.Bold :=True;
finally
vdoc.saveas(templateName+str_filename+'.doc');
vDoc.Close(True) ;
//关闭文并保存
vWord.Quit(False) ;
//退出Word
end ;
end;

procedure llzlword(str_id:string;str_tablename:string;str_filename:string;folderName:string;templateName:string);
//过程 联络资料 生成word 调用该过程
var
vWord,vDoc: Variant;
i,h,y,name1,name2:Integer;
begin
vWord := CreateOleObject('Word.Application') ;//创建Word线程
try
vDoc := vWord.Documents.Open(folderName + str_filename+'.doc');
with DataCon.ADOQuery1do
begin
close;
sql.Clear;
sql.Add('select * from '+str_tablename+' where CrediteyesNO='+''''+str_id+'''');
open;
h:=Fields.Count;
name1:=fieldbyname('省份').FieldNo-1;
name2:=fieldbyname('城市').FieldNo-1;
end;
vdoc.tables.Add(vDoc.Bookmarks.Item('m').Range,h-1,2);
for i := 1 to h-1do
begin
vDoc.Tables.Item(1).Cell(i, 1).Width:=130;//120
vDoc.Tables.Item(1).Cell(i, 1).height:=19;
vDoc.Tables.Item(1).Cell(i, 2).Width:=314;//324
vDoc.Tables.Item(1).Cell(i, 2).height:=19;
vdoc.Tables.Item(1).Cell(i,1).Range.text:=DataCon.ADOQuery1.Fields.FieldName;
vdoc.Tables.Item(1).Cell(i,2).Range.text:=DataCon.ADOQuery1.Fields.AsString;
vdoc.Tables.Item(1).Cell(i,1).Range.ParagraphFormat.Alignment:= taLeftJustify;
end;

y:=0;
for i := 1 to h-1do
begin
if (i=name1) or (i=name2) then
begin
vDoc.Tables.Item(1).Cell(i-y,2).delete;
vDoc.Tables.Item(1).Cell(i-y,1).delete;
y:=y+1;
Continue;
end;

if DataCon.ADOQuery1.Fields.DataType<>ftString then
begin
if DataCon.ADOQuery1.Fields.Value=null then
begin
vDoc.Tables.Item(1).Cell(i-y,2).delete;
vDoc.Tables.Item(1).Cell(i-y,1).delete;
y:=y+1;
end;
end;
if (DataCon.ADOQuery1.Fields.DataType=ftString) or (DataCon.ADOQuery1.Fields.DataType=ftMemo) then
begin
if (DataCon.ADOQuery1.Fields.Value=null) or (DataCon.ADOQuery1.Fields.Value='') then
begin
vDoc.Tables.Item(1).Cell(i-y,2).delete;
vDoc.Tables.Item(1).Cell(i-y,1).delete;
y:=y+1;
end;
end;
end;
//end for
vWord.Selection.Font.Bold :=True;
finally
vdoc.saveas(templateName+str_filename+'.doc');
vDoc.Close(True) ;
//关闭文并保存
vWord.Quit(False) ;
//退出Word
end ;
end;

.......

procedure TFrmBuildWord.Button1Click(Sender: TObject);
var
str_id,id,str_tablename,str_filename:string;
i:integer;
aCheckBox:TCheckBox;
vDoc: Variant;
begin
if CheckBox1.Checked=TRUE then
//报告资料
begin
str_id:=NO;
id:=Rid;
str_tablename:='R报告记录表';
str_filename:='报告资料';
fenxiword(str_id,id,str_tablename,str_filename,folderName,templateName,zl);
end;

if CheckBox2.Checked=TRUE then
//联络资料
begin
str_id:=NO;
str_tablename:='B联络资料';
str_filename:='联络资料';
llzlword(str_id,str_tablename,str_filename,folderName,templateName);
end;

''''''
WordApplication1 := TWordApplication.Create(Application);
wordapplication1.Connect;
wordapplication1.Visible:=true;
wordapplication1.Documents.Add(EmptyParam,EmptyParam,EmptyParam,EmptyParam);
worddocument1.ConnectTo(wordapplication1.ActiveDocument);
wordapplication1.ChangeFileOpenDirectory(templateName);
For i:= 1 to 29do
begin
aCheckBox:=(FindComponent('CheckBox' + IntToStr(i)) as TCheckBox);
if aCheckBox.Checked=true then
begin
wordapplication1.Selection.InsertFile(aCheckBox.Caption+'.DOC',EmptyParam,EmptyParam,EmptyParam,EmptyParam);
end;
end;
ProgressBar1.Position :=100;
end;

procedure TFrmBuildWord.WordApplication1Quit(Sender: TObject);
var
savechanges, originalformat, routedocument: olevariant;
begin
savechanges := wddonotsavechanges;
originalformat := unassigned;
routedocument := unassigned;
try
wordapplication1.quit(savechanges, originalformat, routedocument);
wordapplication1.disconnect;
except
on e: exceptiondo
begin
showmessage(e.message);
wordapplication1.disconnect;
end;
end;
end;

''''''
我希望每个 if CheckBox1.Checked=TRUE then

begin
str_id:=NO;
id:=Rid;
str_tablename:='R报告记录表';
str_filename:='报告资料';
fenxiword(str_id,id,str_tablename,str_filename,folderName,templateName,zl);
end;
。。都是一个线程,那么时间将大大缩减!
问这样的线程如何创建,线程中可以引用定义的函数和过程吗?请明示!

 
这是一个曾经探讨的问题,但无结果,最后模糊总结:
程序可以多线程,但程序调用 word 或者 ole调用是外部 的 进程,
你的程序可能 无法控制的吧 !
 
你可以查看你的CPU占用率,只有在进行操作的时候CPU占用一直比较低,多线程才有意义,而我觉得CPU占用应该一直是比较高的
WORD的自动化操作本身就不快
vWord := CreateOleObject('Word.Application') ;//创建Word线程
try
vDoc := vWord.Documents.Open(folderName+str_filename+'.doc');
这些创建Word.Application 打开Word.Document文件的操作更加缓慢。你可以尝试只是打开Word.Application/Word.Document,对文档不做任何操作,这同样也很缓慢的。我觉得时间的浪费主要就在这里。而这里采用多线程也不能改变什么。
这种操作模式本身就没有太好的解决方法.
如果你能够给客户一个合适的进度提示,我想客户是可以接受的。
 
后退
顶部