当前位置: 代码网 > it编程>前端脚本>Python > 使用Python实现Excel图片插入、提取与压缩操作

使用Python实现Excel图片插入、提取与压缩操作

2026年04月01日 Python 我要评论
​事情是这样的。上个月公司要做一份产品目录,需要把500多款产品的图片插进excel表格里,每个产品对应一行,图片放在第二列,大小还要统一。我打开excel,手动插了一张图——

​事情是这样的。上个月公司要做一份产品目录,需要把500多款产品的图片插进excel表格里,每个产品对应一行,图片放在第二列,大小还要统一。

我打开excel,手动插了一张图——调整大小、拖到单元格里、对齐。看了一眼右下角的时间,我算了一笔账:一张图算30秒,500张就是250分钟,整整4个多小时。关键是这活儿毫无技术含量,纯属机械重复。

那一刻我意识到,这事儿必须用python解决。

后来我用几行代码搞定了这个任务,顺便还研究了怎么从excel里提取图片、怎么压缩图片大小。今天就把这些经验整理出来,希望对你有用。

准备工作:先装好这些库

在动手之前,需要安装几个python库。不同任务需要的库不太一样,但有几个是通用的:

# 基础图像处理
pip install pillow
# 操作excel文件(选一个就行)
pip install openpyxl          # 处理.xlsx文件,不支持图片插入
pip install xlwings           # 需要本地有excel软件
pip install spire.xls.free    # 支持图片操作,无需excel环境

需要说明的是,openpyxl这个库虽然很常用,但它对图片的操作能力非常有限——只能读取已有图片,无法插入或删除。如果你想要完整控制图片的增删改,推荐用spire.xls.free或者xlwings

还有个更轻量的选择叫pywin32,它可以直接调用windows上的excel程序来干活,适合在windows电脑上跑。

插入图片:把图片精准放到单元格里

回到开头那个问题:如何批量把图片插入excel,并且精准对齐到每个单元格?

这里用一个叫xlwings的库来实现。它的原理是启动你电脑上的excel程序,然后像人工操作一样往里填东西。

import xlwings as xw
import os

# 打开excel文件
wb = xw.book('产品目录.xlsx')
sheet = wb.sheets['产品列表']

# 图片存放的文件夹
image_folder = 'product_images/'

# 从第2行开始(假设第1行是表头)
for i, filename in enumerate(os.listdir(image_folder), start=2):
    if filename.endswith(('.png', '.jpg')):
        # 构建图片完整路径
        img_path = os.path.join(image_folder, filename)
        
        # 把图片插入到b列当前行
        sheet.pictures.add(img_path, 
                          left=sheet.range(f'b{i}').left,
                          top=sheet.range(f'b{i}').top,
                          width=100,   # 设置宽度
                          height=80)   # 设置高度
        
        # 可选:调整行高让图片不重叠
        sheet.range(f'{i}:{i}').row_height = 80

wb.save()
wb.close()
print("搞定!图片已全部插入")

这段代码的核心逻辑很简单:遍历文件夹里的所有图片,把它们依次放到excel的b列,从第2行开始往下排。lefttop参数让图片的左上角对齐到单元格的左上角,这样位置就精准了。

如果你的需求更复杂,比如需要把图片放到特定的单元格(而不是按顺序),可以改成这样:

# 假设有一个字典,键是产品编号,值是对应图片路径
product_map = {
    'a001': 'images/a001.jpg',
    'a002': 'images/a002.jpg',
    # ...
}

for product_id, img_path in product_map.items():
    # 找到产品编号在哪一行
    cell = sheet.range('a:a').find(product_id)
    if cell:
        row = cell.row
        sheet.pictures.add(img_path,
                          left=sheet.range(f'c{row}').left,
                          top=sheet.range(f'c{row}').top,
                          width=100,
                          height=80)

这个逻辑是先找到产品编号所在的单元格位置,再把图片插到对应的c列。无论表格顺序怎么变,图片都不会放错。

