728x90
반응형
>> pdf 1장인데 4M라 좀 큼. 1M 정도로 줄이기
from PIL import Image, ImageDraw, ImageFont
import pandas as pd
from datetime import datetime
import fitz # PyMuPDF
import os
# 파일 경로 설정
template_path = "C:/Users/MJ/Desktop/월간리포트만들기/template.png" # 템플릿 이미지
grade_graph_path = "C:/Users/MJ/Desktop/월간리포트만들기/hg.png" # 성적 그래프
progress_graph_path = "C:/Users/MJ/Desktop/월간리포트만들기/hp.png" # 진도 그래프
font_path = "C:/Users/MJ/Desktop/월간리포트만들기/NanumGothic.ttf" # 한글 폰트
excel_path = "C:/Users/MJ/Desktop/월간리포트만들기/StudentName.xlsx" # 엑셀 파일 경로
# 엑셀 파일에서 학생 이름 찾기
try:
df = pd.read_excel(excel_path)
print("엑셀 파일 로드 완료:")
print(df) # 엑셀 파일 내용 확인
except Exception as e:
print(f"엑셀 파일 로드 실패: {e}")
exit()
# 'fg.png'에서 'f' 추출 (student_id)
student_id = grade_graph_path.split('/')[-1][0] # 'f' 추출
print(f"추출된 student_id: {student_id}") # 디버깅 메시지
# student_id와 엑셀 파일의 id 열 데이터 타입 일치시키기
df['id'] = df['id'].astype(str).str.strip() # id 열을 문자열로 변환하고 공백 제거
student_id = str(student_id).strip() # student_id도 문자열로 변환하고 공백 제거
# 학생 이름 찾기
try:
student_name = df.loc[df['id'] == student_id, 'student_name'].values[0]
print(f"찾은 student_name: {student_name}") # 디버깅 메시지
except IndexError:
print(f"⚠️ 오류: student_id '{student_id}'에 해당하는 학생 이름을 찾을 수 없습니다.")
exit()
# 템플릿 및 그래프 이미지 로드
template = Image.open(template_path)
grade_graph = Image.open(grade_graph_path)
progress_graph = Image.open(progress_graph_path)
# 텍스트 피드백 준비 (수동 입력)
feedback_text = """포토샵 CC (Creative Cloud)**는 어도비에서 제공하는 대표적인 이미지 편집 프로그램으로, 그래픽 디자인, 사진 편집, 디지털 아트, 웹 디자인 등 다양한 작업을 할 수 있는 소프트웨어입니다. CC는 "Creative Cloud"의 약자로, 클라우드 기반 서비스로, 인터넷을 통해 최신 버전 업데이트, 파일 공유, 동기화 등이 가능합니다.
포토샵 CC는 레이어 기반 편집, 고급 필터와 효과 적용, 벡터 작업, 타이포그래피 작업 등 다양한 기능을 제공하여 전문가뿐만 아니라 취미로 사용하는 사람들에게도 유용합니다. 스마트 오브젝트, 고급 색상 조정, 3D 모델링 등의 기능도 지원하고 있어, 창의적인 작업을 위한 강력한 도구입니다.
"""
text_box_x = 226
text_box_y = 5334
text_box_width = 4156 # 텍스트 박스 폭
text_box_height = 1021 # 텍스트 박스 높이
# 폰트 크기 및 줄 간격 설정
font_size = 100
min_font_size = 50
max_font_size = 120
line_spacing = 20
max_iterations = 100 # 무한 루프 방지
iteration = 0
# 텍스트 크기 조정 루프
while iteration < max_iterations:
iteration += 1 # 반복 횟수 증가
font = ImageFont.truetype(font_path, font_size)
wrapped_text = []
current_line = ""
for word in feedback_text.split():
test_line = f"{current_line} {word}".strip()
bbox = font.getbbox(test_line)
text_width = bbox[2] - bbox[0]
if text_width <= text_box_width:
current_line = test_line
else:
wrapped_text.append(current_line)
current_line = word
wrapped_text.append(current_line)
# 전체 텍스트 높이 계산
total_height = sum(font.getbbox(line)[3] - font.getbbox(line)[1] + line_spacing for line in wrapped_text) - line_spacing
# 텍스트 크기 조정
if total_height > text_box_height:
font_size -= 2
line_spacing = max(10, line_spacing - 1)
elif total_height < text_box_height * 0.9:
font_size += 2
line_spacing += 1
else:
break # 박스에 적절히 맞으면 종료
# 최소 글자 크기 제한
if font_size < min_font_size:
print("⚠️ 글자 크기가 너무 작아졌습니다. 텍스트 크기 조정을 중단합니다.")
font_size = min_font_size
break
# 디버깅 메시지 출력
print(f"Iteration {iteration}: Font Size = {font_size}, Line Spacing = {line_spacing}")
# 루프 종료 확인
if iteration == max_iterations:
print("🚨 경고: 최대 반복 횟수를 초과하여 루프를 종료합니다.")
print("✅ 최종 텍스트 배치 완료")
# 텍스트 삽입
draw = ImageDraw.Draw(template)
y_position = text_box_y
for line in wrapped_text:
draw.text((text_box_x, y_position), line, font=font, fill="black")
y_position += font.getbbox(line)[3] - font.getbbox(line)[1] + line_spacing
# 그래프 크기 및 위치 설정
grade_graph = grade_graph.resize((4234, 2142))
progress_graph = progress_graph.resize((4270, 1356))
template.paste(grade_graph, (196, 992))
template.paste(progress_graph, (178, 3511))
# PDF 저장 경로 생성
current_month = datetime.now().month
pdf_path = f"C:/Users/MJ/Desktop/월간리포트만들기/MonthlyReport_{student_name}_{current_month}월.pdf"
temp_pdf_path = f"C:/Users/MJ/Desktop/월간리포트만들기/temp_MonthlyReport_{student_name}_{current_month}월.pdf"
# PDF로 저장 (용량 줄이기 위해 quality와 resolution 조정)
template = template.convert("RGB") # JPEG는 RGB 모드만 지원
template.save(temp_pdf_path, "PDF", resolution=200.0, quality=70, optimize=True)
# PDF 압축
doc = fitz.open(temp_pdf_path)
doc.save(pdf_path, garbage=4, deflate=True, clean=True)
doc.close()
# 임시 파일 삭제
os.remove(temp_pdf_path)
print(f"🎉 성적표 PDF가 성공적으로 생성되었습니다: {pdf_path}")
>> 결과물
>> 결론
Hope it's the last revision...
728x90
반응형