[[20191017174915]] 『TreeViewのチェックボックスのチェック状態を親階』(あみ) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『TreeViewのチェックボックスのチェック状態を親階層と子階層で連動させる方法』(あみ)

VBA初心者です。

調べてはみたんですが全く分かりませんでした・・・
下記の情報を知りたいです。ご存知の方がいらっしゃいましたら教えて頂きたいです。
・TreeViewのチェックを付けた、外した時のイベント
・親階層がチェックされた時子階層のチェックを全て外す方法
・子階層のチェックが全て外れたときに親階層のチェックを外す方法(できれば全て外れたときの親階層の子階層をみて全て外れていたらチェックが外れるような処理を付けたいかなとは思っています)
・ノードのチェック状態の取得

結構インターネットでvbaの事を調べようとするとC#とかの他の言語では解説されているけどvbaには書いていないことが多いです。。。私の検索の仕方が悪いのもあると思いますが。。。
どこかに細かい情報まで記載してあるサイトとかがありました教えて頂きたいです。よろしくお願いいたします。

< 使用 Excel:unknown、使用 OS:unknown >


 コメントがつかないようなので、前座で。

 VBAにおけるTreeViewについては
 http://officetanaka.net/excel/vba/treeview/
 が参考になりますが、当然、すでに閲覧されているでしょう。

 # でも、これはちょっと古い記事なんでしょうか。
 # 私の環境(Excel2010、これも十分古いですが)では、
 # 参照設定も違いますし、ImageListコントロールは使えませんでした。

 TreeViewコントロールだけなら、下記を参考に表示はできました。
 http://www.tetsuexcelvba.com/article/430892561.html

 ただし、書かれているニーズに関連して、
 「TreeViewの親ノードのチェックボックスをダブルクリックすると、
 子ノードに親ノードのチェック状態が反映されない場合がある」
 https://support.microsoft.com/ja-jp/help/2781622
 などという悲報もあり、雲行き怪しい感じですね。

 世の中的にそうしたニーズをお持ちの方が少なく、
 いらっしゃってもVB C#方面に転進されることが、
 記事の少ない理由なんでしょうか。

 オブジェクトブラウザーから辿ると、
 TreeViewのプロパティ、メソッド、イベントが解りますから、
 他の言語の仕様も考慮し、それで類推していくしかないかも知れませんね。

(γ) 2019/10/17(木) 21:39


 下記を参考にTreeViewを表示してみました」。
  http://www.tetsuexcelvba.com/article/430892561.html

 オブジェクトブラウザを見ながら、下記の(1)(2)(4)について、
 下記コードを作成してみました。参考にしてみてください。

 |  (1)TreeViewのチェックを付けた、外した時のイベント
 |  (2)親階層がチェックされた時子階層のチェックを全て外す方法
 |  (3)子階層のチェックが全て外れたときに親階層のチェックを外す方法
 |     (できれば全て外れ たときの親階層の子階層をみて全て外れていたら
 |      チェックが外れるような処理を付けたい かなとは思っています)
 |  (4)ノードのチェック状態の取得

 (3)については、NextやPrevious,Parentなどを使うとできるんじゃないでしょうか。
 トライしてみてください。

 Option Explicit

 Private Sub UserForm_Initialize()
     Dim i As Long
     Dim Rltiv As Variant
     Dim Rltsp As TreeRelationshipConstants
     Dim WS As Worksheet
     Dim TV As TreeView

     Set WS = Worksheets(1)
     Set TV = Me.TreeView1
     TV.CheckBoxes = True
     Me.TreeView1.Nodes.Clear
     ' TreeView

     Rltiv = Null
     Rltsp = 0    '変数Rltspの型がTreeRelationshipConstantsなので、tvwFirstでもよ い

     With WS
         For i = 2 To .Cells(.Rows.Count, 1).End(xlUp).Row
             TV.Nodes.Add(Relative:=Rltiv, Relationship:=Rltsp, _
                 Key:="A" & .Cells(i, 1), Text:=.Cells(i, 2)).Expanded = True
                    '■ここだけExpandするよう変更しています。
             Rltiv = "A" & .Cells(i + 1, 3)    '3列目,親ノード(ParentID)を取得
             Rltsp = tvwChild
         Next i
     End With
     Set WS = Nothing
     Set TV = Nothing
 End Sub

 '■以下はノードのチェックをつけたときの対応例です。
 Private Sub TreeView1_NodeCheck(ByVal Node As MSComctlLib.Node)
     Dim ch As Node

     If Node.Checked Then
         If Node.Children > 0 Then
             Set ch = Node.Child
             ch.Checked = False
             Do
                 If Not ch.Next Is Nothing Then
                     Set ch = ch.Next
                     ch.Checked = False
                 Else
                     Exit Do
                 End If
             Loop
         End If
     End If
 End Sub
 # 再帰的にさらに子供に影響することはない仕様のようです。

