메뉴

SQL_PRINT

Sub

엑셀에서 SQL SELECT 쿼리를 실행한 후 결과를 시트에 출력하는 VBA 명령문입니다.

SQL_PRINT 코드 미리보기
구문 SQL_PRINT 연결문자열, 테이블이름, 출력셀, [필드목록], [WHERE절], [JOIN절], [머릿글포함], [열자동맞춤]
인수구분 형식 설명
연결문자열 필수 String
OLEDB(ADO.NET)로 연결할 연결문자열입니다.
테이블이름 필수 String
SELECT 쿼리로 출력할 테이블 이름입니다.
예를 들어 "users" 와 같이 입력합니다.
출력셀 필수 Range
쿼리로 반환된 데이터를 출력할 범위의 시작셀입니다.
필드목록 선택 String
쿼리로 출력할 필드 목록입니다. 기본값은 모든 필드를 선택합니다.
필드가 여러개일 경우 "Field1,Field2,Field3,..." 처럼 쉼표(,)로 구분하여 작성합니다.
WHERE절 선택 String
쿼리의 WHERE 절을 작성합니다.
예를 들어 "id=1" 과 같이 입력합니다.
JOIN절 선택 String
쿼리의 JOIN 절을 작성합니다.
예를 들어 "INNER JOIN TableB ON TableA.id = TableB.id" 와 같이 입력합니다.
머릿글포함 선택 Boolean
데이터 출력시 머릿글 포함 여부입니다. 기본값은 True 입니다.
열자동맞춤 선택 Boolean
데이터 출력 후 열 자동맞춤 여부입니다. 기본값은 False 입니다.

마스터 코드

