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

タイトル SeriesCollection.Add後、Excelのタスクが残る
投稿日: 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

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

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