2012-04-25 18 views
3

私はDelphiアプリケーションからWordオートメーションを使用していますが、非常に遅いです。私は自分のコードを最小限にとどめて、経験がある人が私がどこに間違っているか教えてくれることを願っていました(そして、私は実際にがうまくいき、Delphi XE2からWordオートメーションを高速化するには

私のアプリケーションのオートメーションの本質はブックマークを扱います。アプリケーションは、いくつかの特別なブックマークを持つ文書を開き、それらを実行し、名前に基づいて変更します。実際のバージョンでは、ドキュメント変数やフィールドコードも多用しています。典型的な文書には50-80個のブックマークがあり、そのうちのいくつかは入れ子になっています。私はまた、いくつかの一時的な文書を使用して、生成される文書に連続して配置されるテキストと画像のブロックを構築します。添付されたコードは、この機能を持たないVERYストリップされたバージョンですが、望ましくない動作(つまり、ドキュメントを生成する時間)を表示します。付属のサンプルでは、​​ドキュメントの生成に約2.5秒かかります。典型的な実際の文書の場合、約30〜40秒かかります。

私が望んでいるのは、誰かが「これはすべて間違っていると言いたいのですが、Word AutomationをDelphiから実行するときは、必ずXXXに覚えておく必要があります!

完全プロジェクトが完全に削除されてもかなり大きいので、この小さなアプリケーションを作成しました。私のやり方に明白な間違いがある場合は、このコードからはっきりと分かるはずです。

新しいVCLフォームアプリケーションを作成してください。 Wordを開いて、新しい文書を作成します。最初の行にテキストを入力し、マークを付けてブックマークを挿入します。 2行目にテキストを入力し、これもブックマークしてください。ファイルを 'c:\ temp \ bm.doc'としてWord 97-2003文書として保存します。アプリケーションを実行した後、最初の行に乱数を付けてブックマークを付けないで新しい文書( 'c:\ temp \ bm_generated.doc')を作成する必要があります。

unit Unit1; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, OleServer, WordXP, Vcl.StdCtrls; 

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    procedure Button1Click(Sender: TObject); 
    private 
    { Private declarations } 
    public 

    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    vWordApp : TWordApplication; 
    vDoc  : WordDocument; 
    vFileName : OleVariant; 
    vIndex  : OleVariant; 
    vBookmark : Bookmark; 
    vSave  : OleVariant; 
begin 
    vWordApp := TWordApplication.Create(nil); 
    try 
    vWordApp.ConnectKind := ckNewInstance; 
    vWordApp.Connect; 
    vFileName := 'c:\temp\bm.doc'; 
    vDoc := vWordApp.Documents.Open(vFileName, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam); 

    //Replace bookmark text with random string: 
    vIndex := 1; 
    vBookmark := vDoc.Bookmarks.Item(vIndex); 
    vBookmark.Range.Text := inttostr(random(10000)); //Will also delete the bookmark! 

    //Delete bookmark content and bookmark 
    vIndex := 1; //This will be the bookmark that was originally the first, since that was deleted when we sat the text 
    vBookmark := vDoc.Bookmarks.Item(vIndex); 
    vWordApp.Selection.SetRange(vBookmark.Range.Start, vBookmark.Range.End_); 
    vWordApp.Selection.Text := ''; 

    vFileName := 'c:\temp\bm_generated.doc'; 
    vDoc.SaveAs2000(vFileName, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam); 

    vWordApp.NormalTemplate.Saved := true; //For å slippe spørsmål om "normal.dot" skal lagres 
    vSave := wdDoNotSaveChanges; 
    vWordApp.Quit(vSave); 
    vWordApp.Disconnect; 
    finally 
    vWordApp.Free; 
    end; 
end; 

end. 
+0

ちょっとばかげて、文書を扱うたびに 'TWordApplication'インスタンスを保持するのか、新しいインスタンスを作成しますか?私はあなたがそれを守っていると確信しています。それが愚かな注釈としてマークされている理由です:-) – TLama

+0

そんなに愚かではありません。私は一度にいくつかのドキュメントを生成する場合、同じTWordApplicationを使用しますが、ほとんどの場合、そうではありません。これはERPアプリケーションの印刷ルーチンの一部なので、TWordApplicationを作成すると、印刷ダイアログにワード文書が生成されていることが示され、終了すると解放されます。 –

+1

そのコードは私によく見えます。おそらくそれはちょうどそれがどれくらいの時間かかります。 –

答えて

2

あなたは試みることができる:

vWordApp.ScreenUpdating := False; 

と多分また

vWordApp.Visible := False; 

を(終了後に以前の値に戻って設定することを忘れないでください)。

+2

投稿されたコードにはアプリケーションが表示されません。 –

+0

実際のバージョンでは、単語は見えません。しかし、剥奪されたバージョンでは、私はそれを含めなかった。 (しかし私はScreenUpdatingについて知らなかった、私もそれをテストするだろう) –

+0

いくつかの参照MS Word文書を生成するために必要な時間を考慮することができるいくつかのベンチマークを見ることは良いでしょう。 – truthseeker

0

あなたはVBAにパラメータを供給し、word内の置換を試したことがありますか?私は数年前にクライアント用のワード文書で数百のマクロをやった。それは私が覚えているものからはるかに速い実装でした。これはJavaコードベースからのものでした。

Wordは、最初にドキュメントの読み込みと解析に多くの時間を費やします。それは、大部分の時間が費やされた場所であろう。ブックマークの置き換えを行わないことで、タイミングテストのベースラインを設定します。もう1つのことは、おそらく各置換のフルテキストスキャンを実行していることです。それがVBAがうまくいった理由かもしれません。

+0

ブックマークなしで行うことは選択できません。また、AFAIK VBAはDelphiのようにオブジェクトモデルを使用しているため、速度に影響するとは思われません。 –

+0

うん、それはすべきではないが、それはそうだ。おそらく、Wordは毎回全環境をインスタンス化しています。私は確信していません、私はちょうどそれが問題への劇的な答えだったことを覚えています。毎回スレッドを反転していることを確認してください。そうすれば、通話をしてからApplication.HandleMessageを何度か呼び出すと改善できるかもしれません。それは多くの純粋主義者によるハックと考えられ、私はそれが時々有用であると主張しません。この回答のも​​う1つの部分は、アプリケーション間で行う往復の回数を制限することです。彼らのすべてが遅れを誘発します。 – Michael

関連する問題