업무 자동화/python & CAD

Python 학습] 엑셀 파일에 이미지를 삽입

ToolBOX01 2025. 8. 13. 16:44
반응형

▣ EXCEL(엑셀) 여러 개의 사진, 이미지를 셀 크기 에 맞춰 일괄 삽입하기

Excel에서 여러 이미지를 셀 크기에 맞춰 삽입하려면 다음과 같은 일반적인 단계를 따를 수 있습니다:

  1. Excel 워크시트에서 삽입하려는 셀 범위를 선택합니다.
  2. "삽입" 탭으로 이동하여 "사진" 또는 "이 이미지 삽입" 옵션을 선택합니다.
  3. 여러 이미지를 한꺼번에 선택하여 삽입합니다.
  4. 삽입 후, 이미지 크기를 조정하려면 이미지를 선택하고 셀 크기에 맞게 크기 조절 핸들을 드래그하거나, "서식" 옵션에서 크기를 조정합니다.
  5. 필요하면 셀에 맞춰 자동 조정을 위해 "이미지 서식"에서 "셀 크기에 맞춤" 기능을 사용할 수 있습니다.

▷ 참고 블로그

 

엑셀 그림 깔끔하게 넣는 방법, 표 안에 이미지 고정 맞추기

엑셀을 사용하다보면 간혹 이미지를 넣어야하는 경우가 있습니다. 엑셀에 대해 잘 아시는 분이라면 어려운 ...

blog.naver.com

 


▣ 파이썬으로 EXCEL(엑셀) 여러 개의 사진, 이미지를 셀 크기 에 맞춰 일괄 삽입하기

양식이 사전 정의된 Template 엑셀 파일을 만들어 파이썬 프로그램 결과를 입력 합니다. 이미지가 저장된 폴더를 지정 합니다. 출력물이 저장될 엑셀 파일을 지정 합니다.

[엑셀 양식 파일 예제]

# Define paths

  • excel_path = G:\02 Python\PythonTest02\outform01.xlsx
  • image_folder = G:\02 Python\PythonTest02\image
  • output_path = G:\02 Python\PythonTest02\OUT01.xlsx

▷ CODE 1

import os
from openpyxl import load_workbook
from openpyxl.drawing.image import Image
from PIL import Image as PILImage
import tkinter as tk
from tkinter import messagebox

# 기존 엑셀 파일 로드
excel_path = r"G:\02 Python\PythonTest02\outform01.xlsx"
wb = load_workbook(excel_path)
ws = wb.active

# 출력 파일 경로
output_path = r"G:\02 Python\PythonTest02\OUT01.xlsx"

# 이미지 폴더 경로
image_folder = r"G:\02 Python\PythonTest02\image"

# 지원하는 이미지 확장자
image_extensions = ('.png', '.jpg', '.jpeg', '.bmp', '.gif')

# 폴더에서 이미지 파일 목록 가져오기
image_files = [f for f in os.listdir(image_folder) if f.lower().endswith(image_extensions)]
print(f"찾은 이미지 파일 수: {len(image_files)} - {image_files}")  # 디버깅용 출력

# 이미지 삽입 시작 위치 (B2부터 아래로)
start_row = 2  # B2부터 시작
col = 2  # B 열 (2는 B 열에 해당)

# 셀 크기 고정 (높이 150, 폭 30 단위)
fixed_height = 150  # 높이 150 단위
fixed_width = 30   # 폭 30 단위

# 모든 이미지를 순차적으로 삽입
for idx, image_file in enumerate(image_files):
    image_path = os.path.join(image_folder, image_file)
    img = Image(image_path)
    
    # 원본 이미지 크기 가져오기
    original_img = PILImage.open(image_path)
    original_width, original_height = original_img.size
    
    # 셀 위치 계산
    col_letter = chr(64 + col)  # B 열 (65 = A, 66 = B)
    cell = f"{col_letter}{start_row + idx}"
    
    # 셀 크기 설정 (고정값 사용)
    ws.column_dimensions[col_letter].width = fixed_width
    ws.row_dimensions[start_row + idx].height = fixed_height
    
    # 이미지 크기 조정 (셀 폭 30 단위에 맞춤, 종횡비 유지)
    cell_width = fixed_width * 10  # 30 단위 * 10 = 300픽셀
    cell_height = fixed_height * 10  # 150 단위 * 10 = 1500픽셀
    aspect_ratio = original_height / original_width
    img_width = cell_width  # 너비를 셀 폭(300픽셀)에 맞춤
    img_height = min(cell_height, int(img_width * aspect_ratio))  # 높이를 종횡비에 맞춰 조정, 최대 1500픽셀
    
    img.width = int(img_width)
    img.height = int(img_height)
    
    # 셀에 이미지 삽입
    ws.add_image(img, cell)
    print(f"이미지 {image_file}를 {cell}에 삽입했습니다.")  # 디버깅용 출력

