tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板)
VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板)
[ツリー表示へ]  [ワード検索]  [Home]

タイトル Re: 掛線を書いて、EXCELを終了
投稿日: 2004/07/22(Thu) 01:49
投稿者魔界の仮面弁士
1000番!

> '現在、アクティブなシートを取得する
> objsheet = objApp.ActiveSheet
今回の「プロセスが残る問題」とは、直接関係ありませんが、
ワークシートは、「Excelアプリ」ではなく、「ワークブック」に所属していますので、
「objsheet = objbook.ActiveSheet」の方が適切かと思います。

# ただし、objApp.ActiveSheet の場合は、objbook 以外のシートが取得される可能性も
# ありえますので、厳密に言えば、objbook.ActiveSheet とは別の意味となりますけれどね。

なお、ActiveSheetが返すシートは、ワークシートとは限りませんので(チャートシートの可能性がある)、
シート名等が分かっている場合は、objbook.Worksheets("Sheet1") などの方が良いかも知れません。


> '掛線を引く
> objBorders = _
> objsheet.Cells(1, 1).Borders
> objBorders.LineStyle = Excel.XlLineStyle.xlContinuous
原因はここです。ReleaseComObjectされていないオブジェクトがありますよ。


先の分も含めて修正すると、このようになります。
なお、Option Strict Onに備え、"As Object"な物は、DirectCastでキャストしてあります。

  Dim objCells As Excel.Range
  Dim objRange As Excel.Range
  objsheet = DirectCast(objbook.ActiveSheet, Excel.Worksheet)
  objCells = objsheet.Cells
  objRange = DirectCast(objCells._Default(1, 1), Excel.Range)
  objBorders = objRange.Borders
  objBorders.LineStyle = Excel.XlLineStyle.xlContinuous
  System.Runtime.InteropServices.Marshal.ReleaseComObject(objCells)
  objCells = Nothing
  System.Runtime.InteropServices.Marshal.ReleaseComObject(objRange)
  objRange = Nothing

このコードであれば、プロセスが残る事はありませんでした。(Excel 2002 + VB.NET 2002)


この時、『Cellsプロパティ』の動作に注意してください。もしも上記を、
  Dim objRange As Excel.Range
  objsheet = DirectCast(objbook.ActiveSheet, Excel.Worksheet)
  objRange = DirectCast(objsheet.Cells(1, 1), Excel.Range)
  objBorders = objRange.Borders
  objBorders.LineStyle = Excel.XlLineStyle.xlContinuous
  System.Runtime.InteropServices.Marshal.ReleaseComObject(objRange)
  objRange = Nothing
にした場合は、プロセスが残る結果となりました。

# ただし、
#    objRange = DirectCast(objsheet.Cells(1, 1), Excel.Range)
# ではなく、
#    objRange = objsheet.Range("A1")
# ならば、プロセスは残りません。


さて、Cellsプロパティについてもう少し書いておきます。

実は、
  objsheet.Cells(1, 1)
というのは、
  objsheet.Cells._Default(1, 1)
の省略表記となります。

つまり、Cells(1, 1) という操作の場合、
  objRange = objsheet.Cells(1, 1)
と書くのではなく、
  objCells = objsheet.Cells
  objRange = DirectCast(objCells(1, 1), Excel.Range)
のように、.Cells が返すRangeオブジェクトと、
._Default が返すRangeオブジェクトとは、別々にわけて変数に取り、
それぞれを ReleaseComObject しないといけないわけです。

これは、
   objBook = objApp.Workbooks(1)
ではなく、
   objBooks = objApp.Workbooks
   objBook = objBooks._Default(1)  'または、「objBook = objBooks(1)」
などと管理しなければならないのと、同じ理由による物です。


> 'ガーベジコレクト起動
> GC.Collect()
これを呼んだとしても、Excelのプロセスが残ってしまう件の解決とはなりません。

COMコンポーネントのメモリ管理と、.NETのメモリ管理は別物ですから、
"garbage collect"したからといって、Excelが解放されるという保障は無いのです。

根本的な解決は、「全てのCOMオブジェクトを ReleaseComObject する事」となります。
hhttp://blogs.users.gr.jp/hidori/archive/2004/01/26/916.aspx

- 関連一覧ツリー をクリックするとツリー全体を一括表示します)

古いスレッドにレスはつけられません。