인프런 커뮤니티 질문&답변

이태우님의 프로필 이미지

작성한 질문수

직장인에게 꼭 필요한 파이썬-아래아한글 자동화 레시피

모든 글자에 글자모양, 문단모양 변경없이 스타일 값만 바꿀 수 있을까요?

해결된 질문

23.04.13 15:20 작성

·

506

1

안녕하세요 해당 수업 덕분에 한글을 좀 더 잘 쓸수 있게 되었습니다.

여러문서를 이리저리 합치다 보니 스타일이 막 뒤죽박죽으로 섞여서

예를 들어 바탕체, 바탕체사본1, 바탕체사본2

 

이렇게 섞여있어서 스타일을 좀 정리하고 싶은데

기존에 보니 모든 스타일을 바탕글로 바꾸는 코드는 있던데

표 안에는 적용이 안되고 서식복사기능을 사용하다보니 글씨 모양(볼드체나 색등)이 바뀌게 되던데 본문에 모든 글씨의 글씨모양이나 문단모양, 자간은 그대로 하고 스타일 정보만 바꾸고 싶은데 방법이 있을까요?

 

생각중인건 한 글자씩

  1. 글씨의 모든 정보 조회-> 각 정보를 변수에 저장 -> 원하는 스타일 변경 -> 복사한 변수정보로 대치 하면 될 꺼 같긴 한데, 보통 액션 자체에 변수초기화가 디폴트로 들어가다보니

이렇게 코드를 만드는게 맞는지 궁금합니다.

 

  1. 아니면 스타일값만 바꾸는(글자는 현재보이는 그대로) 다른 액션이나 파라미터셋이 있는지 궁금합니다.

 

내용이 복잡하긴하지만 조금 힌트라도 주시면 감사하겠습니다

 

 

 

답변 2

2

일코님의 프로필 이미지
일코
지식공유자

2023. 10. 26. 03:23

태우님, 안녕하세요?

말씀하신 부분은 약간 까다롭긴 하지만 구현 가능합니다.

다만, "어떤 스타일 문단은 어떤 스타일로 변경해야 한다"는 규칙을 정해서 적용하셔야 합니다.

스타일은 내부적으로 인덱스가 있습니다.

F6을 눌렀을 때 나타나는 순서대로 0번부터 번호가 매겨집니다.

예를 들어 아래와 같은 경우

image

바탕글 : 0
본문 : 1
개요1 : 2
개요2 : 3 ...

이런 방식입니다.

예를 들어 모든 폰트정보를 유지한 채로
스타일만 "개요 1"로 변경하는 코드는 아래와 같습니다.
아마 예상하신 것보다 다소 복잡해 보일 수 있겠지만ㅜㅜㅜ (제 한계입니다...)
구현한 함수 위주로 천천히 읽어보시기를 바랍니다.


요약하면,
파일을 hwpx로 저장한 후 압축을 풀고
hwpx 파일의 소스를 직접 열어서
스타일 정의 부분의 인덱스만 변경한 후
다시 압축해서 hwpx로 변환하는 코드입니다.

image

글자가 다소 작지만,

각각 개요1, 개요2, 개요3으로 적용되어 있던 문단들이
코드 실행 후
전부 개요1로 바뀌는 것을 확인하실 수 있습니다.
서체는 그대로 유지한 채로요.


전체 코드는 아래 적어 둡니다.

import os
import shutil
import zipfile
from glob import glob
from time import sleep

import win32com.client as win32

hwp = win32.gencache.EnsureDispatch("hwpframe.hwpobject")
hwp.XHwpWindows.Item(0).Visible = True
hwp.RegisterModule("FilePathCheckDLL", "FilePathCheckerModule")
hwp.Open(os.path.join(os.getcwd(), "원본.hwp"))


def save_hwpx():
    path = hwp.Path
    hwp.SaveAs(path.replace(".hwp", "_변환.hwpx").replace(".hwpxx", ".hwpx"), "HWPX")
    hwp.Clear()
    hwp.Open(path)