提取图片:把excel里的图片薅出来

有时候反过来,excel文件里已经有一堆图片,需要把它们导出到文件夹里。这个场景常见于从别人发来的报表中提取素材。

openpyxl这个库虽然不能插入图片,但读取图片还是可以的。不过它只能处理.xlsx格式的文件,老版的.xls就不行了。

from openpyxl import load_workbook
from openpyxl_image_loader import sheetimageloader
import os

# 加载excel文件
wb = load_workbook('带图片的报告.xlsx')
sheet = wb.active

# 创建保存图片的文件夹
output_dir = 'extracted_images'
os.makedirs(output_dir, exist_ok=true)

# 用imageloader提取所有图片
image_loader = sheetimageloader(sheet)

# 遍历所有单元格
for row in range(1, sheet.max_row + 1):
    for col in range(1, sheet.max_column + 1):
        cell = sheet.cell(row, col)
        if image_loader.image_in(cell.coordinate):
            img = image_loader.get(cell.coordinate)
            # 保存图片,用行列命名
            img.save(f'{output_dir}/img_{row}_{col}.png')
            print(f'已保存:第{row}行第{col}列的图片')

print(f'提取完成,图片保存在{output_dir}文件夹')

如果你用的是spire.xls库,提取图片的代码会更简洁:

from spire.xls import *

workbook = workbook()
workbook.loadfromfile('带图片的报告.xlsx')
sheet = workbook.worksheets[0]

for i, picture in enumerate(sheet.pictures):
    picture.picture.save(f'extracted_images/pic_{i}.png')

workbook.dispose()

这里有个坑需要注意:如果excel里的图片是“浮”在单元格上方的,而不是“嵌入”在单元格里的,上面的方法可能抓不到。这种情况下可以考虑用pywin32直接操作excel程序来提取。

压缩图片:让臃肿的excel文件瘦身

图片插多了,excel文件会变得巨大。一个几兆的excel,插了几十张高清图后可能变成几百兆,打开都费劲。

压缩图片的核心思路就是降低图片质量。用pil(pillow)库可以轻松做到:

from pil import image
import os

def compress_image(input_path, output_path, quality=50):
    """
    压缩图片
    quality: 1-100,数值越小压缩越狠,文件越小
    """
    img = image.open(input_path)
    # 保存时指定quality,jpeg格式支持压缩
    img.save(output_path, 'jpeg', quality=quality)
    
    # 看看压缩效果
    original_size = os.path.getsize(input_path) / 1024
    compressed_size = os.path.getsize(output_path) / 1024
    print(f'{os.path.basename(input_path)}: '
          f'{original_size:.1f}kb → {compressed_size:.1f}kb')

这个函数可以把一张几兆的图片压缩到几十kb,肉眼几乎看不出差别。quality参数是关键,设为50左右能兼顾文件大小和清晰度。

如果有多张图片需要批量压缩,可以这样:

def batch_compress(folder_path, quality=50):
    for filename in os.listdir(folder_path):
        if filename.endswith(('.png', '.jpg', '.jpeg')):
            input_path = os.path.join(folder_path, filename)
            output_path = os.path.join(folder_path, f'compressed_{filename}')
            compress_image(input_path, output_path, quality)

还有个更高级的玩法:多阶段压缩。如果一次压缩达不到目标大小,就逐步降低质量,甚至缩小尺寸,直到文件够小为止。

def compress_to_target(img_path, target_kb=100, max_attempts=5):
    """反复压缩直到文件小于target_kb"""
    quality = 80
    for attempt in range(max_attempts):
        temp_path = f'temp_{attempt}.jpg'
        compress_image(img_path, temp_path, quality)
        
        if os.path.getsize(temp_path) / 1024 <= target_kb:
            # 压缩成功
            os.replace(temp_path, img_path)
            return true
        
        # 还不够小,继续降低质量
        quality -= 15
        os.remove(temp_path)
    
    return false

