タイトル | : 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
|