☰
Python自动化处理Excel图片:插入、提取与压缩实战
2026/10/11 2:15:32 网站建设 项目流程

1. Python操作Excel图片的完整指南

作为数据分析师,我每天都要处理大量包含图片的Excel报表。手动操作不仅效率低下,还容易出错。Python的openpyxl和Pillow库彻底改变了我的工作方式 - 现在我能用代码批量插入产品图、自动压缩图片节省空间,还能从几百个文件中一键提取所有图片。下面分享我积累的完整解决方案。

2. 环境准备与工具选型

2.1 必备库安装与版本选择

推荐使用Python 3.8+环境,这是目前企业级应用最稳定的版本。通过pip安装以下核心库:

pip install openpyxl==3.0.10 # Excel操作核心库 pip install pillow==9.5.0 # 图片处理神器 pip install python-pptx==0.6.21 # 如需处理PPT

注意:openpyxl 3.1.0+版本对图片处理有重大变更,建议锁定3.0.x版本确保兼容性。我曾在新版本踩过坑,部分图片插入功能会出现异常。

2.2 开发工具配置

VSCode是我的主力工具,配置建议:

  1. 安装Python扩展
  2. 设置Jupyter Notebook交互支持
  3. 添加Excel预览插件(如"Excel Viewer")
# 验证环境是否正常 import openpyxl from PIL import Image print(openpyxl.__version__, Image.__version__) # 应显示3.0.10和9.5.0

3. 图片插入实战技巧

3.1 基础插入方法

from openpyxl.drawing.image import Image as XLImage def insert_image(file_path, img_path, cell_location): wb = openpyxl.load_workbook(file_path) ws = wb.active img = XLImage(img_path) # 创建图片对象 ws.add_image(img, cell_location) # 如'B2' wb.save(file_path) print(f"图片已插入到{cell_location}")

典型问题处理:

  • 图片不显示?检查路径是否含中文/特殊字符
  • 位置偏移?Excel默认以单元格左上角为锚点
  • 大小异常?需提前用Pillow调整尺寸

3.2 高级排版控制

精确控制图片位置和尺寸的参数:

from openpyxl.utils.units import pixels_to_EMU, cm_to_EMU img.width = pixels_to_EMU(300) # 宽度300像素 img.height = pixels_to_EMU(200) # 高度200像素 # 厘米转Excel单位 img.left = cm_to_EMU(2.5) # 距左2.5cm img.top = cm_to_EMU(1.8) # 距上1.8cm

实测案例:为电商报告插入商品图时,保持所有图片宽度统一为5cm,间距1cm,代码实现:

def batch_insert_images(ws, img_folder): for i, img_file in enumerate(os.listdir(img_folder)): img_path = os.path.join(img_folder, img_file) img = XLImage(img_path) # 统一处理尺寸 img.width = cm_to_EMU(5) img.height = cm_to_EMU(5 * img.height/img.width) # 保持比例 # 计算位置 (每行3张图) row = i // 3 col = i % 3 img.left = cm_to_EMU(1 + col*6) img.top = cm_to_EMU(1 + row*6) ws.add_image(img)

4. 图片提取技术解析

4.1 从Excel提取图片的两种方案

方案一:直接解析.xlsx文件.xlsx本质是zip压缩包,图片存储在xl/media目录:

import zipfile def extract_images_xlsx(file_path, output_dir): with zipfile.ZipFile(file_path) as z: for file in z.namelist(): if file.startswith('xl/media/'): z.extract(file, output_dir) print(f"图片已保存到{output_dir}")

方案二:使用openpyxl遍历图形对象适合需要获取图片位置信息的场景:

