강의

멘토링

커뮤니티

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

ㅇㅇㅇㅇ님의 프로필 이미지
ㅇㅇㅇㅇ

작성한 질문수

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

본 예제의 소스코드 및 실행파일(수업자료 다운로드)

한글 자동화 삽도 삽입!!

해결된 질문

작성

·

48

1

안녕하세요
강의 보면서 한글 자동화 겉핥기 중인 수강생입니다.
현재 제가 관리카드 형식의 한글 자동화를 템플릿을 통해 만들고있습니다.
엑셀에 로우데이터 입력 후 엑셀 입력된 데이터들을 한글 템플릿 표 안에 원하는 위치에 까진 입력을 한 상태입니다만.
이후 한글 템플릿 표 안에 삽도를 삽입하는 과정에서 막혔습니다.
ai를 통해 질문해보고 다시 코드를 짜보고 있으나 계속 삽도부분에서 막혀 질문드립니다.

import os
from collections import defaultdict
from io import BytesIO

import pandas as pd
import win32clipboard
import win32com.client as win32
from PIL import Image
import time


def init_hwp(visible=False):
    """
    아래아한글 시작
    """
    hwp = win32.gencache.EnsureDispatch("hwpframe.hwpobject")
    hwp.XHwpWindows.Item(0).Visible = True
    hwp.RegisterModule("FilePathCheckDLL", "FilePathCheckerModule")
    return hwp


def get_nst_table(n):
    """
    n번째 표 앞으로 이동
    n은 0부터 시작함.
    """
    ctrl = hwp.HeadCtrl
    count = 0
    while ctrl:
        if ctrl.CtrlID == "tbl":
            if count == n:
                hwp.SetPosBySet(ctrl.GetAnchorPos(0))
                break
            else:
                ctrl = ctrl.Next
            count += 1
        else:
            ctrl = ctrl.Next


def insert_text(text):
    """
    문서에 텍스트 삽입
    """
    hwp.HAction.GetDefault("InsertText", hwp.HParameterSet.HInsertText.HSet)
    hwp.HParameterSet.HInsertText.Text = text
    hwp.HAction.Execute("InsertText", hwp.HParameterSet.HInsertText.HSet)


def get_text():
    """
    문서 선택범위의 문자열을 추출
    """
    hwp.InitScan(Range=0xff)
    total_text = ""
    state = 2
    while state not in [0, 1]:
        state, text = hwp.GetText()
        total_text += text
    hwp.ReleaseScan()
    return total_text


def append_hwp(filename):
    """
    문서 끼워넣기
    """
    hwp.HAction.GetDefault("InsertFile", hwp.HParameterSet.HInsertFile.HSet)
    hwp.HParameterSet.HInsertFile.KeepSection = 0
    hwp.HParameterSet.HInsertFile.KeepCharshape = 0
    hwp.HParameterSet.HInsertFile.KeepParashape = 0
    hwp.HParameterSet.HInsertFile.KeepStyle = 0
    hwp.HParameterSet.HInsertFile.filename = filename
    hwp.HAction.Execute("InsertFile", hwp.HParameterSet.HInsertFile.HSet)


def 사진리스트추출():
    """
    '삽도폴더' 하위의 모든 서브폴더에서
    모든 그림 파일 경로를 추출하여 단일 리스트로 반환합니다.
    """
    all_pic_paths = []
    # "삽도폴더"의 경로를 설정합니다. (현재 스크립트 위치 기준)
    삽도폴더_경로 = os.path.join(os.getcwd(), "삽도폴더")

    # "삽도폴더"가 존재하는지 확인합니다.
    if not os.path.exists(삽도폴더_경로):
        print(f"경고: '{삽도폴더_경로}' 폴더가 존재하지 않습니다.")
        return []

    # os.walk를 사용하여 서브폴더를 포함한 모든 파일을 탐색합니다.
    for root, _, files in os.walk(삽도폴더_경로):
        for file in files:
            # 이미지 파일 확장자를 확인합니다. 필요에 따라 추가/수정 가능합니다.
            if file.lower().endswith((".png", ".jpg", ".jpeg", ".gif", ".bmp")):
                all_pic_paths.append(os.path.join(root, file))
    return all_pic_paths

