@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

VB.NET(ASP1.0) EXCELが開放されない

投稿者投稿内容
猫だいすき
常連さん
会議室デビュー日: 2007/04/09
投稿数: 27
お住まい・勤務地: 兵庫県
投稿日時: 2008-01-08 16:42
ASP.NET(VB)ver1.0 にて、ウェブアプリケーションの勉強を
しています。

やっていることは画面に入力した内容を既存のエクセルシート
(EXCEL2003)に出力する、というプログラムです。

下記ホームページを参考に開放ロジックを入れたのですが
開放もれがあるようで、EXCEL.EXEが残ってしまいます。
http://www.bcap.co.jp/hanafusa/dotnet/Excel01.htm#no2

ヘッダ部出力のxlRangeの4行をコメントすると正常に開放されます。
現在、エクセルは開放されませんが、シート内には値がセットされています。

悪い場所はxlRangeとわかっていますが、どのように対処したらよいのか
教えていただけたらと思います。
よろしくお願いします。

■プログラムソース(エクセル作成部分のみ抜粋)
-------------------------------------------------
    'エクセルを開く
    Dim Xls1 As New Excel.Application()
    Dim xlBooks As Excel.Workbooks = Xls1.Workbooks
    Dim xlBook As Excel.Workbook = xlBooks.Open(OutFile)
    Dim xlSheets As Excel.Sheets = xlBook.Worksheets
    Dim xlSheet As Excel.Worksheet = xlSheets.Item(1)
    Dim xlCells As Excel.Range = xlSheet.Cells
    Dim xlRange As Excel.Range

    '+------------+
    ' ヘッダ部出力
    '+------------+
    xlRange = Xls1.Range("I2")
    xlRange.Value = "作成日:" & Format(Now(), "yyyy/M/d").ToString
    xlRange = Xls1.Range("A3")
    xlRange.Value = Format(CDate(TextBox3.Text), "yyyy年M月")

    '================== ファイルの保存処理 ================== 
    Xls1.DisplayAlerts = False   '保存時の問合せのダイアログを非表示に設定
    xlSheet.SaveAs(OutFile)     'ファイルに保存
    Xls1.DisplayAlerts = True    '元に戻す
    '================== 終了処理 ===================== 
    MRComObject(xlCells)      'xlCells の解放
    MRComObject(xlRange)      'xlRange の解放
    MRComObject(xlSheet)      'xlSheet の解放
    MRComObject(xlSheets)      'xlSheets の解放
    xlBook.Close(False)       'xlBook を閉じる
    MRComObject(xlBook)       'xlBook の解放
    MRComObject(xlBooks)      'xlBooks の解放
    Xls1.Quit()           'Excelを閉じる
    MRComObject(Xls1)        'Xls1 を解放
  End Sub

  '====================================
  'COM オブジェクトへの参照を解放するプロシージャ(既存のファイルを開く場合も共用)
  '====================================
  Private Sub MRComObject(ByRef objCom As Object)
    'COM オブジェクトの使用後、明示的に COM オブジェクトへの参照を解放する
    Try
      '提供されたランタイム呼び出し可能ラッパーの参照カウントをデクリメントします
      If Not objCom Is Nothing AndAlso System.Runtime.InteropServices. _
                       Marshal.IsComObject(objCom) Then
        Dim I As Integer
        Do
          I = System.Runtime.InteropServices.Marshal.ReleaseComObject(objCom)
        Loop Until I <= 0
      End If
    Catch
    Finally
      '参照を解除する
      objCom = Nothing
    End Try
  End Sub
burton999
ぬし
会議室デビュー日: 2003/10/06
投稿数: 898
お住まい・勤務地: 東京
投稿日時: 2008-01-08 16:49
xlRange = Xls1.Range("I2")
を開放してないからでは?
猫だいすき
常連さん
会議室デビュー日: 2007/04/09
投稿数: 27
お住まい・勤務地: 兵庫県
投稿日時: 2008-01-08 16:58
burton999 様

早速の回答ありがとうございます。
なるほど!
セットするたびに開放してやらなければならないんですね。
試しに入れてみたら正常終了しました。
ありがとうございました♪
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2008-01-08 17:14
引用:

がおがおさんの書き込み (2008-01-08 16:42) より:

コード:

  '====================================
  'COM オブジェクトへの参照を解放するプロシージャ(既存のファイルを開く場合も共用)
  '====================================
  Private Sub MRComObject(ByRef objCom As Object)
    'COM オブジェクトの使用後、明示的に COM オブジェクトへの参照を解放する
    Try
      '提供されたランタイム呼び出し可能ラッパーの参照カウントをデクリメントします
      If Not objCom Is Nothing AndAlso System.Runtime.InteropServices. _
                       Marshal.IsComObject(objCom) Then
        Dim I As Integer
        Do
          I = System.Runtime.InteropServices.Marshal.ReleaseComObject(objCom)
        Loop Until I <= 0
      End If
    Catch
    Finally
      '参照を解除する
      objCom = Nothing
    End Try
  End Sub




この手のサンプルを見るといつも思うのですが、「管理外の参照カウント」 まで影響を及ぼして良いものでしょうか...

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
猫だいすき
常連さん
会議室デビュー日: 2007/04/09
投稿数: 27
お住まい・勤務地: 兵庫県
投稿日時: 2008-01-09 11:35
じゃんぬめっと様

>この手のサンプルを見るといつも思うのですが、「管理外の参照カウント」 まで影響を及ぼして良いものでしょうか...

「管理外の参照カウント」?ちょっとよくわからなかったので調べてみました。
http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/cpguide/html/cpconDeveloperBackgroundsInMemoryManagement.asp
<上記urlより抜粋>----------------------
オブジェクトの参照カウントが 0 になると、オブジェクトは破棄され、そのオブジェクトに割り当てられていたメモリは解放されます。
-----------------------------------------

現在の私の作成したプログラムでは、エクセルに出力して終了のため
問題ないと思われますが、本来はどのようにするべきなのでしょうか?

じゃんぬさんのHPの
http://jeanne.wankuma.com/tips/programing/releasecom.html
のようにTry〜Catchを使ったやり方で行わないといけないのでしょうか?

こういうやり方が良いというのがありましたら、ご指導願います(..)
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2008-01-09 15:41
批判なく書くのが難しいですが、参照カウントが 0 になるまで無条件でデクリメントするのではなく、自アプリケーションが使用した参照だけをデクリメントすべきだと考えています。 そのため 1 変数での参照は 1 度だけというルールを決めてその都度解放するのが行儀が良いと考えています。 逆にあのような実装にしなければいけないのはアプリケーション自身が使った参照を管理できていないということになると私は考えています。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
猫だいすき
常連さん
会議室デビュー日: 2007/04/09
投稿数: 27
お住まい・勤務地: 兵庫県
投稿日時: 2008-01-10 15:32
じゃんぬねっと様

前回の返信では、お名前を間違えていました。申し訳ありません。(u_u*)

>批判なく書くのが難しいですが、参照カウントが 0 になるまで無条件でデクリメントするのではなく、自アプリケーションが使用した参照だけをデクリメントすべきだと考えています。 そのため 1 変数での参照は 1 度だけというルールを決めてその都度解放するのが行儀が良いと考えています。 逆にあのような実装にしなければいけないのはアプリケーション自身が使った参照を管理できていないということになると私は考えています。

そうですね。確かに、全て(何でもかんでも?)開放しているロジックになっていますね。
「その都度開放する」というのは面倒くさいかもしれませんが、プログラムを作成する上では重要なことだと思います。
よくわかりました。
ありがとうございました。
また、お返事が遅くなり申し訳ありません。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2008-01-10 15:59
引用:

がおがおさんの書き込み (2008-01-10 15:32) より:

そうですね。確かに、全て(何でもかんでも?)開放しているロジックになっていますね。


うーん、もし興味があればこのあたりのスレッドをご覧ください。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=29278&forum=7&start=18

結局のところ面倒なので、私は COM 専門の言語を使うという選択をしたいです。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌

スキルアップ/キャリアアップ(JOB@IT)