欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

利用Python自動化處理PPT樣式與結構的解決方案

 更新時間:2025年04月28日 09:36:37   作者:東方佑  
PowerPoint(PPT)是職場中常用的辦公工具,但手動設計和調(diào)整樣式往往耗時耗力,本文將介紹一套基于Python的自動化解決方案,通過代碼實現(xiàn)提取PPT樣式,應用樣式到模板和幻燈片增刪與復制,需要的朋友可以參考下

引言

PowerPoint(PPT)是職場中常用的辦公工具,但手動設計和調(diào)整樣式往往耗時耗力。本文將介紹一套基于Python的自動化解決方案,通過代碼實現(xiàn)以下功能:

  • 提取PPT樣式:將PPT的文本格式、顏色、布局等信息保存為JSON文件。
  • 應用樣式到模板:根據(jù)JSON定義的樣式生成新PPT。
  • 幻燈片增刪與復制:靈活調(diào)整PPT結構,滿足動態(tài)內(nèi)容需求。

代碼功能概述

核心功能模塊

  1. 樣式提取與保存

    • 函數(shù):extract_ppt_with_style(ppt_path, output_json)
    • 功能:遍歷PPT的每一頁,提取文本框的字體、顏色、段落對齊方式等樣式信息,并保存為結構化的JSON文件。
  2. 樣式應用與生成

    • 函數(shù):apply_styles_to_ppt(template_path, json_path, output_pptx, data_json_llm)
    • 功能:根據(jù)JSON定義的樣式,將文本內(nèi)容和格式應用到指定模板,生成符合要求的新PPT。
  3. 幻燈片結構管理

    • 函數(shù):copy_slide_and_insert_after、delete_slide、copy_ppt
    • 功能:復制、刪除幻燈片,并根據(jù)需求動態(tài)調(diào)整中間頁的數(shù)量(如擴展或壓縮內(nèi)容頁)。

代碼詳解

1. 提取PPT樣式(extract_ppt_with_style)

def extract_ppt_with_style(ppt_path, output_json):
    prs = Presentation(ppt_path)
    data = []
    for slide_idx, slide in enumerate(prs.slides):
        slide_data = {
            "slide_number": slide_idx + 1,
            "shapes": []
        }
        for shape in slide.shapes:
            if not shape.has_text_frame:
                continue  # 跳過非文本形狀
            text_frame = shape.text_frame
            text_info = {
                "shape_name": shape.name,
                "paragraphs": []
            }
            for paragraph in text_frame.paragraphs:
                para_info = {
                    "alignment": str(paragraph.alignment),
                    "runs": []
                }
                for run in paragraph.runs:
                    run_info = {
                        "text": run.text,
                        "font": {
                            "name": run.font.name,
                            "size": str(run.font.size),
                            "bold": run.font.bold,
                            "italic": run.font.italic,
                            "color": {
                                "type": "theme" if run.font.color.type == MSO_THEME_COLOR else "rgb",
                                "theme_color": run.font.color.theme_color,
                                "rgb": (run.font.color.rgb[0], run.font.color.rgb[1], run.font.color.rgb[2]) if run.font.color.rgb else None
                            }
                        }
                    }
                    para_info["runs"].append(run_info)
                text_info["paragraphs"].append(para_info)
            slide_data["shapes"].append(text_info)
        data.append(slide_data)
    # 保存并壓縮JSON
    with open(output_json, 'w', encoding='utf-8') as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
    data = json_compress(data)
    with open("compress_" + output_json, 'w', encoding='utf-8') as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
    return data
  • 關鍵點
    • 樣式解析:記錄字體名稱、大小、粗體、斜體、顏色(主題色或RGB值)。
    • 結構化存儲:JSON中每一頁(slide)包含多個形狀(shapes),每個形狀包含段落(paragraphs)和文本片段(runs)。
    • 壓縮優(yōu)化json_compress 函數(shù)簡化冗余數(shù)據(jù)(如通用形狀名稱),提升存儲效率。