# 사용 예시:
# 이 함수를 호출한 결과를 사진리스트 변수에 저장해야 합니다.
# 예: 사진리스트 = 사진리스트추출()

def 사진제목추출():
    제목사전 = defaultdict(list)
    제목리스트 = []
    for 사진파일 in 사진리스트: 
        파일명 = os.path.basename(사진파일)
        본문, _ = os.path.splitext(파일명)
        if "_" not in 본문:
            continue
        연번, 삽도종류 = 본문.split("_", 1) 
        제목명 = f"{연번}_{삽도종류}"
        if 제목명 not in 제목리스트:
            제목리스트.append(제목명)
        제목사전[제목명].append(사진파일)
    return 제목리스트, 제목사전



def 클립보드로_이미지_삽입(filepath):
    """
    한/글 API의 InsertPicture 메서드는
    셀의 크기를 변경하지 않는 반면(이미지가 찌그러짐)
    클립보드를 통해 이미지를 삽입하면
    이미지의 종횡비에 맞춰
    셀의 높이가 자동으로 조절됨.
    """
    이미지 = Image.open(filepath)
    아웃풋 = BytesIO()
    이미지.convert('RGB').save(아웃풋, 'BMP')
    최종데이터 = 아웃풋.getvalue()[14:]
    아웃풋.close()

    win32clipboard.OpenClipboard()
    win32clipboard.EmptyClipboard()
    win32clipboard.SetClipboardData(win32clipboard.CF_DIB, 최종데이터)
    win32clipboard.CloseClipboard()

    hwp.Run("Paste")


def 첫번째행으로_이동():
    """
    표의 A2 셀로 이동
    """
    hwp.Run("TableColBegin")
    hwp.Run("TableColPageUp")
    hwp.Run("TableLowerCell")
    hwp.Run("TableCellBlock")


def 위셀과병합():
    """
    제목 그대로임
    """
    hwp.Run("TableDeleteCell")  # 아래 셀 내용을 지운 후
    hwp.Run("TableCellBlockExtend")  # 셀 다중선택모드
    hwp.Run("TableUpperCell")  # 위 셀까지 선택
    hwp.Run("TableMergeCell")  # 선택된 셀 병합
    hwp.Run("TableCellBlock")  # 다시 셀 선택 모드


def 다음페이지로():
    """
    표에서 나와서
    문서 끝으로 이동 후
    Ctrl-Enter를 통해
    다음페이지로 넘어감
    """
    hwp.Run("Cancel")
    hwp.Run("MoveTopLevelEnd")
    hwp.Run("BreakPage")


def 완료메시지():
    msgbox = hwp.XHwpMessageBox  # 메시지박스 생성
    msgbox.string = "문서작성을 완료하였습니다."
    msgbox.Flag = 0  # [확인] 버튼만 나타나게 설정
    msgbox.DoModal()  # 메시지박스 보이기