# 엑셀 파일 저장 (Save As)
wb.save(output_path)

# 완료 메시지 표시
root = tk.Tk()
root.withdraw()  # 메인 창 숨김
messagebox.showinfo("완료", f"엑셀 파일이 {output_path}에 저장되었습니다.")
root.destroy()

▷ CODE 1 설명

엑셀 파일에 이미지를 삽입하는 기능을 구현하고 있습니다. tkinter를 사용하여 사용자에게 이미지가 성공적으로 추가되었음을 알리는 메시지 상자를 띄우기도 합니다.

import os
from openpyxl import load_workbook
from openpyxl.drawing.image import Image
from PIL import Image as PILImage
import tkinter as tk
from tkinter import messagebox

1.  import : 설치된 라이브러리 호출

  • os: 파일 시스템 경로를 다루는 기능을 제공합니다. 이 코드에서는 파일 경로를 병합하는 데 사용됩니다.
  • openpyxl: Excel 파일을 읽고, 쓰고, 수정하는 데 사용되는 라이브러리입니다. 특히 load_workbook과 drawing.image.Image 모듈이 사용됩니다.
  • PIL (Pillow): 이미지 파일을 처리하는 라이브러리입니다. 코드에서는 이미지를 열고 크기를 확인하는 데 사용됩니다. Image라는 별칭으로 가져와서 openpyxl의 Image와 구분합니다.
  • tkinter: GUI (그래픽 사용자 인터페이스)를 만들기 위한 표준 라이브러리입니다. tkinter의 messagebox를 통해 사용자에게 알림을 띄웁니다.

엑셀 파일과 이미지 파일을 다루기 위한 변수들을 정의하고 있습니다.

# 기존 엑셀 파일 로드
excel_path = r"G:\02 Python\PythonTest02\outform01.xlsx"
wb = load_workbook(excel_path)
ws = wb.active

# 출력 파일 경로
output_path = r"G:\02 Python\PythonTest02\OUT01.xlsx"

# 이미지 폴더 경로
image_folder = r"G:\02 Python\PythonTest02\image"

# 지원하는 이미지 확장자
image_extensions = ('.png', '.jpg', '.jpeg', '.bmp', '.gif')

1. excel_path = r"G:\02 Python\PythonTest02\outform01.xlsx"   :  출력 파일을 정의 합니다

  • excel_path 변수는 처리할 기존 엑셀 파일의 전체 경로를 저장합니다.
  • 여기서 r 접두사는 "Raw string(원본 문자열)"을 의미하며, 문자열 안의 백슬래시(\)를 이스케이프(escape) 문자로 해석하지 않고 있는 그대로 처리하도록 합니다. 파일 경로에 백슬래시가 포함되어 있기 때문에 이 방식을 사용한 것입니다.
  • 이 코드는 G:\02 Python\PythonTest02 폴더에 있는 outform01.xlsx 파일을 대상으로 작업할 것입니다.
  • 출력 파일 위치 및 이름 변경을 할수 있습니다.

2. wb = load_workbook(excel_path)

  • openpyxl 라이브러리의 load_workbook 함수를 사용하여 excel_path에 지정된 엑셀 파일을 메모리로 불러옵니다.
  • 불러온 워크북(엑셀 파일) 객체는 wb 변수에 할당됩니다. 이제 wb를 통해 엑셀 파일의 내용을 읽고 수정할 수 있습니다.

3. ws = wb.active

  • wb 워크북에서 현재 **활성화된 워크시트(시트)**를 선택하여 ws 변수에 할당합니다.
  • 일반적으로 엑셀 파일을 열었을 때 가장 먼저 보이는 시트를 의미합니다. 대부분의 경우 첫 번째 시트가 활성 시트가 됩니다.
  • # 시트 이름이 "KOREA"인 시트를 선택 ws = wb['KOREA']

