본문 바로가기
아래아한글 자동화/python+hwp 입문

2-5. 문서의 필드목록 및 필드 값 취득하기

by 회사원코딩 2022. 11. 7.

지금까지는 필드에 값을 삽입하는 과정을 보여드렸다면,

이번 챕터에서는 한/글 문서의 필드 목록을 가져오거나,

특정 필드의 값을 추출하는 방법을 알려드리겠습니다.

이번 실습에 사용할 한/글 문서는 지난 포스팅에서 완성한 "누름틀필드#완성.hwp"입니다.

지난 포스팅부터 읽어오셨다면 아시겠지만 아래의 문서에는
모든 페이지마다 "이름", "성별", "생일", "취미" 라는 누름틀필드가 생성되어 있고
모든 필드에 값을 입력해놓은 상태입니다.

누름틀필드#완성.hwp
0.02MB

필드명 불러오기 : hwp.GetFieldList(1)

이 문서를 파이썬으로 연 후 필드의 이름 목록을 가져와보겠습니다. (필드에 삽입된 값이 아닙니다.)

필드 리스트를 얻는 코드는 "hwp.GetFieldList()" 입니다.

print(hwp.GetFieldList())

# >>> 이름\x02성별\x02생일\x02취미\x02
# ... 이름\x02성별\x02생일\x02취미\x02
# ... 이름\x02성별\x02생일\x02취미\x02
# ... 이름\x02성별\x02생일\x02취미\x02
# ... 이름\x02성별\x02생일\x02취미\x02
# ... 이름\x02성별\x02생일\x02취미