복사한 코드는 VBA 편집기(Alt + F11) 새 모듈에 붙여넣어 사용하세요
Module1 · SQL_PRINT
Sub SQL_PRINT(Connection As String, Table As String, Rng As Range, Optional Fields As String = "*", _
Optional Where As String = "", Optional JoinCondition As String = "", _
Optional incl_header As Boolean = True, Optional autofit As Boolean = False)
'###############################################################
'오빠두엑셀 VBA 사용자지정함수 (https://www.oppadu.com)
'▶ SQL_PRINT
'▶ SQL 서버에 연결 후 특정 테이블의 DB를 시트 위로 출력합니다.
'▶ 인수 설명
'_____________Connection : SQL OLE DB로 연결할 연결문자열(Connection String)을 입력합니다.
'_____________Table : 데이터를 불러올 테이블 이름입니다.
'_____________Rng : 데이터를 출력할 시작 셀입니다.
'_____________Fields : [선택인수] 출력할 필드명입니다. 기본값은 모든 필드를 출력합니다.
'_____________Where : [선택인수] 출력할 조건절을 입력합니다.
'_____________JoinCondition : [선택인수] 여러 테이블을 연결할 경우, JOIN 절을 작성합니다. e.g) "INNER JOIN 테이블B ON 테이블A.필드 = 테이블B.필드"
'_____________incl_header : [선택인수] 머릿글 출력 여부입니다. 기본값은 TRUE 입니다.
'_____________autofit : [선택인수] 열 너비 자동맞춤 여부입니다. 기본값은 FALSE 입니다.
'▶ 사용 예제
'SQL_PRINT "Server=database.windows.net,1433;User ID=oppadu;Password=123;", "테이블명", ActiveSheet.Range("A1")
'■ 사용된 보조명령문
'Get_RS
'SQL_CONN
'SQL_OPEN
'SQL_SELECT_STRING
'###############################################################
Dim RS As Object
Dim vArr As Variant
Dim x As Long: Dim i As Long
Set RS = Get_RS(Connection, Table, Fields, Where, JoinCondition)
Rng.CurrentRegion.ClearContents
If incl_header = True Then
For i = 0 To RS.Fields.Count - 1
Rng.Offset(0, i).Value = RS.Fields(i).Name
Next
vArr = Application.Transpose(RS.GetRows)
On Error GoTo SingleRow:
If IsNumeric(UBound(vArr, 2)) Then x = UBound(vArr): GoTo NextStep:
SingleRow:
x = 1
NextStep:
On Error GoTo 0
Rng.Offset(1, 0).Resize(x, RS.Fields.Count) = vArr
If autofit = True Then Rng.CurrentRegion.EntireColumn.autofit
Else
Rng.CopyFromRecordset RS
End If
End Sub
Function Get_RS(Connection As String, Table As String, Optional Fields As String = "*", _
Optional Where As String = "", Optional JoinCondition As String = "") As Object
'###############################################################
'오빠두엑셀 VBA 사용자지정함수 (https://www.oppadu.com)
'▶ Get_RS
'▶ SQL 서버에 연결 후 특정 테이블의 DB를 RecordSet Object 로 반환합니다.
'▶ 인수 설명
'_____________Connection : SQL OLE DB로 연결할 연결문자열(Connection String)을 입력합니다.
'_____________Table : 데이터를 불러올 테이블 이름입니다.
'_____________Fields : [선택인수] 출력할 필드명입니다. 기본값은 모든 필드를 출력합니다.
'_____________Where : [선택인수] 출력할 조건절을 입력합니다.
'_____________JoinCondition : [선택인수] 여러 테이블을 연결할 경우, JOIN 절을 작성합니다. e.g) "INNER JOIN 테이블B ON 테이블A.필드 = 테이블B.필드"
'▶ 사용 예제
'Dim RS As Object
'Set RS = Get_RS("Server=database.windows.net,1433;User ID=oppadu;Password=123;", "테이블명")
'■ 사용된 보조명령문
'SQL_CONN
'SQL_OPEN
'SQL_SELECT_STRING
'###############################################################
Dim DB As Object
Dim RS As Object
On Error GoTo EH_CONN:
Set DB = SQL_CONN(Connection)
Set RS = SQL_OPEN(DB, SQL_SELECT_STRING(Table, Fields, Where, JoinCondition))
'Debug.Print SQL_SELECT_STRING(Table, Fields, Where, JoinCondition)
If RS.State = 1 Then
Set Get_RS = RS
Else
GoTo EH_CONN:
End If
Set RS = Nothing
Exit Function
EH_CONN:
MsgBox "쿼리를 실행하는 도중 오류가 발생했습니다." & vbNewLine & _
"쿼리 : " & SQL_SELECT_STRING(Table, Fields, Where, JoinCondition) & vbNewLine & _
"오류 번호 : " & Err.Number & vbNewLine & "오류 내용 : " & Err.Description, vbInformation
End
End Function
Function SQL_SELECT_STRING(Table As String, Fields As String, Where As String, JoinCondition As String) As String
SQL_SELECT_STRING = "SELECT " & Fields & " FROM " & Table
If JoinCondition <> "" Then SQL_SELECT_STRING = SQL_SELECT_STRING & " " & Trim(JoinCondition)
If Where <> "" Then SQL_SELECT_STRING = SQL_SELECT_STRING & " WHERE " & Where
SQL_SELECT_STRING = SQL_SELECT_STRING & ";"
End Function
Function SQL_CONN(CONN_STRING As String) As Object
'###############################################################
'오빠두엑셀 VBA 사용자지정함수 (https://www.oppadu.com)
'▶ SQL_CONN
'▶ SQL 연결 문자열로 OLE DB 연결 후 ADODB 커넥션 개체를 반환합니다.
'▶ 인수 설명
'_____________Connection : SQL OLE DB로 연결할 연결문자열(Connection String)을 입력합니다.
'▶ 사용 예제
'Dim DB As Object
'Set DB = SQL_CONN("Server=database.windows.net,1433;User ID=oppadu;Password=123;")
'###############################################################
Dim DB As Object
Set DB = CreateObject("ADODB.Connection")
If InStr(1, CONN_STRING, "Provider=", vbTextCompare) = 0 Then CONN_STRING = "Provider=SQLOLEDB;" & CONN_STRING
On Error GoTo EH_CONN:
DB.ConnectionTimeout = 3
DB.Open CONN_STRING
If DB.State = 1 Then
Set SQL_CONN = DB
Else
GoTo EH_CONN
End If
Set DB = Nothing
Exit Function
EH_CONN:
MsgBox "서버에 연결할 수 없습니다." & vbNewLine & "인터넷 연결 또는 서버 상태를 확인하세요.", vbInformation
Set DB = Nothing
End
End Function
Function SQL_OPEN(DB As Object, SQL_STRING As String, _
Optional CursorType As Integer = 2, Optional LockType As Integer = 3) As Object
'###############################################################
'오빠두엑셀 VBA 사용자지정함수 (https://www.oppadu.com)
'▶ SQL_OPEN
'▶ SQL로 연결된 ADODB 커넥션에서, SQL 쿼리를 실행하여 ADO 레코드셋 개체로 반환합니다.
'▶ 인수 설명
'_____________DB : SQL OLE DB로 연결된 ADODB Connection 개체입니다.
'_____________SQL_STRING : SQL 쿼리문입니다.
'_____________CursorType : 실행 시 어느 작업을 허용할 지 결정합니다. (기본값: OpenDynamic)
'_____________LockType : 실행 시 잠금 유형을 지정합니다. (기본값: LockOptimistic)
'▶ 사용 예제
'Dim DB As Object
'Dim RS As Object
'Set DB = SQL_CONN(ConnectionString)
'Set RS = SQL_OPEN(DB, SQLString)
'###############################################################
' CursorType
' adOpenForwardOnly = 0 <- 읽기만 가능 (기본값)
' adOpenKeyset = 1 <- 업데이트 가능, 편집하는 모든 과정 잠김
' adOpenDynamic = 2 <- 업데이트 가능, 실행하는 순간에만 잠김 (보편적 사용)
' adOpenStatic = 3 <- 단독 실행시에는 잠기지 않고, 여러 레코드 업데이트시에만 잠김
' LockType
' adLockReadOnly = 1 <- 읽기만 가능 (기본값)
' adLockPessimistic = 2 <- 강한 잠금. 편집이 끝난 후 바로 잠김
' adLockOptimistic = 3 <- 약한 잠금. 편집하는 과정에 잠김 해제 (보편적 사용)
' adLockBatchOptimistic = 4 <- 가장 약한 잠금. 여러 데이터 동시 업데이트 시 사용
Dim RS As Object
Set RS = CreateObject("ADODB.RecordSet")
On Error GoTo EH_CONN:
RS.Open SQL_STRING, DB, CursorType, LockType
If RS.State = 1 Then
Set SQL_OPEN = RS
Else
Set SQL_OPEN = Nothing
End If
Set RS = Nothing
Exit Function
EH_CONN:
MsgBox "데이터를 호출할 수 없습니다." & vbNewLine & "작성한 쿼리가 올바른지 확인하세요." & _
vbNewLine & vbNewLine & SQL_STRING, vbInformation
Set RS = Nothing
End
End Function

