図形のレガシーオブジェクト

Excel VBAのヘルプによれば、図形(描画オブジェクト)は、基本的にShapeオブジェクトおよびShapesコレクション(またはShapeRangeコレクション)を使用して操作するということになっています。
しかし、実際には、Shape/Shapesでは実現できない処理が存在しています。
このような処理には、Shape/Shapesではなく、ヘルプにも載っていないレガシーな(旧時代の)オブジェクトを使用する必要があります。

DrawingObjectsコレクションについて

ExcelのVBAで、Shapeオブジェクトを使って図形を操作しようとした場合、たとえば[オートシェイプの書式設定]ダイアログボックスの[プロパティ]タブの[オブジェクトを印刷する]のオン/オフの設定や、図形にセルの文字列をリンクする操作などを実行することはできません。
また、ShapesコレクションはDeleteメソッドをサポートしていないため、対象のワークシート上にあるすべての図形を一括で削除するといった処理を行うこともできません。
それでは、次のようなコードでSelectionで取得されているのは、Shapesコレクションではないのでしょうか?

ActiveSheet.Shapes.SelectAll
Selection.Delete

答えを言ってしまうと、このときSelectionで取得されているのは、ShapesコレクションやShapeRangeコレクションではなく、DrawingObjectsコレクションです。
したがって、図形を選択することなく一括削除したい場合は、次のようなコードで実現できます。

ActiveSheet.DrawingObjects.Delete

DrawingObjectsは、Shapesコレクションが登場する前にExcel VBAで採用されていた、図形の集合を表すコレクションオブジェクトです。Shapeオブジェクトに相当する、単体の図形を表すオブジェクトは、後述するRectangleなどの各図形ですが、ここでは総称として仮に「DrawingObjectオブジェクト」と呼びます(実際には、DrawingObjectという単体のオブジェクトはありません)。
シート上のすべての図形を表すDrawingObjectsコレクションは、対象のシートを表すオブジェクトのDrawingObjectsメソッドで取得できます。また、DrawingObjectsコレクションにインデックス(数値または名前)を指定することで、特定の図形を表すRectangleなどのオブジェクトが取得できます。

Shapes/Shapeの採用に伴って追加された機能も多いのですが、DrawingObjectsで使用できた機能で、Shapes/Shapeに引き継がれなかったものも、実はいくつか存在しています。
たとえば、最初に例として挙げた「オブジェクトを印刷する」の設定は、DrawingObjectオブジェクトのPrintObjectプロパティとして取得・設定できます。

[オートシェイプの書式設定]ダイアログボックス
[プロパティ]タブの[オブジェクトを印刷する]の設定は、Shapeオブジェクトではなく、DrawingObjectオブジェクト(各図形を表すオブジェクト)のPrintObjectプロパティで設定できる。

アクティブシートの「四角形 1」という名前の図形の「オブジェクトを印刷する」の設定をオフにする操作は、次のようなコードになります。

ActiveSheet.DrawingObjects("四角形 1").PrintObject = False

図形にセルをリンクする操作についても紹介しておきます。次のコードを実行すると、アクティブシートの「四角形 1」上に、常にC2セルと同じ文字列が表示されるようになります。

ActiveSheet.DrawingObjects("四角形 1").Formula = "=C2"

実行前。
「四角形 1」に文字列は表示されていない。

コードの実行例。
「四角形 1」にC2セルの文字列が表示される。C2セルの文字列を変更すると、「四角形 1」の文字列も同様に変更される。

ちなみに、この操作をExcelのワークシート上で行うには、図形を選択した状態で数式バーをクリックし、「=」に続けてリンクしたいセル番地を入力(またはセルをクリック)して、Enterキーを押します。
セル参照や名前以外の数式は入力できません。

もう1つ、DrawingObjectオブジェクトの利用例を紹介しましょう。
図形上に表示する文字列を設定する場合、Shapeオブジェクトでは、次のように何階層ものオブジェクトを経由して指定する必要があります。

ActiveSheet.Shapes("楕円 1").TextFrame.Characters.Text = "Access"

「楕円 1」の内部に「Access」という文字列が表示される。

一方、DrawingObjectオブジェクト(各図形を表すオブジェクト)の場合は、Textプロパティだけで、簡単に指定が可能です。図形が選択されている状態であれば、Selectionに対してTextプロパティを使用することもできます。

ActiveSheet.DrawingObjects("楕円 1").Text = "Excel"

「楕円 1」の内部に「Excel」という文字列が表示される。

このページの先頭へ戻る

オブジェクトの相互変換

直前の操作で図形をShapeオブジェクトとして取得していた場合、これをDrawingObjectオブジェクトに変換することが可能です。
この操作には、DrawingObjectプロパティを使用します。たとえば、次のコードは、ワークシート上にドーナツ図形を作成し、さらにその図形が印刷されないように設定するものです。

ActiveSheet.Shapes.AddShape(msoShapeDonut, 20, 20, 100, 100).DrawingObject.PrintObject = False

コードを実行すると作成されたドーナツ図形が作成される。

作成されたドーナツ図形の[オートシェイプの書式設定]ダイアログボックス
[プロパティ]タブの[オブジェクトを印刷する]の設定がオフになっている。

