2015년 7월 5일 일요일

MS 액세스(Access) VBA를 이용한 엔지니어링(Engineering) 데이터베이스(Database) 어플리캐이션(Application) 개발 Ch. 2

0. 들어가면서

  이글의 모토는 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. 마치며

  글을 쓰기 시작한 이래 예제다운 예제 하나를 이제야 올린 것 같다. 혹시 내용 중 의문나는 사항이 있으시면 댓글을 남겨주시길 부탁드린다. 다음 회부터는 본격적인 엔지니어링 예제에 도전해 보겠다.(아마 두 번에 나누어 글을 올려야 되지 않을까?  ^^;)

2015년 6월 21일 일요일

MS 액세스(Access) VBA를 이용한 엔지니어링(Engineering) 데이터베이스(Database) 어플리캐이션(Application) 개발 Ch. 1


0. 폼을 이용한 데이터베이스(이하 DB) 입력/조회

  사실 엑세스는 기본적으로 DB 테이블을 생성하면 손쉽게 직접 테이블에 입력하거나 폼을 통해 입력과 조회가 가능하게끔 기능들을 구비해 놓았다. 테이블을 생성하고 입력하는 기능은 매우 직관적이기 때문에 굳이 여기서 언급을 할 필요는 없고 간단하게 폼을 이용하여 DB를 입력하고 조회하는 방법을 집고 넘어가보자.
  아래 화면은 심사위원 예제를 만들기 위해 작성한 Members 테이블이다. 이번 예제에서는 이 테이블 하나만을 생성할 것이다. 생성하는 방법은 아주 간단하니(웹 검색을 해보거나, 센스 있는 분들은 직관적으로 깨달을 수 있다) 여기서 과정은 생략하겠다. 이 테이블에는 10개의 필드가 있다. 독자께서는 굳이 10개의 필드를 만들지 않으셔도 되며, 단지 2~3개의 필드로도 예제의 실습이 가능하다.


  간단하게 필드에 대해 설명하자면, ID는 심의위원 고유번호이고, Name은 이름, Affiliation은 소속기관, Department는 부서, Position은 직위, Professional은 전문분야, Office는 사무실 연락처, Mobile은 휴대전화, email은 email 주소, Address는 주소를 나타낸다. 모두 속성은 보시는 바와 같이 텍스트이고, 데이터 크기는 15~70까지 다양하다. 어떤 기준이 있는 것은 아니니 독자께서 적당히 정해주시면 되겠다. 각 필드의 다른 속성들은 나중에 기회가 닿는 데로 설명을 드리겠다.
  테이블을 만들었으면 입력과 조회를 할 수 있는 폼을 만들어 보자. 폼의 제목은 Registration이다. 이전 회에서 폼 만들기를 해 보았으니 과정은 생략하고, 폼이 만들어 졌으면 폼 속성 > 데이터 탭에서 레코드 원본을 아래와 같이 Members 테이블로 지정한다.


다음은 리본메뉴의 디자인 >> 기존필드 추가를 선택하면 아래 화면과 같이 속성창이 있던 자리에 Members 테이블의 필드들이 표시된다. Shift키를 이용하여 전체를 선택한 후 마우스로 드래그하여 폼에다 갖다 놓으면 폼위에 아래 화면과 같이 필드들이 배치된다. 필드 크기에 따라 입력박스의 크기를 조절한다.



