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

한/글 문서 이미지 사이즈를 문서여백에 맞춰 일괄조정 및 캡션 유지하는 방법

by 일코 2022. 2. 10.

안녕하세요?

일상의 코딩, 일코입니다.

예전 포스팅 중에, 이미지 사이즈 일괄변경 관련하는 방법을 올린 적이 있었습니다.

2021.01.07 - [업무자동화/파이썬-아래아한글 자동화 기초] - HWP여백조정 후 이미지 너비/높이를 폭에 맞게 일괄조정하는 방법

 

HWP여백조정 후 이미지 너비/높이를 폭에 맞게 일괄조정하는 방법

HWP포맷을 사용하는 소규모의 출판사가 의외로 많다는 걸 최근들어 알게 되었다. 그도 그럴 것이, 인디자인이나 퍼블리셔 같은 프로그램 없이도 직접 책을 출판하고 SNS로 홍보할 수 있는 시대가

martinii.fun

 

이 글을 쓸 때만 해도

"굉장히 공들여 만든 포스팅"이라고 생각했는데,

댓글알림이 달려서 오랜만에 읽어보니까

'내가 욕심이 어마어마했구나!' 하는 생각이 강하게 드네요.

이것저것 아는 것 전부 다 코드에 우겨넣다 보니까

가독성도 빵이고,

내용도 너무 복잡해져서ㅜㅜ 다시 읽기도 힘드네요.

다섯 조각 이상 쪼개서 시리즈로 다시 연재해도 되겠다 싶네요.

그럼에도, 삽입이미지 사이즈 관련 자동화 작업 하실 때

참고해볼 만한 자료라고는 생각합니다.

리팩토링도 귀찮은데
하물며 리포스팅은...
정말정말 미루고 싶네요.

 

하여튼,

이 포스팅에는 작은 버그가 있어요.

바로, 이미지 사이즈를 조정하면, 캡션이 사라지는 현상이 있습니다ㅜ

이미지 사이즈만 수정했는데 캡션이 사라지네요...

왜 그런지 이유를 추정해보자면,
파라미터셋 테이블의 ShapeObject와 관련 파라미터셋을 찾아 읽어봤는데
"캡션 문자열"은 파라미터셋 안에 아예 포함되어 있지 않더라고요..
그래서인지, GetDefault를 실행해도 현재 캡션의 정보가 파이썬으로 안 넘어오는 것 같아요..

해법은?

복붙을 사용하면 간단히 해결할 수 있습니다.

(가급적 복붙을 자동화에 안 쓰고 싶은데, 이렇게 어쩔 수 없는 경우들이 있네요;)

본 포스팅을 따라해 보고 싶으신 분은

아래 HWP 문서를 다운받아서 따라해봅시다.

여백조정후이미지조정_번호.hwpx
0.62MB

 

전체 작업을 요약하면

0. 문서 여백정보 추출

1. 캡션 복사
    ①이미지의 캡션 칸에 들어가서(Ctrl-N-C)
    ②전체선택(Ctrl-A), 복사(Ctrl-C) 후
    ③캡션영역 밖으로 나감(Shift-Esc)

2. 여백에 맞게 이미지 사이즈 조정(캡션 사라짐)

3. 캡션 다시 붙여넣기
    ①이미지의 캡션 칸에 들어가서(Ctrl-N-C)
    ②전체선택(Ctrl-A), 붙여넣기(Ctrl-V) 후
    ③캡션영역 밖으로 나감(Shift-Esc)

4. 위의 1~3 코드를 반복

위의 1번과 3번 과정은

아래처럼 매크로를 녹화해서

파이썬 함수로 만들어보았습니다.

 

1. 복사하는 과정 매크로 녹화

녹화한 코드

function OnScriptMacro_중국어1성()
{
	HAction.Run("ShapeObjCaption");
	HAction.Run("SelectAll");
	HAction.Run("Copy");
	HAction.Run("CloseEx");
}

파이썬 코드

def 캡션복사():
    hwp.HAction.Run("ShapeObjCaption")
    hwp.HAction.Run("SelectAll")
    hwp.HAction.Run("Copy")
    hwp.HAction.Run("CloseEx")

 

2. 붙여넣는 과정 매크로 녹화

녹화한 코드

function OnScriptMacro_중국어1성()
{
	HAction.Run("ShapeObjCaption");
	HAction.GetDefault("Paste", HParameterSet.HSelectionOpt.HSet);
	with (HParameterSet.HSelectionOpt)
	{
	}
	HAction.Execute("Paste", HParameterSet.HSelectionOpt.HSet);
	HAction.Run("CloseEx");
}

파이썬으로 변환한 코드

def 캡션붙여넣기():
    hwp.HAction.Run("ShapeObjCaption")
    hwp.HAction.Run("SelectAll")
    hwp.HAction.Run("Paste")
    hwp.HAction.Run("CloseEx")

 

3. 두 개의 함수를 코드에 추가

전체 코드가 아래와 같이 완성되었습니다.

from tkinter import Tk  # GUI로 파일 선택하기 위한 모듈
from tkinter.filedialog import askopenfilename  # 파일선택창

import win32com.client as win32  # 한/글 열기 위한 모듈


def hwp_init(filename):  # 한/글 여는 코드가 길어서 미리 만들어둠
    hwp = win32.gencache.EnsureDispatch("HWPFrame.HwpObject")  # 한/글 객체 생성
    hwp.RegisterModule("FilePathCheckDLL", "FilePathCheckerModule")  # 보안모듈 실행
    hwp.Open(filename)  # GUI에서 선택한 파일 열기
    hwp.XHwpWindows.Item(0).Visible = True  # 한/글 창 숨김해제(초기에는 백그라운드상태)
    # hwp.HAction.Run("FrameFullScreen")  # 전체화면
    return hwp  # hwp객체 리턴