def extract(path):
    os.chdir(os.path.dirname(hwp.Path))  # 파일경로 중 경로만 추출해서 그 경로로 이동
    target_path = os.path.join(os.getcwd(), "temp")  # 압축 풀 하위폴더는 "./temp"
    with zipfile.ZipFile(path, 'r') as zf:  # 압축파일 인스턴스를 생성하고
        zf.extractall(path=target_path)  # target_path 안에 압축해제
    while True:
        try:
            os.remove(path)  # hwpx 파일은 단호하게 삭제함
            break
        except PermissionError:
            sleep(0.1)


def convert(src, dst):
    sections = glob("./temp/Contents/section*.xml")
    for section in sections:
        with open(section, "r") as f:
            source = f.read()
            source = source.replace(f'''styleIDRef="{src}"''', f'''styleIDRef="{dst}"''')
        with open(section, "w") as f:
            f.write(source)


def zipdir(path, ziph):
    os.chdir(path)
    for root, dirs, files in os.walk("."):
        for file in files:
            ziph.write(os.path.join(root, file))
    os.chdir("..")


save_hwpx()
extract(hwp.Path.replace(".hwp", "_변환.hwpx").replace(".hwpxx", ".hwpx"))
convert(3, 2)  # "개요2" 스타일을 "개요1"로(서체는 유지)
convert(4, 2)  # "개요3" 스타일도 "개요1"로(서체는 유지)

with zipfile.ZipFile('result.hwpx', 'w', zipfile.ZIP_DEFLATED) as zipf:
    zipdir('temp', zipf)
shutil.rmtree('temp')
hwp.Run("FileClose")
hwp.Open(os.path.join(os.getcwd(), "result.hwpx"))
hwp.SaveAs(os.path.join(os.getcwd(), "result.hwp"), "HWP")

 태우님 문서에 적용해보시려면
원본파일 경로와 코드 하단의 convert 함수 부분만 적절히 매핑하시면 되겠습니다.

 

도움이 되었기를 바랍니다^^;

이태우님의 프로필 이미지
이태우
질문자

2023. 10. 29. 12:07

바쁘신 와중에 답변 주셔서 감사합니다.

간단한 기능일줄 알았는데 꽤나 까다로운 방법이였군요.

그래도 덕분에 여러사람들과 작업한 문서들이

스타일이 중구난방이라 지저분했는데 싹 정리할 수 있어서 감사합니다.

2

인프런 AI 인턴님의 프로필 이미지

2023. 05. 24. 11:25

안녕하세요, 인프런 AI 인턴이에요.
본문에서 원하는 대로 글자의 스타일 정보만 변경하고 글자 모양, 문단 모양, 자간 등은 그대로 두는 것은 가능합니다. 다음은 가능한 방법입니다.

  1. 복사한 스타일 정보를 기반으로 스타일 프로퍼티 값을 변경하는 방법
    알고리즘 설명에서 제시하신 방법과 유사합니다. 한 글자씩 스타일 정보를 조회해서 변수에 저장하고, 필요한 스타일값만 변경합니다. 그리고 스타일을 적용할 범위(예: 특정 셀, 문단, 텍스트 영역 등)를 지정하고, 지정한 범위에 스타일을 적용합니다.

  2. 새로운 스타일을 만들어서 적용하는 방법
    만약 글자의 스타일을 변경해도 되는 경우(예: 특정 스타일을 모두 바탕글로 변경하는 경우), 스타일을 새로 만들어야 합니다. 스타일을 새로 만들 때는, 대부분의 프로그래밍 언어에서 지원하는 스타일 객체를 생성하고, 객체에 스타일 프로퍼티 값을 설정해야 합니다. 그리고 이렇게 만든 스타일 객체를 특정 범위에 적용하면 됩니다.

본문에서 제시한 방법과는 다소 다른 접근법이긴 하지만, 두 방법 모두 글자 모양, 문단 모양, 자간은 그대로 유지하면서 스타일 값을 변경할 수 있습니다.
어떤 방법이 적합한지는 스타일 변경의 목적, 적용 범위, 프로그래밍 언어 등에 따라 다를 수 있으므로, 구체적인 내용이 있으면 추가적인 답변을 드릴 수도 있습니다.
도움이 되었기를 바랍니다. 감사합니다.