[액셀 VBA] 자동화 - 직책별로 뽑은 직원들을 폼에 연동하여 수정 조회 하기

작성자
dra****
작성일
2021-06-03 12:18
조회
1807

마소 FORMS를 활용한 자동 출퇴근 기록, 근태, 급여산정 등등 프로젝트의 일부입니다.

오늘의 주제는 저번에 DB로 직책별로 뽑아낸 DB를 활용하여 리스트박스에 해당 직원들만 넣고, 수정 조회하는 과정입니다.

  1. 직원들 DB 시트가 있고, 1행에는 필드명이 있습니다. 이 필드명과 나중에 폼에 있는 컨트롤들을 같게 해 줄 것입니다.

 

2. 이것을 가지고 직원들을 직책별로 뽑아냅니다. 이 부분은 어떻게 구현했는지 아래 게시글을 보시면 찾으실 수 있을 것입니다.

아래 사진에서 각 테이블마다 표 이름을 "CASHIER", "DINING", "DISHWASHER", "KITCHEN" .. 이런식으로 이름 정의를 합니다.

 

3. 직책을 참조할 수 있는 테이블을 하나 만들고 이름을 "POSITION"으로 정의합니다.

 

4. 폼에 컴보박스의 속성에 있는 RowSource의 값을 POSITION으로 설정합니다.

그러면 아래의 그림 같이 해당 직책들이 나올 것입니다.

 

5. 위의 그림에서 직책을 선택하면 바로 밑에 있는 리스트 박스에 해당 직책을 가진 직원 목록이 뜨도록 해야 겠지요.

Private Sub cboPos_Change()
   Me.lboxEmployees.RowSource = "[" & wbYS.Name & "]SCHEMA!" & Me.cboPos.Value
End Sub

a. "cboPos"는 포지션을 담아 두기 위한 콤보박스 컨트롤 입니다.

b. "lboxEmployees"는 해당 직원 명단을 담아 두기 위한 리스트박스 컨트롤입니다.

c. "[" & wbYS.Name & "]SCHEMA!"  : 워크북이 여러개 실행 되고 있는 중이기에 명확하게 "[워크북 이름]워크시트 이름!"을 앞에 붙여 줍니다. 실제 시트의 이름은 SCHEMA이고 이 뒤에 선택한 콤보박스의 값 "Me.cboPos.Value"값을 붙여 주면 리스트 박스에 해당 직원들의 이름를 아래의 그림같이 가져와 붙여 줍니다.

6. 위 그림의 리스트박스에서 직원을 선택하면 이 직원들의 정보를 가져오는데

a. 직원시트에서 해당 직원을 찾아 폼에 뿌려주기 ▶ 조회만 가능, 업데이트 기능을 따로 넣어 주어야 함

b. 직원시트에 있는 각각의 셀의 주소를 ControlSource에 연동시키기 ▶ 조회 및 바로 수정 가능

목적에 따라 a, b 중에 선택하시면 됩니다.

 

7. 위의 6.b.의 방식, ControlSource로 연동하는 방법의 코딩을 보여 드리겠습니다.

a. 먼저, 폼에 있는 TextBox의 이름을 필드명과 동일하게 합니다. 가령 직원 ID 필드명을 여기서는 "EID"라 명명했습니다.

그럼 폼에 있는 TextBox 중 직원의 ID를 보여줄 녀석의 이름을 EID라고 하면 됩니다. 아래 그림 참조

 

b. 모든 컨트롤의 이름을 필드명과 같게 변경합니다.

c. 리스트박스에서 선택시 직원의 아이디를 추출합니다.

리스트박스에서 보이는 값은 이름 뿐이지만 ColumnCount=3, BoundColumn=1로

그리고 이름만 보이게 ColumnWith = "0pt; 120pt; 0pt" 이렇게 세팅이 되어 있습니다.

위에 직책별 명단의 필드를 보시면 "EID", "FirstName", "SRATE" 이렇게 세 개의 값들이 있습니다.

따라서 직원을 선택하면 BoundColumn=1 이기 때문에 아래코드 Me.lboxEmployees.Value에 직원 ID인 EID값이 넘어오게 됩니다.

 

Private Sub lboxEmployees_Click()
   EMP.EID = Me.lboxEmployees.Value
   If EMP.EID <> vbNullString Then EMP_ConnectPersonalInfoToForm
End Sub

 

d. 직원 개인 정보를 담을 Type형 전역변수로 EMP를 만들어 두고 그것에 EID값을 찾아 직원시트에서 해당 직원을 찾습니다.

전역변수로 만들었다는 말은 이 프로젝트 전체에서 EMP를 쓰겠다는 의도입니다.

d.1. EMP_GetEmpRow()함수로 해당 직원을 찾음 못찾으면 0을 반환하여 종료함

d.2. EMP_SetEmpCellAddressToDictionary()함수로 해당 직원의 정보를 Dictionary에 담고 각 컨트를들의 ControlSource="셀주소" 를 설정함. 끝나면 True를 반환함

