본문 바로가기
업무자동화/파이썬-아래아한글 자동화 기초

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

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

반응형

댓글4

  • 익명 2022.02.10 13:53

    비밀댓글입니다
    답글

  • 밍밍한 일기 2022.02.23 10:17 신고

    안녕하세요 일코님! 항상 게시물을 통해 도움을 받고 있습니다.
    저도 한글 자동화 관련하여 개발을 진행하려고 하는데, 정보가 많이 부족하네요ㅜ
    게시글들을 보니 CopyPage와 같이 한컴 API 명세서에는 없는 정보가 기재되어 있던데
    이와 같은 정보를 어디서 얻을 수 얻으시는 지 알 수 있을까요?
    항상 좋은 글 감사합니다
    답글

  • 기차역 2022.02.23 11:10 신고

    감사합니다..!
    답글