이글의 모토는 Access를 이용한 엔지니어링 어플리케이션 개발경험을 공유하는 것이다. 그런데 쓰다보니 약간은 엉뚱한 기초적인 부분들을 건드리게 되었다. 아마도 이글을 보는 사람들이 DB에 썩 익숙하지 않을 것 같아서 나름 배려를 한 것인데, 필자 자신도 상세하게는 모르는 것들이 많아서 기초부분에 대해 더 많은 지면을 할애해야 할지 고민이 되었다. 솔직히 말하면 필자의 엑세스에 대한 지식은 매우 얄팍하다고 할 수 있다. 단지 필자가 엑세스를 이용한 여러가지 엔지니어링 솔루션을 만들면서 엑세스의 우수성을 알게되고, 보다 많은 사람들이 엑세스를 쓰기를 바라는 마음에서 이런 글을 쓰기 시작한 것이다. 따라서 이 글은 엑세스의 기초를 설명하는 부분은 다른 분들에게 맡기고 되도록 어플리케이션에 집중하고자 한다. 이글에서 부족한 부분은 다른 블로거나 웹싸이트의 지식을 참고하시고, 그래도 부족하면 책을 한권 사시는 것을 추천드리겠다.
1. 심의관리 프로그램(데이터 구조 설계)
회사에서 심의위원회를 하나 관리하고 있다. 심의위원과 심의위원회별로 어떤 위원들이 참여했는지 이력을 손쉽게 관리하고자 프로그램을 만들게 되었다. 엑셀로 관리해도 무방하지만 예제로서는 딱이다 싶어서 내용을 공유하고자 한다.
먼저 두 개의 테이블이 필요하다. 하나는 심의위원(Members) 테이블이고, 다른 하나는 심의위원회(Commitee) 테이블이다. 심의위원 테이블에서는 심의위원회에 참여가능한 전문가들의 개인정보를 관리하고, 심의위원회 테이블에서는 심의위원회 이름, 개최일시, 장소 등에 대한 내용을 관리한다. 그렇다면 심의위원회에 참여한 심의위원들의 정보는 어떻게 관리해야할까? 앞서 설명한 두 테이블 중 하나에 참석한 심의위원의 정보를 추가해야할까? 추가해야한다면 어떤 방식으로 추가해야할까?
엑셀이라면 심의위원회 정보항목에 아래 그림과 같이 심의위원 항목을 추가할 수 있다. 그리고 그 심의위원에 대한 상세정보는 심의위원 정보가 담긴 다른 테이블이나 sheet에서 확인할 수 있다. 그런데 만약 심의위원별로 어느 심의위원회에 참석했는지 정보를 찾아내야 한다면 아래와 같은 테이블 구조로는 손이 많이 갈 수 밖에 없다.
엑셀은 자료를 직관적으로 정리하는데는 매우 유용한 프로그램이다. 그러나 데이터가 많이 쌓이기 시작하고, 여러가지 시각으로 데이터를 분석해야한다면 일량이 만만치 않게 늘어나게된다. 위의 테이블과 반대로 심의위원 테이블에 심의위원이 참석한 이력을 추가한다면, 심의위원회별로 참석한 심의위원을 찾아내기가 수월하지 않게된다. 즉 심의위원회에 참석한 심의위원 정보는 심의위원회 테이블이나 심의위원 테이블 그 어느 곳에 저장하더라도 분석에는 적절치 않다. 그렇다면 어떤 수단을 강구하는 것이 적절한 것일까?
엑세스라면 테이블을 하나 더 만들수 있다. 이 테이블(Deliberation)은 심의위원회 ID와 심의위원 ID로만 구성된 테이블이다. 앞 절에서 DB 테이블을 만들때 레코드의 식별을 위한 일련번호를 부여했었다. 이 일련번호를 이용하는 것이다. 아래 표를 보자. 아래 표에는 3개의 위원회가 열린 것을 나타낸다. 각 위원회의 일련번호는 '1', '2', '5'번이다. 각 위원회에는 2명의 심의위원들이 참여했다. '1'번 위원회에는 일련번호가 '1'과 '2'번인 심의위원이 참석했고, 일련번호가 '2'인 위원회에는 '3', '4'번 심의위원이 참석했다.
위 테이블은 엑세스의 조인(Join)을 이용하면 다양한 정보를 표시해줄 수 있다. 조인을 사용하기 위해 쿼리를 하나 만들어보자. 이 쿼리는 특정 일련번호의 심의위원회 정보와 그 심의위원회에 참석한 위원정보를 제공한다. 이 쿼리의 구조는 아래 그림과 같다. Deliberation 테이블의 CommiteeID를 이용하여 Commitee 테이블과 조인을 하고, MemberID를 이용하여 Members 테이블과 조인을 하였다. 이로인해 생기는 새로운 테이블은 위원회 정보와 참여위원정보를 모두 포함하게 된다. 기본적으로 이 쿼리 테이블은 모든 심의위원이 참석한 모든 심의위원회 정보를 보여줄 수 있다. 그러나 우리가 원하는 것은 모든 정보가 아니라 특정한 심의위원회에 대한 정보만을 요청하는 것이다. 따라서 아래 그림 하단 테이블의 우측 끝에 Commitee ID필드에 대한 조건을 설정해 놓은 것을 볼 수 있다.
조건에 쓰여져 있는 내용은 다음과 같다.
[TempVars]![CommiteeID]
이 의미는 엑세스 매크로에 SetTempVar 함수를 이용해 정의한 CommiteeID라는 변수와 같은 값을 갖는 Commitee 테이블의 ID만을 표시하라는 뜻이다. 즉 쿼리로 심의위원들이 참여한 모든 심의위원회와 심의위원을 표시하지 말고 매크로에서 정의한 특정 변수와 같은 하나의 심의위원회와 그 심의위원회에 참여한 심의위원만을 표시하게된다. 아래 그림은 매크로 정의화면이다. (매크로정의에 대한 자세한 내용은 다른 자료를 참고하시기 바란다)
자 지금까지 내용을 정리하면 우리는 3개의 테이블과 1개의 쿼리, 1개의 매크로 변수를 정의하였다.
2. 기능설계
심의관리 프로그램은 크게 4가지 주 기능을 갖도록 설계하였다.
(1) 심의위원 등록/조회, (2) 심의위원회 등록(심의위원 지정), (3) 심의위원회 조회, (4) 프로그램 종료의 4가지 기능이다. 따라서 엑세스의 메인 첫 화면은 다음과 같다.
다음은 심의위원 등록 화면이다. 엑세스의 기본기능을 활용하였다.
앞 절의 내용을 참고하면 쉽게 만들 수 있는 화면이다. 테이블 전체 내용을 폼에 추가하였다. 단지 Close 버튼만 추가하였는데 버튼은 On_Click 이벤트로 다음 코드를 추가하였다.
DoCmd.Close
심의위원회 등록 및 심의위원 선정화면은 다음과 같다. 이 화면은 엑세스의 기본기능으로 구성하기 복잡하기 때문에 대부분의 기능을 VBA로 구성하였다. 자세한 내용은 다음 절에서 설명하겠다. 기능에 대해서만 간단히 설명하면 화면 상단에 Title, OpenTime, Place, Description은 Commitee 테이블의 각 필드 들이다. 이 필드들에 대해 입력한 후, 아래에서 등록된 위원목록(member list)에서 위원을 선택하고 두 개의 리스트박스 중간에 위치한 버튼을 누르면 좌측 member list의 위원이 commitee member list에 표시된다. 심의위원은 2명만 선택이 가능하고 3명 부터는 기능적으로 추가되지 못하도록 한다. 최종적으로 하단의 Save 버튼을 클릭하면 Commitee 테이블과 Deliberation 테이블에 내용들이 저장되고, Save 버튼은 비활성화된다.(일단 이 예제에서는 한번 저장되면 수정이 불가능하다. ^^;)
자 마지막은 심의위원회 조회 화면이다. 쿼리만 준비되면 아주 간단히 구성할 수 있다. 좌측 리스트 박스의 심의위원회 제목을 클릭하면 우측 리스트 박스에 위원회와 심의위원에 대한 내용을 조회할 수 있다.(쓸데없이 위원회에 대한 내용이 반복적으로 나타나고 있다 ^^;)
3. Coding
메인화면과 첫번째 화면은 사실 코딩 내용이 거의 없다. 폼을 열었다 닫는 정도이다. 그러나 두번째와 세번째 화면에는 코딩이 들어가고 특히 두번째 화면에 많은 코딩이 들어간다. 두번째 화면부터 살펴보자. 먼저 두 개의 리스트박스 사이에 있는 화살표 버튼에 대한 이벤트이다. 아래 화면의 코딩내용을 살펴보자. 화면을 보면 두 개의 리스트 박스가 있다. 좌측의 박스는 lstMember로 Members 테이블에 있는 내용을 표시하도록 설정되어 있다. 리스트박스를 만들때 Members 테이블에 있는 ID, Name, Affiliation, Position, Professional의 다섯개 필드를 가져오도록 하였고, 이 중 오로지 Name만 표시하도록 하였다. 그래서 리스트 박스에는 이름만 표시되지만 안보이는 영역에 4개의 다른 값들을 포함한다. 정의하는 방법은 아래 그림을 참조하기 바란다.
* 주의 : lstCommiteeMember의 Raw Source Type(행원본 유형)은 Value list(값 목록)이어야 한다.
첫 줄의 lstItem이라는 스트링 변수를 선언하였다. 이것은 좌측 리스트박스의 정보를 복사하기 위한 변수이다.
두 번째 줄의 If문은 리스트박스가 선택이 되었는지를 체크하는 기능을 한다. 만약 사용자가 위원목록 중 어느것도 선택하지 않으면 메세지 박스를 띄우고 이벤트를 빠져나간다.
세 번째 줄은 lstItem에 lstMembers 리스트박스에 선택된 행의 정보들을 ','를 구분자로 이용하여 저장한다. 총 5개의 정보가 저장된다.
네 번째 줄은 lstCommiteeMemeber의 리스트를 2개로 제한하는 If문이다. 리스트박스에 리스트가 하나가 있으면 속성 ListCount는 '1'을 나타낸다. 따라서 기본의 리스트박스에 아이템이 없거나 하나만 있을 때 아이템을 추가할 수 있다. 리스트 박스에 리스트를 추가할 때는 다음 형식으로 사용한다.
ListBox.AddItem Item:= StringVariable
특히 'Item:='에 유의하자. 그냥 문법이니 지켜야 한다.
자 다음은 Save 버튼이다.
첫 번째 : Deliberation 테이블에 저장할 CommiteeID를 Long형으로 정의한다.
두 번째 : Deliberation에 2명의 심의위원을 추가해야하므로 for문을 써서 DB 추가를 반복할 예정이다. 따라서 for문에 사용할 카운트 변수 iCount를 정수형으로 정의한다.
세 번째 : Commitee 테이블에 들어갈 각 필드들의 입력값이 Null이나 공란이 들어가지 않도록 필드에 연결된 텍스트박스들을 검사한다. 만약 하나라도 공란이 생기면 이벤트를 빠져나간다. 심의위원도 2명이 선택되지 않으면 저장되지 않는다.
네 번째 : 입력 조건이 만족되면 Commitee 테이블을 연다. rs.AddNew를 이용하여 위원회에 관련된 정보를 입력한 후 레코드와 db를 닫는다. 이때 위원회 ID를 CommiteeID에 저장한다.
다섯 번째 : Deliberation 테이블을 연 후, lstCommiteeMember 리스트박스의 내용 중 첫째 리스트의 Column(0)에 있는 ID값을 CommiteeID와 함께 저장한다. 이 때 반복적으로 저장해야하기 때문에 for 문을 사용하고 lstCommiteeMemeber.Selected(iCount)=true를 이용하여 선택되는 리스트 행을 조정한다. 만약 lstCommiteeMemeber.Selected(0)=true이면 첫째 행이 선택된 것이고, lstCommiteeMemeber.Selected(1)=true이면 둘째 행이 선택된 것이다. 선택된 각 행의 Column(0)에는 위원의 ID 값이 들어 있으므로, 그 값을 테이블에 저장한다.
여섯 번째 : 포커스를 Cancle 버튼으로 옮긴 후, Save 버튼을 비활성화 시킨다.
자 이제 마지막으로 위원회 조회 화면을 살펴보자. 위원회 조회화면은 두 개의 리스트 박스로 구성되고 좌측의 리스트박스의 위원회 제목을 선택하면 우측 리스트박스에 위원회와 심의위원에 대한 정보가 나타난다. 아래 코드를 살펴보자. 놀라울 정도로 단순한다. 그럴수 밖에 없는 이유는 우측 리스트박스는 데이터 구조에서 살펴보았던 바로 그 쿼리 테이블을 나타낸 것이기 때문이다. 이 쿼리 테이블은 위원회 ID([TempVars]![CommiteeID])만 바꿔주면 내용이 갱신된다. 이에 맞추어 코드의 맨 마지막처럼 리스트박스를 Requery해주면 내용이 바뀌는 것이다. 그렇다면 [TempVars]![CommiteeID]는 어떻게 값을 얻어올까? 앞에서 처럼 왼쪽 리스트박스에 선택된 행의 Column(0)값을 가져오면 되는 것이다. 우측의 리스트박스는 위원회 테이블 중 ID와 위원회 이름만으로 리스트들이 구성된다. 그 중 ID는 숨겨진 값이으로 리스트박스에는 표시되지 않는다. 그래도 실제로는 존재하는 값이므로 아래 코드에서와 같이 값을 얻어올 수 있다. 물론 아래코드와 달리 직접
[TempVars]![CommiteeID]=lstCommitee.Column(0)
와 같이 표시해도 코드 실행에는 문제가 없다.
4. 마치며
글을 쓰기 시작한 이래 예제다운 예제 하나를 이제야 올린 것 같다. 혹시 내용 중 의문나는 사항이 있으시면 댓글을 남겨주시길 부탁드린다. 다음 회부터는 본격적인 엔지니어링 예제에 도전해 보겠다.(아마 두 번에 나누어 글을 올려야 되지 않을까? ^^;)
댓글 없음:
댓글 쓰기