EXCEL - VBA

VBA - vworld 사이트에서 토지 특성 조회(4) : 코드 설명(1)

별동산 2025. 3. 13. 08:17
반응형

5. 코드 설명


(1) 명시적 변수 선언 요구

Option Explicit

변수 선언을 명시적으로 하라는 선언입니다. 이렇게 해야 변수의 데이터 형식이 틀어지거나, 값이 잘못 들어가는 오류를 예방할 수 있으므로 필수입니다.
 
(2) Sub 프로시저 시작과 종료

Sub parse_xml()
    변수선언 및 값 할당, 실행문 등
End Sub

Sub 프로시저는 일정한 동작을 처리하는 것으로, 처리한 후 값을 반환하는 Function 프로시저와 구분됩니다.
 
본 매크로에서는 URL을 작성한 후 VWorld 사이트에서 조회한 후 검색결과를 워크시트에 기록하는 전체적인 처리를 Sub 프로시저에서 처리하는데,
 
VWorld에서 조회한 후 검색 결과를 반환하는 부분을 Function 프로시저로 처리했습니다.
 
다시 말하면 Sub 프로시저가 Function을 호출해서 VWorld 조회 부분을 처리하도록 한 후 값을 넘겨받아서 이어서 처리하는 것입니다.
 
(3) 변수 선언

    Dim xmlDoc As Object
    Dim ws As Worksheet
    Dim xmlHttp As New MSXML2.ServerXMLHTTP60
    Dim base_url As String, params As String, search_url As String
    
    Dim dong As String, jibun As String
    Dim value() ' 여러 개 값을 반환받을 수 있도록 반환 값을 배열로 처리
    Dim pnu As String

    Dim endRow As Long, i As Long

 
위는 변수를 선언하는 부분입니다.
 
Dim 다음의 xmlDoc 등이 변수명이고,
As 다음은 데이터 형식입니다.
 
Object는 가장 상위의 데이터 형식이며,
Worksheet는 워크시트 형식, 
String은 문자(열),
Long은 정수 형식인데, 같은 정수 형식인 Integer는 VBA에서 -32,768에서 32,767까지인데, Long은 -2,147,483,648에서 2,147,483,647까지로 훨씬 범위가 넓습니다.
 
특이한 것은 xmlHttp 변수로서 변수 선언과 생성을 같이 하고 있습니다.

다시 말해 Dim으로 xmlHttp 변수를 선언하고,

As New MSXML2.ServerXMLHTTP60로 새로운(New) MSXML2.ServerXMLHTTP60을 생성합니다.

 

MSXML2 다음의 점은 '~의'라는 의미이며, ServerXMLHTTP60은 서버에 URL을 전송하고, XML 형식의  검색 결과를 처리하는 역할을 담당합니다.
 
또 하나 특이한 것은 Dim value()로서

value는 ()가 있으므로 배열이며, 괄호 안에 요소의 개수를 지정하는 것이 원칙인데, 본 매크로에서는 처리하기 전에는 요소의 개수를 알 수 없기 때문에 비어 둔 것입니다.

또한 데이터 형식을 지정하는 As가 없는데, 없으면 Variat(가변)이며, Variant는 생략할 수 있습니다. Variant란 숫자, 문자(열) 등 여러 가지 형태의 데이터를 입력할 수 있는 것입니다.
 
(4) WorkSheet 변수 값 할당

    ' Sheet1 시트를 ws 변수에 저장
    Set ws = ThisWorkbook.Sheets("Sheet1")

VBA는 원칙적으로 변수 선언과 변수에 값을 대입하는 부분이 구분되어 있습니다.
위 구문은 ThisWorkbook., 다시 말해 이 워크북의 Sheet1 시트를 ws 변수에 저장하는 것입니다.
정수, 문자 형식 등의 변수에 값을 대입할 때는 변수명 = 값 식인데, 
WorkSheet, Range 등 Object에 값을 대입할 때는 변수명 앞에 Set을 적습니다.
 
(5) xmlDoc 변수 형식 지정 및 동기화 설정

    ' XML 객체 생성
    Set xmlDoc = CreateObject("MSXML2.DOMDocument.6.0")
    xmlDoc.async = False

xmlDoc도 Oject 변수이므로 Set을 사용했으며,
CreateObject라고 Object를 생성하는데, 
MSXML2의 DOMDocument.6.0 형식으로 지정했습니다.
 
xmlDoc.async = False은 비동기(async)가 False이므로 XML 문서를 완전히 읽을 때까지 다른 작업을 할 수 없도록 하는 것입니다. 
 
(6) 데이터가 있는 마지막 행을 endRow 변수에 대입

    endrow = Cells(Rows.Count, "A").End(xlUp).Row

A열에서 데이터가 있는 맨 아래 줄을 구해서 endRow에 대입하는 구문인데,
Cells(Rows.Count, "A")는 A열의 맨 아래 줄, 1,048,576행을 가리키며,
End(xlUp)은 1,048,576행에서 Ctrl + ↑를 누른 것처럼 맨 위로 올라오는 것이고,
여기서 멈추는 행의 수를 .Row로 구하는 것입니다.
그러면 아래와 같은 경우는 3이 구해지고, 3이 endRow에 대입됩니다.

 
(7) 머리글 입력

    ' 머리글 입력
    ws.Cells(1, 3).value = "주소"
    ws.Cells(1, 4).value = "면적(㎡)"
    ws.Cells(1, 5).value = "기준연도"
    ws.Cells(1, 6).value = "공시지가(원/㎡)"

주소, 면적 등 머리글을 입력하는 부분입니다.
 
(8) 반복문 구문

    For i = 2 To endRow
        처리할 구문
    Next