4. output_path = r"G:\02 Python\PythonTest02\OUT01.xlsx"

  • output_path 변수는 작업을 마친 후 저장될 엑셀 파일의 경로와 이름을 저장합니다.
  • 원본 파일(outform01.xlsx)에 이미지를 추가한 후, 그 결과를 **OUT01.xlsx**라는 새로운 파일로 저장

5. image_folder = r"G:\02 Python\PythonTest02\image"

  • image_folder 변수는 삽입할 이미지 파일들이 저장되어 있는 폴더의 경로를 지정합니다.
  • 이 코드는 G:\02 Python\PythonTest02\image 폴더에 있는 이미지들을 엑셀에 삽입할 것입니다.

6. image_extensions = ('.png', '.jpg', '.jpeg', '.bmp', '.gif')

  • image_extensions 변수는 튜플 형태로 프로그램이 처리할 이미지 파일의 확장자 목록을 저장합니다.
  • 이 목록은 image_folder 내의 파일들 중에서 어떤 파일이 이미지인지 구분하는 데 사용됩니다. 즉, 이 코드에서는 PNG, JPG, JPEG, BMP, GIF 형식의 이미지만을 대상으로 작업하게 됩니다.

특정 폴더에서 이미지 파일 목록을 만드는 역할을 합니다.  image_folder 안에 있는 파일들 중에서 확장자가 .png, .jpg 등으로 끝나는 파일들의 이름만 모아 image_files 리스트에 저장됩니다. 이렇게 만들어진 리스트는 이후 엑셀에 이미지를 삽입하는 작업에 사용

# 폴더에서 이미지 파일 목록 가져오기
image_files = [f for f in os.listdir(image_folder) if f.lower().endswith(image_extensions)]
print(f"찾은 이미지 파일 수: {len(image_files)} - {image_files}")  # 디버깅용 출력
  • image_files = [...]: 리스트 컴프리헨션(List Comprehension)을 사용하여 리스트를 한 줄로 간결하게 만들고 있습니다. 이 코드는 image_folder 내의 모든 파일을 순회하며 특정 조건을 만족하는 파일만 image_files 리스트에 추가합니다.
  • os.listdir(image_folder): os 모듈의 listdir() 함수는 image_folder 경로에 있는 모든 파일과 폴더의 이름을 리스트 형태로 반환합니다. 예를 들어, ['image1.png', 'document.txt', 'image2.jpg']와 같은 형태가 됩니다.
  • for f in ...: 반환된 파일 이름 리스트를 하나씩 f라는 변수에 할당하며 반복합니다.
  • if f.lower().endswith(image_extensions): 이 부분이 파일을 필터링하는 조건입니다.)

 

  1. ) f.lower(): 파일 이름 f를 모두 소문자로 변환합니다. 이렇게 하면 .PNG나 .JPG와 같이 대문자로 된 확장자도 올바르게 인식할 수 있습니다.
  2. ) .endswith(image_extensions): 소문자로 변환된 파일 이름이 image_extensions 튜플에 정의된 확장자 중 하나로 끝나는지 확인합니다. image_extensions는 이전에 .png, .jpg, .jpeg 등을 담고 있는 변수입니다.

준비된 이미지 파일 목록을 순회하며 각 이미지를 엑셀 워크시트에 순차적으로 삽입하는 작업을 수행
여러 이미지를 지정된 열에 차례대로, 일정한 셀 크기에 맞춰 삽입하는 데 매우 유용

# 모든 이미지를 순차적으로 삽입
for idx, image_file in enumerate(image_files):
    image_path = os.path.join(image_folder, image_file)
    img = Image(image_path)
    
    # 원본 이미지 크기 가져오기
    original_img = PILImage.open(image_path)
    original_width, original_height = original_img.size
    
    # 셀 위치 계산
    col_letter = chr(64 + col)  # B 열 (65 = A, 66 = B)
    cell = f"{col_letter}{start_row + idx}"
    
    # 셀 크기 설정 (고정값 사용)
    ws.column_dimensions[col_letter].width = fixed_width
    ws.row_dimensions[start_row + idx].height = fixed_height
    
    # 이미지 크기 조정 (셀 폭 30 단위에 맞춤, 종횡비 유지)
    cell_width = fixed_width * 10  # 30 단위 * 10 = 300픽셀
    cell_height = fixed_height * 10  # 150 단위 * 10 = 1500픽셀
    aspect_ratio = original_height / original_width
    img_width = cell_width  # 너비를 셀 폭(300픽셀)에 맞춤
    img_height = min(cell_height, int(img_width * aspect_ratio))  # 높이를 종횡비에 맞춰 조정, 최대 1500픽셀
    
    img.width = int(img_width)
    img.height = int(img_height)
    
    # 셀에 이미지 삽입
    ws.add_image(img, cell)
    print(f"이미지 {image_file}를 {cell}에 삽입했습니다.")  # 디버깅용 출력

 

