はじめまして
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;
すみません。環境依存は少ないと思いますが、試しているのはDelphi10.1、Windows7 または WindowsServer2012R2Std です。
関係ないかもしれませんが、
Excel := CreateOleObject('EXCEL.Application');
の後に、
Excel.Visible := True;
を、
finallyの前に、
ExcelBook.Close(SaveChanges:=False);
を
置いてみた場合でも、結果は同じですか?
回答ありがとうございます。
試してみましたが、EXCELプロセスは相変わらず残ったままです。
なお、上記コードを試すには
uses ComObj;
が必要ですね。申し訳ありません。
vrange は variant配列なのに適当な開放をしているせいでしょうか?
全体を 無名メソッドでスレッド化すればいいんじゃないか?(適当)
と思いトライしてみましたが、無名メソッドスレッドの中では
CreateOleObject('EXCEL.Application');
が失敗します ^ ^;
workSheet.cells[1, 1],workSheet.cells[10, 10]で取得してるオブジェクトが解放されてないんじゃないかと。
変数で受けてあげれば終了しませんか?
それか、formatかなんかで文字列でセル範囲を指定するようにするか
auさん、まさに私もそれを想像したのですが、
vrange :=unassinged; も
finalize(vrange);も
効果なしでした。
是非開放の仕方を教えてください!!!
いや、workSheet.Rangeで返ってくるオブジェクトだけでなく、Rangeの引数に渡してるCellsの方のオブジェクトもです。
こっちで実験してみた感じだとそれでExcel終了しました
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;
> どうしてもセーブダイアログが出ます。
>ExcelBook := Unassigned;
の前に、
ExcelBook.Close(SaveChanges:=False);
を
置いてみた場合、どうなりますか?
var
Cell1, Cell2: OleVariant;
略
Cell1 := workSheet.cells[1, 1];
Cell2 := workSheet.cells[10, 10];
vrange := workSheet.Range[Cell1, Cell2].value;
Cell1 := Unassigned;
Cell2 := Unassigned;
とかだとどうでしょう
ちょっとやってみました.
質問された方が提示したコードを実行してみました.
全て Windows 7 U64(SP1) + Excel 2010 の結果です.
Delphi XE(UP1) Por --> プロセス EXCEL.EXE は残りません
Delphi 10.1 Berlin Starter --> プロセス EXCEL.EXE が残りました.
au さんのように Range オブジェクトを分けたら,
どちらの Delphi で作成した EXE でもプロセスは残りませんてした.
Unassigned を実行しなくてもプロセスが残ることはありませんでした.
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プロセスが消えてくれました。
重ねて御礼申し上げます。
ツイート | ![]() |