1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ExcelVBAでTreeviewを使う

Posted at

環境

  • Excel for Microsoft365(64bit)

準備

標準ではツールボックスに表示されていないので、以下の手順でツールボックスに追加します。

  1. ツールボックスを右クリックし、「その他のコントロール」を選択
    image.png
  2. リストから「Microsoft TreeView Control,version 6.0」にチェックを入れる
    image.png
  3. ツールボックスに追加されたTreeviewをフォームに配置する
    image.png

基本的な使い方

ノードの追加

ノードの追加はNodesプロパティからAddメソッドを呼び出します。
Addの引数は以下の通り。

  • Key
    ノードを識別するためのパラメータで一意の値を設定します。
    また、Relativeで親子関係を設定する際は、親ノードのKeyを子ノードのRelativeに指定します。
  • Text
    ノードの表示名を指定します。
  • Image
    ノードに対してアイコンを指定する際に使用します。
  • Relative
    子ノードを追加する際に、親ノードのKeyを指定することで親子関係を設定します。
  • Relationship
    子ノードを追加する際に、tvwChild(=4)を設定してノード種類を指定します。

Treeviewコントロールの見た目

コントロールの見た目を調整するための代表的なプロパティを紹介します。

  • Checkboxesプロパティ
    チェックボックスの有無を指定することができます。
    各ノードのCheckedプロパティからチェックのON/OFF状態を取得できます。
    image.png

  • LineStyleプロパティ
    ノード間をつなぐラインの見た目を「0-tvwTreeLines」「1-tvwRootLines」の2種類から設定します。
    TreeLinesの注意点として、デフォルトではノードが畳まれており、ノード展開ボタンも表示されないため子ノードがあるか見た目ではわかりません。
    対策として、ノードのExpandedプロパティにtrueを設定してあらかじめ展開しておくなどするとよいと思います。
    image.png

イベント処理

Treeviewコントロールでは主にNodeCheckとNodeClickの2つのイベントを用いることになります。

  • NodeCheckイベント
    CheckBoxesプロパティを有効にしている時に、ノードのチェック状態が変化した際に呼ばれます。
    チェック状態が変化したノードを引数で受け取れるので、チェック状態に応じた処理を実装します。
    使いどころとしては以下のような機能の有効/無効の設定画面とかでしょうか。
    image.png
    子ノードも含めてまとめてチェック状態の切り替えを行う場合もこのイベントに記述します。
Private Sub TreeView1_NodeCheck(ByVal Node As MSComctlLib.Node)

    '子ノードを取得
    Dim childNode As Node
    Set childNode = Node.Child
    
    While Not childNode Is Nothing
        '親ノードのチェック状態を子に反映
        childNode.Checked = Node.Checked
        
        '次の子ノードに変更
        Set childNode = childNode.Next
    Wend
    
End Sub

使っていて気付いたのが、このイベントは各ノードのチェックボックスを直接変更した時だけ発生します。
ノードのチェック状態を変更する(Node.Checkedプロパティを操作する)実装の場合は発生しませんので、連動させるような場合は気を付ける必要があります。

  • NodeClickイベント
    ノードをクリックした際に呼ばれます。
    クリックしたノードを引数で受け取れるので、ノードに応じた処理を実装します。
    使いどころとしては設定まわりの機能でしょうか。
    選択したノードにあわせてプロパティの内容を入れ替えるというような使い方です。
    image.png

注意点

TreeviewコントロールをMultiPageコントロール上に配置してページを切り替えるとチェック状態が外れるバグ(?)があります。
対策としては、チェック状態を別途配列に保持しておき、ページ切り替えのタイミングで各ノードに反映します。

NodeCheckイベント
Dim NodeChecked(1 To 6) As Boolean

Private Sub TreeView1_NodeCheck(ByVal Node As MSComctlLib.Node)

    '親ノードのチェック状態をバックアップ
    NodeChecked(Node.Index) = Node.Checked

    '子ノードを取得
    Dim childNode As Node
    Set childNode = Node.Child
    
    While Not childNode Is Nothing
        '親ノードのチェック状態を子に反映
        childNode.Checked = Node.Checked
        
        '子ノードのチェック状態をバックアップ
        NodeChecked(childNode.Index) = childNode.Checked
        
        '次の子ノードに変更
        Set childNode = childNode.Next
    Wend
    
End Sub
ページ切り替えイベント
Private Sub MultiPage1_Change()

    'Treeviewコントロールを配置しているページに切り替わった時のみ実行
    If MultiPage1.SelectedItem.Index = 0 Then
    
        'バックアップしていたチェック状態を各ノードに反映する
        For idx = 1 To UBound(NodeChecked)
            TreeView1.Nodes(idx).Checked = NodeChecked(idx)
        Next idx
    End If

End Sub

Node.Indexは1から始まるので配列も同様に定義します。
上記コードでは直値を使っていますが、実コードではノードの登録後にReDimで配列サイズの再定義をするのがよいと思います。

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?