如果你用的是spire.xls库,它自带了图片压缩方法,可以直接在excel内部压缩,不需要先导出再插回:

from spire.xls import *

workbook = workbook()
workbook.loadfromfile('需要压缩图片的表格.xlsx')

for sheet in workbook.worksheets:
    for picture in sheet.pictures:
        # 直接压缩图片,参数是压缩比例
        picture.compress(50)

workbook.savetofile('压缩后的表格.xlsx', excelversion.version2016)
workbook.dispose()

这种方式的好处是操作简单,而且压缩后的图片还待在原来的位置,不用重新排版。

进阶:从图片表格里提取文字到excel

还有一种情况很常见:你手里有一张图片格式的表格(比如扫描件、截图),想把它转成可编辑的excel。

这就用到ocr技术了。tesseract是一个开源的ocr引擎,配合python的pytesseract库可以搞定:

import pytesseract
from pil import image
import pandas as pd

# 如果tesseract没在系统路径里,需要指定一下
pytesseract.pytesseract.tesseract_cmd = r'c:\program files\tesseract-ocr\tesseract.exe'

def image_to_excel(img_path, output_excel):
    # 读取图片
    img = image.open(img_path)
    
    # 识别文字,chi_sim是中文简体模型
    text = pytesseract.image_to_string(img, lang='chi_sim+eng')
    
    # 把识别结果按行分割
    lines = text.strip().split('\n')
    
    # 转换成dataframe并保存
    df = pd.dataframe([line.split('\t') for line in lines])
    df.to_excel(output_excel, index=false, header=false)
    
    print(f'识别完成,结果保存在{output_excel}')

# 使用示例
image_to_excel('表格截图.png', '识别结果.xlsx')

这种方法的识别精度取决于图片质量。如果图片不够清晰,可以先用pil做一下预处理:

def preprocess_image(img_path):
    img = image.open(img_path)
    # 转为灰度图
    img = img.convert('l')
    # 提高对比度
    from pil import imageenhance
    enhancer = imageenhance.contrast(img)
    img = enhancer.enhance(2.0)
    return img

如果你想达到更高的识别准确率(比如98%以上),可以考虑用商业ocr接口,比如百度ocr。它专门优化过表格识别场景,还能自动解析表格的行列结构。不过这是付费服务,有免费额度,适合企业级应用。

避坑指南:这些细节不注意会翻车

路径问题

windows路径里的反斜杠``需要转义,或者直接用正斜杠/。保险的做法是:

img_path = r'c:\users\name\images\product.jpg'
# 或者
img_path = 'c:/users/name/images/product.jpg'

excel被占用

如果你的代码运行时报错说文件被占用,记得先把excel关掉。xlwings这类库启动excel程序时,如果文件已经打开可能会冲突。

图片格式兼容

.png支持透明背景,.jpg压缩率高但不支持透明。插入到excel里两种都能用,但压缩时要注意:png转jpeg会丢失透明通道。

vba权限问题

如果用pywin32的方式插入图片,需要提前在excel里开启“信任对vba项目对象模型的访问”权限。具体路径:excel选项 → 信任中心 → 信任中心设置 → 宏设置 → 勾选这个选项。这步不做会报错。

内存溢出

批量处理大量图片时,如果电脑内存不够用,可以考虑分批处理。比如一次处理100张,处理完释放内存再继续。

收个尾

回头来看,那天下午让我发愁的500张产品图,最后用python不到一分钟就跑完了。代码跑起来的那一刻,看着屏幕上的进度条噌噌往前走,那种感觉确实挺爽的。

excel和图片打交道这件事,用python来搞无非就是三个核心操作:插进去、薅出来、压一压。掌握了这几个套路,以后再遇到类似的活儿,就不用跟excel较劲了。

到此这篇关于使用python实现excel图片插入、提取与压缩操作的文章就介绍到这了,更多相关python操作excel图片内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com