ExcelVBAでグラフ要素の表示/非表示を切り替える

Excelのグラフで沢山の特性を表示させてるとき、この特性だけ見たいんだけど表示切り替えとか出来ない?と要望がありました。毎回同じ特性ならそこだけ抜粋のグラフ作ればいいんだけど、その都度違うという。なるほどと思って作ってみました。
目次
- グラフ用のデータを用意する
- グラフをつくる
- ユーザーフォームをつくる
- ユーザーフォームを表示するコードを記述する
- Excelにユーザーフォーム表示用のボタンを配置する
- 特性を表示/非表示するコードを書く
- 全部表示/全部隠すコードを追加
- ユーザーフォームを閉じた時に全表示にする
- こんな書き方もできます
グラフ用のデータを用意する

実際仕事で使ったのはもっともっと多いんですが、解説用にこのくらいで。
データの入っているセルの高さ/幅をゼロ(非表示)にしてしまうとその部分だけグラフに反映されなくなるので、そこを利用してVBAでセルの高さを操作してやろうという魂胆です。
グラフをつくる

作り終わってから気づいたんですが、特性(要素)を非表示にする際、一番上の要素を非表示にすると項目ラベル(「サンプル1」とかそういうの)が消えてしまうので、上限下限とか“消さない要素”を作っておいて一番上にしておくと安全です。

こんな感じで。折れ線しか試していませんが多分棒グラフとか他の様式でもいけると思います。
グラフがデータの横・下にある場合、セルの表示/非表示を実行するとグラフの高さが変化したり位置が動いたりして見づらいので、データよりも上にグラフがあると良いと思います。
ユーザーフォームをつくる
[ツール]→[マクロ]→[Visual Basic Editor]もしくは[Alt]+[F11]キーでVisual Basic Editorを開きます。

[挿入]→[ユーザーフォーム]で新しいユーザーフォームを作ります。

ツールボックスが一緒に表示されているので、その中からトグルボタンを選んで任意の場所にボタンを作りましょう。

ボタン上でクリックすると名前(Caption)が変えられます。

作成したトグルボタンをコピペして、名前を全部変えましょう。今回はグラフにa~eまでの5特性あるのでこんな感じ。
次はコマンドボタンを選択します。

コマンドボタンを2つ作って、上記のようなボタンも作ります。マウスで囲むように全選択してドラッグすると位置を変えられます。

フォームの右下をドラッグするとフォーム自体の大きさも変えられます。

フォームの名前が「UserForm1」じゃあちょっと味気ないので、Captionに名前を入れてみます。

上部分の「UserForm1」が、「選択表示」になりました!
ユーザーフォームを表示するコードを記述する

そのままVisual Basic Editorで、[挿入]→[標準モジュール]を選びます。

そこへ以下のコードを書きます。
Sub start() UserForm1.Show End Sub
startという名前にしていますが、なんでも良いです。中身はUserForm1を表示しますよ、という意味です。説明するほど難しくはないですね。
Excelにユーザーフォーム表示用のボタンを配置する

Excelに戻って[表示]→[ツールバー]→[フォーム]を選択。

[ボタン]を選んで、

マクロ名を登録!この辺はExcelVBA入門第1回でも書きましたね。

「ボタン1」じゃアレなので、「UserForm表示」という名前にしてみました。押してみるとさっき作ったユーザーフォームが表示されます!でもまだ、どこを押しても何も動きませんね。
特性を表示/非表示するコードを書く

Visual Basic Editorに戻って左上の[プロジェクト]の[UserForm1]をダブルクリックすると、さっき作ったユーザーフォームが出てきます。その中の、[ToggleButton1]をダブルクリック。

するとこんな画面になります。モジュールと似たような画面ですが、さっき書いたコードは見当たりません。これは、UserForm1のコード画面で、UserForm1を何か操作したときに起動する用のコード画面です。[プロジェクト]の[UserForm1]がうっすらグレーになっているのが目印です。
既に何か書いてありますが、[ToggleButton1]をクリックしたときに起動するプログラムだよ!という意味になります。その中に1行追加して、下記のようなコードにします。
Private Sub ToggleButton1_Click() Call main(1, Me.ToggleButton1.Value) End Sub
わかりづらくなってきましたね…。

意味は、こんな感じです。伝わってるでしょうか…。。

では[Module1]をダブルクリックして、モジュールのほうにさきほどCallで指定した“main”というプロシージャを作ります。
Sub main(i As Integer, f As Boolean) Dim n As Integer Application.ScreenUpdating = False '画面更新なしにして高速化 For n = 0 To 3 '4回繰り返す If f = True Then 'トグルボタンがONだったら Rows(3 + (i - 1) + 5 * n).RowHeight = 0 '該当の行高さをゼロ(非表示)に Else 'トグルボタンがOFFだったら Rows(3 + (i - 1) + 5 * n).RowHeight = 13.5 '該当の行高さを標準に End If Next n Application.ScreenUpdating = True '画面更新を戻す End Sub
トグルボタンの番号を引数として連れてきたのは、ボタンによって行が違うので、計算で特定するためです。

今まで、プロシージャはSub test()
のように、最後によくわからないかっこがついてたと思いますが、引数を連れてきた時にこの中に書くためだったんですね!その他の変数は普通にDim
で宣言してあげます。
宣言についてはこちらの記事もどうぞ。

