| タイトル | : SeriesCollection.Add後、Excelのタスクが残る |  
| 記事No | : 12002 |  
| 投稿日 | : 2020/01/27(Mon) 02:39 |  
| 投稿者 | : OrientalMelody  |  
 いつもお世話になっております。
  VB.NETとあまり相性の良くない Microsoft.Office.Interop.Excelによる、 Excel操作での質問です。
  Excel操作でSeriesCollection.Add後、Excelのタスクが残ってしまい、困っています。
  以下のソースは、ExcelのA列をX軸、B列をY軸としたデータでグラフを描くVB.NETによるExcel操作になります。
  (1)WindowsFormアプリの新規VBプロジェクトを作成してください。 (2)参照設定で、「Microsoft Excel 14.0 Object Library」を追加してください。 (3)ツールボックスよりButtonオブジェクトをForm1デザイン画面に貼り付けてください。 (4)その後、以下のソースをForm1コードウィンドウに貼り付けてください。
 
  Option Strict Off Option Explicit On Imports Microsoft.Office.Interop.Excel Imports System.Runtime.InteropServices '確実なオブジェクト解放用 Imports System.Linq Imports System.Collections.Generic Public Class Form1
      ''' <summary>     ''' Excelオブジェクトの完全な開放     ''' </summary>     ''' <param name="obj">Excelオブジェクト</param>     Sub ObjRelease(ByRef obj As Object)         If Not (obj Is Nothing) Then             Marshal.ReleaseComObject(obj)             obj = Nothing             Threading.Thread.Sleep(3) '削除安定待ち時間         End If     End Sub
      Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click         Dim xlAppObj As Application = Nothing         Dim wbksObj As Workbooks = Nothing         Dim wbkObj As Workbook = Nothing         Dim wstsObj As Sheets = Nothing         Dim wstObj As Worksheet = Nothing         Dim rngObj As Range = Nothing         Dim shpsObj As Shapes = Nothing         Dim SeriesCollectionObj As Object = Nothing 'SeriesCollection宣言ではプロパティ代入時になぜかエラー。         Dim srsObj As Series = Nothing         Dim vArrayTXT(,) As Object = {{1, 0}, {6, 3}, {7, 4}, {8, 6.7}, {9, 6}}
          Dim shpObj As Shape = Nothing         Dim chtObj As Chart = Nothing
          Try
              xlAppObj = New Application()             xlAppObj.Visible = True             wbksObj = xlAppObj.Workbooks             wbkObj = wbksObj.Add()             wstsObj = wbkObj.Worksheets
              wstObj = wstsObj(1)
              rngObj = wstObj.Range("A1:B5")             rngObj.Value = vArrayTXT             rngObj.Select()             shpsObj = wstObj.Shapes             shpObj = shpsObj.AddChart
              chtObj = shpObj.Chart             chtObj.ChartType = XlChartType.xlXYScatterLines             'グラフ内1系列のみではこの方法で問題ないが、2系列目以降ではSeriesCollection.Addコマンドが必要になる。             'chtObj.SetSourceData(Source:=rngObj) 
              SeriesCollectionObj = chtObj.SeriesCollection             '系列があったら全て削除する             Do Until SeriesCollectionObj.Count = 0                 ObjRelease(srsObj) '使い回しは解放が必要。                 srsObj = SeriesCollectionObj(1) 'コレクションは代入して消去が必要。                 srsObj.Delete()             Loop
              'Y軸の値の指定             ObjRelease(rngObj) '使い回しは解放が必要。             rngObj = wstObj.Range("B1:B5") 'Y値のみ             ObjRelease(srsObj) '使い回しは解放が必要。             'Return 'ここでは成功
              srsObj = SeriesCollectionObj.Add(Source:=rngObj) '---@             Return 'ここでは失敗             'X軸の値の指定             ObjRelease(rngObj) '使い回しは解放が必要。             rngObj = wstObj.Range("A1:A5") 'X値のみ             srsObj.XValues = rngObj 'X値のみ
              Return 'ここでは失敗
          Finally             '各Excelオブジェクトの解放             ObjRelease(srsObj)             ObjRelease(SeriesCollectionObj)             ObjRelease(rngObj)             ObjRelease(shpsObj)             ObjRelease(chtObj)             ObjRelease(shpObj)             ObjRelease(wstObj)             ObjRelease(wstsObj)
 
              '保存ファイル名の生成。実行ファイルフォルダにSaveXL.xlsxとして保存。             Debug.WriteLine(System.Windows.Forms.Application.StartupPath)             Dim sSaveXLFile As String = System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath, "SaveXL.xlsx")             '上書保存             xlAppObj.DisplayAlerts = False             Call wbkObj.SaveAs(Filename:=sSaveXLFile, FileFormat:=XlFileFormat.xlWorkbookDefault)             xlAppObj.DisplayAlerts = True             wbkObj.Close()
              'その他の上位オブジェクトの解放             ObjRelease(wbkObj)             ObjRelease(wbksObj)             xlAppObj.Quit()             Debug.WriteLine("ここでExcelが非表示になり、タスクマネージャーのバックグラウンドプロセスリストに「Microsoft Excel」が表示される。")             ObjRelease(xlAppObj)             Debug.WriteLine("この時点で「Microsoft Excel」がタスクマネージャーに残っていたら失敗。")         End Try     End Sub
  End Class
 
  なお、各Excelオブジェクトは最後のFinally句内で 子オブジェクトから親オブジェクトの順にObjRelease関数により解放するようにしています。
  このとき、どうしても@の srsObj = SeriesCollectionObj.Add(Source:=rngObj) を実施すると、タスクマネージャーで見るとExcelのタスク「Microsoft Excel」が残ってしまいます。
  これを実施する前では、タスクは綺麗になくなるのですが、 どのようにしたら、SeriesCollection.Add後もエクセルのタスクが消えるようになるのでしょうか?
  実はChartオブジェクト内1系列のみであれば、 chtObj.SetSourceData(Source:=rngObj) でも問題ないのですが、同じChartオブジェクト内2系列のグラフを表示したいと思っております。
  とくにやり方にこだわっていませんので、 別のやり方で逃げる方法のご提案でも結構です。
  もし何かお分かりの方がいらっしゃいましたら、 ご教示のほどよろしくお願いいたします。
 
  使用OS:Windows10 64bit 言語  :VB2017 Excel :Excel2010,Excel2013,Excel2016 
 
 |