(γ) 2019/10/17(木) 22:34


 ついでに、(3)についても書いて見ました。
 全体を少し修正しています。

 <<UserFormモジュール>>
 Private Sub UserForm_Initialize()
     Dim ws As Worksheet
     Dim tv As TreeView
     Dim rltiv As Variant
     Dim rltsp As TreeRelationshipConstants
     Dim i As Long

     Set ws = Worksheets(1)
     Set tv = Me.TreeView1
     tv.CheckBoxes = True    '■ここも追加していました。
     tv.Nodes.Clear

     With ws
         rltiv = Null
         rltsp = tvwFirst
         i = 2
         tv.Nodes.Add(Relative:=rltiv, Relationship:=rltsp, _
                      Key:="A" & .Cells(i, 1), Text:=.Cells(i, 2)).Expanded = True

         For i = 3 To .Cells(.Rows.Count, 1).End(xlUp).Row
             rltiv = "A" & .Cells(i, 3)
             rltsp = tvwChild
             tv.Nodes.Add(Relative:=rltiv, Relationship:=rltsp, _
                          Key:="A" & .Cells(i, 1), Text:=.Cells(i, 2)).Expanded = True
         Next i
     End With
     Set ws = Nothing
     Set tv = Nothing
 End Sub

 Private Sub TreeView1_NodeCheck(ByVal Node As MSComctlLib.Node)
     Dim nd As Node
     Dim flag As Boolean

     If Node.Checked Then    'checkをつけた時
         '子階層のチェックをすべて外す
         If Node.Children > 0 Then
             Set nd = Node.Child     '先頭の子
             nd.Checked = False
             Do
                 If Not nd.Next Is Nothing Then
                     Set nd = nd.Next
                     nd.Checked = False
                 Else
                     Exit Do
                 End If
             Loop
         End If
     Else    'checkを外したとき
         '■同階層のnodeのチェックがすべて外れていたら、親のチェックを外す。
         flag = False
         Set nd = Node.FirstSibling  '同階層の先頭node
         If nd.Checked = True Then
             flag = True
             Exit Sub
         End If
         Do
             If Not nd.Next Is Nothing Then
                 Set nd = nd.Next
                 If nd.Checked = True Then
                     flag = True
                     Exit Sub
                 End If
             Else
                 Exit Do
             End If
         Loop
         If flag = False Then
             If Not nd.Parent Is Nothing Then
                 nd.Parent.Checked = False
             End If
         End If
     End If
 End Sub
 # 必要なのはコードではなく、参考情報ということなら、
 # オブジェクトブラウザです。
(γ) 2019/10/18(金) 10:12

TreeViewコントロールは、VB6に付属していたものであり、64bit OSなんてなかった頃のものです。 情報を探すなら、VBAよりVB6を指定した方が良いかも知れません。

ただし、古いものなので、貴方のPC環境がXP以前なら良いのですが、最近のWINDOWS10、特に64bit版だと、コントロールのレジストリ登録が不完全なのか、ツリーに表示するアイコン指定するためのImageListのプロパティページが使えませんでした。 Excel標準の技術ではないし、MSが既に対応を止めたものだし、上級者でも使えるか判らないコントロールなので、初心者を自称するなら手を出さないのが良いと思います。(もし完成しても、他のPCで使おうとすると、コントロールのエラーになって動かない、とかあり得ます)

それよりも、なぜツリー表現がしたいのでしょうか? Excelに拘らないなら、例えばHTMLならjquery.treeview.cssというJavaScriptのフレームワークを使えば、簡単にツリー表現できます。(アイコンクリックでサブの展開とかアイコン変更とか、勝手にやってくれます) TreeView以外の実現を考えた方が良いと思いますよ。(もしツリー内容が可変ならば、ExcelでHTMLファイルを出力することは可能)
(???) 2019/10/18(金) 10:25


 たしかに古い技術のようですね。

 まあ、それ言うと、ExcelVBAそのものが全体としてはそういう傾向がありますね。
 でも、今や、ユーザーインターフェイスとしてExcelは不可欠です。
 金融(工学)の世界などでは、速度を要するところは他の言語でDLL化しておいて、
 Excelからそれを利用するというのが、全体の80%〜90%なんだそうです。
 Excelはそれだけ世の中で使われているという話。分野が特殊ですけど。

 TreeViewを利用するかどうは、質問者さんのご判断ですね。

 ちなみに、私の挙げた例でも
 >アイコンクリックでサブの展開
 はできています。
 というか、元々、そういう機能が組み込まれていますね。
 チェックボックスのON,OFFのつど、特定の動作をすることも一応実現できています。
 データの読み込みあたりは知らないけど。
 (なお、既定では備わっていないchildNodesを返すメソッドなども、
   Collectionを使えば可能ですし、.Nextがあるので現階層、子階層を
   traverseすることもツール化できるでしょう。)

 =====
 ところで、ネット検索していてすごいなと思ったのをご紹介。【余談につき失礼】

 Common controls treeではなく、MSForms2.0のうえでTreeViewを自作してしまったというもの。

 https://jkp-ads.com/Articles/treeview.asp

 Excel 2000〜Excel 2016 (32 and 64 bit)までは動作を確認してます、とのこと。
 初回公開は2013年。今でも利用者からのコメントがあるようです。

 上記サイトからExcelファイルがダウンロードできます。
 デモがありますし、ドキュメントもしっかりできています。
 パスワードとかは施してないので、クラスモジュールのコードなどもすべて読めます。
 これはすごいなあ。ここまでやっちゃうんだ、というのが感想。
 世間で使うかどうかは別。ダウンロードは3.5万件ほど。

 ご参考まで。

(γ) 2019/10/19(土) 22:41


皆さん回答をありがとうございます!!!
まだ確認の作業ができていないです。。。
また確認を終え次第連絡させていただきます。
(あみ) 2019/10/23(水) 14:34

γさんへ
 参考になるプログラムをありがとうございます。
 ループさせてさらに下の階層にもチェック状態を反映させるようにできました!
 すごく助かりました!!!

???さんへ
 要件定義をよくしておらず、VBAでも頑張れば不可能はないと思ってやっていたからだと思います。。。
 ちゃんと考えてから行動するようにします!!!

(あみ) 2019/10/24(木) 18:10


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.