이것으로 폼을 만드는 작업은 끝났다. 이제 실행만 시켜보면 된다. 실행방법은 전회를 참고바란다. 실행의 결과로 아래 화면이 나타난다. 매우 단순하지만 기본적으로 있을 건 다 있다. 먼저 테이블에서 정의한 필드들의 입력박스들이 모두 나타나있다. ID 입력항목이 (새항목)으로 표시되어 있는 것은 새 레코드 세트가 입력할 준비가 되어있다는 뜻이다. ID 입력창은 편집이 불가능하고 ID하단에 있는 어느 하나의 입력창이라도 입력이 되면 ID에 숫자가 등록된다.


  Members 테이블을 설계할 때 필드속성에 '필수'를 '예'로 지정한 필드들이 있으면 그 필드들을 모두 입력하지 않으면 레크드 세트가 완성되지 않으므로 다음 레코드 세트를 입력할 수 없다. 아래 그림은 테이블을 설계할 때 화면 하단에 나타나는 필드 속성창이다. '필수'라는 필드 속성과 도움말이 나타나 있다.


  레크드 이동은 폼 하단에 아래 화면과 같은 도구 바가 마련되어 있다. 적색 원 안의 아이콘을 클릭하면 다음 레코드로 이동하고 청색 원안의 아이콘을 클릭하면 이전 레코드로 이동한다. 두 아이콘 가운데 2/2로 표시된 것은 총 2개의 레코드 중 2번째 레코드를 폼이 나타내고 있음을 의미한다. 레코드 이동 아이콘 바깥에 있는 아이콘들을 클린하면 각각 레코드의 시작과 끝으로 이동할 수 있다. 바의 오른쪽에 검색은 레코드 중에 필드 데이터를 검색하는 기능을 수행한다.


  아래 화면은 최종적으로 데이터가 입력된 폼이다. 기본적인 작업을 수행하는데 아무런 지장이 없다. 여기에 쿼리 테이블 기능이 추가되면 더욱 다양한 기능들을 수행할 수 있다. 사실 엑세스를 이용한 작업 중 VBA를 사용해야하는 부분은 어떻게 보면 아주 일부라고 할 수 있다. 특수한 작업이나 기능에 대해 VBA가 필요한 것이지 일반적인 작업에는 엑세스가 제공하는 기능만 잘 사용해도 다 커버가 된다.




1. VBA는 어떤 역할을 할 수 있는가

  엑세스의 기본기능으로 구성된 폼을 살펴보자. 이 폼은 DB관리 시스템이 가져야하는 기본적인 기능들은 모두 제공한다. 그렇다면 추가기능을 생각해보자. 이 DB에 특정회사나 직위, 전문분야에 관련된 사람의 수를 파악해보고 싶다면 엑세스의 기본기능으로 곤란하다.
  자 오늘은 VBA로 이 기능을 개발해보자. 개발순서는 다음과 같다. 먼저 버튼을 위에 만들어진 폼에 하나 만든다. 버튼을 누르면 폼이 추가로 하나 생성된다. 그 폼에는 소속기관을 입력할 수 있는 입력박스가 하나 있고, 버튼은 Search(탐색)과 Cancel(취소) 두 개가 있다. Search 버튼을 누르면 메세지 박스로 동일한 소속기관의 숫자를 보여준다. Cancel 버튼을 누르면 폼은 사라진다.
  정리하면, 우리가 만들어야될 객체는 기본화면에 버튼 하나, 추가적인 폼 하나, 추가 폼위에 버튼 두개, 이렇게 네 개를 만들어야 한다. 제일 먼저 해야할 일은 추가 폼을 만드는 일이다. 추가 폼에는 레코드 관련 기능이 필요없다. 따라서 폼을 생성한 후 속성창에서 아래그림과 같이 '형식' 테에서 '레코드 선택기'와 '탐색단추'를 '아니오'로 설정한다.
* 폼을 만들때 '기타' 탭의 팝업 속성은 '예'로 설정한다.



추가된 폼의 이름은 Search로 하고 입력 텍스트박스를 추가하면 아래와 같은 화면이 나타난다. 일단 팝업된 설정 다이얼로그는 취소를 시킨다.


그리고 테스트 입력박스를 선택한 후 속성창의 '기타' 탭에서 이름을 txtAffiliation으로 고친다. 다시 레이블을 선택한 후 속성창 '형식' 탭에서 '캡션'을 Affiliation을 수정한다.

  

이제 두 개의 버튼을 추가하자. 버튼 추가방법은 생략한다. 아래 화면은 추가 폼의 완성된 형태다.


 다음은 기본 폼에서 Search 폼을 나타나게 하는 버튼을 추가한 다음 코드작성기를 이용하여 코드를 작성한다. 버튼의 캡션은 Same Affiliation No. 로 하고 버튼의 이름은 cmdSameAffil로 하자.


코드작성기에 다음과 같은 코드를 추가한다.


이 간단한 코드가 Search 폼을 나타내게 하는 역할을 한다. 여기서 DoCmd에 대해 알아보고 가자. DoCmd는 엑세스에서 다양하게 쓰이는 객체로 주로 기본명령을 수행하는데 사용된다. 즉 폼을 열거나(OpenForm), 폼을 닫거나(Close), 보고서를 열거나 등등의 기능을 수행하는데 자세한 내용은 https://msdn.microsoft.com/en-us/library/office/ff192694.aspx를 참고하기 바란다. 아래 화면은 버튼을 눌러서 실행한 화면이다.


