グラフを削除する


なぜ親オブジェクト(Parent)を削除するのか

ワークシート上の埋め込みグラフを削除するのは、それほど難しくありません。たとえば、下図の「グラフ 1」を削除するのなら、

Sub Sample()
    ActiveSheet.ChartObjects("グラフ 1").Delete
End Sub

だけでいいです。もし、ワークシート上に複数の埋め込みグラフがあって、それらをすべて削除するのでしたら

Sub Sample()
    Dim i As Long
    With ActiveSheet
        For i = .ChartObjects.Count To 1 Step -1
            .ChartObjects(i).Delete
        Next i
    End With
End Sub

みたいにすれば、いいでしょう。マクロ記録をするまでもありませんね。ありませんけど、念のためにExcel 2010でマクロ記録してみましょう。「グラフ 1」を選択してから、Deleteキーを押して削除しました。

Sub Macro()
    ActiveSheet.ChartObjects("グラフ 1").Activate
    ActiveChart.Parent.Delete
End Sub

グラフ(ChartObject)を選択(Activate)して削除(Delete)と、ありきたりなコードですが・・・ん?Parentって?何で親オブジェクトを削除してんの?埋め込みグラフ「グラフ 1」の親オブジェクト(Parent)って、ワークシートですよね。アクティブシートを削除しちゃマズイでしょ。確認のため、次のようにコードを変更してから、この記録されたコードを実行してみます。

Sub Macro()
    Dim msg As String
    ActiveSheet.ChartObjects("グラフ 1").Activate
    msg = msg & "Selection:" & vbCrLf
    msg = msg & TypeName(Selection) & "(" & Selection.Name & ")" & vbCrLf & vbCrLf
    msg = msg & "Selection.Parent:" & vbCrLf
    msg = msg & TypeName(Selection.Parent) & "(" & Selection.Parent.Name & ")" & vbCrLf & vbCrLf
    msg = msg & "ActiveChart:" & vbCrLf
    msg = msg & TypeName(ActiveChart) & "(" & ActiveChart.Name & ")" & vbCrLf & vbCrLf
    msg = msg & "ActiveChart.Parent:" & vbCrLf
    msg = msg & TypeName(ActiveChart.Parent) & "(" & ActiveChart.Parent.Name & ")"
    MsgBox msg
    ActiveChart.Parent.Delete
End Sub

ああ、なるほど。削除されるのは、Selection.Parentではなく、ActiveChart.Parentですか。

ワークシート上の埋め込みグラフは、おおむね次のようなオブジェクト構成になっています。

グラフ本体はChartオブジェクトです。系列とか軸とか凡例とかタイトルとか、グラフを構成するパーツはChartオブジェクトで操作します。そのChartオブジェクトのコンテナがChartObjectオブジェクトです。いわば、埋め込みグラフの枠みたいなもんです。ChartObjectオブジェクト自体には、大したメソッドやプロパティは用意されていません。でも、グラフ本体にアクセスするには、ChartObjectオブジェクトから指定します。もうひとつ、ChartObjectオブジェクトの中にはShapeRangeオブジェクトがあります。こいつは、いわば描画領域で、塗りつぶしなどの設定を行えます。

さて、話を「グラフの削除」に戻しましょう。冒頭でお見せしたコード

Sub Sample()
    ActiveSheet.ChartObjects("グラフ 1").Delete
End Sub

は、埋め込みグラフの枠を削除しています。枠が削除されれば、当然ながらその中のグラフ本体(Chartオブジェクト)も削除されます。では、マクロ記録されたコードは、どういう意味なのでしょう。

したがって、次のようにParentがないと、Chartオブジェクトそのものを削除することになってエラーです。埋め込みグラフの削除は、あくまで枠(ChartObjectオブジェクト)をDeleteしなければいけません。

Sub Macro()
    ActiveSheet.ChartObjects("グラフ 1").Activate
    ActiveChart.Delete    ''エラー
End Sub

あるいは、次のように、選択されているChartObjectオブジェクトを削除してもいいですね。

Sub Macro()
    ActiveSheet.ChartObjects("グラフ 1").Activate
    Selection.Delete
End Sub

これなら、うまくいきます。マクロ記録は、Selectionを操作するのが大好きなのですから、埋め込みグラフの削除も、このように記録されれば悩まずに済むのに。

では、Excel 2003ではどうでしょう。同じように「グラフ 1」を選択して削除する操作をマクロ記録してみます。

Sub Macro()
    ActiveSheet.ChartObjects("グラフ 1").Activate
    ActiveChart.ChartArea.Select
    ActiveWindow.Visible = False
    Selection.Delete
End Sub

Deleteメソッドを実行する前に、3行の命令が実行されています。先と同じように、各行が実行されたとき、何が選択されているのかを調べてみましょう。

Sub Macro()
    ActiveSheet.ChartObjects("グラフ 1").Activate
        ''Selection → ChartArea(グラフ)
        ''ActiveChart → Chart(Sheet1 グラフ 1)
    
    ActiveChart.ChartArea.Select
        ''Selection → ChartArea(グラフ)
        ''ActiveChart → Chart(Sheet1 グラフ 1)
    
    ActiveWindow.Visible = False
        ''Selection → ChartObject(Chart1)
        ''ActiveChart → Chart(Sheet1 グラフ 1)
    
    Selection.Delete
End Sub

まったく違いますね。ぜんぜん違ってます。すっげぇ違いです。こいつは驚いた。

Excel 2007では

ActiveSheet.ChartObjects("グラフ 1").Activate
Selection.Delete    ''正常終了

1行目の「ActiveSheet.ChartObjects("グラフ 1").Activate」でChartObjectオブジェクトが選択されますので、続いて「Selection.Delete」すれば埋め込みグラフが削除できます。対して、Excel 2003では

ActiveSheet.ChartObjects("グラフ 1").Activate
Selection.Delete    ''エラー

1行目の「ActiveSheet.ChartObjects("グラフ 1").Activate」で選択されるのはChartAreaです。ChartObjectオブジェクトではありませんので、続けて「Selection.Delete」するとエラーです。

何かというとSelectionを多用するビギナーにとって、この細かい変更は、きっと頭を悩ませるでしょうね。

Excel 2003のコードは動くか

Excel 2003でマクロ記録した次のコードを、Excel 2007で実行してみます。

Sub Macro()
    ActiveSheet.ChartObjects("グラフ 1").Activate
    ActiveChart.ChartArea.Select
    ActiveWindow.Visible = False
    Selection.Delete
End Sub

【Excel 2007での実行結果】

最後の行でエラーです。おそらく、Selectionが違うのでしょうね。先と同じように調べてみると、Excel 2007では次のようになることがわかりました。

Sub Macro()
    ActiveSheet.ChartObjects("グラフ 1").Activate
        ''Selection → ChartObject(Chart 1)
    ActiveChart.ChartArea.Select
        ''Selection → ChartArea(グラフ)
    ActiveWindow.Visible = False
        ''Selection → ChartArea(グラフ)
    Selection.Delete
End Sub

まとめると・・・

  • Excel 2003とExcel 2007では「ChartObject.Activate」した結果(Selection)が異なる
  • その後Selectionを操作するマクロでは違いが生じる
  • そもそも、Excel 2003でマクロ記録をそのまま使っていたのが原因
  • マクロ記録に頼らないで、VBAをちゃんと学習していたユーザーのマクロは問題なし

ということですね。いずれにしても、埋め込みグラフを削除するのなら、Excel 2003だろうがExcel 2007だろうが

Sub Sample()
    ActiveSheet.ChartObjects("グラフ 1").Delete
End Sub

これで、OKってことです。