def get_image_positions(ws): images = [] for img in ws._images: images.append({ 'anchor': img.anchor._from, 'size': (img.width, img.height), 'path': img.path # 仅在新版本支持 }) return images

踩坑记录:旧版Excel(.xls)需要使用xlrd库,但微软已停止支持。建议统一转为.xlsx格式处理。

4.2 提取图片的命名优化

默认提取的图片名称为"image1.png"、"image2.jpg"等。改进方案:

from openpyxl.drawing.spreadsheet_drawing import SpreadsheetDrawing def extract_with_better_names(file_path): wb = openpyxl.load_workbook(file_path) drawing = SpreadsheetDrawing.from_tree(wb._images[0]) for rel in drawing._rels: img_data = wb._images[rel.target] img_name = f"{ws.title}_{rel.id}.{img_data.format.lower()}" with open(img_name, 'wb') as f: f.write(img_data._data())

5. 图片压缩的工业级方案

5.1 质量与尺寸平衡

使用Pillow进行智能压缩:

from PIL import Image import io def compress_image(img_path, quality=85, max_size=(1024,1024)): img = Image.open(img_path) # 等比例缩放 img.thumbnail(max_size, Image.Resampling.LANCZOS) # 优化存储 buffer = io.BytesIO() img.save(buffer, format='JPEG', quality=quality, optimize=True, progressive=True) return buffer.getvalue()

参数说明:

  • quality: 85是视觉无损的临界点
  • optimize: 启用额外压缩算法
  • progressive: 渐进式加载优化

5.2 批量压缩Excel内图片

完整工作流:

def compress_excel_images(input_path, output_path): # 临时目录处理 temp_dir = 'temp_images' os.makedirs(temp_dir, exist_ok=True) # 提取原图 extract_images_xlsx(input_path, temp_dir) # 创建新工作簿 wb = openpyxl.Workbook() ws = wb.active # 压缩并重新插入 for img_file in os.listdir(temp_dir): img_path = os.path.join(temp_dir, img_file) compressed = compress_image(img_path) with open(img_path, 'wb') as f: f.write(compressed) img = XLImage(img_path) ws.add_image(img) # 清理并保存 shutil.rmtree(temp_dir) wb.save(output_path)

实测数据:一个包含50张手机照片的Excel文件,原始大小28MB,经压缩后仅3.5MB,体积减少87%。

6. 企业级应用案例

6.1 电商商品报告自动化

需求场景:

  • 每日从ERP导出含SKU的Excel
  • 自动匹配图片库中的商品图
  • 生成带图标的采购清单
def generate_product_report(data_excel, img_folder, output_file): # 加载数据 df = pd.read_excel(data_excel) wb = openpyxl.Workbook() ws = wb.active # 写入表头 ws.append(['SKU', '名称', '单价', '库存', '图片']) # 遍历商品 for idx, row in df.iterrows(): img_path = find_image_by_sku(img_folder, row['sku']) if img_path: img = XLImage(img_path) img.width = pixels_to_EMU(100) img.height = pixels_to_EMU(100) ws.add_image(img, f'E{idx+2}') # 从第2行开始 ws.append([row['sku'], row['name'], row['price'], row['stock']]) # 压缩并保存 compress_excel_images(wb, output_file)

6.2 财务报表图片水印

为敏感报表添加动态水印:

from PIL import ImageDraw, ImageFont def add_watermark(img_path, text): img = Image.open(img_path) draw = ImageDraw.Draw(img) font = ImageFont.truetype('arial.ttf', 40) textwidth, textheight = draw.textsize(text, font) # 计算水印位置 x = img.width - textwidth - 10 y = img.height - textheight - 10 # 半透明效果 draw.text((x, y), text, font=font, fill=(255, 255, 255, 128)) return img

7. 性能优化与异常处理

7.1 大文件处理技巧

当Excel超过50MB时:

  1. 使用read_only模式加载
  2. 分块处理图片
  3. 及时清理内存
def process_large_excel(file_path): # 只读模式打开 wb = openpyxl.load_workbook(file_path, read_only=True) try: for sheet in wb: # 分块处理逻辑 process_sheet(sheet) finally: # 确保资源释放 wb.close() del wb

7.2 常见错误排查

  1. 图片破损:

    • 现象:插入后显示红叉
    • 解决方案:用Pillow验证图片完整性
    try: Image.open(img_path).verify() except Exception as e: print(f"图片损坏: {e}")
  2. 位置错乱:

    • 现象:图片覆盖单元格
    • 修复:检查锚点单位是否混淆(pixels vs EMU)
  3. 内存泄漏:

    • 现象:处理大量图片时内存激增
    • 优化:使用生成器逐张处理
    def image_generator(folder): for file in os.listdir(folder): yield Image.open(os.path.join(folder, file))

8. 扩展应用与进阶技巧

8.1 与PPT联动

使用python-pptx库实现跨Office自动化:

from pptx import Presentation def excel_to_ppt(excel_path, ppt_template, output_ppt): prs = Presentation(ppt_template) # 提取Excel图片 images = extract_images(excel_path) # 插入PPT for img_data in images: slide = prs.slides.add_slide(prs.slide_layouts[1]) pic = slide.shapes.add_picture( io.BytesIO(img_data), left=Inches(1), top=Inches(1.5)) prs.save(output_ppt)

8.2 生成动态图表

结合matplotlib创建带图表的Excel:

import matplotlib.pyplot as plt def add_matplotlib_chart(ws, data): fig, ax = plt.subplots() ax.plot(data['x'], data['y']) # 保存为图片缓冲区 buffer = io.BytesIO() fig.savefig(buffer, format='png') buffer.seek(0) # 插入Excel img = XLImage(buffer) ws.add_image(img, 'A10') plt.close(fig)

9. 安全注意事项

  1. 文件操作安全:

    • 检查用户上传的Excel是否包含恶意宏
    • 使用tempfile模块处理临时文件
  2. 图片安全:

    • 验证图片实际格式(防止伪装的.exe)
    def check_image_safety(file_path): try: img = Image.open(file_path) img.verify() return True except: return False
  3. 权限管理:

    • 敏感操作添加水印
    • 记录图片操作日志

10. 完整项目结构示例

excel_image_tool/ ├── core/ │ ├── __init__.py │ ├── extractor.py # 图片提取逻辑 │ ├── inserter.py # 图片插入逻辑 │ └── compressor.py # 压缩处理 ├── utils/ │ ├── file_utils.py # 文件操作 │ └── image_utils.py # Pillow扩展 ├── config.py # 全局配置 └── main.py # 命令行入口

典型命令行接口:

# main.py import click @click.command() @click.option('--input', help='输入Excel文件') @click.option('--output', help='输出路径') def cli(input, output): # 业务逻辑整合 pass if __name__ == '__main__': cli()

使用方式:

python main.py --input report.xlsx --output out/

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询