Python從Excel中按行提取圖片的實現(xiàn)方法
前言
在Excel表格中批量導(dǎo)出圖片,并按行首字段命名保存,是許多辦公場景的剛需。本文提供兩個完整可運行的Python版本:
- 版本一:保持圖片原始格式(PNG、JPG等各自保留)
- 版本二:統(tǒng)一將所有圖片轉(zhuǎn)換為JPG格式(節(jié)省空間、格式統(tǒng)一)
兩個版本均實現(xiàn)了:按工作表分文件夾 → 根據(jù)圖片所在行的A列值命名 → 自動處理重名和非法字符。
一、版本一:保持原始格式
該版本完全保留圖片原始格式(.png / .jpg / .gif等),其他功能完整。
import openpyxl
from PIL import Image as PILImage
import io
import os
def extract_images_from_excel(excel_path, output_dir=None):
"""
按行提取 Excel 中的圖片,存儲到以 Sheet 名稱命名的文件夾下,
圖片命名為該行第一個字段的值(即A列),保持原始格式。
"""
if output_dir is None:
output_dir = os.path.dirname(os.path.abspath(excel_path))
os.makedirs(output_dir, exist_ok=True)
wb = openpyxl.load_workbook(excel_path)
extracted_count = 0
for sheet_name in wb.sheetnames:
ws = wb[sheet_name]
print(f"處理工作表: {sheet_name}")
safe_sheet_name = "".join(
c for c in sheet_name if c not in r'\/:*?"<>|'
).strip()
sheet_dir = os.path.join(output_dir, safe_sheet_name)
os.makedirs(sheet_dir, exist_ok=True)
# 收集每行A列的值
row_first_cell = {}
for row in range(1, ws.max_row + 1):
cell_value = ws.cell(row=row, column=1).value
if cell_value is not None:
row_first_cell[row] = str(cell_value)
for image in ws._images:
anchor = image.anchor
if hasattr(anchor, '_from'):
row_num = anchor._from.row + 1
elif hasattr(anchor, 'row'):
row_num = anchor.row + 1
else:
print(f" ?? 無法確定圖片行號,跳過")
continue
first_cell_value = row_first_cell.get(row_num, None)
if first_cell_value is None:
print(f" ?? 第{row_num}行第一個字段為空,跳過")
continue
safe_name = "".join(
c for c in first_cell_value if c not in r'\/:*?"<>|'
).strip()
if not safe_name:
safe_name = f"row_{row_num}"
img_data = image._data()
img = PILImage.open(io.BytesIO(img_data))
# 獲取原始格式
img_format = img.format.lower() if img.format else 'png'
filename = f"{safe_name}.{img_format}"
filepath = os.path.join(sheet_dir, filename)
counter = 1
base_name = safe_name
while os.path.exists(filepath):
filename = f"{base_name}_{counter}.{img_format}"
filepath = os.path.join(sheet_dir, filename)
counter += 1
img.save(filepath)
extracted_count += 1
print(f" ? 第{row_num}行 -> {safe_sheet_name}/{filename}")
print(f"\n?? 完成!共提取 {extracted_count} 張圖片,保存至: {output_dir}")
if __name__ == '__main__':
excel_path = 'cards.xlsx' # 修改為你的文件
extract_images_from_excel(excel_path, output_dir='images')
二、版本二:統(tǒng)一存儲為JPG格式
該版本將所有提取的圖片統(tǒng)一轉(zhuǎn)換為JPG格式(背景自動填充白色以處理透明通道),可設(shè)置JPG質(zhì)量。適合需要統(tǒng)一格式、減小體積的場景。
import openpyxl
from PIL import Image as PILImage
import io
import os
def extract_images_as_jpg(excel_path, output_dir=None, jpg_quality=85):
"""
按行提取 Excel 中的圖片,統(tǒng)一轉(zhuǎn)換為 JPG 格式存儲。
參數(shù):
excel_path: Excel 文件路徑
output_dir: 輸出根目錄
jpg_quality: JPG 壓縮質(zhì)量 (1-100),默認(rèn)85
"""
if output_dir is None:
output_dir = os.path.dirname(os.path.abspath(excel_path))
os.makedirs(output_dir, exist_ok=True)
wb = openpyxl.load_workbook(excel_path)
extracted_count = 0
for sheet_name in wb.sheetnames:
ws = wb[sheet_name]
print(f"處理工作表: {sheet_name}")
safe_sheet_name = "".join(
c for c in sheet_name if c not in r'\/:*?"<>|'
).strip()
sheet_dir = os.path.join(output_dir, safe_sheet_name)
os.makedirs(sheet_dir, exist_ok=True)
# 收集每行A列的值
row_first_cell = {}
for row in range(1, ws.max_row + 1):
cell_value = ws.cell(row=row, column=1).value
if cell_value is not None:
row_first_cell[row] = str(cell_value)
for image in ws._images:
anchor = image.anchor
if hasattr(anchor, '_from'):
row_num = anchor._from.row + 1
elif hasattr(anchor, 'row'):
row_num = anchor.row + 1
else:
print(f" ?? 無法確定圖片行號,跳過")
continue
first_cell_value = row_first_cell.get(row_num, None)
if first_cell_value is None:
print(f" ?? 第{row_num}行第一個字段為空,跳過")
continue
safe_name = "".join(
c for c in first_cell_value if c not in r'\/:*?"<>|'
).strip()
if not safe_name:
safe_name = f"row_{row_num}"
img_data = image._data()
img = PILImage.open(io.BytesIO(img_data))
# ----- 轉(zhuǎn)換為 JPG 的關(guān)鍵代碼 -----
# 若圖片為 RGBA(帶透明通道),需轉(zhuǎn)換為 RGB(白色背景)
if img.mode in ('RGBA', 'LA', 'P'):
# 創(chuàng)建白色背景
background = PILImage.new('RGB', img.size, (255, 255, 255))
# 將原圖粘貼到背景(使用透明通道作為掩碼)
if img.mode == 'P':
img = img.convert('RGBA')
background.paste(img, mask=img.split()[-1] if img.mode == 'RGBA' else None)
img = background
elif img.mode != 'RGB':
img = img.convert('RGB')
# -----------------------------
filename = f"{safe_name}.jpg"
filepath = os.path.join(sheet_dir, filename)
counter = 1
base_name = safe_name
while os.path.exists(filepath):
filename = f"{base_name}_{counter}.jpg"
filepath = os.path.join(sheet_dir, filename)
counter += 1
# 保存為 JPG,可指定質(zhì)量
img.save(filepath, 'JPEG', quality=jpg_quality)
extracted_count += 1
print(f" ? 第{row_num}行 -> {safe_sheet_name}/{filename} (JPG質(zhì)量={jpg_quality})")
print(f"\n?? 完成!共提取 {extracted_count} 張圖片,已統(tǒng)一為JPG格式,保存至: {output_dir}")
if __name__ == '__main__':
excel_path = 'cards.xlsx' # 修改為你的文件
extract_images_as_jpg(excel_path, output_dir='images_jpg', jpg_quality=85)
三、兩個版本的核心區(qū)別
| 特性 | 版本一(原格式) | 版本二(統(tǒng)一JPG) |
|---|---|---|
| 輸出擴(kuò)展名 | .png / .jpg / .gif 等原樣保留 | 統(tǒng)一為 .jpg |
| 透明背景處理 | 保留原圖(PNG透明通道) | 白色背景填充 |
| 壓縮控制 | 無(原樣保存) | 可調(diào)節(jié) quality 參數(shù) |
| 適用場景 | 需要保留原始質(zhì)量/透明效果 | 統(tǒng)一瀏覽、減小體積 |
| 輸出文件夾 | images/ | images_jpg/ |
四、使用步驟(通用)
安裝依賴
pip install openpyxl pillow
準(zhǔn)備Excel文件
- 確保圖片是“嵌入”到單元格中的(而非浮動鏈接)。
- 每個含圖片的行,A列 必須有值,該值將作為圖片文件名。
選擇版本并修改路徑
將代碼末尾的 excel_path = 'cards.xlsx' 改為實際文件路徑,可修改 output_dir。
運行腳本
python extract_images.py # 或 extract_as_jpg.py
結(jié)果
在輸出目錄下會按工作表名稱創(chuàng)建子文件夾,圖片按 A列值 命名存放。
五、注意事項
- 圖片定位:腳本依賴 openpyxl 的圖片錨點屬性,對于合并單元格或跨行圖片可能定位不準(zhǔn),建議將圖片完整置于某一行內(nèi)。
- 命名沖突:同一工作表中不同行的 A列值相同時,會自動添加
_1、_2后綴。 - 非法字符:文件名中的
/ \ : * ? " < > |會被自動去除。 - JPG 版本:原圖為 GIF 動圖時,只會提取第一幀并轉(zhuǎn)為 JPG;原圖為 CMYK 模式會自動轉(zhuǎn)為 RGB。
六、擴(kuò)展建議
- 修改命名列:將
column=1改為column=2即可使用B列命名。 - 批量處理多個Excel:可在外層增加循環(huán),依次調(diào)用函數(shù)。
- 支持更多輸出格式:在版本二中將
'JPEG'改為'PNG'即可輸出 PNG,但體積較大。 - 保留透明通道轉(zhuǎn)PNG:若希望統(tǒng)一為 PNG 并保留透明,可將版本二的轉(zhuǎn)換代碼去掉,直接保存為 PNG。
七、總結(jié)
本文提供了兩個完整、可直接運行的 Python 腳本,分別滿足“原格式保留”和“統(tǒng)一轉(zhuǎn) JPG”的常見需求。你只需要替換文件路徑即可運行,大大提升從 Excel 批量導(dǎo)出圖片的效率。選擇適合自己的版本,開始自動化辦公吧!
以上就是Python從Excel中按行提取圖片的方法實現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于Python Excel按行提取圖片的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python簡單實現(xiàn)Base64編碼和解碼的方法
這篇文章主要介紹了Python簡單實現(xiàn)Base64編碼和解碼的方法,結(jié)合具體實例形式分析了Python實現(xiàn)base64編碼解碼相關(guān)函數(shù)與使用技巧,需要的朋友可以參考下2017-04-04
基于logstash實現(xiàn)日志文件同步elasticsearch
這篇文章主要介紹了基于logstash實現(xiàn)日志文件同步elasticsearch,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-08-08
Python騷操作完美實現(xiàn)短視頻偽原創(chuàng)
剪輯的視頻上傳到某平臺碰到降權(quán)怎么辦?視頻平臺都有一套自己的鑒別算法,專門用于處理視頻的二次剪輯,本篇我們來用python做一些特殊處理2022-02-02
詳解利用OpenCV提取圖像中的矩形區(qū)域(PPT屏幕等)
這篇文章主要介紹了詳解利用OpenCV提取圖像中的矩形區(qū)域(PPT屏幕等),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-07-07
python GUI庫圖形界面開發(fā)之pyinstaller打包python程序為exe安裝文件
這篇文章主要介紹了python GUI庫圖形界面開發(fā)之pyinstaller打包python程序為exe安裝文件,需要的朋友可以參考下2020-02-02