Public Function EMP_ConnectPersonalInfoToForm() As Boolean
   RowEmp = EMP_GetEmpRow(EMP.EID)     '해당 직원의 행 번호를 찾아 반환
   If RowEmp = 0 Then Exit Function
 
   If EMP_SetEmpCellAddressToDictionary = False Then    '클릭한 직원 행 번호 가져오기. RowEmp는 전역변수기 때문에 매개변수로 넘길 필요 없다.
      EMP_ConnectPersonalInfoToForm = False
      Exit Function
   End If
End Function
 
'클릭한 직원 행 번호 찾아 반고 Dictonary에 셀주소 담기
Public Function EMP_GetEmpRow(EID As String, Optional Col As String = "A") As Long
   Dim RowLast    As Long
   Dim rng        As Range
 
   With wsYS.wsEmp
      RowLast = sh.GetLastRow(Col, wsYS.wsEmp)
      Set rng = .Range("A2:A" & RowLast).Find(What:=EID)      '여기가 직원의 EID로 행 번호를 찾는 부분입니다.
 
      If rng Is Nothing Then
         MsgBox "EID doesn't exist. Check this employees record and try again.", vbInformation
         EMP_GetEmpRow = 0
         Exit Function
      End If
 
      EMP_GetEmpRow = rng.Row
   End With
End Function
'찾은 행번호로 Dictonary에 셀주소 담고 컨트롤에 연동시킴
Public Function EMP_SetEmpCellAddressToDictionary() As Boolean
 
   Dim ColLast As Long
   Dim i As Long
   Dim key As String
   Dim addr As String
   ColLast = sh.GetLastColumn(1, wsYS.wsEmp)  '◀ 마지막 행이나 열 갖은 값을 찾기 위해 만들어 둔 클래스 모듈
 
   dtEmp.RemoveAll
 
   With wsYS.wsEmp
      For i = 1 To ColLast
         key = .Cells(1, i).Value    '◀ 여기에 필드명을 담아 둡니다.
         addr = "[" & wbYS.Name & "]EMPLOYEES!" & .Cells(RowEmp, i).Address '◀ 여기에 셀 주소값을 담아 둠
         On Error Resume Next
            frmEmp.Controls(key).ControlSource = addr     '◀ 이 부분이 해당 폼 컨트를에 각각의 셀을 연동 시켜주는 부분
         On Error GoTo 0                                           '◀ 필드명과 컨트롤의 이름이 같기에 쉽게 루프로 연동 가능
      Next i
   End With
 
   EMP_SetEmpCellAddressToDictionary = True
End Function

 

e. 이제 연동이 끝났습니다. 컴보박스에서 직책을 선택하면 알아서 그 명단을 가져오고, 직원을 선택하면 직원시트에 있는 셀로 알아서 연동해 줄 것입니다. 이러면 직원 조회 및 수정 폼이 끝이 난 것입니다.

Dictioanry에 정보를 담아 둔 이유는 다른 곳에 쓸 용도가 있기 때문입니다.

연동만 하고자 할 때는 굳이 Dictionary에 담아 둘 필요가 없습니다.

 

코딩 팁) 여러개의 워크북과 많은 워크시트를이 동시에 실행되도 있는 상황이면 어느 워크북의 워크시트인지 명확하세 해 두어여 원하는 결과를 처리할 수 있습니다. 하도 에러 경험을 많이 당해서....

그래서 제가 생각한 해결책은

Public wbYS As Workbook               '워크불 이름 명명
 
Public Type pwsYS                         '위의 위크복에 속해 있는 워크시트들
   wsEmp          As Worksheet
   wsSCM          As Worksheet
   wsRH           As Worksheet
   wsSF1          As Worksheet
   wsSF2          As Worksheet
   wsTemp         As Worksheet
   attPasteArea   As Range
End Type
 
Public wsYS As pwsYS                     '워크시트들을 접근할 수 있게 하는 전역변수

위와 같이 사용자 정의 변수(TYPE)을 이용하여 워크시트를 접근합니다. 그리고 폼 실행시 세팅하는 함수 하나 추가

저는 클래스로 자동 세팅하게 해 놓았습니다.

Private Sub SetWorkbooksAndSheets()
   If sh Is Nothing Then Set sh = New clsSheets
   If xlDb Is Nothing Then Set xlDb = New clsXLDataBase
   If DT Is Nothing Then Set DT = New clsDate
   If cUtil Is Nothing Then Set cUtil = New clsControlUtil
 
   Set wbYS = ThisWorkbook
 
   With wsYS
      Set .wsSCM = wbYS.Worksheets("SCHEMA")
      Set .wsEmp = wbYS.Worksheets("EMPLOYEES")
      Set .wsRH = wbYS.Worksheets("Regular Holidays")
      Set .wsSF1 = wbYS.Worksheets("SalaryFormat1")
      Set .wsSF2 = wbYS.Worksheets("SalaryFormat2")
      Set .wsTemp = wbYS.Worksheets("TEMP")
      Set .attPasteArea = .wsTemp.Range("A2")
   End With   
