• ベストアンサー

.NETでエクセル解放時のコーディング・現象についてアドバイスください

AKARI0418の回答

  • AKARI0418
  • ベストアンサー率67% (112/166)
回答No.3

参考になると思います。 http://hanatyan.sakura.ne.jp/dotnet/Excel03.htm きちんとすべての対象にReleaseComObjectを呼んでいるのであれば、 GC.Collect()は必要ないはずです。 GC.Collect()を行わなければ、EXCELが残ってしまうというのは、開放もれがあるはずです。 クラスを経由して行っている場合はその親クラスにあたるインスタンスに対しても、ReleaseComObjectが必要です。 むやみにガベージコレクタに対して、Collectを発行するべきではありません。 GCはジェネレーション管理を行っており、Collectにより世代がどんどん増えていってしまい負荷がかかります。 http://www.atmarkit.co.jp/fdotnet/dotnettips/021gc/gc.html

camputer
質問者

お礼

 AKARI0418 様  ご親切にどうもありがとうございます.  自分のコードをすべて,リンクしていただいたページの書き方に直したところ コードの半分が解放できました.どうもありがとうございます. 自分の思い込みで勝手に解放できないように修正してしまっていたようです. 今までは,質問文にかかせていただいたような    Dim xlSheet As Excel.Worksheet    Dim ChartObject As Object    Dim ChartObjects = xlSheet.ChartObjects    For Each ChartObject In ChartObjects      Dim myChart As Object = ChartObject.Chart      Dim myAxes As Object = myChart.Axes      Dim myAxis1title As Object = myAxes(1).Axistitle という書き方をしておりましたのを,花ちゃんのようにExcel.Axisとして解放されました.    Dim MyAxis As Excel.Axis    Dim MyAxes As Excel.Axes    MyAxes = MyChart.Axes    For Each MyAxis In MyAxes  何故か前者のような書き方でも解放されている個所もありますが, すべて後者に直しました.  以前参考書か何かで「コードの途中でExcel.~と書くと知らないうちに2つ目の Applicationオブジェクトを参照して~解放できなくなる.」というのを 読んだ覚えがありまして,コードをすべて前者のように書き換えておりましたのが原因のようです.  ブラウザの履歴にも残っておりましたが,まったく目が届いておりませんでした.  非常に沢山のアドバイスをいただきどうもありがとうございました. 現時点でもまだ解放できない部分がありますが,おそらく別の要因だと思われるので, また別スレッドで質問させていただきます.  本当にご親切にどうもありがとうございました.

