CreateOleObject で EXCEL を開いた後プロセスが残ってしまう

解決


螺子まき  2017-02-08 19:52:48  No: 48530

はじめまして

EXCELをCreateOleObject で開いた後開放してもダミープロセス?が残ってしまう現象に悩んでいます。
下記に再現コードを載せます。
このままだとプロセスは残りません(タスクマネージャを開いて観察しています)
しかし、★1,2のコメントをはずすとプロセスが残ったままになります。(プログラムを終了すると消えます)
★のコードは高速にアクセスする常套手段のようです。■のコードでアクセスするより2桁ほど早いです。
想像しますに、variantの開放がうまくできていないのではないかとおもいますが回避手段がわかりません。
どうか宜しくお願いします。

procedure TForm1.Button1Click(Sender: TObject);

var
  Excel: OleVariant;
  excelApp, ExcelBook, workSheet: OleVariant;
  vrange: Variant;
  MaxRow: Integer;
  Ctmp: Variant;
begin
  Excel := CreateOleObject('EXCEL.Application');

  try
    excelApp := Excel.application;

    ExcelBook := excelApp.WorkBooks.Open('C:\temp\test.xlsx', False);
    workSheet := ExcelBook.WorkSheets[1];
    // vrange := workSheet.Range[workSheet.cells[1, 1], workSheet.cells[10, 10]].value;  //★2
    Ctmp := workSheet.Cells[1, 1].value; //■
    Memo1.Lines.Add(vartoStr(Ctmp));
    sleep(500);

  finally

    excelApp.Quit;
    Excel := Unassigned;

    excelApp := Unassigned;
    ExcelBook := Unassigned;
    workSheet := Unassigned;
    // vrange := Unassigned;    //★1

  end;

end;


螺子  2017-02-08 19:55:04  No: 48531

すみません。環境依存は少ないと思いますが、試しているのはDelphi10.1、Windows7 または WindowsServer2012R2Std です。


igy  2017-02-08 22:12:43  No: 48532

関係ないかもしれませんが、

Excel := CreateOleObject('EXCEL.Application'); 
の後に、
Excel.Visible := True;
を、

finallyの前に、
ExcelBook.Close(SaveChanges:=False);

置いてみた場合でも、結果は同じですか?


螺子まき  2017-02-09 00:20:27  No: 48533

回答ありがとうございます。

試してみましたが、EXCELプロセスは相変わらず残ったままです。

なお、上記コードを試すには
uses ComObj;
が必要ですね。申し訳ありません。

vrange は  variant配列なのに適当な開放をしているせいでしょうか?


螺子まき  2017-02-09 00:22:24  No: 48534

全体を 無名メソッドでスレッド化すればいいんじゃないか?(適当)
と思いトライしてみましたが、無名メソッドスレッドの中では
CreateOleObject('EXCEL.Application'); 
が失敗します ^ ^;


au  2017-02-09 00:54:12  No: 48535

workSheet.cells[1, 1],workSheet.cells[10, 10]で取得してるオブジェクトが解放されてないんじゃないかと。

変数で受けてあげれば終了しませんか?
それか、formatかなんかで文字列でセル範囲を指定するようにするか


螺子まき  2017-02-09 00:56:23  No: 48536

auさん、まさに私もそれを想像したのですが、
vrange :=unassinged;  も
finalize(vrange);も
効果なしでした。

是非開放の仕方を教えてください!!!


au  2017-02-09 01:38:40  No: 48537

いや、workSheet.Rangeで返ってくるオブジェクトだけでなく、Rangeの引数に渡してるCellsの方のオブジェクトもです。

こっちで実験してみた感じだとそれでExcel終了しました


螺子まき  2017-02-09 02:25:40  No: 48538

auさんありがとうございます

いろいろ試してみました。プロセスを消すことはできましたが変わりにどうしてもセーブダイアログが出ます。( readOnly で開いているのに!)

・・・どうかご教示願います。

procedure TForm1.Button1Click(Sender: TObject);

var
  excelApp, ExcelBook, workSheet: OleVariant;
  vrange: Variant;

begin

  try
    excelApp := GetActiveOleObject('Excel.Application');
  except
    excelApp := CreateOleObject('Excel.Application');
  end;

  try

    ExcelBook := excelApp.WorkBooks.Open(Filename := 'C:\temp\test.xlsx',  readOnly := True);
    //radonly なのになぜかセーブダイアログが出る!!
    workSheet := ExcelBook.WorkSheets[1];
    vrange := workSheet.Range[workSheet.cells[1, 1], workSheet.cells[10, 10]].value; // ★2

    sleep(500);

  finally

    //  この2行必須?
    workSheet.cells[1, 1] := Unassigned;  
    workSheet.cells[10, 10] := Unassigned;

    workSheet := Unassigned;

    ExcelBook := Unassigned;
    vrange := Unassigned; // ★1

    //下記2行どちらかがあるとセーブダイアログは出ないがプロセス残る
    // excelApp.DisplayAlerts := False;
    // excelApp.ActiveWorkBook.Saved:= 1;

    excelApp.Quit;
    excelApp := Unassigned;

  end;

end;


igy  2017-02-09 03:01:41  No: 48539

> どうしてもセーブダイアログが出ます。

>ExcelBook := Unassigned;
の前に、
ExcelBook.Close(SaveChanges:=False); 
を 
置いてみた場合、どうなりますか?


au  2017-02-09 03:10:25  No: 48540

var
  Cell1, Cell2: OleVariant;

  略
  Cell1 := workSheet.cells[1, 1];
  Cell2 := workSheet.cells[10, 10];
  vrange := workSheet.Range[Cell1, Cell2].value; 

  Cell1 := Unassigned;
  Cell2 := Unassigned;

とかだとどうでしょう


Mr.XRAY  2017-02-09 03:28:35  No: 48541

ちょっとやってみました.
質問された方が提示したコードを実行してみました.
全て Windows 7 U64(SP1) + Excel 2010 の結果です.

Delphi XE(UP1) Por --> プロセス EXCEL.EXE は残りません
Delphi 10.1 Berlin Starter --> プロセス EXCEL.EXE が残りました.

au さんのように Range オブジェクトを分けたら,
どちらの Delphi で作成した EXE でもプロセスは残りませんてした.
Unassigned を実行しなくてもプロセスが残ることはありませんでした.


螺子まき  2017-02-10 01:32:54  No: 48542

igy さん、Mr.XRAY さん、au さん
ありがとうございます。

キモは、

    C1 := workSheet.cells[1, 1];
    C2 := workSheet.cells[10, 10];
    vrange := workSheet.Range[C1,C2].value; 

    C1 := Unassigned;
    C2 := Unassigned;

ということですね。。。やっとEXCELプロセスが消えてくれました。
重ねて御礼申し上げます。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加