나눔터  
  HOME > 나눔터 > 묻고답하기 > 엑셀
엑셀
엑셀에 대한 질문과 답변을 올려주세요. 단, 취지에 맞지 않는 글은 운영자가 삭제합니다.
 "000 님, 도와주세요", "부탁 드립니다.", "급합니다!" 등과 같이 막연한 제목을 달지 말아주세요.
[필독] 빠르고 정확한 답변을 얻는 16가지 Tip !
[필독] 저작권법 개정에 따른 이용안내
작성자:  

 조삿갓 (choga21)

추천:  2
파일:     답변_test (1)-170926-1-1.xlsm (20KB) 조회:  2402
제목:   [RE]vba의 함수 실행 질문을 드립니다.
     
  - 엑셀 버전: 2013

* 아래줄에 질문을 작성하세요 >>

병원명에 있는 콤보 박스를 실행시키면 alt+f11 -> vba에 Private Sub Worksheet_Change(ByVal Target As Range)라는 함수? 가 있는데 
콤보박스를 실행을 했을때 어떻게 저 함수가 실행이 되는지 알고싶습니다.
콥보박스에 저 함수가 실행이 되는 무언가가 달려있는건지요..??
자세한 설명 부탁드리겠습니다...ㅠ
==============[김원호님 글에 대한 답변입니다]==============

아마도 다른 분이 기본 개발해 둔 양식에 추가 개발을 원하시는 듯 하군요.

A열에 나타나는 콤보박스는 개체를 삽입해서 나타나는 것이 아니고
데이터유효성 검사의 기능입니다.
즉, 데이터유효성 검사를 '목록'으로 지정했을 때 콤보박스가 나타납니다.

콤보박스에 Worksheet_Change 프로시저가 연결된 것이 아니라
콤보박스를 선택하여 시트에 있는 셀의 값이 바뀌는 경우에
(꼭 콤보박스가 아니고 아무 셀에든지 값을 바꾸어주면)
Worksheet_Change 프로시저가 실행되는 것이 VBA의 원리입니다.
(개체지향 프로그래밍이라고 하지요)

Worksheet_Change 프로시저의 동작에 대해서는
주석으로 설명을 달아 두었으니 참고하시기 바랍니다.

보통 개체_이벤트 형식으로 이름지어진 프로시저를
'이벤트핸들러'라고 합니다. 예를들면

버튼1_Click() 프로시저는 버튼1을 클릭하면 실행되고

Worksheet_Activate() 프로시저는 해당 워크시트가 활성화되었을 때(시트탭을 클릭하여 열었을 때) 실행됩니다.

그런데, 원래 보내주신 파일을 보니
그 Worksheet_Change 프로시저의 코드가 매우 비효율적으로 되어 있어서
효율적으로 수정하였습니다.

사실은 Worksheet_Change 핸들러는 아무 셀이든지 새로운 값을 입력하기만 하면
무조건 호출됩니다.
다만, 프로시저 내에서 IF 조건문을 걸어 두었기 때문에
A열에 입력 값이 바뀐 경우에만 주어진 명령어들이 수행되지요.

그렇게 A열만 필터링하는 방법이 원래 파일에서는 아주 비효율적이었습니다.
답변 파일처럼 직접 행번호와 열번호를 가지고 제어하는 것이 효율적입니다.

아울러 시트 구조를
질문자께서 원하는 기능을 구현하는데 편리하도록 일부 수정하였습니다.
(추가한 수식이 있는 곳에 밝은 녹색 음영을 표시하였음)

원래의 시트에서 적용했던 범위 설정도 오류나 불합리한 점이 있어서 수정하였습니다.

'병원명목록'의 경우 그렇게 지정하시면 중복된 데이터들이 불필요하게 나열됩니다.
중복을 피하고 목록에서 선택하여 입력할 수 있게 하려면
별도의 목록을 답변 파일과 같은 방법으로 만들어 주어야 합니다.

답변 파일에서는 병원명목록 이름 정의가 변경되었습니다.

그리고, A열에 병원을 입력하면
그 병원에 따라 B열에서 보이는 목록의 상황이 달라져야 하는데
그것을 이름으로 고정 정의하면 원하시는 목적을 달성할 수 없습니다.

답변자료처럼, 병원명에 따른 의사목록의 상대 위치 값(시작위치, 의사 수)을
각 행별로 별도 계산하고, 그 값에 따른 offset 함수를 데이터유효성검사 목록에
직접 입력하면 됩니다. 물론 이 때 주소 지정 방식을 절대참조와 상대참조를
적절히 사용해야 하지요.

따라서 기존에 정의된 이름 중에서 의사명목록과 의사코드목록은 무용지물입니다.

의사코드를 표출하는 것은 입력을 하는 것이 아니고
병원명과 의사명이 정해지면 그에 따라 미리 정해진 코드 값이 나타나야 하지요.
따라서 C열은 유효성검사가 아닌 수식으로 해결해야 합니다.

그리고 Worksheet_Change 이벤트 핸들러에 의해서
A열에 병원이름이 추가되거나 삭제되는 것에 따라
C~E열의 수식이 자동으로 입력되거나 지워지게 하였습니다.

그리고 이것은 당초 프로그램에서는 100행까지 한계가 있었지만
이 파일에서는 한계가 없이 워크시트의 마지막 행(1048576)까지 입력 가능합니다.

C~E열의 수식을 보호하는 방법도
시트보호를 할 경우에는 VB코드 안에서 해제했다가 다시 보호하는 코드가 들어가야 하지만
데이터유효성검사를 이용하여 입력 금지를 구현하였으니 참고해 보시기 바랍니다.

코드 시트 역시 Worksheet_Change 이벤트 핸들러를 코딩하여
B열에 데이터를 추가하거나 삭제함에 따라 녹색 음영의 수식이
자동으로 생성되거나 삭제되도록 하였습니다.

한 가지 주의할 것은
병원명은 반드시 동일한 병원은 연속데이터로 입력해야 하고
가-가-나-나-가
이런 식으로 가 병원이 두 군데에 떨어져 입력되면
오류 메시지가 A열에 나타납니다.

이 때에는 자동필터의 정렬 기능을 이용하여 병원명 순서로 정렬하시기 바랍니다.

즉, 답변 파일에서는 코드의 정보가 '고정'이 아닌 '가변'이 되더라도
병원별로 그룹화시켜주는 원칙만 지켜주면 원하는 기능으로 작동한다는 뜻이지요.
 
[불량 게시물 신고]  
        
  

작성일 : 2017-09-26(23:18)
최종수정일 : 2017-09-26(23:18)
 


 ◎ 관련글

  제 목   작성자   날짜
vba의 함수 실행 질문을 드립니다. 김원호 2017-09-26
[개선] 동적 유효성검사 목록 및 Worksheet_Change 이벤트 활용 조삿갓 2017-09-27
[RE]vba의 함수 실행 질문을 드립니다. 조삿갓 2017-09-26