写一个测试脚本(批量处理PPT文件母版里面的logo及文本)

写一个测试脚本(批量处理PPT文件母版里面的logo及文本),仅供测试学习

检测母版图片信息

import os
from pptx import Presentation

# ================== 配置参数 ==================
DEBUG_MODE = True          # 调试模式开关
EMU_TO_PT = 12700          # 1磅 = 12700 EMU

# ================== 单位转换 ==================
def emu_to_pt(emu):
    """EMU转磅"""
    return emu / EMU_TO_PT

def analyze_shapes(shape, slide_width_pt, indent=0):
    """递归分析形状信息"""
    shape_info = []
    
    # 基础信息
    indent_str = "  " * indent
    info = (
        f"{indent_str}形状: {shape.name or '无名'}, "
        f"类型={shape.shape_type}, "
        f"位置=({emu_to_pt(shape.left):.1f},{emu_to_pt(shape.top):.1f})磅, "
        f"大小={emu_to_pt(shape.width):.1f}x{emu_to_pt(shape.height):.1f}磅"
    )
    
    # 额外信息
    if shape.shape_type == 13:  # 图片
        info += " [图片]"
    elif shape.has_text_frame:
        info += f", 文本='{shape.text[:30]}...'"
    
    shape_info.append(info)
    
    # 递归处理组合形状
    if shape.shape_type == 6:  # 组合形状
        for sub_shape in shape.shapes:
            shape_info.extend(analyze_shapes(sub_shape, slide_width_pt, indent+1))
    
    return shape_info

# ================== 文件处理 ==================
def analyze_ppt_file(ppt_path):
    try:
        prs = Presentation(ppt_path)
        slide_width_pt = emu_to_pt(prs.slide_width)
        
        print(f"\n🔍 分析文件: {ppt_path}")
        print(f"幻灯片尺寸: {slide_width_pt:.1f}x{emu_to_pt(prs.slide_height):.1f}磅")
        
        for i, slide_master in enumerate(prs.slide_masters, 1):
            print(f"\n---- 母版 {i} '{slide_master.name}' ----")
            
            # 分析母版本身
            print("[母版形状]")
            for shape in slide_master.shapes:
                for line in analyze_shapes(shape, slide_width_pt):
                    print(line)
            
            # 分析所有版式
            for j, layout in enumerate(slide_master.slide_layouts, 1):
                print(f"\n  -- 版式 {j} '{layout.name}' --")
                for shape in layout.shapes:
                    for line in analyze_shapes(shape, slide_width_pt, 1):
                        print(line)
        
        return True
            
    except Exception as e:
        print(f"❌ 分析失败: {ppt_path} - {str(e)}")
        return False

# ================== 主程序 ==================
def main():
    root_dir = r"F:\04\1\11"
    
    if not os.path.exists(root_dir):
        print(f"❌ 目录不存在: {root_dir}")
        return
    
    print(f"🔍 开始扫描: {root_dir}")
    ppt_files = []
    for root, _, files in os.walk(root_dir):
        for file in files:
            if file.lower().endswith(('.pptx', '.ppt')):
                ppt_files.append(os.path.join(root, file))
    
    if not ppt_files:
        print("⚠️ 未找到PPT文件")
        return
    
    print(f"📂 找到 {len(ppt_files)} 个文件")
    
    for i, file_path in enumerate(ppt_files, 1):
        print(f"\n[{i}/{len(ppt_files)}] ==========================")
        analyze_ppt_file(file_path)

if __name__ == "__main__":
    main()

 

处理代码:

import os
from pptx import Presentation

# ================= 配置参数 =================
DEBUG_MODE = False  # 设置为 True 可打印调试信息
EMU_TO_PT = 12700   # 1磅 = 12700 EMU

# 删除右上角 LOGO 图片的范围(单位:pt)
SLIDE_WIDTH_PT = 720.0  # 幻灯片宽度
TOP_LIMIT_PT = 150.0    # 距离顶部 ≤ 150 pt(≈200px)
RIGHT_LIMIT_PT = 150.0  # 距离右侧 ≤ 150 pt(≈200px)

