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

문서좌표를 활용하는 고급메서드 : GetAnchorPos()

by 일코 2022. 9. 8.

지난 포스팅에서

한/글 문서의 위치정보에 대해 설명드렸습니다.

2022.09.08 - [업무자동화/파이썬-아래아한글 자동화 기초] - 아래아한글 문서의 위치(좌표)체계

 

아래아한글 문서의 위치(좌표)체계

아래아한글 문서의 위치체계 아래아한글 문서에는 명확하게 위치체계가 존재하고, 비어있는 공간이 아닌 이상 좌표(?)가 매겨져 있습니다. 마치 3차원 좌표계(x, y, z)처럼 말이죠. 이 글에서 사용

martinii.fun

(List, Para, Pos)로 구성된 3차원 벡터는 마치 좌표를 연상하게 하는데요.

굳이 누름틀이나 필드를 이용하지 않고도 얼마든지 자유롭게 원하는 위치로, 혹은 오프셋 이동이 가능하기 때문에, 다양한 방법으로 활용할 수 있겠습니다.

 

이번 포스팅은 "이미지마다 캡션 텍스트 달기"

위치정보를 활용하는 메서드인 GetAnchorPos를 간단한 예제를 통해 설명드리겠습니다.

이런 작업을 하고 싶다고 가정해봅시다. 문서 안에 다음과 같은 8장의 사진이 삽입되어 있고,

 

각 사진에 대한 캡션을 스프레드시트에서 다음과 같이 파이썬 리스트 자료형으로 가져온 상태입니다.

caption_list = [
    "구름 낀 하늘", 
    "푸른 하늘", 
    "사막의 잔디", 
    "강 주변", 
    "아프리카 강", 
    "해저 모래", 
    "해저 바닥", 
    "삼엽충"]

각 사진의 아래에 <구름 낀 하늘>, <푸른 하늘>, ... 식으로 텍스트를 삽입하는 작업을 자동화할 수 있을까요?

아래처럼 말예요.

문서 안에 단순하게 그림만 삽입되어 있는 상태라면..

무식하게 키매크로를 활용해서

"아래, 순차대로 텍스트입력, 엔터엔터, <반복>"

이런 식으로 작업할 수는 있겠습니다.

 

그런데 그림 외에도 표나 텍스트가 삽입되어 있는 경우라면?

이런 경우에

그림.GetAnchorPos()를 활용하면 좀 더 정확하고 우아하게 처리할 수 있습니다.

먼저 GetAnchorPos가 어떤 메서드인지 알아봅시다.

 

그럼 GetAnchorPos는 어떤 명령어인가요?

GetAnchorPos는 컨트롤객체(표, 그리기개체 등)의 위치정보를 리턴해주는 메서드입니다.

한/글에서는 좌표체계 외에도, 컨트롤만 순회하며 탐색할 수 있는 기능을 제공하고 있어요.

(hwp.HeadCtrl, hwp.LastCtrl, .Next, .Prev 등.. 링크드리스트 형식임)

컨트롤을 변수로 지정한 상태에서 정보조회, 수정, 삭제 등 간편하게 조작할 수 있어요.

 

예) 아래는 문서의 두 번째 컨트롤개체(푸른하늘 사진)을 지우는 코드예요.

첫 번째 컨트롤은 "구역 정의", 두 번째 컨트롤은 "단 정의"로 예약되어 있어서, 문서에 삽입한 첫 번째 개체가 사실은 세 번째임

 

예) 이미지의 너비를 조회하고 싶을 때는 이렇게 하면 돼요.

정확하네요.

[A4용지의 가로너비] 210mm - [좌우측 여백] 30mm * 2 = 150mm이니까요.

 

다시 본론으로 돌아와서, GetAnchorPos는

해당 컨트롤의 위치를 파라미터셋 개체로 리턴해줘요. 파이썬의 리스트나 튜플 자료형이 아니라서, 리턴받은 값을 조회할 때는 Item이라는 메서드를 사용해야 해요.

 

세 번째 그림이 삽입되어 있는 위치를 얻어오려면?

위의 영상에서 작성한 코드입니다.

pic_index = 3
count = 0

while True:
    if ctrl.UserDesc == "그림":
        count += 1
        if count == pic_index:
            loc = ctrl.GetAnchorPos(0)
            break
        else:
            ctrl = ctrl.Next
    else:
        ctrl = ctrl.Next

loc.Item("List")
# >>> 0

loc.Item("Para")
# >>> 5

loc.Item("Pos")
# >>> 0

위 정보를 활용해서 세 번째 그림의 앞으로 이동한 후

아래에 줄바꿈을 하나 삽입하고, "<사막의 잔디>"라는 텍스트를 입력하겠습니다.

참고로 텍스트 입력 함수는 아래와 같이 정의합니다.

def 문자열삽입(문자열):
    hwp.HAction.GetDefault("InsertText", hwp.HParameterSet.HInsertText.HSet)
    hwp.HParameterSet.HInsertText.Text = 문자열
    hwp.HAction.Execute("InsertText", hwp.HParameterSet.HInsertText.HSet)

위 영상에서 사용한 코드입니다.

ctrl = hwp.HeadCtrl

while True:
    if ctrl.UserDesc == "그림":
        count += 1
        if count == pic_index:
            loc = ctrl.GetAnchorPos(0)
            break
        else:
            ctrl = ctrl.Next
    else:
        ctrl = ctrl.Next

hwp.SetPos(*[loc.Item(i) for i in ["List", "Para", "Pos"]])
hwp.Run("MoveLineEnd")
hwp.Run("BreakPara")
문자열삽입("<사막의 잔디>")

 

최종코드 : 각 이미지에 캡션 삽입

그럼 위 코드를 조합해서 이미지 전체에 캡션(엄밀히는 캡션이 아님ㅜ)을 삽입하는 코드를 작성해보겠습니다.

성공적으로 캡션이 삽입되었습니다.

 

위에서 작성한 스크립트는 아래와 같습니다.

def 문자열삽입(문자열):
    hwp.HAction.GetDefault("InsertText", hwp.HParameterSet.HInsertText.HSet)
    hwp.HParameterSet.HInsertText.Text = 문자열
    hwp.HAction.Execute("InsertText", hwp.HParameterSet.HInsertText.HSet)


caption_list = [
    "구름 낀 하늘", 
    "푸른 하늘", 
    "사막의 잔디", 
    "강 주변", 
    "아프리카 강", 
    "해저 모래", 
    "해저 바닥", 
    "삼엽충"]
    

ctrl = hwp.HeadCtrl
image_loc = []
while True:
    if ctrl.UserDesc == "그림":
        image_loc.append(ctrl.GetAnchorPos(0))
        ctrl = ctrl.Next
    else:
        ctrl = ctrl.Next

for idx, loc in enumerate(image_loc[::-1]):  # 역순으로 탐색
    hwp.SetPos(*[loc.Item(i) for i in ["List", "Para", "Pos"]])
    hwp.Run("MoveLineEnd")
    hwp.Run("BreakPara")
    문자열삽입(f"<{caption_list[::-1][idx]}>")  # 캡션도 역순으로 입력
참고로, 찾아가기도 역순으로, 덩달아 캡션도 역순으로 붙인 이유는
줄바꿈 때문에 아래쪽 모든 그림들의 좌표(Para 요소)값이 바뀌어 버리기 때문입니다.
역순으로 삽입하면 그런 문제가 해결됩니다.

 

댓글