이제부터가 본격적인 VBA 과정이라 할 수 있다. 먼저 쉬운 Cancel 버튼 부터 시작하자. 폼을 닫는 코드는 DoCmd.Close 이다. 간단하게 이 코드를 Cancel 버튼에 연결해주면 추가 폼이 닫히게 된다. 문제는 Search 버튼이다. Search 버튼은 기본적으로 DB 테이블에 접속한 다음 쿼리명령어를 이용하여 원하는 값을 얻어오는 것이다. 먼저 DB접속부터 알아보자
  DB에 접속하기 위해서는 DB 객체를 먼저 생성해야한다. 그리고 객체를 생성하는 첫번째 단계는 선언을 하는 것이다. 선언내용은 다음과 같다.

Dim db as DAO.Database
Dim rs as DAO.Recordset

DAO는 Database Access Object로 DB와 연결하기 위한 객체이다. 객체의 하위에는 Database와 Recordset등이 있다.
자세한 내용 https://en.wikipedia.org/wiki/Data_access_object에서 알아보기 바란다.
객체를 선언했으니 아래와 같이 DB와 접속을 한다.

    Set db = CurrentDb
    Set rs = db.OpenRecordset("select * from [Members] where [Affiliation]='" & strAffiliation & "'", dbOpenDynaset)

첫번째 줄은 거의 관용구라고 생각하면 된다. 두번째는 OpenRecordset함수로 형식은 다음과 같다.

OpenRecordset(Neme, Type, Option, LockEdit)

위의 매개변수 중 Name은 String변수로 레코드세트를 가져올 Source를 나타내며, 테이블 이름이나 쿼리식 또는 SQL문이 될 수 있다. Type은 Variant변수로 접속하려고 하는 레코드세트를 나타낸다. 만약 MS Access DB 객체를 연다면 정의할 필요는 없다. Option도 Variant로 생성하는 레크드세트의 특성을 나타낸다. LockEdit는 Option을 보조해주는 기능을 수행하며 생성객체를 제한한다. 자세한 내용은 http://msaccess.tistory.com/46를 참고하시길...
위에서 Name은 SQL식으로 Members라는 테이블에 접속해서 Affiliation이 strAffiliation 스트링 변수와 같은 값을 갖는 레코드를 모두 찾아서 rs라는 레코드세트에 저장하는 명령어다. strAffiliation은 txtAffiliation 값을 가져오는 변수로 정의된다. 좀더 차근차근 설명하면

select * from [Members] : Members 테이블에서 모든 필드 값을 가져온다.
where [Affiliation]='" & strAffiliation & "'" : Affiliation 필드가 strAffiliation과 값이 같은
원래는 "where [Affiliation]='strAffiliation'" 인데 이렇게 쓰면 strAffiliation변수가 인식이 안되기 때문에 위와 같이 &로 문장을 이어주면서 strAffiliation을 " " 밖으로 빼내어 변수로 인식하겠금 하였다. dbOpenDynaset은 type을 나타내는 상수이다. 가장 무난하게 접속대상을 정의하는 상수라 할 수 있다. Option과 LockEdit는 생략하였다.

전체 코드는 아래와 같다.

    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    Dim strAffiliation As String
 
    strAffiliation = txtAffiliation

    Set db = CurrentDb
    Set rs = db.OpenRecordset("select * from [Members] where [Affiliation]='" &                                                     strAffiliation & "'", dbOpenDynaset)
    rs.MoveLast
 
    MsgBox (rs.RecordCount)
                         
    rs.Close
    db.Close
    Set rs = Nothing

하단의  rs.MoveLast는 레코드세트의 마지막으로 이동하라는 명령으로 레코드세트가 몇 개인지 세기 위해서는 레코드세트의 마지막까지 컴퓨터가 세어 보아야한다. 보통 레코드세트가 생성된 시점에서는 항상 레코드세트의 수를 세면 '0'이다.

다음의 MsgBox는 이전 절에서 학습을 하였고, 눈치 빠른 분은 아셨을 테지만 rs.RecordCount는 레코드세트의 숫를 세는 멤버함수이다. 즉 메세지 박스에는 레코드세트의 숫자가 몇 개인지를 나타내게 된다.