逆に、DrawingObjectsコレクションをShapeRangeコレクションに変換することも可能です。
このようなときに用いるのがShapeRangeプロパティです。ヘルプの解説では、いまいち何に使うのかわかりにくいプロパティですが、最も重要な対象オブジェクトが明記されていないのですから、わかりにくいのも当然かもしれません。
たとえば、「Selection.ShapeRange」というのは、選択された図形の集合を表すDrawingObjectsコレクションをShapeRangeコレクションに変換し、DrawingObjectsでは行えなかった処理を行うための操作です。
ShapeRangeプロパティの具体的な活用例については、以下の項目で紹介します。

このページの先頭へ戻る

特定の種類の図形を表すオブジェクト

DrawingObjectsコレクションの実際のメンバーは、DrawingObjectオブジェクトではなく、四角形や楕円、テキストボックスといった、各図形を表すオブジェクトです(ただし、旧タイプの分類なので、新しく追加されたオートシェイプの図形については、一括でアクセスする方法は用意されていません)。これらのコレクションは、DrawingObjectsコレクションと同様に操作できます。

オブジェクト名コレクション名図形の種類
RectangleRectangles四角形
OvalOvals楕円
LineLines直線
TextBoxTextBoxesテキストボックス
DrawingDrawingsフリーフォーム
PicturePictures図(画像)

このコレクションを使用することによって、特定の種類の図形をまとめて操作することが可能になります。次のコードは、アクティブシート上のすべての四角形を一括で削除するものです。

ActiveSheet.Rectangles.Delete

実行前。
さまざまな種類の図形が作成されている。

コードの実行例。
アクティブシート上のすべての四角形が削除された。

また、各コレクションのAddメソッドで、引数として左、上、幅、高さの各数値を指定すれば、その種類の図形が新たに作成されます。Picturesコレクションに関しては、Insertメソッドで引数として画像ファイル名を指定すれば、アクティブシート上にその画像が挿入されます。
ShapesコレクションのAddPictureメソッドの場合、引数として必ず位置とサイズを指定する必要があるため、必ずしも元の画像と同じ縦横比にならない可能性がありますが、PicturesコレクションのInsertメソッドであれば、元の画像のサイズそのままでワークシートに配置されます。

なお、新しく追加されたオートシェイプの図形(三角形や台形、ハートなど)をDrawingObjectsコレクションから取得した場合、レガシーオブジェクトとしての扱いはやはりRectangleオブジェクトになります。ただし、このRectangleオブジェクトはRectanglesコレクションには含まれないので注意が必要です。

一方、Rectanglesなどのコレクションを利用して特定の種類の図形のみを取得し、それらをShapeRangeプロパティでShapeRangeコレクションに変換して、一括で操作することも可能です。
図形のレガシーオブジェクトで塗りつぶしの色や枠線を設定する場合、InteriorやBorderといった、セルの書式と同じオブジェクトを使用します。線の太さの指定もxlThinやxlThickといった形での指定になり、ポイント単位での設定はできません。詳細な設定を行いたい場合は、やはりShapeRangeコレクションとして操作する必要があります。
次のコードは、アクティブシート上のすべての線を、太さ5ポイントの赤い点線にするものです。

With ActiveSheet.Lines.ShapeRange.Line
    .Weight = 5
    .DashStyle = msoLineRoundDot
    .ForeColor.RGB = vbRed
End With

実行前。
さまざまな種類の図形が作成されている。

コードの実行例。
アクティブシート上のすべての直線の書式が一括で変更される。

このページの先頭へ戻る

特定の種類のコントロールを表すオブジェクト

ボタンやオプションボタン、チェックボックスのような、Excelで使用可能な「コントロール」には、「ActiveXコントロール」と「フォームコントロール」(Excelコントロール)の2種類があります。
これらのコントロールは、Excel 2007では[開発]タブの[コントロール]グループから作成します。また、Excel 2003以前では、ActiveXコントロールは[コントロールツールボックス]から、フォームコントロールは[フォーム]ツールバーから、それぞれ作成できます。
フォームコントロールをExcel VBAで操作する場合、通常は、Shapeオブジェクトとして取得し、ControlFormatプロパティでコントロールとしての操作を行います。
ただ、フォームコントロールは、ActiveXコントロールとは違ってExcelの歴史の中では古株であるため、レガシーオブジェクトとしての固有名を持っています。この名前を使用することで、特定の種類のフォームコントロールだけを一括して処理することが可能です。

オブジェクト名コレクション名コントロールの種類
LabelLabelsラベル
GroupBoxGroupBoxesグループボックス
ButtonButtonsボタン
CheckBoxCheckBoxsチェックボックス
OptionButtonOptionButtonsオプションボタン
ListBoxListBoxesリストボックス
ComboBoxComboBoxesコンボボックス
ScrollBarScrollBarsスクロールバー
SpinnerSpinnersスピンボタン

次のコードは、アクティブシート上に配置されたフォームコントロールのうち、チェックボックスだけを、一番左の位置に合わせるものです。

ActiveSheet.CheckBoxes.ShapeRange.Align msoAlignLefts, False

実行前。
さまざまな種類の図形とコントロールが作成されている。

コードの実行例。
アクティブシート上のすべてのチェックボックスの左端が揃えられる。

このページの先頭へ戻る