動作確認!aのトグルボタンを押すたびに該当の行とaのグラフが表示/非表示に切り替わるはずです!

さて、では他のボタンも同様にして行きましょう。さっきのUserForm1のコードへ戻ります。UserFormのコードは、[プロジェクト]の該当のUserFromを右クリックして[コードの表示]で出てきます。
Private Sub ToggleButton1_Click() Call main(1, Me.ToggleButton1.Value) End Sub
の下に下記を追加します。
Private Sub ToggleButton2_Click() Call main(2, Me.ToggleButton2.Value) End Sub Private Sub ToggleButton3_Click() Call main(3, Me.ToggleButton3.Value) End Sub Private Sub ToggleButton4_Click() Call main(4, Me.ToggleButton4.Value) End Sub Private Sub ToggleButton5_Click() Call main(5, Me.ToggleButton5.Value) End Sub
これで、各ボタンを押した時にそのボタンの番号と内容(ON/OFF)を引き連れてmainというプロシージャに飛ぶことができるわけですね。
全部表示/全部隠すコードを追加
これで一応欲しい機能は出来たといえば出来たわけですが、ちょっと親切じゃないですよね。ユーザーフォームに作った「全部を表示/非表示」ボタンも動くようにしてあげます!
ユーザーフォーム側

Private Sub CommandButton1_Click() Call all_show End Sub Private Sub CommandButton2_Click() Call all_hide End Sub
を追加。CommandButton1(全部表示ボタン)とCommandButton2(全部隠すボタン)を押したときにそれぞれ飛ぶプロシージャを指定します。今回は引数はいらないので書きません!
モジュール側

Sub all_show() Dim i As Integer Application.ScreenUpdating = False Rows("3:22").RowHeight = 13.5 '行高さを標準に For i = 1 To 5 UserForm1("ToggleButton" & i).Value = False 'トグルボタンを全てOFFに Next i Application.ScreenUpdating = True End Sub Sub all_hide() Dim i As Integer Application.ScreenUpdating = False Rows("3:22").RowHeight = 0 '行高さをゼロ(非表示)に For i = 1 To 5 UserForm1("ToggleButton" & i).Value = True 'トグルボタンを全てONに Next i Application.ScreenUpdating = True End Sub
それぞれ、行の高さとトグルボタンのON/OFFを操作します。トグルボタン全てに同じ操作をしたいときは、変数を使うと楽です。こちらの記事を参考にどうぞ。
ユーザーフォームを閉じた時に全表示にする
できたー!と思いたいところですが、使ってみてどうでしょうか?フォームを閉じたときにどこかが非表示のままだと気持ち悪くないですか?私は気持ち悪いかなーと思ったので、下記も追加します。
ユーザーフォーム側

Private Sub UserForm_Terminate() 'フォームが閉じたとき Call f_hide End Sub
モジュール側

Sub f_hide() Application.ScreenUpdating = False Rows("3:22").RowHeight = 13.5 Application.ScreenUpdating = True End Sub
これを追加してあげると、フォームが閉じる度に勝手に全表示になります!
こんな書き方もできます
Private Sub UserForm_Terminate() 'フォームが閉じたとき Application.ScreenUpdating = False Rows("3:22").RowHeight = 13.5 Application.ScreenUpdating = True End Sub
わざわざ“f_hide”というプロシージャを作って飛ばさなくても上記のように書いても出来ます。こっちのほうが楽かもですね。ただ、今回のトグルボタン1~5のように違うボタンで同じような動作をする場合は引数とCallを使ったほうがコードが短くて済むので、状況によって使い分けると良いと思います。
ExcelVBAに興味をお持ちの方は、こちらの記事もどうぞ!
- これからExcelのマクロを始めたいという方に!簡単な練習問題作りました。
- 私がExcelVBAでよく使う便利なコード・スニペットまとめ
- プログラム初心者さんへ贈る、エラーが起きたら試してみて欲しいこと
- ExcelVBAのクラスモジュールって何?という人向けの使い方まとめ
書籍を執筆しています。

4件のコメント
はじめまして
UserFormにグラフを反映させたいのですが
検索するもなかなか見つからず、貴殿のものを参考に作成しましたが、うまくいかず、ご教示願えればと思い投稿いたしました。
やりたいことは、貴殿のエクセルデータのa/b/c/dの左横にセルを挿入し1・2・3・4・5と作り、1(セルを結合)にはa/b/c/dが抽出される。2・3・4・5も同様です。
つまり、1のボタンをおしたら そのa/b/c/dが反映されるようにしたいです。よろしくお願いいたします。
ふじさん さん、はじめまして。この記事の最初にあるデータ図を例にしますと、UserForm上のボタンは4つにして、
コードをこのように書けば良いのではないかと思います。お試しください。
当方初心者にて時間がかかってしまい
お礼のご連絡遅くなりすみません。
試行錯誤した結果、無事作成完了しました。
ありがとうございました。
わぁ、よかったです! こちらこそ、ご報告、ありがとうございました。(*´∀`*)
コメントは承認制ですので、反映までしばらくお待ち下さい。(稀にスパムの誤判定にて届かないこともあるようですので、必要な際はお問い合わせからお願い致します。)
YouTubeでQ&Aコンテンツを企画しています
運営しているYouTubeチャンネルで、ご相談やご質問を募集しています。動画のコメントやお問い合わせページからお気軽にご相談をお寄せください。