레코드세트를 만들었으면 프로그램 모듈이 끝나기 전에 해제해주어야한다. 제일 하단의 3줄은 레코드세트를 해재해주는 절차이다. 아래 화면은 최종적으로 실행한 화면과 코드다.





[끝]


2015년 6월 13일 토요일

MS 액세스(Access) VBA를 이용한 엔지니어링(Engineering) 데이터베이스(Database) 어플리캐이션(Application) 개발 (프롤로그)


0. 글을 시작하기 전에

  나이가 들면 기억력이 감퇴된다는 것을 알았을 땐 이미 많은 중요한 기억들이 사라진 후였다. 나이를 먹었다는 것을 먼저 인지 했는지, 아니면 기억력이 감퇴 되었다는 것을 먼저 인지 했는지는 모르겠다. 다만 이제 일상생활의 불편함 뿐만 아니라 업무 능률에도 영향을 미치기 시작했다는 것이다. 심각성이 커진 것이다.
  여러 날을 대책을 세우기 위해 보냈는데, 결론은 일단 적자는 것이었다. 되도록 노트를 만들어서 내가 배우고 깨달은 중요한 내용들을 적기위해 노력했다. 노트에 적는 것은 효과가 있었다.  그러나 세 가지 문제점이 있다는 것을 깨달았다. 첫째 나는 노트와 펜을 잘 가지고 다니지 않는다는 점이다. 대신 휴대폰과 아이패드(또는 갤럭시 탭)는 항상 가지고 다닌다. 정말 필요할 때 노트와 펜이 없었던 적이 왕왕 발생했다. 둘째 노트에 적어 놓은 것을 찾지 못하는 경우가 발생했다. 더욱이 노트가 바뀌면 이 문제는 더 심각해졌다. 셋째 단편적인 메모를 정보로 만들기 위해서는 구조화가 필요한데, 노트에 적는 것만으로는 부족하다는 점이다. 여기에 대해 두 가지 해결책을 세웠는데, 첫째가 되도록 전자노트-휴대폰, 태블릿의 앱등을 이용한 노트-를 사용하자는 것이고, 둘째가 블로그를 만들자는 것이다. 물론 내가 가진 모든 지식을 블로그로 만들 수는 없다. 그러나 블로그 형식으로 만들수는 있고, 이 중 공개가 가능한 지식은 공유해서 필자와 같은 어려움을 겪었던 사람들에게 도움을 줄 수 있다.
  내가 이글을 읽어주기를 바라는 사람들은 나와 같이 기술개발 업종에 종사하는 회사원(또는 학생)들이다. 특히 데이터베이스로 인해 골머리를 앓은 적이 있거나 앓고 있는 사람들 - 꼭 골머리를 앓아야만 하는 것은 아니다. - 이었으면 좋겠다. 물론 이 사람들만이 도움이 될 것은 아니라고 생각한다. 오히려 정보기술분야에 종사하시는 분들은 더 이해가 쉬울 것이라 생각한다. 여기까지가 이 블로그를 시작하게된 계기가 되겠다. 이제부터 본격적으로 이야기를 시작해보자.


1. 글에 담게될 내용

  앞서 이야기 했던 것 처럼, 이 글은 공개가능한 사적인 기록이다. 따라서 독자들보다 필자 자신을 위해 쓰는 글이다 보니, 차근차근 설명해 가는 것 보다는 일단 갑작스럽게 어떤 주제가 나오고 설명도 중언부언일 수 있다. 이런 점은 독자들께서 넓은 마음으로 이해해 주기 바라며, 앞으로 글에 담게될 내용은 대부분 엑세스 VBA 예제들이 될 것이다. 그러나 각 주제들은 필자의 변덕에 의해 결정될 예정이므로 필자조차 예측은 할 수 없다. 다만 매 주 1개의 주제에 대해 글을 쓸 것이고 - 다루게 될 주제가 심도가 있으면 몇 주 동안도 다루게 될 수 있다. -, 약 10주에서 15주 정도는 계속할 예정이다.


2. Hello World

  역시 프로그램의 시작은 Hello World가 가장 좋겠다. 이 주제에서 DB는 없다. 단지 아주 간단한 폼과 메세지 박스가 있을 뿐이다. 자 첫 주제를 시작해보자
  필자가 사용하는 오피스는 2007 버젼이다. 독자들의 오피스가 2007 보다 상위 버젼이라도 상관없고 하위버젼이라도 2003까지는 큰 문제가 없을 듯 하다. 어쨌든 액세스를 시작하면 아래와 같은 화면이 나타난다.