# 图片尺寸约束(防止误删)
MAX_IMAGE_WIDTH_PT = 100.0
MAX_IMAGE_HEIGHT_PT = 100.0

# 删除中间文本框的区域(单位:pt)
TEXT_REGION = {
    "top": 100,
    "left": 100,
    "right": 650,
    "bottom": 400
}

# =============== 删除逻辑函数 ===============
def is_target_image(shape):
    """判断是否为右上角图片"""
    left_pt = shape.left / EMU_TO_PT
    top_pt = shape.top / EMU_TO_PT
    width_pt = shape.width / EMU_TO_PT
    height_pt = shape.height / EMU_TO_PT

    # 是否在右上角区域内
    is_top_area = top_pt <= TOP_LIMIT_PT
    is_right_area = left_pt >= SLIDE_WIDTH_PT - RIGHT_LIMIT_PT
    is_reasonable_size = width_pt <= MAX_IMAGE_WIDTH_PT and height_pt <= MAX_IMAGE_HEIGHT_PT

    return is_top_area and is_right_area and is_reasonable_size

def should_delete_text(shape):
    """判断是否为需要删除的文本框"""
    left_pt = shape.left / EMU_TO_PT
    top_pt = shape.top / EMU_TO_PT
    return (
        TEXT_REGION["left"] <= left_pt <= TEXT_REGION["right"] and
        TEXT_REGION["top"] <= top_pt <= TEXT_REGION["bottom"]
    )

def process_shape(shape, shapes_to_remove):
    """递归处理形状"""
    if shape.shape_type == 6:  # GROUP
        for sub_shape in shape.shapes:
            process_shape(sub_shape, shapes_to_remove)
    elif shape.shape_type == 13:  # PICTURE
        if is_target_image(shape):
            print(f"[匹配图片] {shape.name} at ({shape.left / EMU_TO_PT:.1f},{shape.top / EMU_TO_PT:.1f})")
            shapes_to_remove.append(shape)
    elif shape.has_text_frame:
        if should_delete_text(shape):
            print(f"[匹配文本] {shape.name} at ({shape.left / EMU_TO_PT:.1f},{shape.top / EMU_TO_PT:.1f}) 文本: {shape.text.strip()[:30]}")
            shapes_to_remove.append(shape)

def process_shape_container(container, label=""):
    shapes_to_remove = []
    for shape in container.shapes:
        process_shape(shape, shapes_to_remove)
    for shape in shapes_to_remove:
        print(f"✅ 删除: {shape.name} from {label}")
        shape._element.getparent().remove(shape._element)
    return bool(shapes_to_remove)

# =============== 处理单个PPT文件 ===============
def process_ppt_file(ppt_path):
    try:
        prs = Presentation(ppt_path)

        if DEBUG_MODE:
            print_all_pictures(prs)

        modified = False
        for slide_master in prs.slide_masters:
            if process_shape_container(slide_master, "母版"):
                modified = True
            for layout in slide_master.slide_layouts:
                if process_shape_container(layout, f"布局: {layout.name}"):
                    modified = True

        if modified:
            prs.save(ppt_path)
            print(f"💾 保存成功: {ppt_path}")
            return True
        else:
            print("❕ 未匹配任何内容")
            return False
    except Exception as e:
        print(f"❌ 处理失败: {ppt_path} - {e}")
        return False

# =============== 可选调试:输出所有图片 ===============
def print_all_pictures(prs):
    print("📷 所有图片信息(单位:pt):")
    for slide_master in prs.slide_masters:
        print(f"--- 母版 ---")
        for shape in slide_master.shapes:
            print_shape_debug(shape)
        for layout in slide_master.slide_layouts:
            print(f"--- 布局: {layout.name} ---")
            for shape in layout.shapes:
                print_shape_debug(shape)

def print_shape_debug(shape):
    if shape.shape_type == 13:  # PICTURE
        left = shape.left / EMU_TO_PT
        top = shape.top / EMU_TO_PT
        width = shape.width / EMU_TO_PT
        height = shape.height / EMU_TO_PT
        print(f"图片: {shape.name}, 位置=({left:.2f}, {top:.2f}), 大小=({width:.2f}, {height:.2f})")
    elif shape.shape_type == 6:
        for sub_shape in shape.shapes:
            print_shape_debug(sub_shape)