i가 2부터 endRow까지 반복하면 For와 Next 안에 있는 구문을 반복해서 처리하는 것입니다.
 
(9) 법정동과 지번을 변수에 대입

        ''PNU 조회
        ' 법정동과 지번으로 구분 입력
        ' 지번 입력시 산과 지번 사이 공백은 있거나 없거나 잘됨
        dong = Range("A" & i)
        jibun = Range("B" & i)

 
작은따옴표 '는 주석 표시입니다. 다시 말해 ' 다음의 문장은 처리가 되지 않고 프로그램에 대한 참고용, 설명용으로 사용되는 것입니다.
 
「'PNU 조회」는 여기서부터 'PNU를 조회하는 코드'라는 의미입니다.
'법정동과 지번으로 구분 입력'이란 법정동과 지번을 묶어서 입력할 수도 있는데, 법정동과 지번을 분리해서 입력하면 입력 시 편리하고, 법정동 코드 조회할 때도 편리하기 때문에 구분해서 처리하도록 주의시키는 의미입니다.
 
dong = Range("A" & i)는 A열 i번째 행의 내용을 dong이란 변수에 대입하는 것이고,
jibun = Range("B" & i)는 B열 i번째 행의 내용을 jibun이란 변수에 대입하는 것입니다.

 
(10) D열과 F열의 셀 서식 지정

        ' D열과 F열의 셀 서식을 3자리마다 쉼표 삽입으로 설정
        'Range("d:d,f:f").NumberFormat = "#,##0"
        Range("d:d").NumberFormat = "#,##0.0"
        Range("f:f").NumberFormat = "#,##0"

D열과 F열의 셀 서식(NumberFormat)을 지정하는 것인데, 소수점 없이 세 자리마다 쉼표를 넣으려고 했는데, 면적은 소수점이하가 있어서 구분해서 소수점이하 첫째 자리까지 표시하도록 하는 것입니다.
 
(11) 검색 URL 만들기(1)

        ' 법정동 코드 조회 검색 URL 만들기(domain 지정안해도 됨)
        base_url = "https://api.vworld.kr/req/address"
        params = "?service=address&request=getcoord&version=2.0&crs=epsg:4326"
        params = params & "&address=" & WorksheetFunction.EncodeURL(dong & " " & jibun)
        params = params & "&refine=true&simple=false&format=xml&type=parcel"
        params = params & "&key=CEB52025-E065-364C-9DBA-44880E3B02B8"

 
법정동 코드를 조회하는 URL은 https://api.vworld.kr/req/address 이므로 이것을 base_url에 대입하고,
get 방식이므로 그 다음에 ?를 붙인 다음 인수명=값 식으로 입력하는데 &로 연결합니다.
 
특이한 것은 주소( (예, 서울특별시 종로구 청운동 1-1, dong & " " jibun)에 공백이 있으므로 EncodeURL 함수를 사용하는데 VBA에 없는 함수이므로 앞에 WorksheetFunction을 붙여 워크시트 함수라는 것을 명시해야 합니다.
 
refine은 출력결과에 refined를 포함할 것인지 여부를 지정하는 것으로 기본값이 true이므로 지정할 필요는 없지만 false로 테스트할 수 있게 넣은 것입니다.

그러나, refine=false라고 입력하면 특정동코드에 해당하는 level4LC(아래 설명에서 level4AC는 오타임)가 표시되지 않기 때문에 에러가 발생합니다.

 
key는 인증키로 vworld사이트에서 활용신청을 하면 받을 수 있으며 자세한 것은
https://lsw3210.tistory.com/622 글을 참고 바랍니다.
 
XML 형식을 처리할 것이기 때문에 format이 xml로 되어 있어야 합니다. JSON이면 안됩니다.
 
(12) 검색 URL 만들기(2)

        ' search_url을 base_url과 params의 결합으로 지정
        search_url = base_url & params

위에서 만든 base_url과 params를 결합해서 search_url을 만듭니다.
 
확인하면 아래와 같습니다. 디버그 다룰 때 따로 설명하겠습니다.
https://api.vworld.kr/req/address?service=address&request=getcoord&version=2.0&crs=epsg:4326&address=%EC%84%9C%EC%9A%B8%ED%8A%B9%EB%B3%84%EC%8B%9C%20%EC%A2%85%EB%A1%9C%EA%B5%AC%20%EC%B2%AD%EC%9A%B4%EB%8F%99%201-1&refine=true&simple=false&format=xml&type=parcel&key=CEB52025-E065-364C-9DBA-44880E3B02B8

(13) 검색 결과를 pnu 변수에 대입

        ' PNU 조회 함수
        value = search_value(ws, i, value, xmlHttp, xmlDoc, search_url)
        pnu = value(0)

 
search_value함수로 구한 결과를 value 배열에 대입합니다.
search_value함수에 필요한 인수로는 ws, i, value, xmlHttp, xmlDoc, search_url이 있습니다.
 
법정동코드 조회 시는 value 배열의 값이 1개이므로 value(0)을 pnu 변수에 대입합니다.
값은 "1111010100100010001"식입니다.
 
(14) pnu가 없을 경우 다음 행 처리

        If pnu = "" Then
            GoTo cont_loc
        End If
(중략)

'중간을 건너뛰고 여기로 옮
cont_loc:

    Next

pnu의 값이 ""이면, 다시 말해 동과 지번이 잘못된 경우는 중간의 처리 문을 모두 처리하지 않고, cont_loc:이라고 쓰인 곳으로 이동하므로 다음 행을 처리하게 됩니다.
 
나머지는 다음 편에서 다루도록 하겠습니다.

반응형