위 화면의 오른쪽을 살펴보면 아래와 같은 모습인데, 파일 이름에 Hello.accdb를 입력하고 만들기 버튼을 누르자.


그러면 아래와 같은 화면이 나타난다. 화면 상단의 메뉴에서 '만들기'를 선택한다.


만들기 하위의 메뉴가 아래 그림같이 열리고, '폼 디자인'을 선택한다. 액세스가 현재 열려있는 테이블을 저장할 것인지를 물어온다.



테이블의 이름을 아래 그림과 같이 'Hello'라고 하자.



디자인 형태의 '폼'이 열린다. 만약 이런 형태의 폼이 아니라면 아래 그림과 같이 화면 왼쪽 상단의 '보기'를 '디자인 보기'로 바꾸면 된다.



숙달되면 아주 간단한 과정이므로 이 글 이후에서 이 과정은 생략할 것이다. 다음은 화면 상단의 디자인 탭에서 아래 그림과 같이 '단추'를 선택한 후 폼 영역에 배치를 시킨다. '단추'를 선택하면 커서가 단추모양으로 바뀌는데, 폼 영역에 단추를 배치할 위치를 클릭한 후 단추 크기만큼 드래그하면 단추가 생성된다. 단추가 생성되면 자동으로 단추에 부여할 기능에 대한 다이얼로그 박스가 아래 그림과 같이 팝업되는데, 우리는 직접 VBA 코드를 입력할 예정이므로 '취소'를 선택한다.


다이얼로그 박스가 사라지면 화면 우측의 속성시트를 보자. 이 때 폼 영역의 단추가 선택되어있는지를 확인하자. 만약 선택이 안되어있다면 속성시트는 단추가 아닌 다른 객체의 속성을 나타내게 된다. 속성시트는 '형식', '데이터', '이벤트', '기타', '모두'의 5개 탭으로 구성되어 있다. '형식' 탭을 선택하고 'Caption'의 내용을 Hello로 변경하자. 기본적으로 'Command0'가 입력되어 있었을 것이다.



이제 폼의 단추를 보면 단추에 쓰여진 캡션이 Hello로 변경되어 있다. 다음은 폼을 선택한 후 속성시트의 '기타' 탭에서 팝업 항목을 '예'로 바꾸자. 이렇게 바꾸는 이유는 나중에 설명하겠다.



다시 단추를 선택하고 속성시트의 '이벤트'를 선택한 후, On Click 우측의 '...' 단추를 선택하자.



그러면 단추를 On Click(한번 클릭) 했을 때 어떻게 이벤트를 만들것인지 선택하는 창이 팝업된다.



우리는 VBA를 이용하여 코드를 작성해야 하므로, 코드 작성기를 선택한다. 아래와 같은 코드 작성기 창이 나타난다. 우리가 만들어 놓은 Command0_Click에 대해 이미 일부 코드가 작성되어 있다. 다만 클릭했을 때 작동되는 실제 내용만 없을 뿐이다.



자 내용을 아래와 같이 채워 넣자. Hello 단추를 선택하면 메세지 박스를 팝업 시키는데, 메세지 박스에는 Hello World가 나타난다는 내용이다. 메세지 박스 중 가장 간단한 예이지만 아주 유용하게 써먹을 수 있다. 메세지 박스에 나타낼 내용을 " "를 이용하여 직접 쓸수도 있지만 String 변수를 써서 나타낼 수 있다. 다음 주제는 메세지 박스에 대해 알아보도록 하자.



자 코드를 입력했으면 실행해 보도록 하자. 실행에 앞서 폼을 저장한다. 폼의 이름은 Hello로 입력한 후, 화면 좌측 상단의 '보기'를 '보기'로 선택하자.


아래와 같이 폼이 나타난다. 만약 폼의 팝업 속성을 '아니오'로 설정하면 아래와 같이 창 형태가 아닌, 화면 전체를 채우는 형태로 나타난다. 독자들은 시험을 해보시라.


이제 Hello 단추를 클릭하면 메세지 박스가 팝업된다. 확인단추를 클릭하면 메세지 박스는 사라진다.



[끝]