関連するQ&A

  • .NETでエクセル解放がうまくいきません.

     ネット上で散々ある良回答を拝見させていただいても, 自分で解決しきれませんでした.どうぞよろしくお願いいたします.  下の2行を追加するとエクセルが解放できなくなってしまいます. Private Sub Excel一括置換(ByRef N As Integer) Dim xlApp As New Excel.Application Dim xlBooks As Excel.Workbooks = xlApp.Workbooks Dim WB As Excel.Workbook Dim xlSheet As Excel.Worksheet Dim Mypath As String = TextBoxパス.Text Dim FName As String FName = Dir(Mypath & "*.xls", vbNormal) Do While FName <> "" WB = xlBooks.Open(Mypath & FName) For Each xlSheet In WB.Worksheets 'For N_s = 1 To WB.Worksheets.Count Next 'Next N_s ' ↑の2行がなくなれば無事解放できます MRComObject(xlSheet) : xlSheet = Nothing WB.Save() : WB.Close() MRComObject(WB) FName = Dir() Loop Me.Activate() xlSheet = Nothing WB = Nothing MRComObject(xlBooks) : xlBooks = Nothing xlApp.Quit() : MRComObject(xlApp) : xlApp = Nothing End Sub  最初の「For N_s = 1 To WB.Worksheets.Count」という書き方だと, ネット上で見かけるWorksheet「暗黙のオブジェクト」になるのかな??と思い, xlSheetを宣言してみましたが,うまくいきません. できればFor N_s = ~ という記述法にしたいのですが...  お詳しい方がいらっしゃれば,どうぞよろしくお願いいたします.

  • (再質問) .NETでエクセル解放に悩んでおります.

     数個前のスレッドで勘違いして,締め切らせていただきました. 申し訳ございません.未解決で同じ質問をさせてください.  コードの流れといたしましては,  エクセル操作  ↓  エクセル解放  ↓  ←下記2行のコードが無ければ,この時点でExcel.exeは消えています.  MsgBox("終了")   ↓  アプリケーションを右上の×マークから終了(下記2行のコードを入れると,Excel.exeがギリギリまで残っております.)       Dim xlApp As New Excel.Application Dim xlBooks As Excel.Workbooks = xlApp.Workbooks Dim WB As Excel.Workbook Dim xlSheets As Excel.Worksheets Dim xlSheet As Excel.Worksheet Dim Mypath As String = TextBoxパス.Text Dim FName As String FName = Dir(Mypath & "*.xls", vbNormal) Do While FName <> ""   WB = xlBooks.Open(Mypath & FName)   For Each xlSheet In WB.Worksheets   Next  ' ↑の2行がなくなれば無事解放できます   WB.Save() : WB.Close()   MRComObject(WB)   FName = Dir() Loop Me.Activate() MRComObject(xlSheet) : xlSheet = Nothing MRComObject(xlSheets) : xlSheets = Nothing WB = Nothing MRComObject(xlBooks) : xlBooks = Nothing xlApp.Quit() : MRComObject(xlApp) : xlApp = Nothing MsgBox("終了")  先ほどのスレッドでアドバイス・指摘していただいた部分とあわせて 色々試してみましたが,自分では怪しそうな個所を見つけることすらできません... 暗黙宣言やNothing,Quit等ネットで見かけるものは一通り試したつもりなのですが...  もしお詳しい方がいらっしゃれば,些細なことでも結構ですので なんでもアドバイスいただければ非常にうれしいです.  どうぞよろしくお願いいたします.

  • VB.NET Excelの解放

    Excel出力の解放について質問です。 下記URLを参考に作成しましたが、出力をし終えたときにプロセスを見るとExcelの解放がされません。 http://hanatyan.sakura.ne.jp/dotnet/Excel01.htm 助言をもらえないでしょうか? With SaveFileDialog1 .FileName = savefilename If .ShowDialog() = Windows.Forms.DialogResult.OK Then wstrPath = .FileName() If Func_Excelチェック(wstrPath) = False Then Exit Function End If End If End With Dim excel As New Excel.Application Dim xlbooks As Excel.Workbooks = excel.Workbooks Dim xlbook As Excel.Workbook = xlbooks.Add Dim xlsheets As Excel.Sheets = xlbook.Worksheets Dim xlsheet As Excel.Worksheet = xlsheets.Item(1) Dim xlCells As Excel.Range Dim xlRange1 As Excel.Range xlCells = xlsheet.Cells Dim i As Integer = 1 作成データテーブルに接続 xlRange1 = xlCells(1, 1) xlRange1.Value = "工場番号" MRComObject(xlRange1, True) While sqlReader.Read xlRange1 = xlCells(i + 1, 1) xlRange1(xlCells(i + 1, 1)).Select() xlRange1.Value = sqlReader("入力_工場番号") MRComObject(xlRange1, True) i += 1 End While excel.DisplayAlerts = False xlsheet.SaveAs(wstrPath) 'Select Case Val(excel.Version) 'Case 9 'xlbook.SaveAs(Filename:=wstrPath) 'Case 12 'xlbook.SaveAs(Filename:=wstrPath, FileFormat:=56) 'End Select 'MRComObject(xlsheet, True) excel.DisplayAlerts = True MRComObject(xlsheet)'xlSheet の解放 MRComObject(xlsheets)'xlSheets の解放 xlbook.Close()'xlBook を閉じる MRComObject(xlbook)'xlBook の解放 MRComObject(xlbooks)'xlBooks の解放 excel.Quit()'Excelを閉じる MRComObject(excel)'excel を解放 Private Function Func_Excelチェック(ByVal arg As String) As Boolean Dim excel As New Excel.Application Dim xlbooks As Excel.Workbooks = excel.Workbooks Dim xlbook As Excel.Workbook excel.Visible = False excel.Application.DisplayAlerts = False Try If System.IO.File.Exists(arg) = True Then xlbook = xlbooks.Open(arg) xlbook.SaveAs(arg, FileFormat:=42, CreateBackup:=False) MRComObject(xlbook, True) Return True Else Return True End If Catch ex As Exception MessageBox.Show("") Return False Finally xlbooks.Close() MRComObject(xlbooks, True) excel.Quit() MRComObject(excel, True) End Try End Function

  • エクセルの開放

    VB2008でエクセルを操作しているのですが、エクセルのプロセスが残ってしまってどうやって解放すればいいのかわかりません。 サンプルプログラム-------------- Dim xlApp As New Excel.Application Dim xlBooks As Excel.Workbooks = xlApp.Workbooks Dim xlBook As Excel.Workbook = xlBooks.Add Dim xlSheets As Excel.Sheets = xlBook.Worksheets Dim xlSheet As Excel.Worksheet = xlSheets.Item(1) Dim xlobj As Object '開放用 xlobj = xlSheet.Range("A1:C3") xlobj.Value = "TEST" MRComObject(xlobj) MRComObject(xlSheet) MRComObject(xlSheets) xlBook.Close(False) MRComObject(xlBook) MRComObject(xlBooks) xlApp.Quit() MRComObject(xlApp) MRComObjectでCOM オブジェクトへの参照を解放しています。 このプログラムでは特に問題ないのですが、 xlobj = xlApp.Worksheets("Sheet2") xlobj2 = xlobj.Range("A1:C2") xlobj2.Value = "TEST" のようにワークシートを指定すると解放できません。 xlSheet = xlBook.Worksheets("Sheet2") としてもプロセスが残ります。 またVB6.0では可能だった xlApp.Worksheets("Sheet2").Select() のようにワークシートを切り替えるときもVB2008ではプロセスが残ってしまいます。 これはどのようにしたら解決するのでしょうか?

  • EXCELのグラフ

    下のようにVBからExcel にデータを送りグラフを表示しています。 印刷プレビューを表示したときにグラフと表が表示されてしまいます。グラフだけを表示して表は表示をしたくないのですが どうすればいいのでしょうか お願いします。 Private Sub Command1_Click() Dim xlApp As Excel.Application Dim xlBook As Excel.Workbook Dim xlSheet As Excel.Worksheet Set xlApp = CreateObject("Excel.Application") Set xlBook = xlApp.Workbooks.Add Set xlSheet = xlBook.Worksheets.Add Dim i As Integer Dim j As Integer For i = 2 To 6 For j = 2 To 6 xlSheet.Cells(j, i) = CInt(71 * Rnd + 30) Next j Next i xlSheet.Cells(2, 1) = "国語" xlSheet.Cells(3, 1) = "数学" xlSheet.Cells(4, 1) = "英語" xlSheet.Cells(5, 1) = "社会" xlSheet.Cells(6, 1) = "体育" xlSheet.Cells(1, 2) = "石原" xlSheet.Cells(1, 3) = "小泉" xlSheet.Cells(1, 4) = "田中" xlSheet.Cells(1, 5) = "平沼" xlSheet.Cells(1, 6) = "森山" Dim MyChart As ChartObject Set MyChart = xlSheet.ChartObjects.Add(10, 100, 600, 330) With MyChart.Chart .SetSourceData xlSheet.Range("A1:F6"), xlColumns .Axes(xlValue).MaximumScale = 100 .Axes(xlValue).MajorUnit = 20 .HasTitle = True .ChartTitle.Text = "中間テスト結果" .ApplyDataLabels (xlDataLabelsShowValue) .Location xlLocationAsObject, xlSheet.Name End With xlApp.Visible = True With xlSheet.PageSetup .PaperSize = xlPaperA4 .Orientation = xlPortrait .LeftMargin = xlApp.CentimetersToPoints(2) .RightMargin = xlApp.CentimetersToPoints(2) .TopMargin = xlApp.CentimetersToPoints(2.5) .BottomMargin = xlApp.CentimetersToPoints(2.5) .HeaderMargin = xlApp.CentimetersToPoints(1) .FooterMargin = xlApp.CentimetersToPoints(1) End With xlSheet.PrintPreview Set MyChart = Nothing Set xlSheet = Nothing Set xlBook = Nothing Set xlApp = Nothing End Sub

  • Excelオブジェクトの解放

    VBでExcelを編集しています。 下記コードを実行するとExcelがタスクに残ったままになります。 どうしたら解放されるでしょうか。 (処理は少し省略しています) Dim objExcel as Object Dim objExcelBook as Object Dim objExcelSheet as Object Set objExcel = CreateObject("excel.application") Set objExcelBook = objExcel.Workbooks.Open(パス, 0) Set objExcelSheet = objExcelBook .Sheets(シート名) With objExcelSheet.Range(Cells(1,2),Cells(3,2)).Borders(xlEgeBottom) .LineStyle = xlContinuous End With Set objExcelSheet = Nothing Set objExcelBook = Nothing Set objExcel = Nothing

  • vb2008で操作中のエクセルが解放されてない?

     質問させていただきます.どうぞよろしくお願いします.  vb2008で,エクセル操作をするアプリケーションの作成を試みております. コードの流れとしましては,  エクセル操作   ↓  オブジェクト・アプリケーション解放   (自分的にはここでタスクマネージャからExcel.exeが              消えると思うのですが,残ります)   ↓  メッセージボックス「終了」   ↓  アプリケーションを右上の×マークで閉じる   (タスクマネージャからExcel.exeが消えます) となります.  色々なページを参考にさせていただいて,Excelが解放されるように したつもりなのですが,VBアプリケーション終了ギリギリまで 存在し続けるという事は,うまく解放できていないということなのでしょうか?  作成したコードは以下のようになります. (バグ取り中に,エクセル操作部分のコードはほとんど消去してみました. しかしまだ上記のような現象になっております) Private Sub ButtonA_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonA.Click Dim N_e As Integer Call Excel一括置換(N_e) MsgBox("終了" ) End Sub Private Sub Excel操作(ByRef N As Integer) Dim xlApp As New Excel.Application Dim xlBooks As Object Dim WB As Object Dim Rng As Object '================== 終了処理 ===================== Rng = Nothing : MRComObject(Rng) WB = Nothing : MRComObject(WB) xlBooks = Nothing : MRComObject(xlBooks) xlApp.Quit() : xlApp = Nothing : MRComObject(xlApp) End Sub Public Shared Sub MRComObject(Of T As Class)(ByRef objCom As T, Optional ByVal force As Boolean = False) If objCom Is Nothing Then Return End If Try If System.Runtime.InteropServices.Marshal.IsComObject(objCom) Then If force Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objCom) Else Dim count As Integer = System.Runtime.InteropServices.Marshal.ReleaseComObject(objCom) Debug.WriteLine(count) End If End If Finally objCom = Nothing End Try End Sub  何か些細なことでもご指摘いただければ非常に助かります. どうぞよろしくお願いたします.

  • グラフの表示

    VB6.0 ACCESS2000で開発しています。 下の様にACCESSからデータを読んでEXCELでグラフを表示して プレビューへ表示しています。 プレビューを表示した後、印刷してEXCELを閉じる。 又は、印刷せずに閉じた場合でも画面上はEXCELは閉じているのですが プロセスに残ってしまいます。 どこが悪いのでしょうか? よろしくお願いします。 Private Sub Command1_Click() Dim ExcelApp As Object 'Excel.Application Dim Book As Object 'Excel.Workbook Dim Sheet As Object 'Excel.Worksheet Dim cn As ADODB.Connection Dim rst As ADODB.Recordset Set cn = New ADODB.Connection cn.ConnectionString = _ "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=C:\temp\db2.mdb" cn.Open Set rs = New ADODB.Recordset rs.Source = SELECT = "SELECT = "SELECT 商品名, 単価 FROM m_品名 rs.ActiveConnection = cn rs.CursorType = adOpenStatic rs.Open Set ExcelApp = CreateObject("Excel.Application") Set Book = ExcelApp.Workbooks.Add Set Sheet = Book.Worksheets(1) Sheet.Cells(1, 1).CopyFromRecordset rst Dim MyChart As ChartObject Set MyChart = Sheet.ChartObjects.Add(10, 100, 600, 330) With MyChart.Chart .SetSourceData Sheet.Range(Range("A1:B1"), Range("A1:B1").End(xlDown)), xlColumns .ChartType = xlBarClustered .Axes(xlValue).MaximumScale = 350 .Axes(xlValue).MajorUnit = 50 .HasTitle = True .ChartTitle.Text = "案件実績合計" .ApplyDataLabels (xlDataLabelsShowValue) '.SeriesCollection(1).ApplyDataLabels (xlDataLabelsShowValue) .Location Where:=xlLocationAsNewSheet End With ExcelApp.Visible = True Book.ActiveSheet.PrintPreview Book.Close ExcelApp.Quit Set Sheet = Nothing Set Book = Nothing Set ExcelApp = Nothing Set rst = Nothing Set cn = Nothing End Sub

  • VB.NETからEXCELの起動が、うまくいかない

    3回目の同じ質問になってしまうのですがよろしくお願いいたします。 下記のようなソースでEXCELファイルを作成し、その後ファイルを開くという処理をしています。 Dim xlApp As New Excel.Application Dim xlBooks As Excel.Workbooks = xlApp.Workbooks Dim xlBook As Excel.Workbook = xlBooks.Add Dim xlSheets As Excel.Sheets = xlBook.Worksheets Dim xlSheet As Excel.Worksheet = xlSheets.Item(1) Dim xlRange As Excel.Range Dim xlCells As Excel.Range = xlSheet.Cells xlRange = xlCells(1, 10) xlRange.Value = "--" xlRange = xlCells(1, 5) xlCells.EntireColumn.AutoFit() xlBook.SaveAs(sPath & "\" & sFileName, Excel.XlFileFormat.xlWorkbookNormal) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlCells) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlRange) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlSheet) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlSheets) xlCells = Nothing xlRange = Nothing xlSheet = Nothing xlSheets = Nothing xlBook.Close() System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlBook) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlBooks) xlBook = Nothing xlBooks = Nothing xlApp.Quit() System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlApp) xlApp = Nothing GC.Collect() System.Diagnostics.Process.Start(sPath & "\" & sFileName) ある特定のPCでのみEXCELのメニューバーとステータスバーのみしか表示されない状態です。 起動部分(Process.Start)をコメントアウトして確認したところ GC.COLLECTでEXCELが終了することなく、アプリの終了時にEXCELが終了する 状態にあります。 これはオブジェクトの開放がうまくいっていないのでしょうか? よろしくお願いいたします。

  • ExcelのVBAでメモリ解放できない

    以下のようなプログラムで、ExcelVBAで作成しております、Webの情報を取得しております。 strGetUrl のところのサイトによっては、メモリが解放できず困っています。 Whileで繰り返すほど、メモリを消費して解放されません。メモリいっぱいになれば解放してくれるのかと思いましたが、止まってしまいました。2回目はOSを壊して再インストールしてもらいました(VPS上で)。 困っております。オブジェクトも”Set xxxx = Nothing”で解放しているつもりです。 考えられる理由をご教授頂けると幸いです。 環境は OSはWindowsServer2008R2 IEはIE8 でVPSなので変更不可と言われました。 ちなみに、Windows8.1の環境ではメモリが溜まっていくことはなかったです。 何か良い方法はありますでしょうか? また、別のWebアクセス方法はありますでしょうか? IE = CreateObject("InternetExplorer.Application")は同じ結果でした。 以下のプログラムでサイトにもよりますが、発生しています。 *********************************** Option Explicit Sub testHtml() Dim doc As Object, objTag1 As Object, objTag2 As Object Dim oHttp As Object Dim strUrl As String, strGetUrl As String Dim rowIndex As Integer ' 基本URL設定 strGetUrl = "http://www.xxxx.xxx.com" rowIndex = 1 '1列目が1行づつ進めてが空になったら終了 While Cells(rowIndex, 1).Value <> "" Set oHttp = CreateObject("MSXML2.XMLHTTP") Set doc = CreateObject("htmlfile") ' *************** HTTPヘッダの作成し、送信してデータを取得 ***************** With oHttp .Open "GET", strGetUrl, False .Send ' 受信したデータをオブジェクトに書き込みます。 doc.Write .responseText End With ' *************** 受信データを解析し、H2データ取得に分割 ***************** For Each objTag1 In doc.body.getElementsByTagName("H2") If objTag1.className = "resultCount" Then Cells(rowIndex, 2).Value = objTag1.innerText End If Next ' Objectの解放 Set objTag1 = Nothing Set objTag2 = Nothing Set doc = Nothing Set oHttp = Nothing rowIndex = rowIndex + 1 Wend End Sub