해결된 질문
작성
·
34
1
안녕하세요 강의를 보면서 한글을 하나씩 건드려보며 재미있게 공부하고 있습니다
엑셀에 데이터 입력하기, 한글에 누름틀, 필드 등으로 데이터 입력하기 등 매우 흥미로운 주제이면서 나도 자동화에 쓸 수 있다는 희망이 보이는 강의입니다.
하지만 확실히 강의로 따라하는 것과 실제 예제에 응용은 쉽지 않다는게 느껴져 해결될 기대를 하며 질문을 남겨봅니다
파일 형태을 확인하실 수 있도록 파일링크를 첨부드립니다
https://docs.google.com/spreadsheets/d/1JsP1BPtFzFXMTtUcjR3k0Qhhs6W7L-ZU/edit?usp=sharing&ouid=115890287739826344876&rtpof=true&sd=true
하고자 하는 자동화는 아래와 같습니다
엑셀에 있는 그래프를 한글 각 페이지에 붙여넣기
붙여 넣을 때는 각 페이지의 마지막 글자를 찾고 두칸 아래에 붙여넣기
엑셀에 있는 테이블 형식의 데이터를 한글 각 페이지에 붙여넣기
붙여 넣을 때는 각 페이지의 마지막 그림(1에서 붙인 그래프)를 찾고 두칸 아래에 붙여넣기
테이블이 출력되면 각 행별로 가장 높은 숫자를 찾아 보고서 워딩을 작성해야 하는데
현재는 파이썬으로 요리조리(??) 작성하여 각 테이블을 순환하면서 높은 수치를 뽑아 워딩을 엑셀에 정리한 후 해당 엑셀을 메일머지로 각 페이지 마다 자동으로 작성되게는 했습니다.
여기서 더 나아가 그래프, 테이블까지 보고서에 자동으로 붙이면 자동화에 좀 더 가깝지 않을까 하여 질문남겨봅니다
엑셀의 테이블을 순환하면서 복사하고 한글에 붙인다는 개념만 잡아두었고 어떻게 접근해야될지 모르겠습니다. 좋은 의견 기다리겠습니다 감사합니다~!
답변 2
1
한준님, 안녕하세요?
덕분에 유쾌한 금요일을 보냈습니다.
기대하신 것보다 복잡한 코드를 보여드리는 것 같아 우려스런 마음이 있습니다만,
막상 아래아한글 파트는 코드 전체에서 열 줄 정도로,
엑셀 차트오브젝트나, 특정 범위를 선택하는 코드가 대부분이기는 하네요.
우선 짧은 시연화면을 먼저 보여드립니다.
한/글에서 그림이나 표의 크기를 조절하는 코드를 빼기 위해 용지의 위아래 여백을 15 정도로 줄여두었습니다. 참고하시기 바랍니다.
코드는 크게 두 부분으로 나누었습니다. 하나씩 보여드리면,
import xlwings as xw
from pyhwpx import Hwp
# 한글 인스턴스 생성
hwp = Hwp()
# 활성화된 Excel 앱과 워크북 가져오기
excel = xw.apps.active
wb = excel.books[0]
# 워크시트 내 차트를 순회하며 처리
for ws in wb.sheets:
shapes = ws.api.Shapes # 모든 도형 가져오기(단, 모든 도형이 차트라는 가정!!)
for i in range(1, shapes.Count + 1): # 모든 도형을 순회하면서
shape = shapes.Item(i) # 도형을 선택하고
if shape.Type == 3: # 3 == 선택한 도형이 차트(ChartObject)이면
shape.CopyPicture() # 그림으로 복사하기 실행 후에
hwp.goto_page(i) # 한/글 문서의 i페이지 시작점으로 이동해서
hwp.MovePageEnd() # 페이지 끝으로 커서를 옮기고
hwp.BreakPara() # 엔터 한 번 친 후에
hwp.Paste() # 차트 이미지 붙여넣기
hwp.BreakPara() # 엔터
주석을 읽어보시면 어느 정도 이해가 되실 거라고 생각합니다^^;
코드를 따라 치지 마시고, 한 줄, 혹은 두 줄씩 기억해서 직접 작성해보시면
더 빠르게 익숙해지실 겁니다.
그리고 아래는 표를 붙여넣는 코드입니다.
이 부분이 조금 까다롭게 느껴질 수 있는데, 아래에 부연설명을 붙이겠습니다.
# 엑셀 열기
ws = wb.sheets[0] # 첫 번째 시트 선택
# A열에서 값이 "구 분"인 셀의 행번호 수집하기
a_values = ws.range(ws.cells(1,1), ws.cells(len(ws.used_range), 1)).value
gubun_rows = [i+1 for i, val in enumerate(a_values) if val == "구 분"]
# 엑셀범위 복사 및 한/글에 표로 붙여넣는 코드
for idx, row in enumerate(gubun_rows, start=1): # 수집한 행번호를 순회하면서
init_cell = ws.range(f"A{row}") # "구 분" 셀로 이동해서(표의 좌측상단)
end_cell = init_cell.end("right").end("down") # 우측하단 끝 셀주소를 찾고
table_range = ws.range(init_cell, end_cell) # 해당 범위를
table_range.copy() # 복사함
hwp.goto_page(idx) # 한/글 문서의 idx페이지 시작점으로 이동한 후
hwp.MovePageEnd() # 커서를 해당페이지 끝으로 이동
hwp.Paste() # 표 붙여넣기
# 표 너비를 본문에 맞춤
i = 0
while hwp.get_into_nth_table(i): # 문서의 i번째 표로 진입한 후
hwp.set_table_width() # 표 너비를 본문 너비에 맞춤
i += 1 # 다음 표로 이동
간결하게나마 라인별로 주석을 달아보았는데,
제 생각에 가장 어렵게 느껴질 부분은 역시 a_values
와 gubun_rows
를 구하는 부분이 아닌가 싶습니다.
이 문법들은 어떤 깊은 원리가 있다기보다, "우리, 이런 동작은 이런 코드로 약속하자" 식의 문법이라서
익숙해지는 것 말고는 왕도가 없는 듯 합니다.
ws.range(ws.cells(1,1), ws.cells(len(ws.used_range), 1)).value
①우선 ws.range
객체는 워크시트의 셀 범위를 자유롭게 선택할 수 있는데, 사용법이 아래 두 가지입니다.
하나는 ws.range("A1:B5").values
이런 식으로 엑셀의 셀 범위 문법을 문자열로 그대로 쓰는 방법과,
다른 하나는 ws.range(ws.cells(1,1), ws.cells(2,5))
식으로 cells
객체를 두 개 넣는 방법입니다.
항상 고정된 범위를 선택해야 하는 경우라면 첫번째 방법인 문자열 방식이 훨씬 직관적이지만,
지금 우리 경우처럼 특정 셀을 찾아야 하거나, 순회하는 경우에는 두 번째 방법이 코딩하기 쉽습니다.
②그리고 len(ws.used_range)
코드가 들어가 있는 이유는,
A열 전체에서 "구 분"
이라는 데이터를 찾으려는 목적인데 ws.Range("A:A")
라고 지정해버리면 셀이 100만개나 선택이 되어버리기 때문에 다소 느립니다.
그래서 "사용한 범위"의 행 갯수만 세서 A1:A100 정도 내에서만 탐색을 하기 위해
"워크시트 사용범위의 행 길이"인 len(ws.used_range)
를 탐색범위로 지정한 것입니다.
[i+1 for i, val in enumerate(a_values) if val == "구 분"]
①enumerate
가 조금 생소하실 수 있겠습니다.
enumerate는 리스트나 문자열 등 순회 가능한 객체를 for문에 넣었을 때,
해당 인덱스의 아이템만 꺼내는 게 아니라, 아이템의 인덱스번호를 같이 리턴해줍니다.
아래는 enumerate의 예시입니다.
>>> a = ["A", "B", "C"]
>>> for i in a:
>>> print(i)
...
A
B
C
>>> for idx, val in enumerate(a):
>>> print(idx, val)
...
0 A
1 B
2 C
for
문 안에서enumerate
함수는 정말 많이 사용됩니다. 익혀 두시면 큰 도움이 될 것입니다.
그러면, A열의 값들이 들어 있는 a_values
리스트 안에서
값이 "구 분"
인 주소의 행번호(인덱스)만 따로 추출하려면
아래와 같이 for
문을 작성하면 됩니다.
gubun_list = []
for i, val in enumerate(a_values): #
if val == "구 분":
gubun_list.append(i + 1) # 파이썬인덱스는 0부터, 엑셀행은 1부터 시작하니까 +1
위처럼 네 줄로 짤 수도 있고요.
파이썬의 "리스트 컴프리헨션"이라는 문법 덕분에
위 네 줄을 간결하게 한 줄로 짤 수 있습니다.
"리스트컴프리헨션"은 "리스트 안에 for문을 포함(comprehension)하는 문법입니다.
타 프로그래밍언어 유저들이 파이썬에서 가장 부러워하는 간결한 문법 세 가지로
문자열 인덱싱, f-스트링 및 리스트&딕셔너리 컴프리헨션을 꼽는다고 합니다.
그래서 최종 코드에는 아래처럼 리스트컴프리헨션을 써서 한 줄로 적었습니다.
gubun_list = [i + 1 for i, val in enumerate(a_list) if val == "구 분"]
혹시 잘 이해가 안 되시거나 어렵게 느껴지는 부분이 있다면
추가로 질문 남겨주세요.
전적으로 제 설명력 부족 탓입니다ㅜ
엑셀 관련 코드를 짤 때는, 셀이나 범위, 현재 선택위치 등을 생각하면서
제법 까다롭게 시행착오를 거쳐야 하는 경우가 많지만,
대부분 매크로 녹화를 통해 큰 틀의 코드가 잡힙니다.
그리고 VBA와 파이썬 코드는 비슷한 부분이 있어서
녹화한 엑셀매크로를 그대로 조금만 수정하면
잘 돌아가는 파이썬 코드를 금방 얻을 수 있습니다.
아래아한글도 비슷합니다. 대부분은 스크립트매크로 녹화를 통해
특정 수작업이나 프로세스에 대응되는 액션을 찾아내고,
그 외에 매크로 녹화가 안 되는 액션이나,
필드, 이미지 삽입 같은 특수한 메서드는 API문서에서 검색하는 방식으로
코드를 완성합니다.
요즘은 한글개발자포럼이라고,
한컴 개발자 분들이 직접 답변을 달아주는 고마운 사이트가 하나 생겼습니다.
https://forum.developer.hancom.com/
감사하게도 보통 하루 안에 상세한 답변을 달아주시고,
열정적인 커뮤니티 분들이 더 빠르게 답변을 달아주시기도 해서
저도 종종 방문합니다.
답변이 도움이 되었길 바랍니다.
그리고 분명히 충분한 답변이 아니라는 것도 짐작이 갑니다.
추가로 질문 남겨주세요ㅎ
즐거운 주말 보내세요~^^
1
안녕하세요, 인프런 AI 인턴입니다.
류한준님께서 말씀하신 엑셀의 그래프와 테이블을 한글 문서의 각 페이지에 자동으로 삽입하는 작업은 조금 복잡하지만, 적절한 라이브러리를 사용하여 충분히 구현할 수 있는 작업입니다.
기본적인 방향:
엑셀과 한글 파일 열기:
pandas
와 openpyxl
혹은 win32com
패키지를 사용하여 엑셀 파일을 열고 데이터를 읽습니다.pywin32
라이브러리를 사용하여 한글 문서를 제어할 수 있습니다.그래프 자동화 삽입:
matplotlib
를 사용하여 그래프를 시각화하고 저장하는 방법도 고려해 볼 수 있습니다.테이블 데이터의 삽입 및 보고서 작성:
win32com
라이브러리를 사용하여 엑셀 데이터의 스타일을 유지하며 붙여넣기 할 수 있습니다.관련 자료:
누름틀 없는 한글문서 엑셀로 취합하기 응용 질문드려요: 이 질문에서는 특정 파일 안에 있는 동일한 양식의 데이터를 엑셀로 옮기는 사례를 설명하고 있으니, 테이블 자동화를 구현할 때 참고할 수 있습니다.
셀필드 응용 질문: 엑셀 데이터를 한글 문서에 삽입하는 것과 GUI를 활용하여 데이터를 실시간으로 갱신하는 방법을 설명하고 있습니다.
각종 데이터 삽입 및 리포트 자동화 목적으로 위의 예제들이 도움이 되리라 생각됩니다. 더 나아가, 자동화 작업을 보다 효율적으로 수행하고 싶다면, 파이썬
의 다양한 라이브러리를 활용한 스크립트를 조합하는 방식을 시도해 보세요.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.