VBA TreeView CheckBox 체크 이벤트 막기

⌜ VBA TreeView Checkbox  체크 이벤트 막기 ⌟

안녕하세요. 창원에 서식하고 있는 BIG MAN입니다.

오늘은 TreeView의 NodeCheck 이벤트에서 Checkboxes에 체크(Checked) 속성을 취소(Checked  = False) 시키는 방법에 대해 알아보겠습니다. TreeView를 자주 사용 경우 알고있으면 매우 유용한 기능이죠.

 

주의) 포스팅되는 모든 글은 게시자의 주관적인 관점이 포함되어 있으며, 절대적인 가이드가 아닙니다. 포스팅 글을 참조 후 발생되는 모든 책임은 본인에게 있음을 알려드립니다.

 

TreeView의 Checkboxes에 체크를 하게되면 TreeView_NodeCheck 이벤트가 발생하는데, 언뜻보기에는 NodeCheck 이벤트에서 끝나는 것 같지만 사실 그렇지가 않다.

NodeCheck 이벤트

그래서 NodeCheck 이벤트에서 "TreeView.Nodes.Item(1).Checked = False"라고 코드를 입력하고 실행해 보면 계속 1번 item의 Checkboxes에는 체크가 True 상태로 변화가 없다. 

 

분명 Checkboxes에 체크를 했는데, 이벤트는 "NodeCheck -> Click" 순서로 발생하는 것을 확인 할 수가있다. 정확한 이유는 모르겠지만, 디버그 상태에는 NodeCheck 이벤트에서 끝이 난다.

NodeChek 이벤트에서  Click 이벤트로 끝이 난다

그래서 마지막 이벤트인 Click 이벤트에 NodeCheck 프로시저에서 테스트해 보았던 "TreeView.Nodes.Item(1).Checked = False" 코드를 입력하고 실행하면 어떻게 될까? 아래와 같이 문제가 해결되었다. 즉, Checkboxes에 체크를 하는순간 Click 이벤트도 함께 발생하기 때문에 NodeCheck 이벤트에서 Checked = False로 설정해도 다시 Click 이벤트가 실행어 다시 Checked = True가 되어서 종료되기 때문에 발생되는 현상이다.

Click 이벤트에서 Checked = False를 설정해야 한다

문제점은 찾아냈다. 그럼 코드를 마무리해보자. 우선 TreeView에 item이 1개라면 위와 같이 하드코딩을 하면되지만, 보통 몇개에서 수십개의 item이 자동으로 등록되는 경우가 대부분이다. 따라서 NodeCheck 이벤트의 Node 정보를 Click 이벤트로 가져오면 간단하게 해결된다.

Node를 객체화 하거나, Index 만 가져오거나, Sheet에 Index를 담았다가 가져오거나.. 여러 방법이 있지만 첫번째 방법인 객체화하여 가져오는 방법으로 진행해 보자. 프로시저 간에 자료를 전달해야하므로 지역 객체변수를 선언한다. Node를 전달 받을 것이기 때문에 데이터 형식은 Node이다.

Private TreeViewNode As Node

NodeCheck 프로시저에서 객체변수에 Node를 할당한다. 이 Node는 클릭한 item의 Node 객체의 정보를 모두 가지고 있다. 즉, 어떤 item을 클릭해도 해당 Node를 쉽게 조작할 수 있다.

Private Sub tvTestTree_NodeCheck(ByVal Node As MSComctlLib.Node)
    Debug.Print "Private Sub tvTestTree_NodeCheck(ByVal Node As MSComctlLib.Node)"
    Set TreeViewNode = Node
End Sub

마지막으로 Click 이벤트에서 마무리하자. 여기서는 무조건 Checked = False 되어야 하기 때문에 False로 고정하였지만, 상황에 따라 조건은 변경하면된다. 마지막으로 사용이 완료된 객체를 메모리에서 비워주면 된다.

Private Sub tvTestTree_Click()
    Debug.Print "Private Sub tvTestTree_Click()"
    tvTestTree.Nodes.Item(TreeViewNode.Index).Checked = False
    Set TreeViewNode = Nothing
End Sub

Item은 생략가능하므로 아래와 같이 입력도 가능하다. 가능하면 명시적으로 입력하는 것을 추천한다.

    tvTestTree.Nodes(TreeViewNode.Index).Checked = False

여기서 하나 문제점이 발견된다. NodeCheck 이벤트가 발생되지 않은는 Click 이벤트에서 오류가 발생한다. Node가 Nothing인 상태이기 때문이다. 그럼 if 문으로 한번 체크하고 실행하게 되면 문제는 해결된다. Is 연산자와 Nothing 키워드를 사용하면 간단하게 확인이 가능하다. 

Private Sub tvTestTree_Click()
    Debug.Print "Private Sub tvTestTree_Click()"
    If Not TreeViewNode Is Nothing Then
        tvTestTree.Nodes.Item(TreeViewNode.Index).Checked = False
        Set TreeViewNode = Nothing
    End If
End Sub

그럼 전체 코드를 보자. 관련 파일은 아래 첨부 파일에 다운로드가 가능하다.

    Option Explicit
    Private TreeViewNode As Node

Private Sub tvTestTree_Click()
    Debug.Print "Private Sub tvTestTree_Click()"
    If Not TreeViewNode Is Nothing Then
        tvTestTree.Nodes(TreeViewNode.Index).Checked = False
        Set TreeViewNode = Nothing
    End If

End Sub

Private Sub tvTestTree_NodeCheck(ByVal Node As MSComctlLib.Node)
    Debug.Print "Private Sub tvTestTree_NodeCheck(ByVal Node As MSComctlLib.Node)"
    Set TreeViewNode Node
End Sub

Private Sub UserForm_Initialize()
    Call TreeViewItemADD
End Sub

업무상 어쩔 수 없이 VBA을 독학으로 배우다 보니 설명이 부족한 점이 많이 있습니다. 궁금한 점이 있다면 언제든지 댓글 남겨주시면 추가 설명드리도록 하겠습니다. 

 

👾코로나18👾과 항상 친하게 지내시고, 싸우지 마세요. 이젠 그들과 함께하는 수 밖에 없습니다. 감사합니다. 👋🏻😃

✅ 참고

2021.08.05 - VBA AutoFilter 배열을 이용한 다중 선택 방법

2021.07.05 - VBA Outlook Categories Remove, ADD - 범주 색상 제거 및 추가

2021.06.28 - VBA 변화는 Column 위치 쉽게 찾기

더 많은 정보는...

 

✅ 첨부 파일

TreeViewNodeCheckboxes.xlsm
0.02MB

 

728x90