python excel图片批量拼接导出

一、使用openpyxl库导出,用某一列命名,把同一行的图片全部拼接在一起

  • 原文件是xls另存为xlsx文件,执行的时候报错。文件损坏,重新建一个xlsx文件,把数据复制过去
python 复制代码
#!/usr/bin/env python
#-*- coding: utf-8 -*-
# vim:fenc=utf-8
# @author tlwlmy
# @version 2026-01-31


import os
import io
from openpyxl import load_workbook
from openpyxl.drawing.image import Image
import re
from PIL import Image as PILImage
from PIL import ImageOps

def merge_images_vertical(image_paths, output_folder, filename):
    """
    纵向拼接多张图片(上下排列)
    :param image_paths: 图片路径列表(如 ["1.png", "2.png"])
    :param output_folder: 保存目录
    :param filename: 图片名字
    """

    # 1. 打开所有图片并存储
    images = []
    for open_images in image_paths:
        img = PILImage.open(io.BytesIO(open_images._data()))
        images.append(img)
    
    if not images:
        print("无有效图片可拼接!")
        return
    
    # 2. 计算拼接后总尺寸:宽度取最大的图片宽度,高度累加所有图片高度
    max_width = max(img.width for img in images)
    total_height = sum(img.height for img in images)
    
    # 3. 创建空白画布(背景白色)
    merged_img = PILImage.new("RGB", (max_width, total_height), color="white")
    
    # 4. 逐张粘贴图片
    current_y = 0  # 记录当前粘贴的y坐标
    for img in images:
        # 若图片宽度小于最大宽度,居中粘贴(可选,也可左对齐)
        offset_x = (max_width - img.width) // 2
        merged_img.paste(img, (offset_x, current_y))
        current_y += img.height  # 更新y坐标


    # 保存图片
    filepath = os.path.join(output_folder, filename)
    
    # 5. 保存拼接后的图片
    merged_img.save(filepath)

    print(f"纵向拼接完成!保存至:{filepath}")

def export_images_by_column_openpyxl(excel_path, name_column='A', output_folder="named_images", image_columns=None, sheet_name=None):
    """
    根据指定列的单元格内容为图片命名
    
    参数:
    - excel_path: Excel文件路径
    - name_column: 用于命名的列字母(如 'A', 'B', 'C')
    - output_folder: 输出文件夹
    - sheet_name: 指定工作表名称,None表示所有工作表
    """
    # 创建输出文件夹
    os.makedirs(output_folder, exist_ok=True)
    
    # 加载工作簿
    wb = load_workbook(excel_path)
    
    # 确定要处理的工作表
    if sheet_name:
        sheets = [wb[sheet_name]]
    else:
        sheets = wb.worksheets
    
    image_count = 0
    
    for ws in sheets:
        print(f"\n正在处理工作表: {ws.title}")
        
        # 获取所有图片
        images = ws._images

        # images_dict
        images_dict = {}
        
        for img in images:
            image_count += 1
            
            # 获取图片的锚点位置
            # openpyxl中,图片位置信息在anchor属性中
            if hasattr(img, 'anchor'):
                # 获取图片左上角所在的单元格
                # 不同版本的openpyxl可能有所不同
                try:
                    # 方法1:尝试获取from属性
                    if hasattr(img.anchor, '_from'):
                        col_idx = img.anchor._from.col  # 列索引(1开始)
                        row_idx = img.anchor._from.row + 1  # 行索引(1开始)
                        print(col_idx, row_idx)
                    # 方法2:尝试直接获取属性
                    elif hasattr(img, 'left') and hasattr(img, 'top'):
                        # 通过坐标计算最近单元格
                        col_idx = int(img.left // 64) + 1  # 近似计算
                        row_idx = int(img.top // 20) + 1   # 近似计算
                    else:
                        print(f"  图片{image_count}: 无法获取位置信息,使用默认名称")
                        col_idx = row_idx = None
                except:
                    col_idx = row_idx = None
                
                if col_idx and row_idx:
                    # 确定命名列的位置
                    # 假设图片与命名单元格在同一行
                    try:
                        # 获取命名列的单元格值
                        name_cell = f"{name_column}{row_idx}"
                        print('name_cell', name_cell)
                        name_value = ws[name_cell].value
                        
                        if name_value:
                            # 清理文件名(移除非法字符)
                            clean_name = clean_filename(str(name_value))
                            filename = f"{clean_name}.png"
                        else:
                            filename = f"图片{image_count}.png"
                    except:
                        filename = f"图片{image_count}.png"
                else:
                    filename = f"图片{image_count}.png"
            else:
                filename = f"图片{image_count}.png"


            print('col', col_idx, row_idx)
            # 筛选第几列的图片
            if image_columns is not None:
                if col_idx not in image_columns:
                    print('continue')
                    continue

            # 查询图片是否是多张
            if filename not in images_dict.keys():
                images_dict[filename] = [img]
            else:
                images_dict[filename].append(img)

    for filename in images_dict.keys():
        # 拼接图片
        merge_images_vertical(images_dict[filename], output_folder, filename)

    print(f"\n{'='*50}")
    print(f"处理完成!")
    print(f"总图片数: ", len(images_dict.keys()))
    print(f"保存位置: {os.path.abspath(output_folder)}")
    
def clean_filename(filename):
    """清理文件名,移除非法字符"""
    # 移除非法字符
    illegal_chars = r'[<>:"/\\|?*]'
    filename = re.sub(illegal_chars, '', filename)
    
    # 限制长度
    if len(filename) > 100:
        filename = filename[:100]
    
    # 移除首尾空格
    filename = filename.strip()
    
    # 如果清空后为空,使用默认名称
    if not filename:
        filename = "未命名"
    
    return filename

# 使用示例
if __name__ == "__main__":
    excel_file = "123.xlsx"
    
    # 示例1:使用A列的内容命名
    export_images_by_column_openpyxl(
        excel_path=excel_file,
        name_column='D',  # 使用B列命名
        output_folder="image",
        image_columns=[9, 10],
        sheet_name=None   # 处理所有工作表
    )
相关推荐
酉鬼女又兒2 小时前
零基础入门前端JavaScript Object 对象完全指南:从基础到进阶(可用于备赛蓝桥杯Web应用开发赛道)
开发语言·前端·javascript·职场和发展·蓝桥杯
R-sz2 小时前
坐标转换踩坑实录:UTM → WGS84 → GCJ02 前端后端一致实现
开发语言·前端·python
2301_816651222 小时前
Python游戏中的碰撞检测实现
jvm·数据库·python
cm6543202 小时前
Python Lambda(匿名函数):简洁之道
jvm·数据库·python
小陈工2 小时前
ModelEngine智能体开发实战:知识库自动生成与多Agent协作
大数据·网络·数据库·人工智能·python·django·异步
HWL56792 小时前
uni-app中路由的使用
前端·uni-app
小陈工2 小时前
2026年3月23日技术资讯洞察:AI Agent失控,Claude Code引领AI编程新趋势
开发语言·数据库·人工智能·后端·python·性能优化·ai编程
程序员陆业聪2 小时前
上下文工程与提示词工程:拆解 OpenClaw 是如何「喂养」大模型的
前端
wuhen_n2 小时前
初识Function Calling:让AI学会“调用工具”
前端·vue.js·ai编程