End Sub

각각의 워크북들과 워크시트를 이런식으로 해놓으면, 코드 입력시 아래와 같이 뜨기 때문에 편합니다.

큰 프로젝트를 하다보면 Activesheet, Thisworkbook, ActiveCell, Worksheets("Sheet1") 같은 것을 쓰는 것이 좋지 않다는 것을 아시게 될 겁니다. 의도하지 않은 곳에서 혼자 자동화하고 있을 수도 있습니다.

 

신고
스크랩
공유
회원등급 : 30레벨
포인트 : 4702 EP
전체 3

전체 165
번호 제목 작성자 작성일 추천 조회
알림
[📚진짜쓰는 실무엑셀] IT/오피스 '1위' 베스트셀러! 엑셀 공부, 이 교재로 마스터하세요! (315)
오빠두엑셀 | 2022.02.03 | 추천 575 | 조회 609803
오빠두엑셀 2022.02.03 575 609803
78094
[M365] 수식으로 고급필터 구현하기 첨부파일 (3)
마법의손 | 2025.04.11 | 추천 1 | 조회 133
마법의손 2025.04.11 1 133
78009
LOOKUP을 XLOOKUP 처럼 사용 (2019 이하 필독) 첨부파일 (1)
박정호 | 2025.04.06 | 추천 0 | 조회 129
박정호 2025.04.06 - 129
78002
[VBA] 괄호가 대응되게 문자열 잘라주는 함수
마법의손 | 2025.04.05 | 추천 0 | 조회 70
마법의손 2025.04.05 - 70
77792
엑셀 그림 삽입이 안될 때.. (그림 삽입 비활성화 해결) (1)
더블유에이 | 2025.03.24 | 추천 2 | 조회 448
더블유에이 2025.03.24 2 448
77667
언피벗 툴 업그레이드 버전입니다. 첨부파일 (2)
박정호 | 2025.03.17 | 추천 0 | 조회 118
박정호 2025.03.17 - 118
77635
머리글로 데이터 합치기 툴 첨부파일 (4)
박정호 | 2025.03.15 | 추천 1 | 조회 127
박정호 2025.03.15 1 127
77598
MERGE(자석처럼 자료 붙이기) 툴입니다. 첨부파일 (2)
박정호 | 2025.03.13 | 추천 0 | 조회 170
박정호 2025.03.13 - 170
77577
[VBA] 시트명들 가져오는 함수 첨부파일 (4)
마법의손 | 2025.03.12 | 추천 1 | 조회 132
마법의손 2025.03.12 1 132
77544
LOOKUP 함수 사용법(2019 이하 필독) 첨부파일 (6)
박정호 | 2025.03.11 | 추천 0 | 조회 206
박정호 2025.03.11 - 206
77543
[함수TIP] Date함수로 Eomonth함수 대체하기 (3)
마법의손 | 2025.03.11 | 추천 3 | 조회 86
마법의손 2025.03.11 3 86
77481
쉽게 쓸 수 있는 언피벗 툴 첨부파일 (2)
박정호 | 2025.03.08 | 추천 2 | 조회 133
박정호 2025.03.08 2 133
77468
월간단위 월주차 함수 첨부파일 (3)
팍셀 | 2025.03.07 | 추천 0 | 조회 155
팍셀 2025.03.07 - 155
77385
TEXTJOIN 을 SUMPRODUCT 공식으로 2차원 데이터 다루기 첨부파일
박정호 | 2025.03.04 | 추천 0 | 조회 106
박정호 2025.03.04 - 106
77355
TEXTJOIN 으로 2차원 데이터 다루기 첨부파일 (3)
박정호 | 2025.03.02 | 추천 1 | 조회 110
박정호 2025.03.02 1 110
77353
& 기호로 SUMPRODUCT 2차원 데이터 다루기 첨부파일 (2)
박정호 | 2025.03.02 | 추천 0 | 조회 87
박정호 2025.03.02 - 87
77351
단어 포함 여부 검색, 원하는 단어로 출력 첨부파일
박정호 | 2025.03.02 | 추천 1 | 조회 119
박정호 2025.03.02 1 119
77238
휴일이면 1 아니면 0이 나오는 함수 첨부파일 (4)
박정호 | 2025.02.24 | 추천 0 | 조회 158
박정호 2025.02.24 - 158
77072
SUMPRODUCT로 VLOOKUP 대체 (2차원 룩업 가능) 첨부파일 (1)
박정호 | 2025.02.16 | 추천 0 | 조회 274
박정호 2025.02.16 - 274
76915
SUMPRODUCT로 2차원 데이터 다루기[응용] 첨부파일 (6)
박정호 | 2025.02.09 | 추천 1 | 조회 238
박정호 2025.02.09 1 238
76913
SUMPRODUCT로 2차원 데이터 sumifs 처럼 다루기 첨부파일 (1)
박정호 | 2025.02.09 | 추천 0 | 조회 199
박정호 2025.02.09 - 199