# =============== 主程序入口 ===============
def main():
    root_dir = r"F:\04\6\1"  # 修改为你的目录路径

    if not os.path.exists(root_dir):
        print(f"❌ 目录不存在: {root_dir}")
        return

    print(f"🔍 开始扫描目录: {root_dir}")
    ppt_files = []
    for root, _, files in os.walk(root_dir):
        for file in files:
            if file.lower().endswith('.pptx'):
                ppt_files.append(os.path.join(root, file))

    if not ppt_files:
        print("❗ 未找到任何 PPTX 文件")
        return

    print(f"✅ 共发现 {len(ppt_files)} 个 PPTX 文件")
    modified_count = 0

    for idx, file_path in enumerate(ppt_files, 1):
        print(f"\n[{idx}/{len(ppt_files)}] 处理: {file_path}")
        if process_ppt_file(file_path):
            modified_count += 1

    print(f"\n🎉 完成!共修改 {modified_count}/{len(ppt_files)} 个文件")

if __name__ == "__main__":
    main()

 

进阶版(删除右上角logo、居中文本、居中图片)

import os
from pptx import Presentation

# ================= 配置参数 =================
DEBUG_MODE = False  # 设置为 True 可打印调试信息
EMU_TO_PT = 12700   # 1磅 = 12700 EMU

# 删除右上角 LOGO 图片的范围(单位:pt)
SLIDE_WIDTH_PT = 720.0  # 幻灯片宽度
TOP_LIMIT_PT = 150.0    # 距离顶部 ≤ 150 pt(≈200px)
RIGHT_LIMIT_PT = 150.0  # 距离右侧 ≤ 150 pt(≈200px)

# 图片尺寸约束(防止误删)
MAX_IMAGE_WIDTH_PT = 100.0
MAX_IMAGE_HEIGHT_PT = 100.0

# 删除中间文本框的区域(单位:pt)
TEXT_REGION = {
    "top": 100,
    "left": 100,
    "right": 650,
    "bottom": 400
}

# =============== 删除逻辑函数 ===============
def is_target_image(shape):
    left_pt = shape.left / EMU_TO_PT
    top_pt = shape.top / EMU_TO_PT
    width_pt = shape.width / EMU_TO_PT
    height_pt = shape.height / EMU_TO_PT

    # 删除图片1:右上角 LOGO 区域
    is_top_area = top_pt <= TOP_LIMIT_PT
    is_right_area = left_pt >= SLIDE_WIDTH_PT - RIGHT_LIMIT_PT
    is_reasonable_size = width_pt <= MAX_IMAGE_WIDTH_PT and height_pt <= MAX_IMAGE_HEIGHT_PT
    is_logo_image = is_top_area and is_right_area and is_reasonable_size

    # 删除图片2:中间大图(位置 + 尺寸 精准匹配)
    is_center_image = (
        abs(left_pt - 236.6) <= 2.0 and
        abs(top_pt - 108.0) <= 2.0 and
        abs(width_pt - 246.8) <= 2.0 and
        abs(height_pt - 189.0) <= 2.0
    )

    return is_logo_image or is_center_image


def should_delete_text(shape):
    """判断是否为需要删除的文本框"""
    left_pt = shape.left / EMU_TO_PT
    top_pt = shape.top / EMU_TO_PT
    return (
        TEXT_REGION["left"] <= left_pt <= TEXT_REGION["right"] and
        TEXT_REGION["top"] <= top_pt <= TEXT_REGION["bottom"]
    )

def process_shape(shape, shapes_to_remove):
    """递归处理形状"""
    if shape.shape_type == 6:  # GROUP
        for sub_shape in shape.shapes:
            process_shape(sub_shape, shapes_to_remove)
    elif shape.shape_type == 13:  # PICTURE
        if is_target_image(shape):
            print(f"[匹配图片] {shape.name} at ({shape.left / EMU_TO_PT:.1f},{shape.top / EMU_TO_PT:.1f})")
            shapes_to_remove.append(shape)
    elif shape.has_text_frame:
        if should_delete_text(shape):
            print(f"[匹配文本] {shape.name} at ({shape.left / EMU_TO_PT:.1f},{shape.top / EMU_TO_PT:.1f}) 文本: {shape.text.strip()[:30]}")
            shapes_to_remove.append(shape)