2. 應用樣式生成PPT(apply_styles_to_ppt)

def apply_styles_to_ppt(template_path, json_path, output_pptx, data_json_llm):
    with open(json_path, 'r', encoding='utf-8') as f:
        data = json.load(f)
    prs = Presentation(template_path)
    for slide_idx, slide in enumerate(prs.slides):
        for shape_idx, shape in enumerate(slide.shapes):
            if not shape.has_text_frame:
                continue
            text_frame = shape.text_frame
            for paragraph_idx, paragraph in enumerate(text_frame.paragraphs):
                for run_idx, run in enumerate(paragraph.runs):
                    run_info = data[slide_idx]["shapes"][shape_idx]["paragraphs"][paragraph_idx]["runs"][run_idx]
                    # 應用文本內(nèi)容
                    run.text = data_json_llm[slide_idx]["shapes"].pop()["paragraphs"]
                    # 應用樣式
                    run.font.name = run_info["font"]["name"]
                    run.font.bold = run_info["font"]["bold"]
                    run.font.italic = run_info["font"]["italic"]
                    # 處理顏色
                    color_data = run_info["font"]["color"]
                    if color_data["type"] == "rgb":
                        r, g, b = color_data["rgb"]
                        run.font.color.rgb = RGBColor(r, g, b)
                    elif color_data["type"] == "theme":
                        theme_color = getattr(MSO_THEME_COLOR, color_data["theme_color"], MSO_THEME_COLOR.ACCENT_1)
                        run.font.color.theme_color = theme_color
    prs.save(output_pptx)
  • 關鍵點
    • 樣式復用:從JSON中讀取字體、顏色等信息,直接應用到模板PPT的對應位置。
    • 動態(tài)內(nèi)容替換:通過 data_json_llm 參數(shù),可結合LLM(如GPT)生成的文本內(nèi)容動態(tài)填充PPT。

3. 幻燈片結構管理

3.1 復制與插入幻燈片

def copy_slide_and_insert_after(prs, source_index, target_index):
    source_slide = prs.slides[source_index]
    new_slide = prs.slides.add_slide(source_slide.slide_layout)
    # 復制形狀和關系
    for shape in source_slide.shapes:
        new_el = deepcopy(shape.element)
        new_slide.shapes._spTree.insert_element_before(new_el, 'p:extLst')
    # 調(diào)整位置
    slides = list(prs.slides._sldIdLst)
    new_slide_id = slides.pop()
    slides.insert(target_index + 1, new_slide_id)
    prs.slides._sldIdLst[:] = slides
  • 功能:復制指定幻燈片并插入到目標位置后,保持布局和元素一致性。

3.2 刪除幻燈片

def delete_slide(prs, slide_index):
    if slide_index < 0 or slide_index >= len(prs.slides):
        print("無效的幻燈片索引")
        return
    xml_slides = list(prs.slides._sldIdLst)
    slides_id_to_delete = xml_slides[slide_index]
    prs.slides._sldIdLst.remove(slides_id_to_delete)
  • 功能:通過移除幻燈片ID實現(xiàn)刪除,避免直接操作可能導致的格式錯誤。

3.3 動態(tài)擴展/壓縮PPT頁數(shù)

