霞と側杖を食らう

ほしいものです。なにかいただけるとしあわせです。[https://www.amazon.jp/hz/wishlist/ls/2EIEFTV4IKSIJ?ref_=wl_share]

ExcelVBAのグラフの構造を理解したいときの覚書

【用途】

最近、Excel VBAを学び始めたが、グラフの作り方を理解するのに恐ろしく時間がかかった。ググっても、マクロの記録をすればいいじゃないみたいな答えだとか、マクロの記録をしたコードをドヤ顔で載せている記事が散見されて、少し辛い思いをした。そんな辛い思いをもう二度としないためのメモ。

【内容】

ExcelVBAでグラフを描くのに必要な知識について記述する。

グラフの描き方は大きく分けて2種類あるが、それを理解するには、まず、オブジェクトの階層構造について知る必要がある。オブジェクトとはVBAの処理の対象になるものである(ex. WorksheetやRange)。同じ種類のオブジェクトの集まりをコレクション(ex. WorkSheetsやChartObjects)という。あるオブジェクトからみて1つ上位の階層のオブジェクト(親オブジェクト)のことをコンテナと呼ぶ。
階層構造について理解するには、以下のサイトにある図がとても参考になる(ただし、2000のヘルプを参考にされているため、少し古いかもしれない。後に記述するようにShapesがどう繋がるのかは、この図からは分からない。)。

https://euc-access-excel-db.com/tips/ct07_se/ct075012_xls2k_vba_tips/real-obj_n_vba-obj01

https://euc-access-excel-db.com/00000WPhtml/Excel2000-obj-model01.png

以下、階層図を見ながら読むと分かりやすい。Applicationを第一階層とすると、WorkbooksやAddInsが第二階層となる。Workbooksの下の第三階層にWorkSheets, Charts, Windowsが存在する。WorkSheetsの下の第四階層にRangeやChartObjectsがある。ChartObjectsの下の第五階層にChartsが存在する。
第三階層のChartsと第五階層のChartsが同じ名前なのが混乱を生む諸悪の根源である。この二つのChartsの違いは、前者はグラフシートに作成されるグラフオブジェクトであり、後者はWorkSheetに作成される埋め込みグラフであるということだ。まず、この違いを理解する必要がある。

この違いが分かれば、グラフシートのグラフについては理解しやすいので、以後触れず、埋め込みグラフについて書いていく。
埋め込みグラフの作り方だが、worksheet.ChartObjectsから作るルートとworksheet.shapesから作るルートがある。Excel 2007から、ShapeオブジェクトにChartプロパティが追加されている。ChartObjectオブジェクトのChartプロパティと同様、Shapeとして取得したグラフをChartオブジェクトとして取得し直す機能になっている。シートに埋め込まれたグラフも、図形と一緒に扱えるようになったということだろうが、ChartObjectとShapeの両方からアクセスできるということを理解しないと混乱してしまう。Excel 2007以降に埋め込みグラフの追加をマクロで記録すると、Shapes.AddChartで記録されるようだ。ChartObjects.AddではなくShapes.AddChartを使用するメリットは、Type、Left、Top、Width、Heightの各引数がデフォルトで入っていて、指定が任意になっている点のようだが、わざわざVBAで書くならば、そのメリットは薄いように感じられる。

Dim ChObj1 As ChartObject  
Set ChObj1 = ActiveSheet.ChartObjects.Add( _  
                          Left:=Range("H3").Left, Top:=Range("H3").Top, _  
                          Width:=500, Height:=300)    ' 位置とサイズ指定  
                      ' Left:=500, Top:=100, Width:=450, Height:=300)'数値指定可  

などとして、どちらかのルートでグラフが加えられたら、ChartObjectオブジェクトであるChObj1のChartプロパティに繋いで、指定を加えていけばよい。

複数グラフを重ねて複合グラフを作りたい場合はChartプロパティのSeriesCollectionを使えばよい。
既に系列1がある場合ならば

With ChObj1.Chart  
        .SeriesCollection.NewSeries  
        .SeriesCollection(2).Name = "=""系列2の名前"""  
        .SeriesCollection(2).ChartType = xlXYScatter  
        .SeriesCollection(2).XValues = (系列2のRange)  
        .SeriesCollection(2).Values = (系列2のRange)  
End With  

などと書き加えればよい。
ChartTypeの指定は以下のサイトの一覧から確認するとよい。
http://officetanaka.net/excel/vba/graph/06.htm

参考にしたもの ・できる大事典 Excel VBA 2016/2013/2010/2007 対応 (できる大事典シリーズ)
https://www.amazon.co.jp/dp/4295000914/ref=cm_sw_r_tw_dp_U_x_Amo8DbN4W2R32
VBAグラフを作る方法
https://qiita.com/asterisk9101/items/7ca75226d3ab2ba2fa55
・2軸のグラフをデータ系列毎に分けてグラフを作成する
http://www.k1simplify.com/vba/tipsleaf/graph05.html
・Shapeとしてのグラフ
http://blog.clayhouse.jp/article/29906791.html
Excel VBA グラフ(Chart)操作 グラフの作成と詳細設定をする方法
https://officedic.com/excel-vba-chartset/

【記憶の検索キーワード】

Excel, VBA, Chart, Shape, ChartObject, グラフ, 階層構造