def Hwp유닛을_밀리미터로(HWP유닛):  # MiliToHwpUnit메서드의 반대. 계산 귀찮아서 만들어둠.
    return HWP유닛 / 7200 * 25.4  # 1 inch = 7200 HWPUNIT, 1mm = 283.465 HWPUNIT


def ctrl로_이동하기(ctrl):  # 그리기객체나 표 등 컨트롤 오브젝트로 이동하는 함수
    위치세트 = ctrl.GetAnchorPos(0)  # 현재 선택된 컨트롤의 위치파라미터 추출
    위치 = (위치세트.Item("List"), 위치세트.Item("Para"), 위치세트.Item("Pos"))  # 튜플로 변환
    hwp.SetPos(*위치)  # 해당 위치로 커서(캐럿) 이동


def 캡션복사():
    hwp.HAction.Run("ShapeObjCaption")
    hwp.HAction.Run("SelectAll")
    hwp.HAction.Run("Copy")
    hwp.HAction.Run("CloseEx")


def 사이즈조정():
    hwp.FindCtrl()  # 해당 객체 선택
    이미지액션 = hwp.CreateAction("ShapeObjDialog")  # 이미지수정액선 실행준비
    이미지세트 = 이미지액션.CreateSet()  # 이미지수정을 위한 파라미터 배열(비어있음) 생성
    이미지액션.GetDefault(이미지세트)  # 빈 파라미터 배열에 현재문서의 값을 채워넣음
    기존너비 = Hwp유닛을_밀리미터로(이미지세트.Item("Width"))  # 선택 이미지의 현재너비 저장
    기존높이 = Hwp유닛을_밀리미터로(이미지세트.Item("Height"))  # 선택 이미지의 현재높이 저장
    변경쪽너비 = 종이너비 - 좌측여백 - 우측여백 - (0 if 제본타입 == 2 else 제본여백)  # 변경할 쪽너비 계산
    파라미터셋 = 이미지세트.CreateItemSet("ShapeObject", "ShapeObject")  # 이미지 수정을 위한 파라미터셋 생성
    파라미터셋.SetItem("Width", hwp.MiliToHwpUnit(변경쪽너비))  # 이미지너비 변경값 입력
    파라미터셋.SetItem("Height", hwp.MiliToHwpUnit(기존높이 * 변경쪽너비 / 기존너비))  # 이미지높이 변경값 입력
    이미지액션.Execute(파라미터셋)  # 입력한 값 적용


def 캡션붙여넣기():
    hwp.HAction.Run("ShapeObjCaption")
    hwp.HAction.Run("SelectAll")
    hwp.HAction.Run("Paste")
    hwp.HAction.Run("CloseEx")


if __name__ == '__main__':  # 메인함수 파트
    root = Tk()  # GUI(그래픽 유저 인터페이스) 인스턴스 생성
    filename = askopenfilename()  # 파일열기창 실행
    root.destroy()  # 파일선택 후 tkinter 종료
    hwp = hwp_init(filename=filename)  # 위에서 정의한 한/글 열기 함수
    페이지액션 = hwp.CreateAction("PageSetup")  # 페이지셋업 액션 실행준비
    페이지세트 = 페이지액션.CreateSet()  # 페이지 설정을 위한 파라미터 배열(비어있음) 생성
    페이지액션.GetDefault(페이지세트)  # 파라미터에 현재문서의 값을 채워넣음
    종이너비 = Hwp유닛을_밀리미터로(페이지세트.Item("PageDef").Item("PaperWidth"))  # 채워넣은 값 중 종이너비
    좌측여백 = Hwp유닛을_밀리미터로(페이지세트.Item("PageDef").Item("LeftMargin"))  # 채워넣은 값 중 좌측여백
    우측여백 = Hwp유닛을_밀리미터로(페이지세트.Item("PageDef").Item("RightMargin"))  # 채워넣은 값 중 우측여백
    제본여백 = Hwp유닛을_밀리미터로(페이지세트.Item("PageDef").Item("GutterLen"))  # 채워넣은 값 중 제본여백
    제본타입 = Hwp유닛을_밀리미터로(페이지세트.Item("PageDef").Item("GutterType"))  # 0:한쪽, 1:맞쪽, 2: 위쪽

    ctrl = hwp.HeadCtrl  # 문서 중 첫번째 컨트롤 선택
    while ctrl != None:  # 마지막 컨트롤까지 순회할 것.
        if ctrl.CtrlID == "gso":  # 컨트롤아이디가 그리기객체(gso)이면
            ctrl로_이동하기(ctrl)  # 위에서 정의한 이동함수
            캡션복사()
            사이즈조정()
            캡션붙여넣기()
        else:  # 컨트롤아이디가 그리기객체가 아니면
            pass  # 그냥 넘어가기
        ctrl = ctrl.Next  # 다음 컨트롤로 이동
구현기능에 비해
코드가 굉장히 복잡하고 장황해 보이는데.....
이게 다 제 내공 탓입니다.
부끄럽습니다ㅜ

실행화면은 아래와 같습니다.

 

이미지 사이즈 조정 후에도, 캡션이 유지되네요!

의도한 대로 잘 실행되는 것 같네요.

더 깔끔한 구현방법이 있지 않을까 하는 작은 아쉬움이

정말 좁쌀만큼은 있지만,

이쯤에서 욕심을 버리려고 합니다.

 

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

행복한 하루 되세요^^

 


donaricano-btn

댓글