def copy_ppt(pages, template_path="template.pptx", modified_path="modified.pptx"):
    prs = Presentation(template_path)
    copy_pages = pages - 2  # 排除首尾固定頁
    center_pages = len(prs.slides) - 2
    if copy_pages < center_pages:
        # 刪除多余頁
        for _ in range(center_pages - copy_pages):
            delete_slide(prs, len(prs.slides)-1)
    else:
        # 復制中間頁
        n = (copy_pages // center_pages) * center_pages
        for _ in range(n):
            for i in range(1, center_pages+1):
                copy_slide_and_insert_after(prs, i, i)
    prs.save(modified_path)
  • 應用場景:根據(jù)需求動態(tài)調(diào)整中間頁的數(shù)量(如擴展到5頁或壓縮到3頁),保持首尾頁固定。

使用示例

場景1:生成符合樣式的PPT

# 1. 提取原始PPT的樣式
extract_ppt_with_style("template.pptx", "output_styles.json")

# 2. 生成新內(nèi)容(例如通過LLM)
llm_json = [...]  # LLM生成的文本內(nèi)容

# 3. 應用樣式生成最終PPT
apply_styles_to_ppt("template.pptx", "output_styles.json", "new_ppt.pptx", llm_json)

場景2:動態(tài)調(diào)整PPT頁數(shù)

# 假設原始模板有5頁(首尾固定,中間3頁)
copy_ppt(pages=7, template_path="template.pptx")  # 最終生成7頁:1(首)+5(中間復制)+1(尾)

應用場景

  • 企業(yè)報告自動化:根據(jù)數(shù)據(jù)動態(tài)生成季度報告,保持統(tǒng)一格式。
  • 培訓材料生成:批量創(chuàng)建多套PPT,僅需調(diào)整中間內(nèi)容頁。
  • 營銷素材管理:快速復制產(chǎn)品介紹模板,替換文本和樣式。

總結

本文提供的代碼庫實現(xiàn)了從PPT樣式提取、動態(tài)內(nèi)容生成到結構管理的全流程自動化。開發(fā)者可通過以下方式進一步優(yōu)化:

  • 集成LLM:將文本生成部分與GPT等模型結合,實現(xiàn)從內(nèi)容到樣式的全自動化。
  • 圖形處理:擴展對圖片、圖表樣式的解析與應用。
  • 用戶界面:封裝為GUI工具,降低使用門檻。

通過這種方式,企業(yè)可大幅減少PPT制作時間,專注于內(nèi)容創(chuàng)新而非格式調(diào)整。

from pptx import Presentation
from pptx.enum.dml import MSO_THEME_COLOR
from pptx.dml.color import RGBColor
from copy import deepcopy
import json


def extract_ppt_with_style(ppt_path, output_json):
    prs = Presentation(ppt_path)
    data = []

    for slide_idx, slide in enumerate(prs.slides):
        slide_data = {
            "slide_number": slide_idx + 1,
            "shapes": []
        }
        for shape in slide.shapes:
            if not shape.has_text_frame:
                continue  # 跳過非文本形狀

            text_frame = shape.text_frame
            text_info = {
                "shape_name": shape.name,
                "paragraphs": []
            }

            for paragraph in text_frame.paragraphs:
                para_info = {
                    "alignment": str(paragraph.alignment),
                    "runs": []
                }
                for run in paragraph.runs:
                    run_info = {
                        "text": run.text,
                        "font": {
                            "name": run.font.name,
                            "size": str(run.font.size) if run.font.size else None,
                            "bold": run.font.bold,
                            "italic": run.font.italic,
                            "color": {
                                "type": "theme" if run.font.color.type == MSO_THEME_COLOR else "rgb",
                                "theme_color": run.font.color.theme_color,
                                "rgb": (run.font.color.rgb[0], run.font.color.rgb[1],
                                        run.font.color.rgb[2]) if run.font.color.rgb else None
                            }
                        },
                        # "highlight_color": str(run.highlight_color)  # 修改:從 run 而非 run.font 獲取
                    }
                    para_info["runs"].append(run_info)
                text_info["paragraphs"].append(para_info)
            slide_data["shapes"].append(text_info)
        data.append(slide_data)

    with open(output_json, 'w', encoding='utf-8') as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
    data = json_compress(data)

    with open("compress" + "_" + output_json, 'w', encoding='utf-8') as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
    return data


def apply_styles_to_ppt(template_path, json_path, output_pptx, data_json_llm):
    with open(json_path, 'r', encoding='utf-8') as f:
        data = json.load(f)

    prs = Presentation(template_path)

    for slide_idx, slide in enumerate(prs.slides):

        for shape_idx, shape in enumerate(slide.shapes):
            if not shape.has_text_frame:
                continue  # 跳過非文本形狀

            text_frame = shape.text_frame

            for paragraph_idx, paragraph in enumerate(text_frame.paragraphs):

                for run_idx, run in enumerate(paragraph.runs):
                    run_info = data[slide_idx]["shapes"][shape_idx]["paragraphs"][paragraph_idx]["runs"][run_idx]
                    text = data_json_llm[slide_idx]["shapes"].pop()
                    # run.text = run_info["text"]
                    run.text = text["paragraphs"]
                    run.font.name = run_info["font"]["name"]
                    # run.font.size = run_info["font"]["size"]
                    run.font.bold = run_info["font"]["bold"]
                    # run.font.size = run_info["font"]["size"]
                    run.font.italic = run_info["font"]["italic"]

                    # 假設 run_data 是從 JSON 中讀取的字典
                    color_data = run_info["font"]["color"]

                    if color_data["type"] == "rgb":
                        # 解析 RGB 值
                        r_str, g_str, b_str = color_data["rgb"]
                        r = r_str
                        g = g_str
                        b = b_str
                        run.font.color.rgb = RGBColor(r, g, b)
                    elif color_data["type"] == "hex":
                        # 解析十六進制顏色
                        hex_color = color_data["hex"].lstrip("#")
                        r = int(hex_color[0:2], 16)
                        g = int(hex_color[2:4], 16)
                        b = int(hex_color[4:6], 16)
                        run.font.color.rgb = RGBColor(r, g, b)
                    elif color_data["type"] == "theme":
                        # 使用主題顏色(如 MSO_THEME_COLOR.ACCENT_1)
                        theme_color_name = color_data["theme_color"]
                        theme_color = getattr(MSO_THEME_COLOR, theme_color_name, MSO_THEME_COLOR.ACCENT_1)
                        run.font.color.theme_color = theme_color
                    else:
                        # 默認顏色(黑色)
                        run.font.color.rgb = RGBColor(0, 0, 0)

    prs.save(output_pptx)


def json_compress(json_data):
    for slide in json_data:
        for shape in slide["shapes"]:
            if "Shape" in shape["shape_name"]:
                shape["paragraphs"] = {}
            else:
                for paragraph in shape["paragraphs"]:
                    for run in paragraph["runs"]:
                        shape["paragraphs"] = run["text"]
    json_data_new = []
    for slide in json_data:
        shapes = {"shapes": [], 'slide_number': slide['slide_number']}
        for shape in slide["shapes"]:
            if "Shape" in shape["shape_name"]:
                shape["paragraphs"] = {}
            else:
                shapes["shapes"].append(shape)
        json_data_new.append(shapes)

    return json_data_new


def copy_slide_and_insert_after(prs, source_index, target_index):
    """
    復制源幻燈片并將其插入到目標幻燈片的后面。

    :param prs: Presentation 對象
    :param source_index: 源幻燈片的索引(從0開始)
    :param target_index: 目標幻燈片的索引(新幻燈片將插入到其后面)
    """
    # 獲取源幻燈片
    source_slide = prs.slides[source_index]

    # 創(chuàng)建新幻燈片(使用相同的布局)
    new_slide_layout = source_slide.slide_layout
    new_slide = prs.slides.add_slide(new_slide_layout)

    # 復制所有形狀(包括文本框、圖片、圖表等)
    for shape in source_slide.shapes:
        el = shape.element
        new_el = deepcopy(el)
        new_slide.shapes._spTree.insert_element_before(new_el, 'p:extLst')

    # 復制關系(如超鏈接、注釋等)
    for rel in source_slide.part.rels.values():
        if "notesSlide" not in rel.reltype:  # 排除注釋頁
            # 使用 relate_to 方法而不是 add 方法
            new_slide.part.relate_to(
                rel._target,
                rel.reltype
            )

    # 調(diào)整幻燈片順序:將新幻燈片移動到目標位置的后面
    slides = list(prs.slides._sldIdLst)
    new_position = target_index + 1  # 插入到目標幻燈片的后面
    # 移除剛添加的新幻燈片(默認在最后)
    new_slide_id = slides.pop()
    # 插入到正確的位置
    slides.insert(new_position, new_slide_id)
    prs.slides._sldIdLst[:] = slides


def delete_slide(prs, slide_index):
    # prs = Presentation(template_path)
    """
    刪除給定索引處的幻燈片。

    :param prs: Presentation 對象
    :param slide_index: 要刪除的幻燈片的索引(從0開始)
    """
    # 確保索引在范圍內(nèi)
    if slide_index < 0 or slide_index >= len(prs.slides):
        print("無效的幻燈片索引")
        return
    # 獲取幻燈片ID列表
    xml_slides = list(prs.slides._sldIdLst)

    # 根據(jù)索引找到對應的幻燈片ID并移除
    slides_id_to_delete = xml_slides[slide_index]
    prs.slides._sldIdLst.remove(slides_id_to_delete)

    # 保存修改后的PPT
    # prs.save(modified_path)


def copy_ppt(pages, template_path="template.pptx", source_index=1, target_index=1,
             modified_path="modified_example.pptx"):
    prs = Presentation(template_path)
    copy_pages, center_pages = pages - 2, len(prs.slides) - 2
    if copy_pages != center_pages:

        if copy_pages < center_pages:
            start_page_index = center_pages
            for _ in range(center_pages - copy_pages):
                delete_slide(prs, start_page_index)
                start_page_index -= 1
        else:
            n = (copy_pages // center_pages) * center_pages
            m = (copy_pages // center_pages + 1) * center_pages - copy_pages
            start_page_index = center_pages
            for _ in range(n):
                for i in range(1, center_pages + 1):
                    copy_slide_and_insert_after(prs, i, start_page_index)
                    start_page_index += 1
            if m:

                for _ in range(m):
                    delete_slide(prs, start_page_index)
                    start_page_index -= 1

    prs.save(modified_path)


if __name__ == '__main__':
    # 使用示例
    # data=extract_ppt_with_style("template.pptx", "output_styles.json")
    #
    # prompt_text=f"""
    # # ppt json 模版
    # {data}
    # # 模版使用說明
    # - 每個 slide  的  shapes 的 結構 (元素個數(shù))是不可變得
    # - 每個 slide  的  shapes 里面的字典的key 不可變 值是可以變 的
    # - 第一 slide  是不可被復制的  且 必須在第一個位置   但是內(nèi)容 是可變的   slide_number 也是可變的
    # - 最后一個 slide 也是不可復制的 且 必須在最后一個位置  但是內(nèi)容 是可變的  slide_number 也是可變的
    # - 中簡的  slide  是可以被復制的 但是順序不能改變
    #     - 例如  中間 有 兩個 slide  2,3   如果你的ppt 中間需要5個 slide  那么復制 順序是  2,3,2,3,2 復制后可以改其他slide_number 名字
    # # 明白上述模版使用要求之后  請 完成主題為:人工智能改變世界的ppt大綱 并且 使用上述模版 生成對應的json
    # """
    llm_json =[]
    # copy_ppt(len(llm_json))
    data = extract_ppt_with_style("modified_example.pptx", "output_styles.json")

    apply_styles_to_ppt("modified_example.pptx", "output_styles.json", "new_ppt.pptx", llm_json)

到此這篇關于利用Python自動化處理PPT樣式與結構的解決方案的文章就介紹到這了,更多相關Python自動化處理PPT內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論