활용 예제

users 테이블에서 login_id에 abc가 포함된 레코드를 A1셀에 출력하기
Dim ConnString As String
ConnString = "Server=database.windows.net,1433;User ID=oppadu;Password=123;"
SQL_PRINT ConnString, "users", Range("A1"), , "login_id LIKE '%abc%'"

안내사항

SQL_PRINT 는 Get_RS·SQL_CONN·SQL_OPEN·SQL_SELECT_STRING 보조 명령문을 사용하므로 전체 코드를 같은 모듈에 붙여넣어야 합니다.
ORDER BY 와 GROUP BY 절은 지원하지 않으며, 필요할 경우 SQL_SELECT_STRING 코드를 수정하여 추가할 수 있습니다.
댓글 9
4.3 (6개 평가)
요나
요나 2022.12.06 01:18
123
요나
요나 2022.12.06 02:50
공백인 칼럼들도 불러오려면 어떻게 해야하나요??
오빠두엑셀
오빠두엑셀 작성자 2022.12.06 15:42
안녕하세요.
함수를 사용하면 공백을 포함한 모든 데이터를 기본으로 불러옵니다 :)
공백이 출력되지 않는다면 WHERE 절로 null 데이터를 제외했는지 확인해보세요
저지레
저지레 2023.05.11 08:27
애저sql 아닌 mssql 에 연결해봤는데, 다른 부분은 모두 잘 됩니다. 그런데, 테이블 내 데이터에 (null) 값이 있는 경우, SQL_PRINT 함수에서 에러가 나고, 디버그하면, vArr = Application.Transpose(RS.GetRows) 부분에 오류가 있다고 나옵니다. ('13' 런타임 오류가 발생하였습니다: 형식이 일치하지 않습니다) 따로 where 절을 걸지는 않았구요. 혹시 어떤 부분에 문제가 있을까요.
오빠두엑셀
오빠두엑셀 작성자 2023.05.15 17:18
엑셀에서 기본으로 제공하는 Transpose 함수의 경우 null 데이터를 처리 할 수 없어서 발생하는 문제입니다.
3가지 대안책이 있습니다.
  1. SQL 문에서 IFNULL 또는 COALESCE 함수로 NULL 을 "" 로 변환합니다.
  2. VBA Loop 문을 작성해서, SQL로 반환된 데이터 중 NULL 데이터가 있을 경우 "" 로 변환합니다.
  3. VBA 로 transpose 함수를 작성 해서 사용합니다.
Function transposeArray(myarr As Variant) As Variant
  Dim myvar As Variant
  ReDim myvar(LBound(myarr, 2) To UBound(myarr, 2), LBound(myarr, 1) To UBound(myarr, 1))
  For i = LBound(myarr, 2) To UBound(myarr, 2)
    For j = LBound(myarr, 1) To UBound(myarr, 1)
      myvar(i, j) = myarr(j, i)
    Next
  Next
  transposeArray = myvar
End Function
감사합니다.
저지레
저지레 2023.11.17 08:55
덕분에 너무나 감사하게 잘 사용하고 있습니다.
그런데, sql DB의 테이블을 불러올 때, 형식이 varchar가 아닌 text인 경우, 형식이 틀리다며 에러가 나는데, 이에 대한 해결책이 있을런지요.
오빠두엑셀
오빠두엑셀 작성자 2023.11.18 20:17
안녕하세요.
그럴 경우 cStr 또는 cDbl 등으로 데이터의 형식을 텍스트 또는 숫자로 모두 통일시킨 후 함수를 사용해보세요.
감사합니다.
강민준🤗
강민준🤗 2024.08.11 13:05
좋은 자료 감사합니다.🙇‍♂️
jowoori
jowoori 2025.04.18 21:43
최근에 갑자기
strConn = "Provider= Microsoft.ACE.OLEDB.12.0;" & "Data Source= " & ThisWorkbook.FullName & ";" & _
      "Extended Properties= Excel 12.0;" 처리 속도저하 문제가 발생하고 있는데, 혹시 원인을 아시는 분?
현재 data source가 vba코드가 들어 있는 thisworkbook.fullname에서 읽을 때 응답이 엄청 느려지는 현상이 생기고 있어서요....(외부화일을 source로 읽을 때는 문제가 발생하지 않고...)
스크랩 완료