if __name__ == '__main__':
    hwp = init_hwp()
    # hwp.Open(os.path.join(os.getcwd(), "예시파일.hwp"))
    hwp.Run("FileOpen")
    os.chdir(hwp.Path.rsplit("\\", maxsplit=1)[0])  # 현재 열린 문서가 위치한 경로로 이동
    df = pd.read_excel(os.path.join(os.getcwd(), "관리카드 데이터 정리.xlsx"))

    사진리스트 = 사진리스트추출()
    사진리스트

    제목리스트, 제목사전 = 사진제목추출()
    제목리스트
    제목사전

    관리카드_리스트 = df
    pd.set_option('display.max_rows', None) 
    관리카드_리스트
        # === 이 부분이 가장 중요합니다! NaN 값을 빈 문자열로 채우는 코드 ===
    관리카드_리스트 = 관리카드_리스트.fillna('')

    훼손지_리스트 = [i.split("_")[0] for i in 제목리스트]
    훼손지_리스트
    삽도명_종류 = [i.split("_")[1] for i in 제목리스트]
    삽도명_종류


    for i in range(len(관리카드_리스트)): 

    # ========================엑셀 내부 데이터 값 정의===============================
        연번_누름틀_값 = 관리카드_리스트.iloc[i]["연번_누름틀"]
        순번_값 = 관리카드_리스트.iloc[i]["순번"]
        토지이용현황_값 = 관리카드_리스트.iloc[i]["토지이용현황"]
        소유구분_값 = 관리카드_리스트.iloc[i]["소유구분"]
        당초차량진출입_값 = 관리카드_리스트.iloc[i]["당초차량진출입"]
        검토내용_값 = 관리카드_리스트.iloc[i]["검토내용"]
        도로포장_값 = 관리카드_리스트.iloc[i]["도로포장"]
        교행여부_값 = 관리카드_리스트.iloc[i]["교행여부"]
        검토결과_값 = 관리카드_리스트.iloc[i]["검토결과"]
        i_지적도 = 관리카드_리스트.iloc[i]["지적도"]
        i_항공사진 = 관리카드_리스트.iloc[i]["항공사진"]
        i_현장사진_1 = 관리카드_리스트.iloc[i]["현장사진_1"]
        i_현장사진_2 = 관리카드_리스트.iloc[i]["현장사진_2"]
        i_검토결과_사진 = 관리카드_리스트.iloc[i]["검토결과_사진"]

    # ========================표 내부 데이터 입력하기================================
        append_hwp(os.path.join(os.getcwd(), "템플릿1.hwp")) # 문서 끼워넣기
        # hwp.RenameField("연번_누름틀",연번_누름틀_값) # 누름틀 필드 이름 바꾸기
        # hwp.PutFieldText(연번_누름틀_값,연번_누름틀_값) # 누름틀에 연번_누름틀 값 텍스트로 넣기
        hwp.RenameField("순번",순번_값) 
        hwp.PutFieldText(순번_값,순번_값) 
        hwp.RenameField("토지이용현황",토지이용현황_값) 
        hwp.PutFieldText(토지이용현황_값,토지이용현황_값) 
        hwp.RenameField("소유구분",소유구분_값) 
        hwp.PutFieldText(소유구분_값,소유구분_값) 
        hwp.RenameField("당초차량진출입",당초차량진출입_값) 
        hwp.PutFieldText(당초차량진출입_값,당초차량진출입_값) 
        hwp.RenameField("검토내용",검토내용_값) 
        hwp.PutFieldText(검토내용_값,검토내용_값) 
        hwp.RenameField("도로포장",도로포장_값) 
        hwp.PutFieldText(도로포장_값,도로포장_값) 
        hwp.RenameField("교행여부",교행여부_값) 
        hwp.PutFieldText(교행여부_값,교행여부_값) 
        hwp.RenameField("검토결과",검토결과_값) 
        hwp.PutFieldText(검토결과_값,검토결과_값) 
        hwp.RenameField("지적도",i_지적도) 
        hwp.PutFieldText(i_지적도,i_지적도) 
        hwp.RenameField("항공사진",i_항공사진) 
        hwp.PutFieldText(i_항공사진,i_항공사진) 
        hwp.RenameField("현장사진_1",i_현장사진_1) 
        hwp.PutFieldText(i_현장사진_1,i_현장사진_1) 
        hwp.RenameField("현장사진_2",i_현장사진_2) 
        hwp.PutFieldText(i_현장사진_2,i_현장사진_2) 
        hwp.RenameField("검토결과_사진",i_검토결과_사진) 
        hwp.PutFieldText(i_검토결과_사진,i_검토결과_사진) 
        hwp.Run("MoveTopLevelEnd")
        hwp.Run("BreakPage")

 

위 코드를 실행하여 만든 결과물입니다.

 

화면 캡처 2025-10-30 152706.jpg.webp

 

 

지적도, 항공사진, 현장사진1,2, 검토결과_사진에 강의에 올라온 사진리스트 추출을 이용하여 삽도들을 삽입하고 싶습니다.
어떻게 해야 할까요??ㅠ
답변 기다리겠습니다.
감사합니다.

답변 2

1

ㅇㅇㅇㅇ님의 프로필 이미지
ㅇㅇㅇㅇ
질문자

메일 확인하였습니다.
바쁘신 와중에 신경 써주셔서 감사합니다.
제가 원했던 방식이 정확하게 맞아서 너무 감사합니다 ㅠㅠㅠㅠ

1

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

ㅇㅇㅇㅇ님! 메일로 코드 송부드렸습니다. 확인 부탁드립니다.

행복한 하루 되세요!!!

ㅇㅇㅇㅇ님의 프로필 이미지
ㅇㅇㅇㅇ

작성한 질문수

질문하기