엑셀 시트 데이터 연결 :: Connect_DB 명령문 사용법 정리
엑셀 Connect_DB 명령문 목차 바로가기
요약
엑셀 Connect_DB 함수는 서로 다른 두 시트를 관계형 데이터베이스로 연결하는 엑셀 사용자지정함수입니다.
명령문 구문
Array = Connect_DB ( 기존DB, ID번호, 연결할시트, 불러올필드, [머릿글포함] )
사용된 인수 및 변수 알아보기
| 인수 | 설명 |
| 기존DB [Variant] |
원본 시트의 데이터가 배열형태로 입력된 DB 입니다. Get_DB 함수로 받아옵니다. |
| ID번호 [Long] |
기존DB에서 연결할 시트의 ID로 참조 될 외래ID가 입력된 필드의 열 번호입니다. |
| 연결할시트 [WorkSheet] |
기존 DB와 연결할 시트입니다. |
| 불러올필드 [String] |
연결할 시트에서 불러올 필드명입니다. 여러 필드를 불러올 경우 쉼표(,)로 구분하여 입력합니다. |
| 머릿글포함 [Boolean, 선택인수] |
머릿글 포함여부입니다. TRUE일 경우 머릿글을 포함하여 병합합니다. |
예제파일 다운로드
오빠두엑셀의 강의 예제파일은 여러분을 위해 자유롭게 제공하고 있습니다.
- [엑셀VBA함수] Connect_DB 명령문예제파일
상세 설명
엑셀 Connect_DB 함수는 서로 다른 두 시트를 관계형 데이터베이스로 연결하는 사용자 지정 함수입니다. 관계형 데이터베이스에 대한 기초 설명은 아래 엑셀 vs 관계형데이터베이스 기초 강의를 참고하세요.
Connect_DB 함수를 올바르게 사용하려면 원본 시트와 연결할 시트에는 아래 규칙을 지켜 데이터를 입력해야 합니다.
- 시트의 값은 반드시 A1셀부터 시작해야 합니다.
- 병합된 셀이 없어야 합니다.
- 연결 할 시트의 ID는 반드시 A열에 입력되어야 합니다.
- 머릿글은 반드시 1행에 입력되어야 합니다.
Connect_DB 함수는 데이터베이스 관련 VBA 함수 중 하나입니다. 더 다양한 DB 관련 함수는 아래 링크를 참고해주세요.
실전 사용 예제
- 판매내역의 제품ID를 참조하여 제품 시트 연결하기
' 판매내역 : 판매ID | 제품ID | 날짜 | 수량 | 단가 ' 제품정보 : 제품ID | 제품명 | 구매처 Dim DB As Variant Dim WS As Worksheet Set WS = ThisWorkbook.Worksheets("제품정보") DB = Get_DB(ThisWorkbook.Worksheets("판매내역")) DB = Connect_DB(DB, 2, WS, "제품명, 구매처") ' DB로 판매ID | 제품ID | 날짜 | 수량 | 단가 | 제품명 | 구매처 가 반환됩니다.
- 급여내역의 직원ID를 참조하여 직원 정보 추가하기
' 급여내역 : 급여ID | 직원ID | 지급월 | 급여 ' 직원정보 : 직원ID | 직원명 | 직급 | 부서 Dim DB As Variant Dim WS As Worksheet Set WS = ThisWorkbook.Worksheets("직원정보") DB = Get_DB(ThisWorkbook.Worksheets("급여내역")) DB = Connect_DB(DB, 2, WS, "직원명") ' DB로 급여ID | 직원ID | 지급월 | 급여 | 직원명 이 반환됩니다.
엑셀 시트 데이터 연결, Connect_DB 명령문 동작원리
Connect_DB 명령문 전체 코드
Function Connect_DB(DB As Variant, ForeignID_Fields As Variant, FromWS As Worksheet, Fields As String, Optional IncludeHeader As Boolean = False) '############################################################### '오빠두엑셀 VBA 사용자지정함수 (https://www.oppadu.com) '수정 및 배포 시 출처를 반드시 명시해야 합니다. '■ Connect_DB 함수 '■ 서로 다른 두 시트를 연결합니다. FromWS의 첫번째 필드는 반드시 고유값(ID)이 입력되어야 합니다. '■ 사용방법 'Array = Connect_DB(Get_DB(Sheet1),2,Sheet2, "필드1, 필드2, 필드3") '■ 인수 설명 '_____________DB : 병합할 원본 DB입니다. '_____________ForeignID_Fields : 연결할 시트에서 참조할 외래ID가 입력된 열번호입니다. '_____________FromWS : 연결할 시트입니다. '_____________Fields : 연결할 시트에서 불러올 필드목록입니다. 쉼표(,)로 구분하여 입력합니다. '_____________IncludeHeader : 머릿글 포함여부입니다. 기본값은 False 입니다. '■ 사용된 보조명령문 'Get_Dict 함수 '############################################################### Dim cRow As Long: Dim cCol As Long Dim vForeignID_Fields As Variant: Dim vForeignID_Field As Variant Dim ForeignID As Variant Dim vFields As Variant: Dim vField As Variant Dim vID As Variant: Dim vFieldNo As Variant Dim Dict As Object Dim vTemp As Variant Dim i As Long: Dim j As Long Dim AddCols As Long cRow = UBound(DB, 1) cCol = UBound(DB, 2) If InStr(1, Fields, ",") > 1 Then AddCols = Len(Fields) - Len(Replace(Fields, ",", "")) + 1 vFields = Split(Fields, ",") Else AddCols = 1 vFields = Array(Fields) End If ReDim Preserve DB(1 To cRow, 1 To cCol + AddCols) Set Dict = Get_Dict(FromWS) For Each vTemp In Dict.keys vID = Dict(vTemp) Exit For Next ReDim vFieldNo(0 To UBound(vFields)) For Each vField In vFields For i = 1 To UBound(vID) If vID(i) = Trim(vField) Then vFieldNo(j) = i: j = j + 1 Next Next If InStr(1, ForeignID_Fields, ",") > 0 Then vForeignID_Fields = Split(ForeignID_Fields, ",") Else vForeignID_Fields = Array(ForeignID_Fields) For Each vForeignID_Field In vForeignID_Fields For i = 1 To cRow If IncludeHeader = True And i = 1 Then ForeignID = vTemp Else ForeignID = DB(i, Trim(vForeignID_Field)) If Dict.Exists(ForeignID) Then For j = 1 To AddCols DB(i, cCol + j) = Dict(ForeignID)(vFieldNo(j - 1)) Next End If Next Next Connect_DB = DB End Function Function Get_Dict(WS As Worksheet) As Object '############################################################### '오빠두엑셀 VBA 사용자지정함수 (https://www.oppadu.com) '수정 및 배포 시 출처를 반드시 명시해야 합니다. '■ Get_Dict 함수 '■ 시트에 입력된 데이터를 Dictionary로 반환합니다. 첫번째 필드는 반드시 고유값이 입력되어야 합니다. '■ 사용방법 'Dictionary = Get_Dict(시트) '■ 인수 설명 '_____________WS : Dictionary로 변환할 시트입니다. '############################################################### Dim cRow As Long: Dim cCol As Long Dim Dict As Object Dim vArr As Variant Dim i As Long: Dim j As Long Set Dict = CreateObject("Scripting.Dictionary") With WS cRow = .Cells(.Rows.Count, 1).End(xlUp).Row cCol = .Cells(1, .Columns.Count).End(xlToLeft).Column For i = 1 To cRow ReDim vArr(1 To cCol - 1) For j = 2 To cCol vArr(j - 1) = .Cells(i, j) Next Dict.Add .Cells(i, 1).Value, vArr Next End With Set Get_Dict = Dict End Function
명령문 동작원리 단계별 알아보기
- 명령문에 사용 될 변수를 선언합니다.
Dim cRow As Long: Dim cCol As Long Dim vForeignID_Fields As Variant: Dim vForeignID_Field As Variant Dim ForeignID As Variant Dim vFields As Variant: Dim vField As Variant Dim vID As Variant: Dim vFieldNo As Variant Dim Dict As Object Dim vTemp As Variant Dim i As Long: Dim j As Long Dim AddCols As Long
- 기존 DB의 행/열 개수를 계산합니다.
cRow = UBound(DB, 1) cCol = UBound(DB, 2)
- 불러올 필드를 배열로 반환한 뒤, 필드 개수에 따라 임시 배열에 추가할 열 개수 값을 계산합니다.
If InStr(1, Fields, ",") > 1 Then AddCols = Len(Fields) - Len(Replace(Fields, ",", "")) + 1 vFields = Split(Fields, ",") Else AddCols = 1 vFields = Array(Fields) End If
- 임시 배열(DB)의 열 개수를 추가합니다.
ReDim Preserve DB(1 To cRow, 1 To cCol + AddCols)
- 연결할 시트를 Dictionary 개체로 변환한 뒤, 머릿글을 배열로 반환합니다.
Set Dict = Get_Dict(FromWS) For Each vTemp In Dict.keys vID = Dict(vTemp) Exit For Next
- 불러올 필드의 열 번호를 계산합니다.
ReDim vFieldNo(0 To UBound(vFields)) For Each vField In vFields For i = 1 To UBound(vID) If vID(i) = Trim(vField) Then vFieldNo(j) = i: j = j + 1 Next Next If InStr(1, ForeignID_Fields, ",") > 0 Then vForeignID_Fields = Split(ForeignID_Fields, ",") Else vForeignID_Fields = Array(ForeignID_Fields)
- DB의 값을 하나씩 돌아가며, 연결할 시트에서 불러올 값을 배열의 오른쪽으로 추가합니다.
For Each vForeignID_Field In vForeignID_Fields For i = 1 To cRow If IncludeHeader = True And i = 1 Then ForeignID = vTemp Else ForeignID = DB(i, Trim(vForeignID_Field)) If Dict.Exists(ForeignID) Then For j = 1 To AddCols DB(i, cCol + j) = Dict(ForeignID)(vFieldNo(j - 1)) Next End If Next Next
- 임시 배열을 함수의 결과값으로 반환한 뒤 명령문을 종료합니다.
Connect_DB = DB

DB = Connect_DB(원본시트,중간셀열번호,연결할시트,불러올필드)
로 함수를 사용해보세요
Connect_DB에 사용된 Get_Dict 함수 중
이 부분을 3열(C)에서 받아 Dictionary에 추가되도록 명령문을 수정해주세요.
필드를 중간에 추가하려면 적어드린 명령문으로는 구현이 어렵고 코드를 새로 작성해야 합니다.^^;
형식에 맞게 잘 입력하였고, 몇번을 검토하였는데요.
13 런타임 오류가 계속 발생이 됩니다.
질답란에 검색하다보니 vid 값이 empty라 그렇다고 하시던데,
입력이 뭐가 잘못되어서 vid 값이 0이 나오는지 모르겠네요....
데이터들은 다 존재합니다.
코드 실행중 발생하는 오류에는 다양한 원인이 있을 수 있기 때문에 사용중이신 raw data로 직접 살펴보는 것이 가장 좋습니다.
오류가 발생하는 부분 전 단계에 F9 키로 중단점 설정 후, F8키로 단계별로 실행하면서 오류 발생원인을 찾아보세요.
그렇게 해봐서 vid값이 empty가 나오더라고요.
재고관리 영상에서 강의하신 내용대로 똑같이 해봐도 13에러가 떠서 f8로 단계별로 봤더니 vid값이 empty가 뜨더라고요.
근데 vid 값이 뭔지를 모르겠습니다 ㅎㅎ;;
vid는 Dictionary 개체에서 받아오는 키(=id) 값입니다.
같은 1 이여도 '숫자'와 '문자' 데이터는 각각 다르게 처리됩니다.
따라서 cStr(문자변환) 또는 cDbl(숫자변환) 함수로 데이터 형식을 통일한 수 활용해보세요.
cDbl을 문자에 사용할 경우 오류가 발생할 수 있으므로, cStr 함수를 사용해 문자로 일괄통일 후 고유값 처리하시면 될 것 같습니다.
감사합니다.
알려주신 내용을 바탕으로 조직관리 Sheet를 잘 만들고 있습니다.
현재 두 가지 문제를 해결하지 못해서 많은 시간을 들여 공부를 하고 있습니다만, 역부족으로 해결이 어렵네요... ㅜㅜ
Connect_DB, Insert_Record, Update_Cbo 함수에 관련한 질문들입니다.
1)
알려주신대로, 첫 열에 머리글은 "ID"로 입력했고, 그 아래 ID값들은 숫자(100001, 100002...)로 입력을 했습니다.
Insert_Record 함수를 실행해서 DB값들이 해당 Sheet에 잘 쌓여지고 있습니다.
그런데, Connect_DB 사용시에 ID값 매칭이 잘 되지 않아서, Connect_DB 함수 실행 직후의 해당 값들이 모두 Empty 입니다.
혹시나해서 ID값들을 문자를 섞어서 수정(A00001, A00002...)을 한 후에 Connect_DB를 실행을 하면 매칭이 잘 되어 원하는 값들이 잘 들어옵니다.
그런데 여기서 함정은, 문자를 섞은 ID값들로 Insert_Record를 실행하면 오류가 납니다. ID값들을 숫자로 계속 사용해야 할 것 같은데, 그러려면 Connect_DB 매칭 오류를 해결해야 하는 상황입니다.
Connect_DB 사용시에 숫자 키값이 매칭이 안되는 이유가 뭘까요? 키값열의 속성을 TEXT로 변경하고 진행해도 안되기는 마찬가지입니다.
2)
콤보박스 두 개를 연계 시켜서, "본부" 선택시 해당 "팀"들을 나타나게 하려고 하니다. Update_Cbo 함수로 하려면 어떻게 해야 할까요?
감사합니다!
1) ID 값을 매칭시키기 전, cStr(값) 으로 값을 텍스트로 강제 변환 후 매칭시켜보시길 바랍니다. 만약 텍스트로 변환해도 매칭되지 않는다면 줄바꿈, 공백 등 보이지 않는 기호가 원인일 수 있으며 그럴 경우 trim 으로도 묶어서 해결할 수 있으나 ID 키가 잘못된 것이므로 근본적인 해결책은 아닙니다.
2) 콤보박스1을 선택 하면, Filtered_DB 함수로 콤보박스1의 값으로 팀을 필터링 후 콤보박스2를 만들도록 함수를 작성해보시길 바랍니다.
감사합니다.
두 가지를 모두 해결 했습니다.
다만, 1번의 경우에는 Dic 배열에 Double로 입력이 되고 있는 것을 확인을 했는데요, cStr이나 trim을 사용해도 해결을 하지 못해서(제가 실력이 부족하여 적절한 곳을 찾지 못한 것 같아요), Insert시에 ID가 입력되는 부분에서 IF문으로 ID앞에 문자를 더해서 입력을 하였습니다. ^^;
도움주셔서 감사합니다.
Update_lstMain
End Sub
Sub Update_lstMain()
Dim DB As Variant
DB = Get_DB(shtltem)
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑여기까지는 잘되는데요...
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓여기부터가
13런타임오류가 나오면서 이것저것해봐도안되네요...
엑셀 을 1도모르다가 여기서 배워가면서 따라하고있는데..
이상하게 잘안되네요ㅜㅜ
DB = Connect_DB(DB, 3, shtCategory, "제품구분")
Stop
Update_List Me.lstMain, DB, "50,50,50,50,50,50"
End Sub
13 Runtime 오류는 개체 형식이 일치하제 않을 때 발생합니다.
코드만 봐서는 이상이 없어보이나, 아마도 shtCategory라는 시트가 잘못 지정되어서 그런것으로 보입니다.
좌측 프로젝트목록에서 shtCategory 라는 시트가 있는지 한번 확인해보세요.
감사합니다.