1. 루프 시작 (for idx, image_file in enumerate(image_files):)

  • enumerate(image_files)는 image_files 리스트를 순회하며, 각 요소의 인덱스(idx)와 값(image_file)을 동시에 반환합니다.
  • idx는 0부터 시작하는 순서 번호로, 이미지를 삽입할 행 번호를 계산하는 데 사용됩니다.
  • image_file은 'image1.png', 'image2.jpg'와 같은 이미지 파일 이름입니다.

2. 이미지 준비

  • image_path = os.path.join(image_folder, image_file): 이미지 파일이 있는 전체 경로를 생성합니다. 예를 들어, G:\02 Python\PythonTest02\image\image1.png와 같이 경로와 파일 이름을 결합합니다.
  • img = Image(image_path): openpyxl 라이브러리에서 사용할 수 있도록 Image 객체를 생성합니다. 이 객체를 통해 엑셀에 이미지를 삽입할 수 있습니다.
  • original_img = PILImage.open(image_path): 이미지의 원본 크기를 확인하기 위해 Pillow 라이브러리를 사용하여 이미지를 엽니다.
  • original_width, original_height = original_img.size: 이미지의 원래 가로(width)와 세로(height) 크기를 픽셀 단위로 가져옵니다.

3. 셀 위치 및 크기 설정

  • col_letter = chr(64 + col): col 변수(예: col = 2일 경우)를 사용해 'A', 'B'와 같은 열 문자열로 변환합니다. chr(65)는 'A'를 반환하므로, 64 + 2는 66이고 chr(66)은 'B'가 됩니다.
  • cell = f"{col_letter}{start_row + idx}": 이미지가 삽입될 셀 주소(예: 'B4', 'B5', ...)를 만듭니다. start_row 변수(예: 4)에 idx를 더하여 행을 순차적으로 늘려갑니다.
  • ws.column_dimensions[col_letter].width = fixed_width: 'B' 열의 너비를 fixed_width 변수에 저장된 고정된 값(예: 30)으로 설정합니다.
  • ws.row_dimensions[start_row + idx].height = fixed_height: 이미지가 삽입될 각 행의 높이를 fixed_height 변수에 저장된 고정된 값(예: 150)으로 설정합니다.

 

4. 이미지 크기 조정

  • cell_width = fixed_width * 10: openpyxl의 셀 너비 단위는 픽셀과 직접 일치하지 않으므로, 임의의 비율(여기서는 10)을 곱해 픽셀 단위의 너비를 계산합니다. 30 * 10 = 300 픽셀이 됩니다.
  • cell_height = fixed_height * 10: 마찬가지로, 셀 높이도 픽셀 단위로 변환합니다. 150 * 10 = 1500 픽셀이 됩니다.
  • aspect_ratio = original_height / original_width: 이미지의 종횡비를 계산하여, 크기를 조정할 때 비율이 깨지지 않도록 합니다.
  • img_width = cell_width: 이미지의 너비를 셀의 너비(300픽셀)에 맞춥니다.
  • img_height = min(cell_height, int(img_width * aspect_ratio)):

 

  1. ) img_width * aspect_ratio를 계산하여 종횡비를 유지하면서 이미지를 조정했을 때의 높이를 구합니다.
  2. ) 이 높이가 셀의 최대 높이(cell_height, 즉 1500픽셀)를 넘지 않도록 min() 함수를 사용해 제한합니다.

 

  • img.width = int(img_width)와 img.height = int(img_height): 최종적으로 계산된 이미지의 가로, 세로 크기를 openpyxl Image 객체에 적용합니다.

엑셀의 cell 크기를 이미지 크기 단위인 픽셀로 환산하는 코드가 있습니다. 알캡쳐와 같이 픽셀 크기를 고정 하여 스크린 캡쳐하는 프로그램을 사용 해야 합니다.

by korealionkk@gmail.com


 

 

반응형