def process_shape_container(container, label=""):
    shapes_to_remove = []
    for shape in container.shapes:
        process_shape(shape, shapes_to_remove)
    for shape in shapes_to_remove:
        print(f"✅ 删除: {shape.name} from {label}")
        shape._element.getparent().remove(shape._element)
    return bool(shapes_to_remove)

# =============== 处理单个PPT文件 ===============
def process_ppt_file(ppt_path):
    try:
        prs = Presentation(ppt_path)

        if DEBUG_MODE:
            print_all_pictures(prs)

        modified = False
        for slide_master in prs.slide_masters:
            if process_shape_container(slide_master, "母版"):
                modified = True
            for layout in slide_master.slide_layouts:
                if process_shape_container(layout, f"布局: {layout.name}"):
                    modified = True

        if modified:
            prs.save(ppt_path)
            print(f"💾 保存成功: {ppt_path}")
            return True
        else:
            print("❕ 未匹配任何内容")
            return False
    except Exception as e:
        print(f"❌ 处理失败: {ppt_path} - {e}")
        return False

# =============== 可选调试:输出所有图片 ===============
def print_all_pictures(prs):
    print("📷 所有图片信息(单位:pt):")
    for slide_master in prs.slide_masters:
        print(f"--- 母版 ---")
        for shape in slide_master.shapes:
            print_shape_debug(shape)
        for layout in slide_master.slide_layouts:
            print(f"--- 布局: {layout.name} ---")
            for shape in layout.shapes:
                print_shape_debug(shape)

def print_shape_debug(shape):
    if shape.shape_type == 13:  # PICTURE
        left = shape.left / EMU_TO_PT
        top = shape.top / EMU_TO_PT
        width = shape.width / EMU_TO_PT
        height = shape.height / EMU_TO_PT
        print(f"图片: {shape.name}, 位置=({left:.2f}, {top:.2f}), 大小=({width:.2f}, {height:.2f})")
    elif shape.shape_type == 6:
        for sub_shape in shape.shapes:
            print_shape_debug(sub_shape)

# =============== 主程序入口 ===============
def main():
    root_dir = r"F:\04\6\1"  # 修改为你的目录路径

    if not os.path.exists(root_dir):
        print(f"❌ 目录不存在: {root_dir}")
        return

    print(f"🔍 开始扫描目录: {root_dir}")
    ppt_files = []
    for root, _, files in os.walk(root_dir):
        for file in files:
            if file.lower().endswith('.pptx'):
                ppt_files.append(os.path.join(root, file))

    if not ppt_files:
        print("❗ 未找到任何 PPTX 文件")
        return

    print(f"✅ 共发现 {len(ppt_files)} 个 PPTX 文件")
    modified_count = 0

    for idx, file_path in enumerate(ppt_files, 1):
        print(f"\n[{idx}/{len(ppt_files)}] 处理: {file_path}")
        if process_ppt_file(file_path):
            modified_count += 1

    print(f"\n🎉 完成!共修改 {modified_count}/{len(ppt_files)} 个文件")

if __name__ == "__main__":
    main()

 

版权声明 1. 本网站名称:稻草人笔记   永久网址:https://www.facekun.com
2. 本文链接:写一个测试脚本(批量处理PPT文件母版里面的logo及文本): https://www.facekun.com/arts/1449.html
3. 部分文章内容来源于网络,仅作为学习展示之用,版权归原作者所有
4. 因部分文章网络流转次数较多,已无法追溯至原作者,若遗漏导致侵犯了您的权益,请您来信告知我,确认后会尽快删除。
5. 本站禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
6. 如无特别声明本文即为原创文章仅代表个人观点,版权归《稻草人笔记》所有,欢迎转载,转载请保留原文链接。
THE END
分享
二维码
< <上一篇
下一篇>>