참고로 괄호 안에 Number와 option, 두 개의 인자가 동시에 들어갈 수 있습니다.
<Number>
0: 아무 기호 없이 순서대로 필드의 이름을 나열(기본값)
1: 필드 이름 뒤에 일련번호가 {{#}}과 같은 형식으로 붙음
2. 필드 이름 뒤에 해당필드의 갯수가 {{#}}과 같은 형식으로 붙음

<option>
0: 문서 내의 모든 필드 리스트를 구함
1: 셀에 부여된 필드 리스트만 구함
2: 누름틀에 부여된 필드 리스트만 구함
5: 선택범위 안에 존재하는 셀 필드 리스트만 구함
6: 선택범위 안에 존재하는 누름틀 필드 리스트만 구함

다양한 업무자동화 케이스에 활용하기 위해 여러 개의 옵션이 있지만,

가장 많이 사용되는 인자와 파라미터는 hwp.GetFieldList(Number=1)이며,

이는 hwp.GetFieldList(1)로 단축하여 입력 가능합니다.

필드명 뒤에 "{{인덱스}}"를 추가한 형식입니다.

hwp.GetFieldList(1)

그런데 이상한 점이 하나 보입니다.

리턴되는 값이 리스트나 튜플이 아닌 하나의 "문자열"인데요. 구분자가 "\x02"입니다.

문자열 클래스의 split 메서드를 사용해서 리스트로 변환해보겠습니다.

print(hwp.GetFieldList(1).split("\x02"))

# >>> ['이름{{0}}', '성별{{0}}', '생일{{0}}', '취미{{0}}',
# ...  '이름{{1}}', '성별{{1}}', '생일{{1}}', '취미{{1}}',
# ...  '이름{{2}}', '성별{{2}}', '생일{{2}}', '취미{{2}}',
# ...  '이름{{3}}', '성별{{3}}', '생일{{3}}', '취미{{3}}',
# ...  '이름{{4}}', '성별{{4}}', '생일{{4}}', '취미{{4}}',
# ...  '이름{{5}}', '성별{{5}}', '생일{{5}}', '취미{{5}}']

여기까지 필드명을 추출하는 방법을 알아보았습니다.

필드 값 불러오기 : hwp.GetFieldText(필드명)

그럼 이번엔, 이 필드명 리스트를 사용해서 모든 필드 값들을 불러오는 과정을 진행해볼까요?

필드 값을 불러오는 명령어는 hwp.GetFieldText(필드명) 입니다.

필드명 뒤에 {{인덱스}}를 넣으면 동일명의 필드 중 해당 순서의 필드 값이 리턴됩니다.

{{인덱스}}를 넣지 않고 필드명만 입력하면 첫 번째로 나타나는 필드의 값이 리턴됩니다.

필드명과 필드값을 모두 출력해보겠습니다.

field_list = hwp.GetFieldList(1).split("\x02")

for i in field_list:
    print(i, hwp.GetFieldText(i))

# >>> 이름{{0}} 마크
# ... 성별{{0}} 남
# ... 생일{{0}} 1984년 5월 14일
# ... 취미{{0}} VR
# ... 이름{{1}} 빌
# ... 성별{{1}} 남
# ... 생일{{1}} 1955년 10월 28일
# ... 취미{{1}} 기부
# ... 이름{{2}} 일론
# ... 성별{{2}} 남
# ... 생일{{2}} 1971년 6월 28일
# ... 취미{{2}} 트위터
# ... 이름{{3}} 제프
# ... 성별{{3}} 남
# ... 생일{{3}} 1964년 1월 12일
# ... 취미{{3}} 독서
# ... 이름{{4}} 리사
# ... 성별{{4}} 여
# ... 생일{{4}} 1969년 11월 7일
# ... 취미{{4}} 게임
# ... 이름{{5}} 슬아
# ... 성별{{5}} 여
# ... 생일{{5}} 1983년 6월 16일
# ... 취미{{5}} 쇼핑

굳이 for문이 아니라, 특정 필드명을 직접 입력해서 값을 추출하는 것도 가능합니다.

print(hwp.GetFieldText("취미{{4}}"))

# >>> 게임

이번엔,

파이썬의 if문을 사용해서 "제프"의 "취미"가 무엇인지 알아볼 수 있을까요?

page_count = hwp.XHwpDocuments.Item(0).XHwpDocumentInfo.PageCount

print(page_count)
# >>> 6

for i in range(page_count):
    if hwp.GetFieldText(f"이름{{{{{i}}}}}") == "제프":
        print(hwp.GetFieldText(f"취미{{{{{i}}}}}"))
# >>> 독서

이걸 간편하게 함수로 만들어 볼 수도 있겠네요.(별 쓸모는 없겠지만요ㅜ)

def 취미(이름):
    page_count = hwp.XHwpDocuments.Item(0).XHwpDocumentInfo.PageCount

    for i in range(page_count):
        if hwp.GetFieldText(f"이름{{{{{i}}}}}") == 이름:
            return hwp.GetFieldText(f"취미{{{{{i}}}}}")

취미("마크")
# >>> VR

취미("제프")
# >>> 독서

취미("리사")
# >>> 게임


마치며

여기까지 중간정리를 해 보면,

이번 포스팅에서 한/글 문서의 필드 목록을 구하거나 필드의 값을 구하는 방법,

그리고 이전 포스팅 시리즈에서 필드에 값을 입력하는 방법,

엑셀문서에서 값을 가져오는 방법,

그리고 더 이전에 한/글 문서를 열고닫는 법, 저장하는 법,

그리고 문서정보를 취득하는 방법 등을 간략히 설명해 드렸습니다.

개인적으로는 이 과정까지 여러분의 것으로 만드셨다면

여러분 업무 중 많은 케이스의 한/글 보고서 업무자동화는 넉넉하게 가능하실 거라고 생각합니다.

이후 과정들은 배우고 익히는 데 시간이 많이 걸리지만,

그리 효용성이 높지 않은,

비교적 특이한 케이스에 사용되는 코드들이기 때문입니다.

그래서, 여기까지 읽기를 마치고

여러분의 업무를 하나씩 자동화해보시다가

한/글 누름틀 필드로는 해결되지 않는 문제를 만나셨을 때 

다시 찾아오셔서 이후 과정을 이어 읽으시기를 권장드립니다.

(이고잉님 존경합니다.)

그럼 이 포스팅은 여기서 마치겠습니다.

수고하셨습니다.


<부록 : 왜 필드인덱스에 중괄호를 다섯 겹 씩이나 붙일까?>

별로 중요한 내용은 아닙니다.

f스트링 안에 인덱스를 입력할 때 왜 중괄호를 "{{{{{i}}}}}"처럼 다섯 겹씩이나 입력해야 하는지

궁금하다고 생각하신 분 계신가요? (아주 좋은 자세라고 생각합니다.)

그 이유는 아래와 같습니다.

먼저 한/글의 필드명에 인덱스를 붙일 때는 중괄호를 두 겹으로 넣어야 합니다.

"이름{{4}}", "취미{{5}}" 이런 식으로 말이죠.

그리고 대부분 아시다시피, 파이썬의 f-string 안에 변수 값을 삽입할 때에는

한 겹의 중괄호로 덮어야 하죠.

name = "신명진"
print(f"제 이름은 {name}입니다.")
# >>> 제 이름은 신명진입니다.

여기서 사소한 충돌(?)이 발생합니다.

중괄호 한 겹은 f스트링이 소모해버리는데,

한/글 API문법으로 인한 중괄호 두 겹을 추가로 입력하려면

중괄호가 두 겹씩 네 겹이 되어야 합니다. 왜냐면?

그 이유는 (불행 중 다행으로) f스트링 안에서 중괄호를 두 겹 입력하면

f스트링 시퀀스가 아닌, 순수 문자열의 중괄호 한 겹으로 변환되기 때문이죠.

빠른 이해를 돕기 위해 아래 예시를 보여드리겠습니다.

i = 4

print(f"이름{i}")  # 한 겹 : f-string 적용(변수로 인식)
# >>> 이름4

print(f"이름{{i}}")  # 두 겹 : f-string 해제(문자열로 인식)
# >>> 이름{i}

print(f"이름{{{i}}}")  # 세 겹 : f-string 적용(변수로 인식)
# >>> 이름{4}

print(f"이름{{{{i}}}}")  # 네 겹 : f-string 해제(문자열로 인식)
# >>> 이름{{i}}

print(f"이름{{{{{i}}}}}")  # 다섯 겹. 우리가 원하는 결과
# >>> 이름{{4}}

우리가 원하는 건 마지막 케이스인 "이름{{4}}"이므로

번거롭지만 중괄호를 다섯 겹씩 붙여야 한답니다..

비슷하게 번거롭지만,  다른 방법으로, 따옴표 앞에 rf를 붙이면

아래 방법처럼 세 겹의 중괄호로도 한/글 필드 인덱스 입력이 가능합니다.

i = 4

print(rf"이름{{{i}}}")
# >>> 이름{{4}}

 

첫 번째 방법 : f"이름{{{{{i}}}}}"  # 다섯 겹

두 번째 방법 : rf"이름{{{i}}}"  # 세 겹

위 두 가지 방법 중 여러분의 기호에 맞게 취사선택하시면 되겠습니다.

반응형

댓글0