项目工坊 | 高效自动化:Python-pptx生成ppt全流程详解(呕心沥血版)

目录

1摘要

2目的:python-pptx设计模板

2模块安装

3PPT结构与python接口关系

4初认识python-pptx

4.1新建一个PPT文件,并重命名

4.1.1简单示例

4.1.2扩展封装成函数

4.2查看PPT总页数

4.2.1简单示例

4.2.2扩展封装成函数

4.3项目开始-python新建PPT

4.3.1创建项目

4.3.2项目结构说明

4.3.3完善office_ppt_ser.py

4.3.4完善main.py

5文本框

5.1函数-插入文本框

5.1.1导入模块

5.1.2定义titlebox函数

5.1.3打开PPT文件并选择幻灯片

5.1.4添加文本框

5.1.5写入文本内容

5.1.6设置文本颜色

5.1.7设置文本对齐方式

5.1.8设置字体样式

5.1.9保存PPT文件

5.1.10调用函数

5.2项目新增文本框

5.2.1完善office_ppt_ser.

5.2.2完善main.py

5.2.3项目效果

6形状

6.1函数-插入长方形

6.1.1导入库

6.1.2定义 shape_rectangle 函数

6.1.3打开 PPT 文件并选择幻灯片

6.1.4 添加矩形框

6.1.5设置矩形框的旋转角度

6.1.6设置矩形框的填充颜色

6.1.7设置矩形框为背景(可选)

6.1.8设置矩形框的边框宽度

6.1.9保存 PPT 文件

6.1.10调用函数

6.2项目新增形状

6.2.1完善office_ppt_ser.py

6.2.2完善main.py

6.2.3项目效果

7图片

7.1函数-插入图片

7.1.1导入模块

7.1.2定义 add_picture 函数

7.1.3加载 PowerPoint 文件

7.1.4获取指定幻灯片

7.1.5设置图片的位置和大小

7.1.6插入图片

7.1.7保存 PowerPoint 文件

7.1.8调用函数

7.2项目新增图片

7.2.1完善office_ppt_ser.py

7.2.2完善main.py

7.2.3效果展示

8表格

8.1函数-插入表格

8.1.1导入库

8.1.2定义函数 table_Nrows_17cols

8.1.3打开 PPT 文件并选择幻灯片

8.1.4确定表格的行数和列数

8.1.5计算表格的总宽度和高度

8.1.6添加表格到幻灯片

8.1.7填充表头和数据

8.1.8设置行高

8.1.9修改表格样式

8.1.10保存 PPT 文件

8.1.11调用函数

8.2项目新增表格

8.2.1完善office_ppt_ser.py

8.2.2完善main.py

8.2.3效果展示

9图表

9.1函数-插入柱状图

9.1.1导入库

9.1.2定义颜色集合

9.1.3定义函数 chart_clustered_bar_self_color

9.1.4调用函数

9.2项目新增柱状图

9.2.1完善office_ppt_ser.py

9.2.2完善main.py

9.3.4效果展示

10项目代码main.py升级

10.1提取函数参数

10.2数据参数化

10.3封装为函数

10.4调用函数

11总结


1摘要

本文详细介绍了如何利用 Python 的 python-pptx 模块来自动化生成 PowerPoint 报告。文章通过一个具体的案例,展示了如何从零开始构建一个自动化生成 PPT 的工具,涵盖了从安装模块、PPT 结构分析、基础操作(如新建 PPT、添加幻灯片、插入文本框、形状、图片、表格和图表)到最终生成完整报告的整个过程。

2目的:python-pptx设计模板

场景:张三接到领导的任务,负责每周整理销售周报,格式如下图所示。这项工作繁琐且耗时:他需要从多个 Excel 表格中提取并整理数据,最终生成完整的周报。起初尚能应付,但随着时间的推移,他发现每次都是重复性操作。这种低效且机械的工作方式不仅耗费精力,还容易出错,给张三带来了巨大压力。

为了实现张三工作的全面自动化,可以分以下三个步骤完成:

  1. 第一步:利用 Python 设计 PPT 模板,并在模板中预留数据接口,确保数据能够动态填充到指定位置。

  2. 第二步:通过 Python 爬虫技术从指定数据源(如网页或数据库)爬取数据,或从 Excel 表格中收集数据,并使用 Pandas 模块对数据进行分析,生成 PPT 所需的结构化数据。

  3. 第三步:将第一步和第二步整合为一个完整的自动化脚本,实现从数据收集到 PPT 生成的全程自动化。

本文将从 Python-pptx 模块的底层原理入手,结合 PPT 的核心结构,重点讲解第1个步骤的实现方法

2模块安装

模块的安装方法与常规安装一致,使用以下命令即可:

pip install python-pptx

如不会安装可以参考另一篇文章《PyCharm 与 Anaconda 下载安装及 PyCharm 新建项目指南》

3PPT结构与python接口关系

通过对上述 PPT 模板的分析,其核心设计主要包含以下 6 个要素,以及与 python-pptx 接口的对应关系:

  1. 母版设计(幻灯片布局),功能:定义幻灯片的整体结构和布局。对应接口:SlideLayout 类

  2. 文本框,功能:用于填充标题、正文等文本内容。对应接口:TextFrame 类

  3. 形状,功能:包括矩形、圆形等图形元素,用于装饰或强调信息。对应接口:Shape 类

  4. 图片,功能:插入图像以增强视觉效果。对应接口:Picture 类

  5. 表格,功能:用于展示结构化数据。对应接口:Table 类

  6. 图表,功能:通过可视化形式呈现数据趋势或对比。对应接口:Chart 类

PPT 的结构与 python-pptx 接口的对应关系如下图所示。

此外,python-pptx 还提供了其他接口,例如:幻灯片母版:SlideMaster 类,备注:NotesSlide 类,超链接:Hyperlink 类。由于本次模板设计中未涉及这些功能,因此不再展开讲解。本文将重点围绕上述 6 种核心接口进行详细说明。

4初认识python-pptx

在日常制作PPT时,我们通常会进行一些基础操作,例如新建一个PPT文件对文件进行重命名,以及查看当前PPT的总页数。这些操作虽然简单,但却是PPT制作过程中不可或缺的步骤。接下来,我们将使用 python-pptx 库,通过代码逐一实现这些功能,展示如何用编程的方式高效完成这些常规任务,涉及Presentation类、SlideLayout类、Slide类。

4.1新建一个PPT文件,并重命名

4.1.1简单示例

from pptx import Presentation  # 引入python-pptx中的Presentation类

template = r'F:\070_Digitize数字化\ppt自动化测试\模版.pptx'
prs = Presentation(template)  # 用Presentation读取PPT模板
prs.slides.add_slide(prs.slide_layouts[0])  # 模板template中增加幻灯片,引用prs.slide_layouts[0]代表母版第1个幻灯片
new_ppt_path = r'F:\070_Digitize数字化\ppt自动化测试\新建PPT.pptx'
prs.save(new_ppt_path)  # 对ppt保存

运行效果在那个文件夹下会有1个PPT,名叫《新建PPT.pptx》,如下:

代码解读

 1、引入 Presentation 类

from pptx import Presentation  # 引入python-pptx中的Presentation类
  • python-pptx 是一个用于创建和更新 PowerPoint (.pptx) 文件的 Python 库。

  • Presentation 类是 python-pptx 中的核心类,用于表示一个 PowerPoint 文件。

2、定义模板文件路径

template = r'F:\070_Digitize数字化\ppt自动化测试\模版.pptx'
  • template 变量存储了模板文件的路径。r 前缀表示原始字符串,避免转义字符的影响。

  • 这个路径指向一个现有的 PowerPoint 模板文件。

3、读取模板文件

prs = Presentation(template)  # 用Presentation读取PPT模板
  • Presentation(template) 使用 Presentation 类加载指定路径的 PowerPoint 文件。

  • prs 是一个 Presentation 对象,代表整个 PowerPoint 文件。

4、添加新幻灯片

prs.slides.add_slide(prs.slide_layouts[0])  # 模板template中增加幻灯片,引用prs.slide_layouts[0]代表母版第1个幻灯片
  • prs.slide_layouts 是一个列表,包含了模板中定义的所有幻灯片布局(母版幻灯片)。

  • prs.slides.add_slide() 方法使用指定的布局向 PowerPoint 文件中添加一张新的幻灯片。

  • prs.slide_layouts[0] 表示使用模板中的第一个幻灯片布局。引用prs.slide_layouts[0]代表母版第1个幻灯片,给的测试模版PPT-《模版.pptx》(附件已上传文件),里面的模板有三页如下图,若是改写成prs.slides.add_slide(prs.slide_layouts[3])是会报错的,意思:尝试访问一个不存在的幻灯片布局索引

4.1.2扩展封装成函数

将上述代码封装为函数,便于复用。如果不清楚如何将代码重构为函数或类,可以参考上一篇文章《Python代码变形记:一个简单案例的N次重构,函数与类的华丽转身》,以下代码定义了一个函数 new_ppt_add_slide,用于基于指定的 PowerPoint 模板创建新的 PPT 文件,并添加指定布局的幻灯片。

import os  # 文件类模块

from pptx import Presentation  # 引入python-pptx中的Presentation类


def new_ppt_add_slide(template, page_num=[0], PPT_Name='新建 Microsoft PowerPoint 演示文稿.pptx',
                      save_path='C:\\Users\\XXXX\\Desktop'):
    """
    :param template: PPT模板
    :param page_num: 列表,代表PPT模板里面的幻灯片序号,从0开始
    :param PPT_Name: PPT名字
    :param save_path: 保存路径
    :return:返回新的PPT路径
    """
    if os.path.isdir(save_path):  # save_path是目录
        new_ppt_path = os.path.join(save_path, PPT_Name)  # 将保存路径和PPT名字拼接在一起
    else:
        new_ppt_path = PPT_Name  # save_path不是目录,就不需要拼接
    prs = Presentation(template)  # 用Presentation读取PPT模板
    for i in page_num:  # 遍历需要增加的页数
        prs.slides.add_slide(prs.slide_layouts[i])  # 模板template中增加幻灯片
    prs.save(new_ppt_path)  # 对ppt保存
    return new_ppt_path

值得注意的是

①这边增加一个判定“检查保存路径”

if os.path.isdir(save_path):  # save_path是目录
    new_ppt_path = os.path.join(save_path, PPT_Name)  # 将保存路径和PPT名字拼接在一起
else:
    new_ppt_path = PPT_Name  # save_path不是目录,就不需要拼接
  • 如果 save_path 是一个有效的目录路径,则将 PPT_Name 拼接到 save_path 后面,形成完整的新PPT文件路径。

  • 如果 save_path 不是一个有效的目录路径,则直接将 PPT_Name 作为新PPT文件的路径。

②通过 page_num 参数(列表形式),支持一次性添加多张幻灯片。

for i in page_num:  # 遍历需要增加的页数
    prs.slides.add_slide(prs.slide_layouts[i])  # 添加幻灯片

4.2查看PPT总页数

4.2.1简单示例

from pptx import Presentation  # 引入python-pptx中的Presentation类

template = r'F:\070_Digitize数字化\ppt自动化测试\模版.pptx'
prs = Presentation(template) # 用Presentation读取PPT模板
slide_number = len(prs.slides)#利用slides属性,用len读取当前有多少PPT
print(slide_number)

运行结果:0(说明模版里面没有1页PPT)

代码解读:

1、统计幻灯片数量

slide_number = len(prs.slides) # 利用slides属性,用len读取当前有多少PPT
  • prs.slides 是 Presentation 对象的一个属性,表示当前 PowerPoint 文件中的所有幻灯片。

  • len(prs.slides) 返回幻灯片的数量,并将其赋值给 slide_number

2、打印幻灯片数量

print(slide_number)
  • 使用 print() 函数输出幻灯片数量。

4.2.2扩展封装成函数

将上述代码封装为函数,便于复用。

from pptx import Presentation  # 引入python-pptx中的Presentation类

def ppt_slide_number(ppt_script):
    prs = Presentation(ppt_script)
    slide_number = len(prs.slides)
    return slide_number

这个函数的作用是读取一个PPT文件,并返回该文件中幻灯片的数量。它的核心步骤是:使用 Presentation 类加载PPT文件;通过 prs.slides 获取所有幻灯片的列表;使用 len() 函数计算幻灯片的数量并返回。

4.3项目开始-python新建PPT

项目启动指南:创建《销售周报.pptx》报告

4.3.1创建项目

  • 项目初始化,请新建一个Python项目(项目名称可自定义), 可以参考另一篇文章《PyCharm 与 Anaconda 下载安装及 PyCharm 新建项目指南》
  • 获取项目资源,PPT模板素材已准备就绪,通过网盘分享的文件:素材链接: https://pan.baidu.com/s/1sZcvVHkJzQkMGeaEv_I6Hg?pwd=ia6w 提取码: ia6w

  • 模板说明,下载的PPT模板包含以下特点:

pycharm新建项目如下图

将下载的《PPT模板.pptx》放在该项目下,如下图

新建py文件office_ppt_ser.py

4.3.2项目结构说明

 项目文件结构如下,PPT模板文件:用于存储预设的PPT模板样式。main.py:主程序入口文件,包含程序的主要执行逻辑。office_ppt_ser.py:PPT服务模块,封装了所有与PPT操作相关的功能函数。main.py引用了office_ppt_series.py的函数,关于函数之间相互引用可以参考文章《Python 中文件夹、包、模块定义及函数或类模块引用》在接下来的开发中,将集中精力对 main.py 和 office_ppt_ser.py 进行功能完善和代码优化。

4.3.3完善office_ppt_ser.py

完善office_ppt_ser.py,将上述写的函数ppt_slide_number和new_ppt_add_slide均复制到office_ppt_ser.py文件中

import os  # 文件类模块

from pptx import Presentation  # 引入python-pptx中的Presentation类


def new_ppt_add_slide(template, page_num=[0], PPT_Name='新建 Microsoft PowerPoint 演示文稿.pptx',
                      save_path='C:\\Users\\weidong.guo\\Desktop'):
    """
    :param template: PPT模板
    :param page_num: 列表,代表PPT模板里面的幻灯片序号,从0开始
    :param PPT_Name: PPT名字
    :param save_path: 保存路径
    :return:返回新的PPT路径
    """
    if os.path.isdir(save_path):  # save_path是目录
        new_ppt_path = os.path.join(save_path, PPT_Name)  # 将保存路径和PPT名字拼接在一起
    else:
        new_ppt_path = PPT_Name  # save_path不是目录,就不需要拼接
    prs = Presentation(template)  # 用Presentation读取PPT模板
    for i in page_num:  # 遍历需要增加的页数
        prs.slides.add_slide(prs.slide_layouts[i])  # 模板template中增加幻灯片
    prs.save(new_ppt_path)  # 对ppt保存
    return new_ppt_path


def ppt_slide_number(ppt_script):
    prs = Presentation(ppt_script)
    slide_number = len(prs.slides)
    return slide_number



4.3.4完善main.py

from office_ppt_ser import new_ppt_add_slide
from office_ppt_ser import ppt_slide_number


def main():
    new_ppt = r'PPT模版.pptx'
    new_ppt_path = new_ppt_add_slide(new_ppt, page_num=[1], PPT_Name='销售周报.pptx')
    print(new_ppt_path)

    slide_number = ppt_slide_number(new_ppt_path)
    print(new_ppt_path)


# 按装订区域中的绿色按钮以运行脚本。
if __name__ == '__main__':
    main()

运行main.py,结果在该项目文件下会自动生成一个PPT《销售周报.pptx》,里面含有1页空白PPT如下

分享上述完整代码路径:
链接: https://pan.baidu.com/s/1CnUIhopJL7LGojlvfEILVg?pwd=c2t8 提取码: c2t8

5文本框

在新建的PPT文档中,我们需要使用TextFrame类来插入和编辑文本内容。具体操作如下:首先通过text_frame = shape.text_frame来访问文本框对象,然后使用text_frame.text = "Some text"语句即可添加文本内容。在实际应用中,我们通常需要对文本框进行多项格式设置,主要包括:调整文本框位置、设置字体样式、定义字号大小、配置文本颜色、选择对齐方式以及应用加粗效果等排版设计。接下来将根据一个函数-插入文本框进行详细讲解。

5.1函数-插入文本框

from pptx import Presentation
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
from pptx.util import Cm
from pptx.util import Pt


def titlebox(ppt_script, page_num=0, content_text='Backup', font_size=18, left=0.55, top=2.12,
             width=25.81, height=1.08, font_bold=True, font_name='方正兰亭黑_GBK', font_color='',
             alignment='左对齐',
             word_wrap=False):
    """
    参数:
        ppt_script (str): PPT文件路径。
        page_num (int): 幻灯片页码(从0开始)。
        content_text (str): 文本框内容。
        font_size (int): 字体大小(单位:磅)。
        left (float): 文本框左上角的水平位置(单位:厘米)。
        top (float): 文本框左上角的垂直位置(单位:厘米)。
        width (float): 文本框宽度(单位:厘米)。
        height (float): 文本框高度(单位:厘米)。
        font_bold (bool): 是否加粗。
        font_name (str): 字体名称。
        font_color (str): 字体颜色(支持'blue', 'green', 'red', 'yellow', 'orange', 'white', 'gray1', 'black')。
        alignment (str): 对齐方式(支持'左对齐', '居中')。
        word_wrap (bool): 是否自动换行。
        return: 
    """
    # ppt_script=r'C:\Users\hp\Desktop\汇总拆分\111.pptx'
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    # 在指定位置添加文本框
    textbox = slide.shapes.add_textbox(Cm(left), Cm(top), Cm(width), Cm(height))
    tf = textbox.text_frame
    tf.word_wrap = word_wrap
    # 在文本框中写入文字
    # 题目
    para = tf.paragraphs[0]  # 新增段落
    para.text = content_text  # 向段落写入文字
    if font_color == 'blue':
        para.font.color.rgb = RGBColor(0, 30, 80)  # 蓝色
    elif font_color == 'green':
        para.font.color.rgb = RGBColor(0, 176, 80)  # 绿色
    elif font_color == 'red':
        para.font.color.rgb = RGBColor(255, 0, 0)  # 红色
    elif font_color == 'yellow':
        para.font.color.rgb = RGBColor(255, 255, 0)  # 红色
    elif font_color == 'orange':
        para.font.color.rgb = RGBColor(255, 192, 0)  # 红色
    elif font_color == 'white':
        para.font.color.rgb = RGBColor(255, 255, 255)  # 红色
    elif font_color == 'gray1':
        para.font.color.rgb = RGBColor(182, 191, 197)  # 红色
    else:
        para.font.color.rgb = RGBColor(0, 0, 0)  # 黑色
    if alignment == '左对齐':
        para.alignment = PP_ALIGN.LEFT
    else:
        para.alignment = PP_ALIGN.CENTER  # 居中

    # 设置字体
    font = para.font
    font.name = font_name  # 字体类型
    font.bold = font_bold  # 加粗
    font.size = Pt(font_size)  # 大小

    prs.save(ppt_script)  # 对ppt保存


ppt_script = '销售周报.pptx'
titlebox(ppt_script)

接下来对上述函数一一解读

5.1.1导入模块

from pptx import Presentation
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
from pptx.util import Cm
from pptx.util import Pt
  • Presentation:用于创建或打开PPT文件。

  • RGBColor:用于设置文本颜色。

  • PP_ALIGN:用于设置文本对齐方式。

  • CmPt:用于设置尺寸单位(厘米和磅)。

5.1.2定义titlebox函数

def titlebox(ppt_script, page_num=0, content_text='Backup', font_size=18, left=0.55, top=2.12,
             width=25.81, height=1.08, font_bold=True, font_name='方正兰亭黑_GBK', font_color='',
             alignment='左对齐', word_wrap=False):
  • 参数说明:

    • ppt_script:PPT文件路径。

    • page_num:幻灯片页码(默认第1页)。

    • content_text:文本框内容(默认'Backup')。

    • font_size:字体大小(默认18磅)。

    • lefttop:文本框左上角的坐标(默认0.55cm和2.12cm)。

    • widthheight:文本框的宽度和高度(默认25.81cm和1.08cm)。

    • font_bold:是否加粗(默认True)。

    • font_name:字体名称(默认'方正兰亭黑_GBK')。

    • font_color:字体颜色(默认黑色)。

    • alignment:对齐方式(默认左对齐)。

    • word_wrap:是否自动换行(默认False)。

5.1.3打开PPT文件并选择幻灯片

prs = Presentation(ppt_script)
slide = prs.slides[page_num]
  • 打开指定路径的PPT文件,并选择指定页码的幻灯片。

5.1.4添加文本框

textbox = slide.shapes.add_textbox(Cm(left), Cm(top), Cm(width), Cm(height))
tf = textbox.text_frame
tf.word_wrap = word_wrap
  • word_wrap控制文本是否自动换行。

  • 在幻灯片上添加一个文本框,并设置其位置和大小。如何查看文本框的位置和大小如下

5.1.5写入文本内容

para = tf.paragraphs[0]  # 新增段落
para.text = content_text  # 向段落写入文字
  • 在文本框中写入指定的文本内容。

5.1.6设置文本颜色

if font_color == 'blue':
    para.font.color.rgb = RGBColor(0, 30, 80)  # 蓝色
elif font_color == 'green':
    para.font.color.rgb = RGBColor(0, 176, 80)  # 绿色
elif font_color == 'red':
    para.font.color.rgb = RGBColor(255, 0, 0)  # 红色
elif font_color == 'yellow':
    para.font.color.rgb = RGBColor(255, 255, 0)  # 黄色
elif font_color == 'orange':
    para.font.color.rgb = RGBColor(255, 192, 0)  # 橙色
elif font_color == 'white':
    para.font.color.rgb = RGBColor(255, 255, 255)  # 白色
elif font_color == 'gray1':
    para.font.color.rgb = RGBColor(182, 191, 197)  # 灰色
else:
    para.font.color.rgb = RGBColor(0, 0, 0)  # 黑色
  • 根据font_color参数设置文本颜色。

5.1.7设置文本对齐方式

if alignment == '左对齐':
    para.alignment = PP_ALIGN.LEFT
else:
    para.alignment = PP_ALIGN.CENTER  # 居中

5.1.8设置字体样式

font = para.font
font.name = font_name  # 字体类型
font.bold = font_bold  # 加粗
font.size = Pt(font_size)  # 大小
  • 设置字体名称、加粗状态和字体大小。

5.1.9保存PPT文件

prs.save(ppt_script)  # 对ppt保存
  • 保存修改后的PPT文件。

5.1.10调用函数

ppt_script = '销售周报.pptx'
titlebox(ppt_script)
  • 调用titlebox函数,在销售周报.pptx中插入默认样式的文本框。

效果如下

5.2项目新增文本框

5.2.1完善office_ppt_ser.

项目将在 4.3节项目开始的基础上继续推进,进一步完善代码,增加新增文本框的功能。具体实现方式是将上述函数迁移至 office_ppt_ser.py 文件中。将上述函数迁移至 office_ppt_ser.py 文件中。

office_ppt_ser.py如下

import os  # 文件类模块

from pptx import Presentation
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
from pptx.util import Cm
from pptx.util import Pt


def new_ppt_add_slide(template, page_num=[0], PPT_Name='新建 Microsoft PowerPoint 演示文稿.pptx',
                      save_path='C:\\Users\\weidong.guo\\Desktop'):
    """
    :param template: PPT模板
    :param page_num: 列表,代表PPT模板里面的幻灯片序号,从0开始
    :param PPT_Name: PPT名字
    :param save_path: 保存路径
    :return:返回新的PPT路径
    """
    if os.path.isdir(save_path):  # save_path是目录
        new_ppt_path = os.path.join(save_path, PPT_Name)  # 将保存路径和PPT名字拼接在一起
    else:
        new_ppt_path = PPT_Name  # save_path不是目录,就不需要拼接
    prs = Presentation(template)  # 用Presentation读取PPT模板
    for i in page_num:  # 遍历需要增加的页数
        prs.slides.add_slide(prs.slide_layouts[i])  # 模板template中增加幻灯片
    prs.save(new_ppt_path)  # 对ppt保存
    return new_ppt_path


def ppt_slide_number(ppt_script):
    prs = Presentation(ppt_script)
    slide_number = len(prs.slides)
    return slide_number


def titlebox(ppt_script, page_num=0, content_text='Backup', font_size=18, left=0.55, top=2.12,
             width=25.81, height=1.08, font_bold=True, font_name='方正兰亭黑_GBK', font_color='',
             alignment='左对齐',
             word_wrap=False):
    """
    参数:
        ppt_script (str): PPT文件路径。
        page_num (int): 幻灯片页码(从0开始)。
        content_text (str): 文本框内容。
        font_size (int): 字体大小(单位:磅)。
        left (float): 文本框左上角的水平位置(单位:厘米)。
        top (float): 文本框左上角的垂直位置(单位:厘米)。
        width (float): 文本框宽度(单位:厘米)。
        height (float): 文本框高度(单位:厘米)。
        font_bold (bool): 是否加粗。
        font_name (str): 字体名称。
        font_color (str): 字体颜色(支持'blue', 'green', 'red', 'yellow', 'orange', 'white', 'gray1', 'black')。
        alignment (str): 对齐方式(支持'左对齐', '居中')。
        word_wrap (bool): 是否自动换行。
        return:
    """
    # ppt_script=r'C:\Users\hp\Desktop\汇总拆分\111.pptx'
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    # 在指定位置添加文本框
    textbox = slide.shapes.add_textbox(Cm(left), Cm(top), Cm(width), Cm(height))
    tf = textbox.text_frame
    tf.word_wrap = word_wrap
    # 在文本框中写入文字
    # 题目
    para = tf.paragraphs[0]  # 新增段落
    para.text = content_text  # 向段落写入文字
    if font_color == 'blue':
        para.font.color.rgb = RGBColor(0, 30, 80)  # 蓝色
    elif font_color == 'green':
        para.font.color.rgb = RGBColor(0, 176, 80)  # 绿色
    elif font_color == 'red':
        para.font.color.rgb = RGBColor(255, 0, 0)  # 红色
    elif font_color == 'yellow':
        para.font.color.rgb = RGBColor(255, 255, 0)  # 红色
    elif font_color == 'orange':
        para.font.color.rgb = RGBColor(255, 192, 0)  # 红色
    elif font_color == 'white':
        para.font.color.rgb = RGBColor(255, 255, 255)  # 红色
    elif font_color == 'gray1':
        para.font.color.rgb = RGBColor(182, 191, 197)  # 红色
    else:
        para.font.color.rgb = RGBColor(0, 0, 0)  # 黑色
    if alignment == '左对齐':
        para.alignment = PP_ALIGN.LEFT
    else:
        para.alignment = PP_ALIGN.CENTER  # 居中

    # 设置字体
    font = para.font
    font.name = font_name  # 字体类型
    font.bold = font_bold  # 加粗
    font.size = Pt(font_size)  # 大小

    prs.save(ppt_script)  # 对ppt保存

5.2.2完善main.py

先看看我们的样板,可以发现有7处文字,要依此了解这7处文字设置的字体样式、字体大小、字体颜色、字体位置、是否加粗等,并把相应参数更改即可

具体main.py代码如下

from office_ppt_ser import new_ppt_add_slide
from office_ppt_ser import ppt_slide_number
from office_ppt_ser import titlebox


def main():
    new_ppt = r'PPT模版.pptx'
    new_ppt_path = new_ppt_add_slide(new_ppt, page_num=[1], PPT_Name='销售周报.pptx')
    print(new_ppt_path)

    slide_number = ppt_slide_number(new_ppt_path)
    print(new_ppt_path)

    # 部门报告
    titlebox(new_ppt_path, page_num=0, content_text='部门报告', font_size=20, left=0.55, top=0.94,
             width=3.36, height=1.11, font_bold=True, font_name='方正兰亭黑_GBK', font_color='blue',
             alignment='左对齐',
             word_wrap=False)

    # ■部门商品库存记录
    titlebox(new_ppt_path, page_num=0, content_text='■部门商品库存记录', font_size=12, left=0.58, top=2.14,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # ■部门商品销售记录
    titlebox(new_ppt_path, page_num=0, content_text='■部门商品销售记录', font_size=12, left=0.58, top=6.34,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # ■总结
    titlebox(new_ppt_path, page_num=0, content_text='■总结', font_size=12, left=0.58, top=11.65,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # 2025近期窗帘销售额最高是4000,近期下降最多的是窗帘,下降额是1000
    titlebox(new_ppt_path, page_num=0, content_text='2025近期窗帘销售额最高是4000,近期下降最多的是窗帘,下降额是1000',
             font_size=12, left=0.58, top=12.58,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # 红灯
    titlebox(new_ppt_path, page_num=0, content_text='红灯',
             font_size=18, left=16.68, top=0.76,
             width=1.8, height=1.03, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='居中',
             word_wrap=False)

    # 绿灯
    titlebox(new_ppt_path, page_num=0, content_text='绿灯',
             font_size=18, left=20.32, top=0.76,
             width=1.8, height=1.03, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='居中',
             word_wrap=False)


# 按装订区域中的绿色按钮以运行脚本。
if __name__ == '__main__':
    main()

5.2.3项目效果

方便展示效果,我把“红灯”“绿灯”的颜色均调成黑色:

分享上述完整代码路径:
链接: https://pan.baidu.com/s/1Gas4UeIXRvcH71lWBfD5cQ?pwd=dgy7 提取码: dgy7

6形状

在 PowerPoint 中,形状(Shape)是幻灯片上的一个可视化元素。每个形状都有一个类型(如文本框、矩形、椭圆等),并且可以具有各种属性,如位置、大小、颜色、边框、填充等。python-pptx 提供了 Shape 类来表示 PowerPoint 中的形状。可以通过 Slide.shapes 属性来访问幻灯片上的形状。

  • 获取形状
from pptx import Presentation

# 打开一个演示文稿
prs = Presentation('example.pptx')

# 获取第一张幻灯片
slide = prs.slides[0]

# 获取幻灯片上的所有形状
for shape in slide.shapes:
    print(shape.shape_type)
  • 添加形状

from pptx.enum.shapes import MSO_SHAPE

# 添加一个矩形
left = top = width = height = Inches(1.0)
shape = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, left, top, width, height)

# 设置形状的填充颜色
fill = shape.fill
fill.solid()
fill.fore_color.rgb = RGBColor(255, 0, 0)  # 红色

接下来将根据一个函数-插入长方形进行详细讲解。

6.1函数-插入长方形

from pptx import Presentation
from pptx.dml.color import RGBColor
from pptx.enum.shapes import MSO_SHAPE
from pptx.util import Cm
from pptx.util import Pt


# 在PPT中添加矩形框
def shape_rectangle(ppt_script, page_num=0, Left=0.96, Top=3.2, Width=12.5, Height=5.87, fore_color='gray',
                    line_width=0, rotation=0, shape_is_background=False):
    # ppt_script=r'C:\Users\hp\Desktop\汇总拆分\111.pptx'
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    # 在指定位置添加矩形
    shape = slide.shapes.add_shape(autoshape_type_id=MSO_SHAPE.RECTANGLE, left=Cm(Left), top=Cm(Top),
                                   width=Cm(Width), height=Cm(Height))
    # 调整角度
    shape.rotation = rotation
    # 填充背景色
    fill = shape.fill
    fill.solid()

    # 调整线宽
    line = shape.line

    if fore_color == 'gray':
        fill.fore_color.rgb = RGBColor(242, 242, 242)
        line.color.rgb = RGBColor(242, 242, 242)
    elif fore_color == 'gray1':
        fill.fore_color.rgb = RGBColor(127, 127, 127)
        line.color.rgb = RGBColor(127, 127, 127)
    elif fore_color == 'blue':
        fill.fore_color.rgb = RGBColor(0, 30, 80)
        line.color.rgb = RGBColor(0, 30, 80)
    elif fore_color == 'red':
        fill.fore_color.rgb = RGBColor(192, 0, 0)
        line.color.rgb = RGBColor(192, 0, 0)
    elif fore_color == 'yellow':
        fill.fore_color.rgb = RGBColor(255, 255, 0)
        line.color.rgb = RGBColor(255, 255, 0)
    elif fore_color == 'white':
        fill.fore_color.rgb = RGBColor(255, 255, 255)
        line.color.rgb = RGBColor(255, 255, 255)
    elif fore_color == 'lightblue':
        fill.fore_color.rgb = RGBColor(212, 228, 255)
        line.color.rgb = RGBColor(212, 228, 255)

    # fill.fore_color.brightness = 0  # 设为透明
    if shape_is_background == True:
        shape.fill.background()
        # fill.background()
        # fill.back_color.rgb = RGBColor(255, 255, 255)

    line.color.brightness = 0
    line.width = Pt(line_width)
    line.fill.background()  # 调成背景色
    prs.save(ppt_script)  # 对ppt保存


ppt_script = '销售周报.pptx'
shape_rectangle(ppt_script)

这段代码的主要功能是在 PowerPoint 文件的指定幻灯片上添加一个矩形框,并可以自定义矩形框的位置、大小、颜色、边框宽度、旋转角度等属性。通过调用 shape_rectangle 函数,可以轻松地在 PPT 中添加自定义的矩形框。

6.1.1导入库

from pptx import Presentation
from pptx.dml.color import RGBColor
from pptx.enum.shapes import MSO_SHAPE
from pptx.util import Cm
from pptx.util import Pt
  • Presentation:用于创建或打开 PowerPoint 文件。

  • RGBColor:用于定义颜色。

  • MSO_SHAPE:定义了 PowerPoint 中的各种形状类型。

  • Cm 和 Pt:用于设置长度单位(厘米和磅)。

6.1.2定义 shape_rectangle 函数

def shape_rectangle(ppt_script, page_num=0, Left=0.96, Top=3.2, Width=12.5, Height=5.87, fore_color='gray',
                    line_width=0, rotation=0, shape_is_background=False):
  • ppt_script:PPT 文件的路径。

  • page_num:要操作的幻灯片页码,默认为第 0 页(第一页)。

  • Left 和 Top:矩形框左上角的坐标,单位为厘米。

  • Width 和 Height:矩形框的宽度和高度,单位为厘米。

  • fore_color:矩形框的填充颜色,默认为灰色。

  • line_width:矩形框边框的宽度,单位为磅。

  • rotation:矩形框的旋转角度。

  • shape_is_background:是否将矩形框设置为背景。

6.1.3打开 PPT 文件并选择幻灯片

prs = Presentation(ppt_script)
slide = prs.slides[page_num]
  • prs:打开指定的 PowerPoint 文件。

  • slide:选择要操作的幻灯片。

6.1.4 添加矩形框

shape = slide.shapes.add_shape(autoshape_type_id=MSO_SHAPE.RECTANGLE, left=Cm(Left), top=Cm(Top),
                               width=Cm(Width), height=Cm(Height))
  • add_shape:在幻灯片上添加一个矩形框,位置和大小由 lefttopwidth 和 height 参数决定。

  • autoshape_type_id=MSO_SHAPE.RECTANGLE这一句是设置为长方形,要查看所有可用的形状类型,可以查阅 python-pptx 的官方文档MSO_AUTO_SHAPE_TYPE或直接查看 pptx.enum.shapes.MSO_SHAPE 的源代码如下

    ​
    from pptx.enum.shapes import MSO_SHAPE
    
    # 打印所有 MSO_SHAPE 的成员
    for shape_name in dir(MSO_SHAPE):
        if not shape_name.startswith('__'):  # 过滤掉内置方法
            print(shape_name)
    
    ​
  • 罗列所有形状的参数,需要的小伙伴可以看看

    ACTION_BUTTON_BACK_OR_PREVIOUS:后退或上一项动作按钮
    ACTION_BUTTON_BEGINNING:开始动作按钮
    ACTION_BUTTON_CUSTOM:自定义动作按钮
    ACTION_BUTTON_DOCUMENT:文档动作按钮
    ACTION_BUTTON_END:结束动作按钮
    ACTION_BUTTON_FORWARD_OR_NEXT:前进或下一项动作按钮
    ACTION_BUTTON_HELP:帮助动作按钮
    ACTION_BUTTON_HOME:主页动作按钮
    ACTION_BUTTON_INFORMATION:信息动作按钮
    ACTION_BUTTON_MOVIE:影片动作按钮
    ACTION_BUTTON_RETURN:返回动作按钮
    ACTION_BUTTON_SOUND:声音动作按钮
    ARC:弧形
    BALLOON:气球
    BENT_ARROW:弯曲箭头
    BENT_UP_ARROW:向上弯曲箭头
    BEVEL:斜角
    BLOCK_ARC:块弧形
    CAN:罐形
    CHART_PLUS:图表加号
    CHART_STAR:图表星形
    CHART_X:图表叉号
    CHEVRON:V形标志
    CHORD:弦形
    CIRCULAR_ARROW:环形箭头
    CLOUD:云形
    CLOUD_CALLOUT:云形标注
    CORNER:角落
    CORNER_TABS:角落标签
    CROSS:十字形
    CUBE:立方体
    CURVED_DOWN_ARROW:向下弯曲箭头
    CURVED_DOWN_RIBBON:向下弯曲丝带
    CURVED_LEFT_ARROW:向左弯曲箭头
    CURVED_RIGHT_ARROW:向右弯曲箭头
    CURVED_UP_ARROW:向上弯曲箭头
    CURVED_UP_RIBBON:向上弯曲丝带
    DECAGON:十边形
    DIAGONAL_STRIPE:对角条纹
    DIAMOND:菱形
    DODECAGON:十二边形
    DONUT:圆环
    DOUBLE_BRACE:双大括号
    DOUBLE_BRACKET:双方括号
    DOUBLE_WAVE:双波浪形
    DOWN_ARROW:向下箭头
    DOWN_ARROW_CALLOUT:向下箭头标注
    DOWN_RIBBON:向下丝带
    EXPLOSION1:爆炸形1
    EXPLOSION2:爆炸形2
    FLOWCHART_ALTERNATE_PROCESS:流程图交替过程
    FLOWCHART_CARD:流程图卡片
    FLOWCHART_COLLATE:流程图校对
    FLOWCHART_CONNECTOR:流程图连接器
    FLOWCHART_DATA:流程图数据
    FLOWCHART_DECISION:流程图决策
    FLOWCHART_DELAY:流程图延迟
    FLOWCHART_DIRECT_ACCESS_STORAGE:流程图直接访问存储
    FLOWCHART_DISPLAY:流程图显示
    FLOWCHART_DOCUMENT:流程图文档
    FLOWCHART_EXTRACT:流程图提取
    FLOWCHART_INTERNAL_STORAGE:流程图内部存储
    FLOWCHART_MAGNETIC_DISK:流程图磁盘
    FLOWCHART_MANUAL_INPUT:流程图手动输入
    FLOWCHART_MANUAL_OPERATION:流程图手动操作
    FLOWCHART_MERGE:流程图合并
    FLOWCHART_MULTIDOCUMENT:流程图多文档
    FLOWCHART_OFFLINE_STORAGE:流程图离线存储
    FLOWCHART_OFFPAGE_CONNECTOR:流程图离页连接器
    FLOWCHART_OR:流程图或
    FLOWCHART_PREDEFINED_PROCESS:流程图预定义过程
    FLOWCHART_PREPARATION:流程图准备
    FLOWCHART_PROCESS:流程图过程
    FLOWCHART_PUNCHED_TAPE:流程图穿孔纸带
    FLOWCHART_SEQUENTIAL_ACCESS_STORAGE:流程图顺序访问存储
    FLOWCHART_SORT:流程图排序
    FLOWCHART_STORED_DATA:流程图存储数据
    FLOWCHART_SUMMING_JUNCTION:流程图求和连接点
    FLOWCHART_TERMINATOR:流程图终止符
    FOLDED_CORNER:折角
    FRAME:框架
    FUNNEL:漏斗
    GEAR_6:6齿齿轮
    GEAR_9:9齿齿轮
    HALF_FRAME:半框架
    HEART:心形
    HEPTAGON:七边形
    HEXAGON:六边形
    HORIZONTAL_SCROLL:水平卷轴
    ISOSCELES_TRIANGLE:等腰三角形
    LEFT_ARROW:向左箭头
    LEFT_ARROW_CALLOUT:向左箭头标注
    LEFT_BRACE:左大括号
    LEFT_BRACKET:左方括号
    LEFT_CIRCULAR_ARROW:向左环形箭头
    LEFT_RIGHT_ARROW:左右箭头
    LEFT_RIGHT_ARROW_CALLOUT:左右箭头标注
    LEFT_RIGHT_CIRCULAR_ARROW:左右环形箭头
    LEFT_RIGHT_RIBBON:左右丝带
    LEFT_RIGHT_UP_ARROW:左右上箭头
    LEFT_UP_ARROW:左上箭头
    LIGHTNING_BOLT:闪电
    LINE_CALLOUT_1:标注线1
    LINE_CALLOUT_1_ACCENT_BAR:带强调条的标注线1
    LINE_CALLOUT_1_BORDER_AND_ACCENT_BAR:带边框和强调条的标注线1
    LINE_CALLOUT_1_NO_BORDER:无边框的标注线1
    LINE_CALLOUT_2:标注线2
    LINE_CALLOUT_2_ACCENT_BAR:带强调条的标注线2
    LINE_CALLOUT_2_BORDER_AND_ACCENT_BAR:带边框和强调条的标注线2
    LINE_CALLOUT_2_NO_BORDER:无边框的标注线2
    LINE_CALLOUT_3:标注线3
    LINE_CALLOUT_3_ACCENT_BAR:带强调条的标注线3
    LINE_CALLOUT_3_BORDER_AND_ACCENT_BAR:带边框和强调条的标注线3
    LINE_CALLOUT_3_NO_BORDER:无边框的标注线3
    LINE_CALLOUT_4:标注线4
    LINE_CALLOUT_4_ACCENT_BAR:带强调条的标注线4
    LINE_CALLOUT_4_BORDER_AND_ACCENT_BAR:带边框和强调条的标注线4
    LINE_CALLOUT_4_NO_BORDER:无边框的标注线4
    LINE_INVERSE:反直线
    MATH_DIVIDE:除号
    MATH_EQUAL:等号
    MATH_MINUS:减号
    MATH_MULTIPLY:乘号
    MATH_NOT_EQUAL:不等号
    MATH_PLUS:加号
    MOON:月亮
    NON_ISOSCELES_TRAPEZOID:非等腰梯形
    NOTCHED_RIGHT_ARROW:缺口向右箭头
    NO_SYMBOL:无符号
    OCTAGON:八边形
    OVAL:椭圆形
    OVAL_CALLOUT:椭圆形标注
    PARALLELOGRAM:平行四边形
    PENTAGON:五边形
    PIE:饼形
    PIE_WEDGE:饼形楔子
    PLAQUE:徽章
    PLAQUE_TABS:徽章标签
    QUAD_ARROW:四向箭头
    QUAD_ARROW_CALLOUT:四向箭头标注
    RECTANGLE:长方形
    RECTANGULAR_CALLOUT:长方形标注
    REGULAR_PENTAGON:正五边形
    RIGHT_ARROW:向右箭头
    RIGHT_ARROW_CALLOUT:向右箭头标注
    RIGHT_BRACE:右大括号
    RIGHT_BRACKET:右方括号
    RIGHT_TRIANGLE:直角三角形
    ROUNDED_RECTANGLE:圆角长方形
    ROUNDED_RECTANGULAR_CALLOUT:圆角长方形标注
    ROUND_1_RECTANGLE:单圆角长方形
    ROUND_2_DIAG_RECTANGLE:双对角圆角长方形
    ROUND_2_SAME_RECTANGLE:双同侧圆角长方形
    SMILEY_FACE:笑脸
    SNIP_1_RECTANGLE:单切角长方形
    SNIP_2_DIAG_RECTANGLE:双对角切角长方形
    SNIP_2_SAME_RECTANGLE:双同侧切角长方形
    SNIP_ROUND_RECTANGLE:切角圆角长方形
    SQUARE_TABS:方形标签
    STAR_10_POINT:10角星
    STAR_12_POINT:12角星
    STAR_16_POINT:16角星
    STAR_24_POINT:24角星
    STAR_32_POINT:32角星
    STAR_4_POINT:4角星
    STAR_5_POINT:5角星
    STAR_6_POINT:6角星
    STAR_7_POINT:7角星
    STAR_8_POINT:8角星
    STRIPED_RIGHT_ARROW:条纹向右箭头
    SUN:太阳
    SWOOSH_ARROW:嗖嗖箭头
    TEAR:泪滴形
    TRAPEZOID:梯形
    UP_ARROW:向上箭头
    UP_ARROW_CALLOUT:向上箭头标注
    UP_DOWN_ARROW:上下箭头
    UP_DOWN_ARROW_CALLOUT:上下箭头标注
    UP_RIBBON:向上丝带
    U_TURN_ARROW:U形转弯箭头
    VERTICAL_SCROLL:垂直卷轴
    WAVE:波浪形
    as_integer_ratio:转换为整数比
    bit_count:比特计数
    bit_length:比特长度
    conjugate:共轭
    denominator:分母
    from_bytes:从字节转换
    imag:虚部
    is_integer:是否为整数
    numerator:分子
    real:实部
    to_bytes:转换为字节

6.1.5设置矩形框的旋转角度

shape.rotation = rotation

6.1.6设置矩形框的填充颜色

fill = shape.fill
fill.solid()
  • fill.solid():将矩形框的填充设置为纯色。

根据 fore_color 参数的不同,设置不同的颜色,使用if语句,若没有需求颜色可自行添加:

if fore_color == 'gray':
    fill.fore_color.rgb = RGBColor(242, 242, 242)
    line.color.rgb = RGBColor(242, 242, 242)
elif fore_color == 'gray1':
    fill.fore_color.rgb = RGBColor(127, 127, 127)
    line.color.rgb = RGBColor(127, 127, 127)
elif fore_color == 'blue':
    fill.fore_color.rgb = RGBColor(0, 30, 80)
    line.color.rgb = RGBColor(0, 30, 80)
elif fore_color == 'red':
    fill.fore_color.rgb = RGBColor(192, 0, 0)
    line.color.rgb = RGBColor(192, 0, 0)
elif fore_color == 'yellow':
    fill.fore_color.rgb = RGBColor(255, 255, 0)
    line.color.rgb = RGBColor(255, 255, 0)
elif fore_color == 'white':
    fill.fore_color.rgb = RGBColor(255, 255, 255)
    line.color.rgb = RGBColor(255, 255, 255)
elif fore_color == 'lightblue':
    fill.fore_color.rgb = RGBColor(212, 228, 255)
    line.color.rgb = RGBColor(212, 228, 255)
  • fill.fore_color.rgb:设置矩形框的填充颜色。

  • line.color.rgb:设置矩形框边框的颜色。

6.1.7设置矩形框为背景(可选)

if shape_is_background == True:
    shape.fill.background()
  • shape.fill.background():将矩形框设置为背景。

6.1.8设置矩形框的边框宽度

line.color.brightness = 0
line.width = Pt(line_width)
line.fill.background()  # 调成背景色
  • line.width:设置矩形框边框的宽度。

  • line.fill.background():将边框颜色设置为背景色。

6.1.9保存 PPT 文件

prs.save(ppt_script)
  • prs.save(ppt_script):保存对 PPT 文件的修改。

6.1.10调用函数

ppt_script = '销售周报.pptx'
shape_rectangle(ppt_script)
  • 调用 shape_rectangle 函数,在 销售周报.pptx 的第一页添加一个默认样式的矩形框。

6.2项目新增形状

6.2.1完善office_ppt_ser.py

项目将在 5.2节项目新增文本框的基础上继续推进,进一步完善代码,增加形状的功能。具体实现方式是将上述函数迁移至 office_ppt_ser.py 文件中。

import os  # 文件类模块

from pptx import Presentation
from pptx.dml.color import RGBColor
from pptx.enum.shapes import MSO_SHAPE
from pptx.enum.text import PP_ALIGN
from pptx.util import Cm
from pptx.util import Pt


def new_ppt_add_slide(template, page_num=[0], PPT_Name='新建 Microsoft PowerPoint 演示文稿.pptx',
                      save_path='C:\\Users\\weidong.guo\\Desktop'):
    """
    :param template: PPT模板
    :param page_num: 列表,代表PPT模板里面的幻灯片序号,从0开始
    :param PPT_Name: PPT名字
    :param save_path: 保存路径
    :return:返回新的PPT路径
    """
    if os.path.isdir(save_path):  # save_path是目录
        new_ppt_path = os.path.join(save_path, PPT_Name)  # 将保存路径和PPT名字拼接在一起
    else:
        new_ppt_path = PPT_Name  # save_path不是目录,就不需要拼接
    prs = Presentation(template)  # 用Presentation读取PPT模板
    for i in page_num:  # 遍历需要增加的页数
        prs.slides.add_slide(prs.slide_layouts[i])  # 模板template中增加幻灯片
    prs.save(new_ppt_path)  # 对ppt保存
    return new_ppt_path


def ppt_slide_number(ppt_script):
    prs = Presentation(ppt_script)
    slide_number = len(prs.slides)
    return slide_number


def titlebox(ppt_script, page_num=0, content_text='Backup', font_size=18, left=0.55, top=2.12,
             width=25.81, height=1.08, font_bold=True, font_name='方正兰亭黑_GBK', font_color='',
             alignment='左对齐',
             word_wrap=False):
    """
    参数:
        ppt_script (str): PPT文件路径。
        page_num (int): 幻灯片页码(从0开始)。
        content_text (str): 文本框内容。
        font_size (int): 字体大小(单位:磅)。
        left (float): 文本框左上角的水平位置(单位:厘米)。
        top (float): 文本框左上角的垂直位置(单位:厘米)。
        width (float): 文本框宽度(单位:厘米)。
        height (float): 文本框高度(单位:厘米)。
        font_bold (bool): 是否加粗。
        font_name (str): 字体名称。
        font_color (str): 字体颜色(支持'blue', 'green', 'red', 'yellow', 'orange', 'white', 'gray1', 'black')。
        alignment (str): 对齐方式(支持'左对齐', '居中')。
        word_wrap (bool): 是否自动换行。
        return:
    """
    # ppt_script=r'C:\Users\hp\Desktop\汇总拆分\111.pptx'
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    # 在指定位置添加文本框
    textbox = slide.shapes.add_textbox(Cm(left), Cm(top), Cm(width), Cm(height))
    tf = textbox.text_frame
    tf.word_wrap = word_wrap
    # 在文本框中写入文字
    # 题目
    para = tf.paragraphs[0]  # 新增段落
    para.text = content_text  # 向段落写入文字
    if font_color == 'blue':
        para.font.color.rgb = RGBColor(0, 30, 80)  # 蓝色
    elif font_color == 'green':
        para.font.color.rgb = RGBColor(0, 176, 80)  # 绿色
    elif font_color == 'red':
        para.font.color.rgb = RGBColor(255, 0, 0)  # 红色
    elif font_color == 'yellow':
        para.font.color.rgb = RGBColor(255, 255, 0)  # 红色
    elif font_color == 'orange':
        para.font.color.rgb = RGBColor(255, 192, 0)  # 红色
    elif font_color == 'white':
        para.font.color.rgb = RGBColor(255, 255, 255)  # 红色
    elif font_color == 'gray1':
        para.font.color.rgb = RGBColor(182, 191, 197)  # 红色
    else:
        para.font.color.rgb = RGBColor(0, 0, 0)  # 黑色
    if alignment == '左对齐':
        para.alignment = PP_ALIGN.LEFT
    else:
        para.alignment = PP_ALIGN.CENTER  # 居中

    # 设置字体
    font = para.font
    font.name = font_name  # 字体类型
    font.bold = font_bold  # 加粗
    font.size = Pt(font_size)  # 大小

    prs.save(ppt_script)  # 对ppt保存


# 在PPT中添加矩形框
def shape_rectangle(ppt_script, page_num=0, Left=0.96, Top=3.2, Width=12.5, Height=5.87, fore_color='gray',
                    line_width=0, rotation=0, shape_is_background=False):
    # ppt_script=r'C:\Users\hp\Desktop\汇总拆分\111.pptx'
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    # 在指定位置添加矩形
    shape = slide.shapes.add_shape(autoshape_type_id=MSO_SHAPE.RECTANGLE, left=Cm(Left), top=Cm(Top),
                                   width=Cm(Width), height=Cm(Height))
    # 调整角度
    shape.rotation = rotation
    # 填充背景色
    fill = shape.fill
    fill.solid()

    # 调整线宽
    line = shape.line

    if fore_color == 'gray':
        fill.fore_color.rgb = RGBColor(242, 242, 242)
        line.color.rgb = RGBColor(242, 242, 242)
    elif fore_color == 'gray1':
        fill.fore_color.rgb = RGBColor(127, 127, 127)
        line.color.rgb = RGBColor(127, 127, 127)
    elif fore_color == 'blue':
        fill.fore_color.rgb = RGBColor(0, 30, 80)
        line.color.rgb = RGBColor(0, 30, 80)
    elif fore_color == 'red':
        fill.fore_color.rgb = RGBColor(192, 0, 0)
        line.color.rgb = RGBColor(192, 0, 0)
    elif fore_color == 'yellow':
        fill.fore_color.rgb = RGBColor(255, 255, 0)
        line.color.rgb = RGBColor(255, 255, 0)
    elif fore_color == 'white':
        fill.fore_color.rgb = RGBColor(255, 255, 255)
        line.color.rgb = RGBColor(255, 255, 255)
    elif fore_color == 'lightblue':
        fill.fore_color.rgb = RGBColor(212, 228, 255)
        line.color.rgb = RGBColor(212, 228, 255)

    # fill.fore_color.brightness = 0  # 设为透明
    if shape_is_background == True:
        shape.fill.background()
        # fill.background()
        # fill.back_color.rgb = RGBColor(255, 255, 255)

    line.color.brightness = 0
    line.width = Pt(line_width)
    line.fill.background()  # 调成背景色
    prs.save(ppt_script)  # 对ppt保存

6.2.2完善main.py

先看看我们的样板,可以发现有2处是长方形框,要依此了解这2处文字设置的位置、背景色等,并把相应参数更改即可

main.py代码如下

from office_ppt_ser import new_ppt_add_slide
from office_ppt_ser import ppt_slide_number
from office_ppt_ser import titlebox
from office_ppt_ser import shape_rectangle


def main():
    new_ppt = r'PPT模版.pptx'
    new_ppt_path = new_ppt_add_slide(new_ppt, page_num=[1], PPT_Name='销售周报.pptx')
    print(new_ppt_path)

    slide_number = ppt_slide_number(new_ppt_path)
    print(new_ppt_path)

    # 部门报告
    titlebox(new_ppt_path, page_num=0, content_text='部门报告', font_size=20, left=0.55, top=0.94,
             width=3.36, height=1.11, font_bold=True, font_name='方正兰亭黑_GBK', font_color='blue',
             alignment='左对齐',
             word_wrap=False)

    # ■部门商品库存记录
    titlebox(new_ppt_path, page_num=0, content_text='■部门商品库存记录', font_size=12, left=0.58, top=2.14,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # ■部门商品销售记录
    titlebox(new_ppt_path, page_num=0, content_text='■部门商品销售记录', font_size=12, left=0.58, top=6.34,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # ■总结
    titlebox(new_ppt_path, page_num=0, content_text='■总结', font_size=12, left=0.58, top=11.65,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # 2025近期窗帘销售额最高是4000,近期下降最多的是窗帘,下降额是1000
    titlebox(new_ppt_path, page_num=0, content_text='2025近期窗帘销售额最高是4000,近期下降最多的是窗帘,下降额是1000',
             font_size=12, left=0.58, top=12.58,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # 方框1
    shape_rectangle(new_ppt_path, page_num=0, Left=15.89, Top=0.79, Width=3.36, Height=1, fore_color='gray',
                    line_width=0, rotation=0, shape_is_background=False)

    # 方框2
    shape_rectangle(new_ppt_path, page_num=0, Left=19.54, Top=0.79, Width=3.36, Height=1, fore_color='gray',
                    line_width=0, rotation=0, shape_is_background=False)

    # 红灯
    titlebox(new_ppt_path, page_num=0, content_text='红灯',
             font_size=18, left=16.68, top=0.76,
             width=1.8, height=1.03, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='居中',
             word_wrap=False)

    # 绿灯
    titlebox(new_ppt_path, page_num=0, content_text='绿灯',
             font_size=18, left=20.32, top=0.76,
             width=1.8, height=1.03, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='居中',
             word_wrap=False)


# 按装订区域中的绿色按钮以运行脚本。
if __name__ == '__main__':
    main()

6.2.3项目效果

分享上述完整代码路径:
链接: https://pan.baidu.com/s/1-FtAfU0okSl0nFXgqqdL7g?pwd=g796 提取码: g796

7图片

在 python-pptx 库中,图片(Image)是 PowerPoint 幻灯片中的一种特殊形状。在python-pptx中使用 slide.shapes.add_picture() 方法可以在幻灯片中插入图片。该方法需要指定图片文件的路径以及图片的位置和大小。接下来将根据一个函数-插入图片进行详细讲解。

7.1函数-插入图片

import os

from pptx import Presentation
from pptx.util import Cm


# 在PPT中添加矩形框
def add_picture(img_path, ppt_script, page_num=0, left=0, top=0, width=4):
    # ppt_script=r'C:\Users\hp\Desktop\汇总拆分\111.pptx'
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    # Left, Top, Width, Height = Cm(left), Cm(top), Cm(width), Cm(height)  # 预设位置及大小
    # slide.shapes.add_picture(img_path, Left, Top, Width, Height)  # 在指定位置按预设值添加图片
    Left, Top, Width = Cm(left), Cm(top), Cm(width)  # 预设位置及大小
    slide.shapes.add_picture(img_path, Left, Top, Width)  # 在指定位置按预设值添加图片
    prs.save(ppt_script)  # 对ppt保存


ppt_script = '销售周报.pptx'
img_path = os.path.abspath(r'.\icon\logo.png')
add_picture(img_path, ppt_script)

代码解读

7.1.1导入模块

import os
from pptx import Presentation
from pptx.util import Cm
  • os: Python 标准库,用于处理文件路径和操作系统相关功能。

  • pptxpython-pptx 库,用于创建和修改 PowerPoint 文件。

  • Cmpptx.util 中的工具函数,用于将厘米转换为 python-pptx 所需的单位。

7.1.2定义 add_picture 函数

def add_picture(img_path, ppt_script, page_num=0, left=0, top=0, width=4):
  • 功能: 在指定的 PowerPoint 文件的某一页幻灯片中插入图片。

  • 参数:

    • img_path: 图片的路径。

    • ppt_script: PowerPoint 文件的路径。

    • page_num: 要插入图片的幻灯片页码(默认是第一页,索引为 0)。

    • left: 图片左侧距离幻灯片左侧的距离(默认 0 厘米)。

    • top: 图片顶部距离幻灯片顶部的距离(默认 0 厘米)。

    • width: 图片的宽度(默认 4 厘米)。

7.1.3加载 PowerPoint 文件

prs = Presentation(ppt_script)
  • 使用 Presentation(ppt_script) 加载指定的 PowerPoint 文件(ppt_script 是文件路径)。

7.1.4获取指定幻灯片

slide = prs.slides[page_num]
  • 通过 prs.slides[page_num] 获取指定页码的幻灯片对象(page_num 是幻灯片的索引,从 0 开始)。

7.1.5设置图片的位置和大小

Left, Top, Width = Cm(left), Cm(top), Cm(width)
  • 使用 Cm() 函数将厘米转换为 python-pptx 所需的单位。

  • Left: 图片左侧距离幻灯片左侧的距离。

  • Top: 图片顶部距离幻灯片顶部的距离。

  • Width: 图片的宽度(高度会根据宽度自动调整,保持图片的原始宽高比)。

7.1.6插入图片

slide.shapes.add_picture(img_path, Left, Top, Width)
  • 使用 slide.shapes.add_picture() 方法将图片插入到幻灯片中。

  • 参数:

    • img_path: 图片路径。

    • Left: 图片的左侧位置。

    • Top: 图片的顶部位置。

    • Width: 图片的宽度。

7.1.7保存 PowerPoint 文件

prs.save(ppt_script)
  • 使用 prs.save() 方法保存修改后的 PowerPoint 文件(覆盖原文件)。

7.1.8调用函数

ppt_script = '销售周报.pptx'
img_path = os.path.abspath(r'.\icon\logo.png')
add_picture(img_path, ppt_script)
  • ppt_script: PowerPoint 文件的路径(销售周报.pptx)。

  • img_path: 图片的路径(使用 os.path.abspath() 将相对路径转换为绝对路径)。

  • add_picture(): 调用函数,将图片插入到 PowerPoint 文件的第一页幻灯片中。

7.2项目新增图片

7.2.1完善office_ppt_ser.py

项目将在 6.2节‘项目新增形状’的基础上继续推进,进一步完善代码,增加图片的功能。具体实现方式是将上述函数迁移至 office_ppt_ser.py 文件中。

import os

from pptx import Presentation
from pptx.dml.color import RGBColor
from pptx.enum.shapes import MSO_SHAPE
from pptx.enum.text import PP_ALIGN
from pptx.util import Cm
from pptx.util import Pt


def new_ppt_add_slide(template, page_num=[0], PPT_Name='新建 Microsoft PowerPoint 演示文稿.pptx',
                      save_path='C:\\Users\\weidong.guo\\Desktop'):
    """
    :param template: PPT模板
    :param page_num: 列表,代表PPT模板里面的幻灯片序号,从0开始
    :param PPT_Name: PPT名字
    :param save_path: 保存路径
    :return:返回新的PPT路径
    """
    if os.path.isdir(save_path):  # save_path是目录
        new_ppt_path = os.path.join(save_path, PPT_Name)  # 将保存路径和PPT名字拼接在一起
    else:
        new_ppt_path = PPT_Name  # save_path不是目录,就不需要拼接
    prs = Presentation(template)  # 用Presentation读取PPT模板
    for i in page_num:  # 遍历需要增加的页数
        prs.slides.add_slide(prs.slide_layouts[i])  # 模板template中增加幻灯片
    prs.save(new_ppt_path)  # 对ppt保存
    return new_ppt_path


def ppt_slide_number(ppt_script):
    prs = Presentation(ppt_script)
    slide_number = len(prs.slides)
    return slide_number


def titlebox(ppt_script, page_num=0, content_text='Backup', font_size=18, left=0.55, top=2.12,
             width=25.81, height=1.08, font_bold=True, font_name='方正兰亭黑_GBK', font_color='',
             alignment='左对齐',
             word_wrap=False):
    """
    参数:
        ppt_script (str): PPT文件路径。
        page_num (int): 幻灯片页码(从0开始)。
        content_text (str): 文本框内容。
        font_size (int): 字体大小(单位:磅)。
        left (float): 文本框左上角的水平位置(单位:厘米)。
        top (float): 文本框左上角的垂直位置(单位:厘米)。
        width (float): 文本框宽度(单位:厘米)。
        height (float): 文本框高度(单位:厘米)。
        font_bold (bool): 是否加粗。
        font_name (str): 字体名称。
        font_color (str): 字体颜色(支持'blue', 'green', 'red', 'yellow', 'orange', 'white', 'gray1', 'black')。
        alignment (str): 对齐方式(支持'左对齐', '居中')。
        word_wrap (bool): 是否自动换行。
        return:
    """
    # ppt_script=r'C:\Users\hp\Desktop\汇总拆分\111.pptx'
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    # 在指定位置添加文本框
    textbox = slide.shapes.add_textbox(Cm(left), Cm(top), Cm(width), Cm(height))
    tf = textbox.text_frame
    tf.word_wrap = word_wrap
    # 在文本框中写入文字
    # 题目
    para = tf.paragraphs[0]  # 新增段落
    para.text = content_text  # 向段落写入文字
    if font_color == 'blue':
        para.font.color.rgb = RGBColor(0, 30, 80)  # 蓝色
    elif font_color == 'green':
        para.font.color.rgb = RGBColor(0, 176, 80)  # 绿色
    elif font_color == 'red':
        para.font.color.rgb = RGBColor(255, 0, 0)  # 红色
    elif font_color == 'yellow':
        para.font.color.rgb = RGBColor(255, 255, 0)  # 红色
    elif font_color == 'orange':
        para.font.color.rgb = RGBColor(255, 192, 0)  # 红色
    elif font_color == 'white':
        para.font.color.rgb = RGBColor(255, 255, 255)  # 红色
    elif font_color == 'gray1':
        para.font.color.rgb = RGBColor(182, 191, 197)  # 红色
    else:
        para.font.color.rgb = RGBColor(0, 0, 0)  # 黑色
    if alignment == '左对齐':
        para.alignment = PP_ALIGN.LEFT
    else:
        para.alignment = PP_ALIGN.CENTER  # 居中

    # 设置字体
    font = para.font
    font.name = font_name  # 字体类型
    font.bold = font_bold  # 加粗
    font.size = Pt(font_size)  # 大小

    prs.save(ppt_script)  # 对ppt保存


# 在PPT中添加矩形框
def shape_rectangle(ppt_script, page_num=0, Left=0.96, Top=3.2, Width=12.5, Height=5.87, fore_color='gray',
                    line_width=0, rotation=0, shape_is_background=False):
    # ppt_script=r'C:\Users\hp\Desktop\汇总拆分\111.pptx'
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    # 在指定位置添加矩形
    shape = slide.shapes.add_shape(autoshape_type_id=MSO_SHAPE.RECTANGLE, left=Cm(Left), top=Cm(Top),
                                   width=Cm(Width), height=Cm(Height))
    # 调整角度
    shape.rotation = rotation
    # 填充背景色
    fill = shape.fill
    fill.solid()

    # 调整线宽
    line = shape.line

    if fore_color == 'gray':
        fill.fore_color.rgb = RGBColor(242, 242, 242)
        line.color.rgb = RGBColor(242, 242, 242)
    elif fore_color == 'gray1':
        fill.fore_color.rgb = RGBColor(127, 127, 127)
        line.color.rgb = RGBColor(127, 127, 127)
    elif fore_color == 'blue':
        fill.fore_color.rgb = RGBColor(0, 30, 80)
        line.color.rgb = RGBColor(0, 30, 80)
    elif fore_color == 'red':
        fill.fore_color.rgb = RGBColor(192, 0, 0)
        line.color.rgb = RGBColor(192, 0, 0)
    elif fore_color == 'yellow':
        fill.fore_color.rgb = RGBColor(255, 255, 0)
        line.color.rgb = RGBColor(255, 255, 0)
    elif fore_color == 'white':
        fill.fore_color.rgb = RGBColor(255, 255, 255)
        line.color.rgb = RGBColor(255, 255, 255)
    elif fore_color == 'lightblue':
        fill.fore_color.rgb = RGBColor(212, 228, 255)
        line.color.rgb = RGBColor(212, 228, 255)

    # fill.fore_color.brightness = 0  # 设为透明
    if shape_is_background == True:
        shape.fill.background()
        # fill.background()
        # fill.back_color.rgb = RGBColor(255, 255, 255)

    line.color.brightness = 0
    line.width = Pt(line_width)
    line.fill.background()  # 调成背景色
    prs.save(ppt_script)  # 对ppt保存


def add_picture(img_path, ppt_script, page_num=0, left=0, top=0, width=4):
    # ppt_script=r'C:\Users\hp\Desktop\汇总拆分\111.pptx'
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    # Left, Top, Width, Height = Cm(left), Cm(top), Cm(width), Cm(height)  # 预设位置及大小
    # slide.shapes.add_picture(img_path, Left, Top, Width, Height)  # 在指定位置按预设值添加图片
    Left, Top, Width = Cm(left), Cm(top), Cm(width)  # 预设位置及大小
    slide.shapes.add_picture(img_path, Left, Top, Width)  # 在指定位置按预设值添加图片
    prs.save(ppt_script)  # 对ppt保存

7.2.2完善main.py

import os

from office_ppt_ser import add_picture
from office_ppt_ser import new_ppt_add_slide
from office_ppt_ser import ppt_slide_number
from office_ppt_ser import shape_rectangle
from office_ppt_ser import titlebox


def main():
    new_ppt = r'PPT模版.pptx'
    new_ppt_path = new_ppt_add_slide(new_ppt, page_num=[1], PPT_Name='销售周报.pptx')
    print(new_ppt_path)

    slide_number = ppt_slide_number(new_ppt_path)
    print(new_ppt_path)

    # 部门报告
    titlebox(new_ppt_path, page_num=0, content_text='部门报告', font_size=20, left=0.55, top=0.94,
             width=3.36, height=1.11, font_bold=True, font_name='方正兰亭黑_GBK', font_color='blue',
             alignment='左对齐',
             word_wrap=False)

    # ■部门商品库存记录
    titlebox(new_ppt_path, page_num=0, content_text='■部门商品库存记录', font_size=12, left=0.58, top=2.14,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # ■部门商品销售记录
    titlebox(new_ppt_path, page_num=0, content_text='■部门商品销售记录', font_size=12, left=0.58, top=6.34,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # ■总结
    titlebox(new_ppt_path, page_num=0, content_text='■总结', font_size=12, left=0.58, top=11.65,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # 2025近期窗帘销售额最高是4000,近期下降最多的是窗帘,下降额是1000
    titlebox(new_ppt_path, page_num=0, content_text='2025近期窗帘销售额最高是4000,近期下降最多的是窗帘,下降额是1000',
             font_size=12, left=0.58, top=12.58,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # 方框1
    shape_rectangle(new_ppt_path, page_num=0, Left=15.89, Top=0.79, Width=3.36, Height=1, fore_color='gray',
                    line_width=0, rotation=0, shape_is_background=False)

    # 方框2
    shape_rectangle(new_ppt_path, page_num=0, Left=19.54, Top=0.79, Width=3.36, Height=1, fore_color='gray',
                    line_width=0, rotation=0, shape_is_background=False)

    # 红灯
    titlebox(new_ppt_path, page_num=0, content_text='红灯',
             font_size=18, left=16.68, top=0.76,
             width=1.8, height=1.03, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='居中',
             word_wrap=False)

    # 绿灯
    titlebox(new_ppt_path, page_num=0, content_text='绿灯',
             font_size=18, left=20.32, top=0.76,
             width=1.8, height=1.03, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='居中',
             word_wrap=False)

    # 增加图片
    img_path = os.path.abspath(r'.\icon\logo.png')
    add_picture(img_path, new_ppt_path, page_num=0, left=23.25, top=0.12, width=1.7)


# 按装订区域中的绿色按钮以运行脚本。
if __name__ == '__main__':
    main()

7.2.3效果展示

需要注意的是增加图片素材

分享上述完整代码路径:
链接: https://pan.baidu.com/s/1Au0sqXcPA6--GA9WBZWvGg?pwd=paxm 提取码: paxm

8表格

在 python-pptx 库中,表格(Table)是 PowerPoint 幻灯片中的一种特殊形状,在python-pptx中使用 slide.shapes.add_table() 方法可以在幻灯片中插入表格。该方法需要指定表格的行数、列数以及表格的位置和大小。接下来将根据一个函数-插入表格(N行17列)进行详细讲解。

8.1函数-插入表格

import os

import pandas as pd
from pptx import Presentation
from pptx.dml.color import RGBColor
from pptx.enum.text import MSO_ANCHOR
from pptx.enum.text import PP_ALIGN
from pptx.util import Cm
from pptx.util import Pt


# 在PPT中添加矩形框
def table_Nrows_17cols(ppt_script, page_num=0,
                       title_list=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
                       col_width=[1.15, 2, 5.2, 1, 1.4, 1.4, 1, 1, 1, 1, 1.4, 1, 1, 1, 1, 1, 1], row_height=0.56,
                       fontname='方正兰亭黑_GBK',
                       fontsize=6, leftx=0.55, topx=2.85,
                       df=pd.DataFrame({
                           f'col{i}': range(5) for i in range(17)  # 每列数据为 0 到 4
                       })):
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    if df.shape[0] > 13:
        rows, cols = 14, 17  # 设定5行 14列
    else:
        rows = df.shape[0] + 1
        cols = 17
    print('>>>>>>>>>>>>>')
    print(rows, cols)
    left = Cm(leftx)
    top = Cm(topx)
    col_temp = 0
    # 计算表格总列宽
    for i in range(cols):
        col_temp += col_width[i]
    width = Cm(col_temp)
    # 计算表格总行宽
    height = Cm(row_height * rows)
    heightx = row_height * rows
    table = slide.shapes.add_table(rows, cols, left, top, width, height).table
    for i in range(cols):
        table.columns[i].width = Cm(col_width[i])  # 列高

    # 填写表格表头
    for j in range(cols):
        table.cell(0, j).text = str(title_list[j])
    # 填写表格内容
    if df.shape[0] > 13:
        for i in range(rows - 1):
            for j in range(cols):
                table.cell(i + 1, j).text = str(df.iat[i, j])
    else:
        for i in range(df.shape[0]):
            for j in range(cols):
                table.cell(i + 1, j).text = str(df.iat[i, j])

    # 行宽
    for i in range(0, rows):
        table.rows[i].heigth = Cm(row_height)

    # 修改表格样式
    for row in range(rows):
        for col in range(cols):
            # Write column titles
            new = table.cell(row, col).text_frame.paragraphs[0]
            new.font.name = fontname
            if row == 0:
                # 设置文字大小
                table.cell(row, col).text_frame.paragraphs[0].font.size = Pt(fontsize)
                # 设置文字颜色
                table.cell(row, col).text_frame.paragraphs[0].font.color.rgb = RGBColor(255, 255, 255)
                # 设置文字左右对齐
                table.cell(row, col).text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
                # 设置文字上下对齐
                table.cell(row, col).vertical_anchor = MSO_ANCHOR.MIDDLE
                # 设置背景为填充
                table.cell(row, col).fill.solid()
                # 设置背景颜色
                table.cell(row, col).fill.fore_color.rgb = RGBColor(0, 30, 80)
            else:
                table.cell(row, col).text_frame.paragraphs[0].font.size = Pt(fontsize)
                table.cell(row, col).text_frame.paragraphs[0].font.color.rgb = RGBColor(0, 0, 0)
                table.cell(row, col).text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
                table.cell(row, col).vertical_anchor = MSO_ANCHOR.MIDDLE
                table.cell(row, col).fill.solid()
                if row % 2 == 0:
                    table.cell(row, col).fill.fore_color.rgb = RGBColor(231, 231, 233)
                else:
                    table.cell(row, col).fill.fore_color.rgb = RGBColor(203, 204, 208)
    prs.save(ppt_script)  # 对ppt保存
    return heightx


ppt_script = '销售周报.pptx'
img_path = os.path.abspath(r'.\icon\logo.png')
table_Nrows_17cols(ppt_script)

代码解读

这段代码的主要功能是通过 python-pptx 库在 PowerPoint 文件中自动生成一个表格,并将 Pandas 数据框中的数据填充到表格中。以下是代码的详细解读:

8.1.1导入库

import pandas as pd
from pptx import Presentation
from pptx.dml.color import RGBColor
from pptx.enum.text import MSO_ANCHOR, PP_ALIGN
from pptx.util import Cm, Pt
  • pandas as pd: 用于处理数据框(DataFrame)。

  • pptx: 用于操作 PowerPoint 文件。

    • Presentation: 用于创建或打开 PPT 文件。

    • RGBColor: 用于设置颜色。

    • MSO_ANCHORPP_ALIGN: 用于设置文本的对齐方式。

    • CmPt: 用于设置长度单位(厘米和磅)。

8.1.2定义函数 table_Nrows_17cols

def table_Nrows_17cols(ppt_script, page_num=0,
                       title_list=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
                       col_width=[1.15, 2, 5.2, 1, 1.4, 1.4, 1, 1, 1, 1, 1.4, 1, 1, 1, 1, 1, 1], row_height=0.56,
                       fontname='方正兰亭黑_GBK',
                       fontsize=6, leftx=0.55, topx=2.85,
                       df=pd.DataFrame({
                           f'col{i}': range(5) for i in range(17)  # 每列数据为 0 到 4
                       })):
  • 参数说明:

    • ppt_script: PPT 文件路径。

    • page_num: 操作的幻灯片页码(默认第 0 页)。

    • title_list: 表格的表头内容(默认 17 列)。

    • col_width: 每列的宽度(单位:厘米)。

    • row_height: 每行的高度(单位:厘米)。

    • fontname: 字体名称。

    • fontsize: 字体大小(单位:磅)。

    • leftxtopx: 表格左上角的坐标(单位:厘米)。

    • df: 要填充到表格中的数据框(默认生成一个 5 行 17 列的 DataFrame)。

8.1.3打开 PPT 文件并选择幻灯片

prs = Presentation(ppt_script)
slide = prs.slides[page_num]
  • 打开指定的 PPT 文件,并选择要操作的幻灯片。

8.1.4确定表格的行数和列数

if df.shape[0] > 13:
    rows, cols = 14, 17  # 设定5行 14列
else:
    rows = df.shape[0] + 1
    cols = 17
  • 如果数据框的行数超过 13 行,则表格设置为 14 行(包括表头);否则,表格行数为数据框行数加 1(表头)。

  • 列数固定为 17 列。

8.1.5计算表格的总宽度和高度

left = Cm(leftx)
top = Cm(topx)
col_temp = 0
for i in range(cols):
    col_temp += col_width[i]
width = Cm(col_temp)
height = Cm(row_height * rows)
heightx = row_height * rows
  • left 和 top 是表格左上角的坐标。

  • col_temp 是表格的总宽度(各列宽度之和)。

  • width 和 height 是表格的总宽度和高度(单位:厘米)。

  • heightx 是表格的总高度(单位:厘米),用于返回值。

8.1.6添加表格到幻灯片

table = slide.shapes.add_table(rows, cols, left, top, width, height).table
for i in range(cols):
    table.columns[i].width = Cm(col_width[i])  # 列高
  • 在幻灯片中添加一个表格,并设置每列的宽度。

8.1.7填充表头和数据

# 填写表格表头
for j in range(cols):
    table.cell(0, j).text = str(title_list[j])

# 填写表格内容
if df.shape[0] > 13:
    for i in range(rows - 1):
        for j in range(cols):
            table.cell(i + 1, j).text = str(df.iat[i, j])
else:
    for i in range(df.shape[0]):
        for j in range(cols):
            table.cell(i + 1, j).text = str(df.iat[i, j])
  • 表头填充:将 title_list 的内容写入表格的第一行。

  • 数据填充:将数据框 df 的内容写入表格的其余行。

8.1.8设置行高

for i in range(0, rows):
    table.rows[i].heigth = Cm(row_height)
  • 设置每行的高度。

8.1.9修改表格样式

for row in range(rows):
    for col in range(cols):
        new = table.cell(row, col).text_frame.paragraphs[0]
        new.font.name = fontname
        if row == 0:
            # 设置表头样式
            table.cell(row, col).text_frame.paragraphs[0].font.size = Pt(fontsize)
            table.cell(row, col).text_frame.paragraphs[0].font.color.rgb = RGBColor(255, 255, 255)
            table.cell(row, col).text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
            table.cell(row, col).vertical_anchor = MSO_ANCHOR.MIDDLE
            table.cell(row, col).fill.solid()
            table.cell(row, col).fill.fore_color.rgb = RGBColor(0, 30, 80)
        else:
            # 设置数据行样式
            table.cell(row, col).text_frame.paragraphs[0].font.size = Pt(fontsize)
            table.cell(row, col).text_frame.paragraphs[0].font.color.rgb = RGBColor(0, 0, 0)
            table.cell(row, col).text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
            table.cell(row, col).vertical_anchor = MSO_ANCHOR.MIDDLE
            table.cell(row, col).fill.solid()
            if row % 2 == 0:
                table.cell(row, col).fill.fore_color.rgb = RGBColor(231, 231, 233)
            else:
                table.cell(row, col).fill.fore_color.rgb = RGBColor(203, 204, 208)
  • 设置表格的样式:

    • 表头:白色文字、深蓝色背景、居中对齐。

    • 数据行:黑色文字、交替浅灰色背景、居中对齐。

8.1.10保存 PPT 文件

prs.save(ppt_script)  # 对ppt保存
return heightx
  • 保存修改后的 PPT 文件,并返回表格的总高度。

8.1.11调用函数

ppt_script = '销售周报.pptx'
table_Nrows_17cols(ppt_script)
  • 调用函数,在指定的 PPT 文件中生成表格。

8.2项目新增表格

8.2.1完善office_ppt_ser.py

项目将在 7.2节‘项目新增图片’的基础上继续推进,进一步完善代码,增加表格的功能。具体实现方式是将上述函数迁移至 office_ppt_ser.py 文件中。

import os

import pandas as pd
from pptx import Presentation
from pptx.dml.color import RGBColor
from pptx.enum.shapes import MSO_SHAPE
from pptx.enum.text import MSO_ANCHOR
from pptx.enum.text import PP_ALIGN
from pptx.util import Cm
from pptx.util import Pt


def new_ppt_add_slide(template, page_num=[0], PPT_Name='新建 Microsoft PowerPoint 演示文稿.pptx',
                      save_path='C:\\Users\\weidong.guo\\Desktop'):
    """
    :param template: PPT模板
    :param page_num: 列表,代表PPT模板里面的幻灯片序号,从0开始
    :param PPT_Name: PPT名字
    :param save_path: 保存路径
    :return:返回新的PPT路径
    """
    if os.path.isdir(save_path):  # save_path是目录
        new_ppt_path = os.path.join(save_path, PPT_Name)  # 将保存路径和PPT名字拼接在一起
    else:
        new_ppt_path = PPT_Name  # save_path不是目录,就不需要拼接
    prs = Presentation(template)  # 用Presentation读取PPT模板
    for i in page_num:  # 遍历需要增加的页数
        prs.slides.add_slide(prs.slide_layouts[i])  # 模板template中增加幻灯片
    prs.save(new_ppt_path)  # 对ppt保存
    return new_ppt_path


def ppt_slide_number(ppt_script):
    prs = Presentation(ppt_script)
    slide_number = len(prs.slides)
    return slide_number


def titlebox(ppt_script, page_num=0, content_text='Backup', font_size=18, left=0.55, top=2.12,
             width=25.81, height=1.08, font_bold=True, font_name='方正兰亭黑_GBK', font_color='',
             alignment='左对齐',
             word_wrap=False):
    """
    参数:
        ppt_script (str): PPT文件路径。
        page_num (int): 幻灯片页码(从0开始)。
        content_text (str): 文本框内容。
        font_size (int): 字体大小(单位:磅)。
        left (float): 文本框左上角的水平位置(单位:厘米)。
        top (float): 文本框左上角的垂直位置(单位:厘米)。
        width (float): 文本框宽度(单位:厘米)。
        height (float): 文本框高度(单位:厘米)。
        font_bold (bool): 是否加粗。
        font_name (str): 字体名称。
        font_color (str): 字体颜色(支持'blue', 'green', 'red', 'yellow', 'orange', 'white', 'gray1', 'black')。
        alignment (str): 对齐方式(支持'左对齐', '居中')。
        word_wrap (bool): 是否自动换行。
        return:
    """
    # ppt_script=r'C:\Users\hp\Desktop\汇总拆分\111.pptx'
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    # 在指定位置添加文本框
    textbox = slide.shapes.add_textbox(Cm(left), Cm(top), Cm(width), Cm(height))
    tf = textbox.text_frame
    tf.word_wrap = word_wrap
    # 在文本框中写入文字
    # 题目
    para = tf.paragraphs[0]  # 新增段落
    para.text = content_text  # 向段落写入文字
    if font_color == 'blue':
        para.font.color.rgb = RGBColor(0, 30, 80)  # 蓝色
    elif font_color == 'green':
        para.font.color.rgb = RGBColor(0, 176, 80)  # 绿色
    elif font_color == 'red':
        para.font.color.rgb = RGBColor(255, 0, 0)  # 红色
    elif font_color == 'yellow':
        para.font.color.rgb = RGBColor(255, 255, 0)  # 红色
    elif font_color == 'orange':
        para.font.color.rgb = RGBColor(255, 192, 0)  # 红色
    elif font_color == 'white':
        para.font.color.rgb = RGBColor(255, 255, 255)  # 红色
    elif font_color == 'gray1':
        para.font.color.rgb = RGBColor(182, 191, 197)  # 红色
    else:
        para.font.color.rgb = RGBColor(0, 0, 0)  # 黑色
    if alignment == '左对齐':
        para.alignment = PP_ALIGN.LEFT
    else:
        para.alignment = PP_ALIGN.CENTER  # 居中

    # 设置字体
    font = para.font
    font.name = font_name  # 字体类型
    font.bold = font_bold  # 加粗
    font.size = Pt(font_size)  # 大小

    prs.save(ppt_script)  # 对ppt保存


# 在PPT中添加矩形框
def shape_rectangle(ppt_script, page_num=0, Left=0.96, Top=3.2, Width=12.5, Height=5.87, fore_color='gray',
                    line_width=0, rotation=0, shape_is_background=False):
    # ppt_script=r'C:\Users\hp\Desktop\汇总拆分\111.pptx'
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    # 在指定位置添加矩形
    shape = slide.shapes.add_shape(autoshape_type_id=MSO_SHAPE.RECTANGLE, left=Cm(Left), top=Cm(Top),
                                   width=Cm(Width), height=Cm(Height))
    # 调整角度
    shape.rotation = rotation
    # 填充背景色
    fill = shape.fill
    fill.solid()

    # 调整线宽
    line = shape.line

    if fore_color == 'gray':
        fill.fore_color.rgb = RGBColor(242, 242, 242)
        line.color.rgb = RGBColor(242, 242, 242)
    elif fore_color == 'gray1':
        fill.fore_color.rgb = RGBColor(127, 127, 127)
        line.color.rgb = RGBColor(127, 127, 127)
    elif fore_color == 'blue':
        fill.fore_color.rgb = RGBColor(0, 30, 80)
        line.color.rgb = RGBColor(0, 30, 80)
    elif fore_color == 'red':
        fill.fore_color.rgb = RGBColor(192, 0, 0)
        line.color.rgb = RGBColor(192, 0, 0)
    elif fore_color == 'yellow':
        fill.fore_color.rgb = RGBColor(255, 255, 0)
        line.color.rgb = RGBColor(255, 255, 0)
    elif fore_color == 'white':
        fill.fore_color.rgb = RGBColor(255, 255, 255)
        line.color.rgb = RGBColor(255, 255, 255)
    elif fore_color == 'lightblue':
        fill.fore_color.rgb = RGBColor(212, 228, 255)
        line.color.rgb = RGBColor(212, 228, 255)

    # fill.fore_color.brightness = 0  # 设为透明
    if shape_is_background == True:
        shape.fill.background()
        # fill.background()
        # fill.back_color.rgb = RGBColor(255, 255, 255)

    line.color.brightness = 0
    line.width = Pt(line_width)
    line.fill.background()  # 调成背景色
    prs.save(ppt_script)  # 对ppt保存


def add_picture(img_path, ppt_script, page_num=0, left=0, top=0, width=4):
    # ppt_script=r'C:\Users\hp\Desktop\汇总拆分\111.pptx'
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    # Left, Top, Width, Height = Cm(left), Cm(top), Cm(width), Cm(height)  # 预设位置及大小
    # slide.shapes.add_picture(img_path, Left, Top, Width, Height)  # 在指定位置按预设值添加图片
    Left, Top, Width = Cm(left), Cm(top), Cm(width)  # 预设位置及大小
    slide.shapes.add_picture(img_path, Left, Top, Width)  # 在指定位置按预设值添加图片
    prs.save(ppt_script)  # 对ppt保存


# 在PPT中表格
def table_Nrows_17cols(ppt_script, page_num=0,
                       title_list=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
                       col_width=[1.15, 2, 5.2, 1, 1.4, 1.4, 1, 1, 1, 1, 1.4, 1, 1, 1, 1, 1, 1], row_height=0.56,
                       fontname='方正兰亭黑_GBK',
                       fontsize=6, leftx=0.55, topx=2.85,
                       df=pd.DataFrame({
                           f'col{i}': range(5) for i in range(17)  # 每列数据为 0 到 4
                       })):
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    if df.shape[0] > 13:
        rows, cols = 14, 17  # 设定5行 14列
    else:
        rows = df.shape[0] + 1
        cols = 17
    print('>>>>>>>>>>>>>')
    print(rows, cols)
    left = Cm(leftx)
    top = Cm(topx)
    col_temp = 0
    # 计算表格总列宽
    for i in range(cols):
        col_temp += col_width[i]
    width = Cm(col_temp)
    # 计算表格总行宽
    height = Cm(row_height * rows)
    heightx = row_height * rows
    table = slide.shapes.add_table(rows, cols, left, top, width, height).table
    for i in range(cols):
        table.columns[i].width = Cm(col_width[i])  # 列高

    # 填写表格表头
    for j in range(cols):
        table.cell(0, j).text = str(title_list[j])
    # 填写表格内容
    if df.shape[0] > 13:
        for i in range(rows - 1):
            for j in range(cols):
                table.cell(i + 1, j).text = str(df.iat[i, j])
    else:
        for i in range(df.shape[0]):
            for j in range(cols):
                table.cell(i + 1, j).text = str(df.iat[i, j])

    # 行宽
    for i in range(0, rows):
        table.rows[i].heigth = Cm(row_height)

    # 修改表格样式
    for row in range(rows):
        for col in range(cols):
            # Write column titles
            new = table.cell(row, col).text_frame.paragraphs[0]
            new.font.name = fontname
            if row == 0:
                # 设置文字大小
                table.cell(row, col).text_frame.paragraphs[0].font.size = Pt(fontsize)
                # 设置文字颜色
                table.cell(row, col).text_frame.paragraphs[0].font.color.rgb = RGBColor(255, 255, 255)
                # 设置文字左右对齐
                table.cell(row, col).text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
                # 设置文字上下对齐
                table.cell(row, col).vertical_anchor = MSO_ANCHOR.MIDDLE
                # 设置背景为填充
                table.cell(row, col).fill.solid()
                # 设置背景颜色
                table.cell(row, col).fill.fore_color.rgb = RGBColor(0, 30, 80)
            else:
                table.cell(row, col).text_frame.paragraphs[0].font.size = Pt(fontsize)
                table.cell(row, col).text_frame.paragraphs[0].font.color.rgb = RGBColor(0, 0, 0)
                table.cell(row, col).text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
                table.cell(row, col).vertical_anchor = MSO_ANCHOR.MIDDLE
                table.cell(row, col).fill.solid()
                if row % 2 == 0:
                    table.cell(row, col).fill.fore_color.rgb = RGBColor(231, 231, 233)
                else:
                    table.cell(row, col).fill.fore_color.rgb = RGBColor(203, 204, 208)
    prs.save(ppt_script)  # 对ppt保存
    return heightx

8.2.2完善main.py

import os

import pandas as pd

from office_ppt_ser import add_picture
from office_ppt_ser import new_ppt_add_slide
from office_ppt_ser import ppt_slide_number
from office_ppt_ser import shape_rectangle
from office_ppt_ser import table_Nrows_17cols
from office_ppt_ser import titlebox


def main():
    new_ppt = r'PPT模版.pptx'
    new_ppt_path = new_ppt_add_slide(new_ppt, page_num=[1], PPT_Name='销售周报.pptx')
    print(new_ppt_path)

    slide_number = ppt_slide_number(new_ppt_path)
    print(new_ppt_path)

    # 部门报告
    titlebox(new_ppt_path, page_num=0, content_text='部门报告', font_size=20, left=0.55, top=0.94,
             width=3.36, height=1.11, font_bold=True, font_name='方正兰亭黑_GBK', font_color='blue',
             alignment='左对齐',
             word_wrap=False)

    # ■部门商品库存记录
    titlebox(new_ppt_path, page_num=0, content_text='■部门商品库存记录', font_size=12, left=0.58, top=2.14,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # ■部门商品销售记录
    titlebox(new_ppt_path, page_num=0, content_text='■部门商品销售记录', font_size=12, left=0.58, top=6.34,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # ■总结
    titlebox(new_ppt_path, page_num=0, content_text='■总结', font_size=12, left=0.58, top=11.65,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # 2025近期窗帘销售额最高是4000,近期下降最多的是窗帘,下降额是1000
    titlebox(new_ppt_path, page_num=0, content_text='2025近期窗帘销售额最高是4000,近期下降最多的是窗帘,下降额是1000',
             font_size=12, left=0.58, top=12.58,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # 方框1
    shape_rectangle(new_ppt_path, page_num=0, Left=15.89, Top=0.79, Width=3.36, Height=1, fore_color='gray',
                    line_width=0, rotation=0, shape_is_background=False)

    # 方框2
    shape_rectangle(new_ppt_path, page_num=0, Left=19.54, Top=0.79, Width=3.36, Height=1, fore_color='gray',
                    line_width=0, rotation=0, shape_is_background=False)

    # 红灯
    titlebox(new_ppt_path, page_num=0, content_text='红灯',
             font_size=18, left=16.68, top=0.76,
             width=1.8, height=1.03, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='居中',
             word_wrap=False)

    # 绿灯
    titlebox(new_ppt_path, page_num=0, content_text='绿灯',
             font_size=18, left=20.32, top=0.76,
             width=1.8, height=1.03, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='居中',
             word_wrap=False)

    # 增加图片
    img_path = os.path.abspath(r'.\icon\logo.png')
    add_picture(img_path, new_ppt_path, page_num=0, left=23.25, top=0.12, width=1.7)

    # 增加表格
    table_Nrows_17cols(new_ppt_path, page_num=0,
                       title_list=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
                       col_width=[1.15, 2, 5.2, 1, 1.4, 1.4, 1, 1, 1, 1, 1.4, 1, 1, 1, 1, 1, 1], row_height=0.56,
                       fontname='方正兰亭黑_GBK',
                       fontsize=6, leftx=0.55, topx=2.85,
                       df=pd.DataFrame({
                           f'col{i}': range(5) for i in range(17)  # 每列数据为 0 到 4
                       }))


# 按装订区域中的绿色按钮以运行脚本。
if __name__ == '__main__':
    main()

8.2.3效果展示

分享上述完整代码路径:
链接: https://pan.baidu.com/s/1j1zoYekpNLCJpdJhBbtHfA?pwd=cg72 提取码: cg72

9图表

在 python-pptx 库中,图表(Chart)是 PowerPoint 幻灯片中的一种特殊形状,这python-pptx中使用 slide.shapes.add_chart() 方法可以在幻灯片中插入图表。该方法需要指定图表类型、数据、位置和大小。接下来将根据一个函数-插入柱状图(可以调整颜色)进行详细讲解。

9.1函数-插入柱状图

import pandas as pd
from pptx import Presentation
from pptx.chart.data import ChartData
from pptx.dml.color import RGBColor
from pptx.enum.chart import XL_CHART_TYPE
from pptx.enum.chart import XL_DATA_LABEL_POSITION
from pptx.enum.chart import XL_LEGEND_POSITION
from pptx.util import Cm
from pptx.util import Pt

colors_collection = {
    '2_orange_green': [RGBColor(255, 192, 0), RGBColor(0, 176, 80)],
    '2_green_orange': [RGBColor(0, 176, 80), RGBColor(255, 192, 0)],
    '2_orange_olive': [RGBColor(255, 192, 0), RGBColor(0, 176, 180)],
    '2_olive_green': [RGBColor(0, 176, 180), RGBColor(0, 176, 80)],
    '2_white_olive': [RGBColor(255, 255, 255), RGBColor(0, 176, 180)],
    '2_blue_lightblue': [RGBColor(0, 176, 240), RGBColor(169, 227, 255)],
    '2_olive_orange': [RGBColor(0, 176, 180), RGBColor(255, 192, 0)],
    '2_gray_lightblue2': [RGBColor(182, 191, 197), RGBColor(169, 227, 255)],
    '1_olive': [RGBColor(0, 176, 180)],
    '1_orange': [RGBColor(255, 192, 0)],
    '1_gray': [RGBColor(182, 191, 197)],
    '1_lightblue': [RGBColor(0, 176, 240)],
    '1_tangerine': [RGBColor(255, 102, 153)],
    '2_tangerine_gray': [RGBColor(255, 102, 153), RGBColor(182, 191, 197)],
    '2_gray_tangerine': [RGBColor(182, 191, 197), RGBColor(255, 102, 153)],
    '2_gray_lightblue': [RGBColor(182, 191, 197), RGBColor(0, 176, 240)],
    '2_green_gray': [RGBColor(0, 176, 80), RGBColor(182, 191, 197)],
    '2_olive_gray': [RGBColor(0, 176, 180), RGBColor(182, 191, 197)]
}


def chart_clustered_bar_self_color(ppt_script, page_num=0, left=0.96, top=3.86, width=12.5, height=5.87,
                                   font_size=6,
                                   has_legend=True, value_axis_maximum_scale=None, data_position='居中',
                                   value_axis_minimum_scale=None,
                                   has_data_labels=True,
                                   df=pd.DataFrame(
                                       {'区域1': ['9', '11'], '区域2': ['6', '9'], '区域3': ['13', '7'],
                                        '区域4': ['9', '11'],
                                        '区域5': ['6', '9'],
                                        '区域6': ['13', '7']},
                                       index=['主题1', '主题2']), self_chart_style='2_orange_green',
                                   y_axis_visible=True,
                                   legend_font_size='',
                                   data_labels_font_size='', data_percent=False):
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]

    # 定义图表数据
    chart_data = ChartData()
    chart_data.categories = df.columns
    for i in range(df.shape[0]):
        chart_data.add_series(df.index[i], df.iloc[i])
    # 定义图表位置
    Left, Top, Width, Height = Cm(left), Cm(top), Cm(width), Cm(height)  # 预设位置及大小
    print(Left, Top, Width, Height)
    # 添加图表
    graphic_frame = slide.shapes.add_chart(XL_CHART_TYPE.COLUMN_CLUSTERED, Left, Top, Width, Height, chart_data)

    # 将图表美化
    chart = graphic_frame.chart  # 从生成的图表中取出图表类

    # 控制柱状图颜色
    if self_chart_style != '':
        colors_collection_dic = colors_collection
        if self_chart_style in colors_collection:
            colors = colors_collection_dic[self_chart_style]  # 设置颜色列表
            if len(colors) == df.shape[0]:
                for i_x, series in enumerate(chart.series):
                    fill = series.format.fill
                    fill.solid()
                    fill.fore_color.rgb = colors[i_x]
            else:
                chart.chart_style = 8  # 图表整体颜色风格
    else:
        chart.chart_style = 8  # 图表整体颜色风格
    chart.has_title = False  # 不显示标题

    category_axis = chart.category_axis  # category_axis 为chart的category控制类
    category_axis.has_major_gridlines = False  # 是否显示纵轴线
    category_axis.has_minor_gridlines = False
    category_axis.tick_labels.font.italic = False  # tick_labels为图表下标签,置为斜体
    # category_axis.tick_labels.font.name= '方正兰亭黑_GBK'
    category_axis.tick_labels.font.size = Pt(font_size)  # 下标签字体大小
    category_axis.tick_labels.font.color.rgb = RGBColor(0, 0, 0)  # 标签字体颜色

    value_axis = chart.value_axis  # value_axis 为chart的value控制类
    value_axis.visible = y_axis_visible  # 是否隐藏y轴
    value_axis.has_major_gridlines = False  # 是否显示纵轴线
    value_axis.has_minor_gridlines = False
    if value_axis_maximum_scale != None:
        try:
            value_axis.maximum_scale = value_axis_maximum_scale  # 纵坐标最大值
        except:
            pass

    if value_axis_minimum_scale != None:
        value_axis.minimum_scale = value_axis_minimum_scale  # 纵坐标最小值

    # value_axis.minor_tick_mark = XL_TICK_MARK.CROSS
    tick_labels = value_axis.tick_labels  # tick_labels 为chart的纵轴标签控制类
    # tick_labels.number_format = '0%'  # 标签显示样式
    tick_labels.font.bold = False  # 字体加粗
    # tick_labels.font.name = '方正兰亭黑_GBK'
    tick_labels.font.size = Pt(font_size)  # 字体大小
    tick_labels.font.color.rgb = RGBColor(0, 0, 0)  # 标签颜色

    plot = chart.plots[0]  # 取图表中第一个plot
    if has_data_labels == True:
        plot.has_data_labels = has_data_labels  # 是否显示数据标签
        data_labels = plot.data_labels  # 数据标签控制类
        data_labels.font.name = '方正兰亭黑_GBK'
        if data_labels_font_size == '':
            data_labels.font.size = Pt(font_size)  # 字体大小
        else:
            data_labels.font.size = Pt(data_labels_font_size)  # 字体大小
        if data_percent == True:
            data_labels.number_format = '0.0%'  # 标签显示样式
        data_labels.font.color.rgb = RGBColor(0, 0, 0)  # 字体颜色
        if data_position == '居中':
            data_labels.position = XL_DATA_LABEL_POSITION.CENTER  # 字体位置

    chart.has_legend = has_legend  # 是否含有下方的说明
    if has_legend == True:
        chart.legend.position = XL_LEGEND_POSITION.TOP
        chart.legend.horz_offset = 0  # 说明位移量 [-1, 1] 默认为0
        # chart.legend.include_in_layout = True  # 图例在绘图区之外显示
        chart.legend.font.name = '方正兰亭黑_GBK'
        if legend_font_size == '':
            chart.legend.font.size = Pt(font_size)
        else:
            chart.legend.font.size = Pt(legend_font_size)

    prs.save(ppt_script)  # 对ppt保存


ppt_script = '销售周报.pptx'
chart_clustered_bar_self_color(ppt_script)

这段代码的主要功能是使用 python-pptx 库在 PowerPoint 中自动生成一个带有自定义颜色的簇状柱状图。以下是对代码的详细解读:

9.1.1导入库

import pandas as pd
from pptx import Presentation
from pptx.chart.data import ChartData
from pptx.dml.color import RGBColor
from pptx.enum.chart import XL_CHART_TYPE
from pptx.enum.chart import XL_DATA_LABEL_POSITION
from pptx.enum.chart import XL_LEGEND_POSITION
from pptx.util import Cm
from pptx.util import Pt
  • pandas:用于处理数据,生成图表所需的数据源。

  • pptx:用于创建和操作 PowerPoint 文件。

    • Presentation:表示一个 PowerPoint 文件。

    • ChartData:用于定义图表的数据。

    • RGBColor:用于定义颜色。

    • XL_CHART_TYPE:定义图表类型(如柱状图、饼图等)。

    • XL_DATA_LABEL_POSITION:定义数据标签的位置。

    • XL_LEGEND_POSITION:定义图例的位置。

    • Cm 和 Pt:用于设置尺寸和字体大小的单位。

9.1.2定义颜色集合

colors_collection = {
    '2_orange_green': [RGBColor(255, 192, 0), RGBColor(0, 176, 80)],
    '2_green_orange': [RGBColor(0, 176, 80), RGBColor(255, 192, 0)],
    ...
}
  • 这是一个颜色集合字典,键是颜色方案的名称,值是由 RGBColor 定义的颜色列表。

  • 例如,'2_orange_green' 表示两种颜色:橙色和绿色。

9.1.3定义函数 chart_clustered_bar_self_color

这是代码的核心函数,用于在 PowerPoint 中生成簇状柱状图。

9.1.3.1函数参数

def chart_clustered_bar_self_color(
    ppt_script,               # PowerPoint 文件路径
    page_num=0,               # 幻灯片页码(默认第1页)
    left=0.96, top=3.86,      # 图表左上角位置(单位:厘米)
    width=12.5, height=5.87,  # 图表宽度和高度(单位:厘米)
    font_size=6,              # 字体大小
    has_legend=True,          # 是否显示图例
    value_axis_maximum_scale=None,  # 纵坐标最大值
    data_position='居中',      # 数据标签位置
    value_axis_minimum_scale=None,  # 纵坐标最小值
    has_data_labels=True,     # 是否显示数据标签
    df=pd.DataFrame(...),     # 图表数据(默认提供一个示例数据)
    self_chart_style='2_orange_green',  # 图表颜色方案
    y_axis_visible=True,      # 是否显示纵轴
    legend_font_size='',      # 图例字体大小
    data_labels_font_size='', # 数据标签字体大小
    data_percent=False        # 数据标签是否显示为百分比
):
  • 参数非常灵活,可以自定义图表的位置、大小、颜色、数据标签等。

9.1.3.2函数实现

  • 加载 PowerPoint 文件

    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    打开指定的 PowerPoint 文件,并选择指定的幻灯片。
  • 定义图表数据

    chart_data = ChartData()
    chart_data.categories = df.columns
    for i in range(df.shape[0]):
        chart_data.add_series(df.index[i], df.iloc[i])
    • 使用 ChartData 定义图表的数据。

    • categories 是横轴标签(列名)。

    • add_series 添加数据系列(行数据)。

  • 添加图表到幻灯片

    graphic_frame = slide.shapes.add_chart(
        XL_CHART_TYPE.COLUMN_CLUSTERED,  # 图表类型
        Left, Top, Width, Height,        # 图表位置和大小
        chart_data                       # 图表数据
    )
    • 在幻灯片上添加一个簇状柱状图。

  • 美化图表

    • 设置颜色

      if self_chart_style != '':
          colors = colors_collection[self_chart_style]
          for i_x, series in enumerate(chart.series):
              fill = series.format.fill
              fill.solid()
              fill.fore_color.rgb = colors[i_x]
      • 根据 self_chart_style 设置柱状图的颜色。

    • 设置标题

      chart.has_title = False
      • 不显示图表标题。

    • 设置横轴和纵轴

      category_axis.tick_labels.font.size = Pt(font_size)
      value_axis.visible = y_axis_visible
      • 调整横轴和纵轴的字体大小、可见性等。

    • 设置数据标签

      if has_data_labels:
          data_labels.position = XL_DATA_LABEL_POSITION.CENTER
      • 显示数据标签,并设置其位置和格式。

    • 设置图例

      chart.has_legend = has_legend
      chart.legend.position = XL_LEGEND_POSITION.TOP
      • 显示图例,并设置其位置和字体大小。

  • 保存 PowerPoint 文件

    prs.save(ppt_script)
    • 保存修改后的 PowerPoint 文件。

9.1.4调用函数

ppt_script = '销售周报.pptx'
chart_clustered_bar_self_color(ppt_script)
  • 指定 PowerPoint 文件路径,并调用函数生成图表。

9.2项目新增柱状图

9.2.1完善office_ppt_ser.py

项目将在 8.2节‘项目新增表格’的基础上继续推进,进一步完善代码,增加柱状图的功能。具体实现方式是将上述函数迁移至 office_ppt_ser.py 文件中。

import os

import pandas as pd
from pptx import Presentation
from pptx.dml.color import RGBColor
from pptx.enum.shapes import MSO_SHAPE
from pptx.enum.text import MSO_ANCHOR
from pptx.enum.text import PP_ALIGN
from pptx.util import Cm
from pptx.util import Pt

import pandas as pd
from pptx import Presentation
from pptx.chart.data import ChartData
from pptx.dml.color import RGBColor
from pptx.enum.chart import XL_CHART_TYPE
from pptx.enum.chart import XL_DATA_LABEL_POSITION
from pptx.enum.chart import XL_LEGEND_POSITION
from pptx.util import Cm
from pptx.util import Pt

colors_collection = {
    '2_orange_green': [RGBColor(255, 192, 0), RGBColor(0, 176, 80)],
    '2_green_orange': [RGBColor(0, 176, 80), RGBColor(255, 192, 0)],
    '2_orange_olive': [RGBColor(255, 192, 0), RGBColor(0, 176, 180)],
    '2_olive_green': [RGBColor(0, 176, 180), RGBColor(0, 176, 80)],
    '2_white_olive': [RGBColor(255, 255, 255), RGBColor(0, 176, 180)],
    '2_blue_lightblue': [RGBColor(0, 176, 240), RGBColor(169, 227, 255)],
    '2_olive_orange': [RGBColor(0, 176, 180), RGBColor(255, 192, 0)],
    '2_gray_lightblue2': [RGBColor(182, 191, 197), RGBColor(169, 227, 255)],
    '1_olive': [RGBColor(0, 176, 180)],
    '1_orange': [RGBColor(255, 192, 0)],
    '1_gray': [RGBColor(182, 191, 197)],
    '1_lightblue': [RGBColor(0, 176, 240)],
    '1_tangerine': [RGBColor(255, 102, 153)],
    '2_tangerine_gray': [RGBColor(255, 102, 153), RGBColor(182, 191, 197)],
    '2_gray_tangerine': [RGBColor(182, 191, 197), RGBColor(255, 102, 153)],
    '2_gray_lightblue': [RGBColor(182, 191, 197), RGBColor(0, 176, 240)],
    '2_green_gray': [RGBColor(0, 176, 80), RGBColor(182, 191, 197)],
    '2_olive_gray': [RGBColor(0, 176, 180), RGBColor(182, 191, 197)]
}


def new_ppt_add_slide(template, page_num=[0], PPT_Name='新建 Microsoft PowerPoint 演示文稿.pptx',
                      save_path='C:\\Users\\weidong.guo\\Desktop'):
    """
    :param template: PPT模板
    :param page_num: 列表,代表PPT模板里面的幻灯片序号,从0开始
    :param PPT_Name: PPT名字
    :param save_path: 保存路径
    :return:返回新的PPT路径
    """
    if os.path.isdir(save_path):  # save_path是目录
        new_ppt_path = os.path.join(save_path, PPT_Name)  # 将保存路径和PPT名字拼接在一起
    else:
        new_ppt_path = PPT_Name  # save_path不是目录,就不需要拼接
    prs = Presentation(template)  # 用Presentation读取PPT模板
    for i in page_num:  # 遍历需要增加的页数
        prs.slides.add_slide(prs.slide_layouts[i])  # 模板template中增加幻灯片
    prs.save(new_ppt_path)  # 对ppt保存
    return new_ppt_path


def ppt_slide_number(ppt_script):
    prs = Presentation(ppt_script)
    slide_number = len(prs.slides)
    return slide_number


def titlebox(ppt_script, page_num=0, content_text='Backup', font_size=18, left=0.55, top=2.12,
             width=25.81, height=1.08, font_bold=True, font_name='方正兰亭黑_GBK', font_color='',
             alignment='左对齐',
             word_wrap=False):
    """
    参数:
        ppt_script (str): PPT文件路径。
        page_num (int): 幻灯片页码(从0开始)。
        content_text (str): 文本框内容。
        font_size (int): 字体大小(单位:磅)。
        left (float): 文本框左上角的水平位置(单位:厘米)。
        top (float): 文本框左上角的垂直位置(单位:厘米)。
        width (float): 文本框宽度(单位:厘米)。
        height (float): 文本框高度(单位:厘米)。
        font_bold (bool): 是否加粗。
        font_name (str): 字体名称。
        font_color (str): 字体颜色(支持'blue', 'green', 'red', 'yellow', 'orange', 'white', 'gray1', 'black')。
        alignment (str): 对齐方式(支持'左对齐', '居中')。
        word_wrap (bool): 是否自动换行。
        return:
    """
    # ppt_script=r'C:\Users\hp\Desktop\汇总拆分\111.pptx'
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    # 在指定位置添加文本框
    textbox = slide.shapes.add_textbox(Cm(left), Cm(top), Cm(width), Cm(height))
    tf = textbox.text_frame
    tf.word_wrap = word_wrap
    # 在文本框中写入文字
    # 题目
    para = tf.paragraphs[0]  # 新增段落
    para.text = content_text  # 向段落写入文字
    if font_color == 'blue':
        para.font.color.rgb = RGBColor(0, 30, 80)  # 蓝色
    elif font_color == 'green':
        para.font.color.rgb = RGBColor(0, 176, 80)  # 绿色
    elif font_color == 'red':
        para.font.color.rgb = RGBColor(255, 0, 0)  # 红色
    elif font_color == 'yellow':
        para.font.color.rgb = RGBColor(255, 255, 0)  # 红色
    elif font_color == 'orange':
        para.font.color.rgb = RGBColor(255, 192, 0)  # 红色
    elif font_color == 'white':
        para.font.color.rgb = RGBColor(255, 255, 255)  # 红色
    elif font_color == 'gray1':
        para.font.color.rgb = RGBColor(182, 191, 197)  # 红色
    else:
        para.font.color.rgb = RGBColor(0, 0, 0)  # 黑色
    if alignment == '左对齐':
        para.alignment = PP_ALIGN.LEFT
    else:
        para.alignment = PP_ALIGN.CENTER  # 居中

    # 设置字体
    font = para.font
    font.name = font_name  # 字体类型
    font.bold = font_bold  # 加粗
    font.size = Pt(font_size)  # 大小

    prs.save(ppt_script)  # 对ppt保存


# 在PPT中添加矩形框
def shape_rectangle(ppt_script, page_num=0, Left=0.96, Top=3.2, Width=12.5, Height=5.87, fore_color='gray',
                    line_width=0, rotation=0, shape_is_background=False):
    # ppt_script=r'C:\Users\hp\Desktop\汇总拆分\111.pptx'
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    # 在指定位置添加矩形
    shape = slide.shapes.add_shape(autoshape_type_id=MSO_SHAPE.RECTANGLE, left=Cm(Left), top=Cm(Top),
                                   width=Cm(Width), height=Cm(Height))
    # 调整角度
    shape.rotation = rotation
    # 填充背景色
    fill = shape.fill
    fill.solid()

    # 调整线宽
    line = shape.line

    if fore_color == 'gray':
        fill.fore_color.rgb = RGBColor(242, 242, 242)
        line.color.rgb = RGBColor(242, 242, 242)
    elif fore_color == 'gray1':
        fill.fore_color.rgb = RGBColor(127, 127, 127)
        line.color.rgb = RGBColor(127, 127, 127)
    elif fore_color == 'blue':
        fill.fore_color.rgb = RGBColor(0, 30, 80)
        line.color.rgb = RGBColor(0, 30, 80)
    elif fore_color == 'red':
        fill.fore_color.rgb = RGBColor(192, 0, 0)
        line.color.rgb = RGBColor(192, 0, 0)
    elif fore_color == 'yellow':
        fill.fore_color.rgb = RGBColor(255, 255, 0)
        line.color.rgb = RGBColor(255, 255, 0)
    elif fore_color == 'white':
        fill.fore_color.rgb = RGBColor(255, 255, 255)
        line.color.rgb = RGBColor(255, 255, 255)
    elif fore_color == 'lightblue':
        fill.fore_color.rgb = RGBColor(212, 228, 255)
        line.color.rgb = RGBColor(212, 228, 255)

    # fill.fore_color.brightness = 0  # 设为透明
    if shape_is_background == True:
        shape.fill.background()
        # fill.background()
        # fill.back_color.rgb = RGBColor(255, 255, 255)

    line.color.brightness = 0
    line.width = Pt(line_width)
    line.fill.background()  # 调成背景色
    prs.save(ppt_script)  # 对ppt保存


def add_picture(img_path, ppt_script, page_num=0, left=0, top=0, width=4):
    # ppt_script=r'C:\Users\hp\Desktop\汇总拆分\111.pptx'
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    # Left, Top, Width, Height = Cm(left), Cm(top), Cm(width), Cm(height)  # 预设位置及大小
    # slide.shapes.add_picture(img_path, Left, Top, Width, Height)  # 在指定位置按预设值添加图片
    Left, Top, Width = Cm(left), Cm(top), Cm(width)  # 预设位置及大小
    slide.shapes.add_picture(img_path, Left, Top, Width)  # 在指定位置按预设值添加图片
    prs.save(ppt_script)  # 对ppt保存


# 在PPT中表格
def table_Nrows_17cols(ppt_script, page_num=0,
                       title_list=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
                       col_width=[1.15, 2, 5.2, 1, 1.4, 1.4, 1, 1, 1, 1, 1.4, 1, 1, 1, 1, 1, 1], row_height=0.56,
                       fontname='方正兰亭黑_GBK',
                       fontsize=6, leftx=0.55, topx=2.85,
                       df=pd.DataFrame({
                           f'col{i}': range(5) for i in range(17)  # 每列数据为 0 到 4
                       })):
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]
    if df.shape[0] > 13:
        rows, cols = 14, 17  # 设定5行 14列
    else:
        rows = df.shape[0] + 1
        cols = 17
    print('>>>>>>>>>>>>>')
    print(rows, cols)
    left = Cm(leftx)
    top = Cm(topx)
    col_temp = 0
    # 计算表格总列宽
    for i in range(cols):
        col_temp += col_width[i]
    width = Cm(col_temp)
    # 计算表格总行宽
    height = Cm(row_height * rows)
    heightx = row_height * rows
    table = slide.shapes.add_table(rows, cols, left, top, width, height).table
    for i in range(cols):
        table.columns[i].width = Cm(col_width[i])  # 列高

    # 填写表格表头
    for j in range(cols):
        table.cell(0, j).text = str(title_list[j])
    # 填写表格内容
    if df.shape[0] > 13:
        for i in range(rows - 1):
            for j in range(cols):
                table.cell(i + 1, j).text = str(df.iat[i, j])
    else:
        for i in range(df.shape[0]):
            for j in range(cols):
                table.cell(i + 1, j).text = str(df.iat[i, j])

    # 行宽
    for i in range(0, rows):
        table.rows[i].heigth = Cm(row_height)

    # 修改表格样式
    for row in range(rows):
        for col in range(cols):
            # Write column titles
            new = table.cell(row, col).text_frame.paragraphs[0]
            new.font.name = fontname
            if row == 0:
                # 设置文字大小
                table.cell(row, col).text_frame.paragraphs[0].font.size = Pt(fontsize)
                # 设置文字颜色
                table.cell(row, col).text_frame.paragraphs[0].font.color.rgb = RGBColor(255, 255, 255)
                # 设置文字左右对齐
                table.cell(row, col).text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
                # 设置文字上下对齐
                table.cell(row, col).vertical_anchor = MSO_ANCHOR.MIDDLE
                # 设置背景为填充
                table.cell(row, col).fill.solid()
                # 设置背景颜色
                table.cell(row, col).fill.fore_color.rgb = RGBColor(0, 30, 80)
            else:
                table.cell(row, col).text_frame.paragraphs[0].font.size = Pt(fontsize)
                table.cell(row, col).text_frame.paragraphs[0].font.color.rgb = RGBColor(0, 0, 0)
                table.cell(row, col).text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
                table.cell(row, col).vertical_anchor = MSO_ANCHOR.MIDDLE
                table.cell(row, col).fill.solid()
                if row % 2 == 0:
                    table.cell(row, col).fill.fore_color.rgb = RGBColor(231, 231, 233)
                else:
                    table.cell(row, col).fill.fore_color.rgb = RGBColor(203, 204, 208)
    prs.save(ppt_script)  # 对ppt保存
    return heightx


def chart_clustered_bar_self_color(ppt_script, page_num=0, left=0.96, top=3.86, width=12.5, height=5.87,
                                   font_size=6,
                                   has_legend=True, value_axis_maximum_scale=None, data_position='居中',
                                   value_axis_minimum_scale=None,
                                   has_data_labels=True,
                                   df=pd.DataFrame(
                                       {'区域1': ['9', '11'], '区域2': ['6', '9'], '区域3': ['13', '7'],
                                        '区域4': ['9', '11'],
                                        '区域5': ['6', '9'],
                                        '区域6': ['13', '7']},
                                       index=['主题1', '主题2']), self_chart_style='2_orange_green',
                                   y_axis_visible=True,
                                   legend_font_size='',
                                   data_labels_font_size='', data_percent=False):
    prs = Presentation(ppt_script)
    slide = prs.slides[page_num]

    # 定义图表数据
    chart_data = ChartData()
    chart_data.categories = df.columns
    for i in range(df.shape[0]):
        chart_data.add_series(df.index[i], df.iloc[i])
    # 定义图表位置
    Left, Top, Width, Height = Cm(left), Cm(top), Cm(width), Cm(height)  # 预设位置及大小
    print(Left, Top, Width, Height)
    # 添加图表
    graphic_frame = slide.shapes.add_chart(XL_CHART_TYPE.COLUMN_CLUSTERED, Left, Top, Width, Height, chart_data)

    # 将图表美化
    chart = graphic_frame.chart  # 从生成的图表中取出图表类

    # 控制柱状图颜色
    if self_chart_style != '':
        colors_collection_dic = colors_collection
        if self_chart_style in colors_collection:
            colors = colors_collection_dic[self_chart_style]  # 设置颜色列表
            if len(colors) == df.shape[0]:
                for i_x, series in enumerate(chart.series):
                    fill = series.format.fill
                    fill.solid()
                    fill.fore_color.rgb = colors[i_x]
            else:
                chart.chart_style = 8  # 图表整体颜色风格
    else:
        chart.chart_style = 8  # 图表整体颜色风格
    chart.has_title = False  # 不显示标题

    category_axis = chart.category_axis  # category_axis 为chart的category控制类
    category_axis.has_major_gridlines = False  # 是否显示纵轴线
    category_axis.has_minor_gridlines = False
    category_axis.tick_labels.font.italic = False  # tick_labels为图表下标签,置为斜体
    # category_axis.tick_labels.font.name= '方正兰亭黑_GBK'
    category_axis.tick_labels.font.size = Pt(font_size)  # 下标签字体大小
    category_axis.tick_labels.font.color.rgb = RGBColor(0, 0, 0)  # 标签字体颜色

    value_axis = chart.value_axis  # value_axis 为chart的value控制类
    value_axis.visible = y_axis_visible  # 是否隐藏y轴
    value_axis.has_major_gridlines = False  # 是否显示纵轴线
    value_axis.has_minor_gridlines = False
    if value_axis_maximum_scale != None:
        try:
            value_axis.maximum_scale = value_axis_maximum_scale  # 纵坐标最大值
        except:
            pass

    if value_axis_minimum_scale != None:
        value_axis.minimum_scale = value_axis_minimum_scale  # 纵坐标最小值

    # value_axis.minor_tick_mark = XL_TICK_MARK.CROSS
    tick_labels = value_axis.tick_labels  # tick_labels 为chart的纵轴标签控制类
    # tick_labels.number_format = '0%'  # 标签显示样式
    tick_labels.font.bold = False  # 字体加粗
    # tick_labels.font.name = '方正兰亭黑_GBK'
    tick_labels.font.size = Pt(font_size)  # 字体大小
    tick_labels.font.color.rgb = RGBColor(0, 0, 0)  # 标签颜色

    plot = chart.plots[0]  # 取图表中第一个plot
    if has_data_labels == True:
        plot.has_data_labels = has_data_labels  # 是否显示数据标签
        data_labels = plot.data_labels  # 数据标签控制类
        data_labels.font.name = '方正兰亭黑_GBK'
        if data_labels_font_size == '':
            data_labels.font.size = Pt(font_size)  # 字体大小
        else:
            data_labels.font.size = Pt(data_labels_font_size)  # 字体大小
        if data_percent == True:
            data_labels.number_format = '0.0%'  # 标签显示样式
        data_labels.font.color.rgb = RGBColor(0, 0, 0)  # 字体颜色
        if data_position == '居中':
            data_labels.position = XL_DATA_LABEL_POSITION.CENTER  # 字体位置

    chart.has_legend = has_legend  # 是否含有下方的说明
    if has_legend == True:
        chart.legend.position = XL_LEGEND_POSITION.TOP
        chart.legend.horz_offset = 0  # 说明位移量 [-1, 1] 默认为0
        # chart.legend.include_in_layout = True  # 图例在绘图区之外显示
        chart.legend.font.name = '方正兰亭黑_GBK'
        if legend_font_size == '':
            chart.legend.font.size = Pt(font_size)
        else:
            chart.legend.font.size = Pt(legend_font_size)

    prs.save(ppt_script)  # 对ppt保存

9.2.2完善main.py

import os

import pandas as pd

from office_ppt_ser import add_picture
from office_ppt_ser import new_ppt_add_slide
from office_ppt_ser import ppt_slide_number
from office_ppt_ser import shape_rectangle
from office_ppt_ser import table_Nrows_17cols
from office_ppt_ser import titlebox
from office_ppt_ser import table_Nrows_17cols
from office_ppt_ser import chart_clustered_bar_self_color


def main():
    new_ppt = r'PPT模版.pptx'
    new_ppt_path = new_ppt_add_slide(new_ppt, page_num=[1], PPT_Name='销售周报.pptx')
    print(new_ppt_path)

    slide_number = ppt_slide_number(new_ppt_path)
    print(new_ppt_path)

    # 部门报告
    titlebox(new_ppt_path, page_num=0, content_text='部门报告', font_size=20, left=0.55, top=0.94,
             width=3.36, height=1.11, font_bold=True, font_name='方正兰亭黑_GBK', font_color='blue',
             alignment='左对齐',
             word_wrap=False)

    # ■部门商品库存记录
    titlebox(new_ppt_path, page_num=0, content_text='■部门商品库存记录', font_size=12, left=0.58, top=2.14,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # ■部门商品销售记录
    titlebox(new_ppt_path, page_num=0, content_text='■部门商品销售记录', font_size=12, left=0.58, top=6.34,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # ■总结
    titlebox(new_ppt_path, page_num=0, content_text='■总结', font_size=12, left=0.58, top=11.65,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # 2025近期窗帘销售额最高是4000,近期下降最多的是窗帘,下降额是1000
    titlebox(new_ppt_path, page_num=0, content_text='2025近期窗帘销售额最高是4000,近期下降最多的是窗帘,下降额是1000',
             font_size=12, left=0.58, top=12.58,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # 方框1
    shape_rectangle(new_ppt_path, page_num=0, Left=15.89, Top=0.79, Width=3.36, Height=1, fore_color='gray',
                    line_width=0, rotation=0, shape_is_background=False)

    # 方框2
    shape_rectangle(new_ppt_path, page_num=0, Left=19.54, Top=0.79, Width=3.36, Height=1, fore_color='gray',
                    line_width=0, rotation=0, shape_is_background=False)

    # 红灯
    titlebox(new_ppt_path, page_num=0, content_text='红灯',
             font_size=18, left=16.68, top=0.76,
             width=1.8, height=1.03, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='居中',
             word_wrap=False)

    # 绿灯
    titlebox(new_ppt_path, page_num=0, content_text='绿灯',
             font_size=18, left=20.32, top=0.76,
             width=1.8, height=1.03, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='居中',
             word_wrap=False)

    # 增加图片
    img_path = os.path.abspath(r'.\icon\logo.png')
    add_picture(img_path, new_ppt_path, page_num=0, left=23.25, top=0.12, width=1.7)

    # 增加表格
    table_Nrows_17cols(new_ppt_path, page_num=0,
                       title_list=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
                       col_width=[1.15, 2, 5.2, 1, 1.4, 1.4, 1, 1, 1, 1, 1.4, 1, 1, 1, 1, 1, 1], row_height=0.56,
                       fontname='方正兰亭黑_GBK',
                       fontsize=6, leftx=0.55, topx=2.85,
                       df=pd.DataFrame({
                           f'col{i}': range(5) for i in range(17)  # 每列数据为 0 到 4
                       }))
    # 增加柱状图
    chart_clustered_bar_self_color(new_ppt_path, page_num=0, left=0.9, top=7.14, width=23.2, height=4.46,
                                   font_size=6,
                                   has_legend=True, value_axis_maximum_scale=None, data_position='居中',
                                   value_axis_minimum_scale=None,
                                   has_data_labels=True,
                                   df=pd.DataFrame(
                                       {'区域1': ['9', '11'], '区域2': ['6', '9'], '区域3': ['13', '7'],
                                        '区域4': ['9', '11'],
                                        '区域5': ['6', '9'],
                                        '区域6': ['13', '7']},
                                       index=['主题1', '主题2']), self_chart_style='2_orange_green',
                                   y_axis_visible=True,
                                   legend_font_size='',
                                   data_labels_font_size='', data_percent=False)


# 按装订区域中的绿色按钮以运行脚本。
if __name__ == '__main__':
    main()

9.3.4效果展示

分享上述完整代码路径:
链接: https://pan.baidu.com/s/1u3rwNOnZXeqtlnoP_YGZDg?pwd=nhu9 提取码: nhu9

10项目代码main.py升级

对main.py代码通过引入函数参数化,使得生成PPT的过程更加灵活,能够根据不同的输入生成不同的内容

10.1提取函数参数

将main.py代码硬编码文本内容(如“部门报告”、“■部门商品库存记录”等)和数据提取为函数参数。

def generate_ppt(text1, text2, text3, text4, text5, text6, df_table_data, df_chart):
    # 函数体

10.2数据参数化

将表格和图表的数据提取为参数。

# 表格数据
df_table_data = pd.DataFrame({
    f'col{i}': range(5) for i in range(17)  # 每列数据为 0 到 4
})

# 柱状图数据
df_chart = pd.DataFrame(
    {'区域1': ['9', '11'], '区域2': ['6', '9'], '区域3': ['13', '7'],
     '区域4': ['9', '11'],
     '区域5': ['6', '9'],
     '区域6': ['13', '7']},
    index=['主题1', '主题2'])

10.3封装为函数

将生成PPT的逻辑封装到一个函数中

def generate_ppt(text1, text2, text3, text4, text5, text6, df_table_data, df_chart):
    new_ppt = r'PPT模版.pptx'
    new_ppt_path = new_ppt_add_slide(new_ppt, page_num=[1], PPT_Name='销售周报.pptx')
    print(new_ppt_path)

    slide_number = ppt_slide_number(new_ppt_path)
    print(new_ppt_path)

    # 部门报告
    titlebox(new_ppt_path, page_num=0, content_text=text1, font_size=20, left=0.55, top=0.94,
             width=3.36, height=1.11, font_bold=True, font_name='方正兰亭黑_GBK', font_color='blue',
             alignment='左对齐',
             word_wrap=False)

    # ■部门商品库存记录
    titlebox(new_ppt_path, page_num=0, content_text=text2, font_size=12, left=0.58, top=2.14,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # ■部门商品销售记录
    titlebox(new_ppt_path, page_num=0, content_text=text3, font_size=12, left=0.58, top=6.34,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # ■总结
    titlebox(new_ppt_path, page_num=0, content_text=text4, font_size=12, left=0.58, top=11.65,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # 2025近期窗帘销售额最高是4000,近期下降最多的是窗帘,下降额是1000
    titlebox(new_ppt_path, page_num=0, content_text='2025近期窗帘销售额最高是4000,近期下降最多的是窗帘,下降额是1000',
             font_size=12, left=0.58, top=12.58,
             width=24.24, height=0.77, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='左对齐',
             word_wrap=False)

    # 方框1
    shape_rectangle(new_ppt_path, page_num=0, Left=15.89, Top=0.79, Width=3.36, Height=1, fore_color='gray',
                    line_width=0, rotation=0, shape_is_background=False)

    # 方框2
    shape_rectangle(new_ppt_path, page_num=0, Left=19.54, Top=0.79, Width=3.36, Height=1, fore_color='gray',
                    line_width=0, rotation=0, shape_is_background=False)

    # 红灯
    titlebox(new_ppt_path, page_num=0, content_text=text5,
             font_size=18, left=16.68, top=0.76,
             width=1.8, height=1.03, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='居中',
             word_wrap=False)

    # 绿灯
    titlebox(new_ppt_path, page_num=0, content_text=text6,
             font_size=18, left=20.32, top=0.76,
             width=1.8, height=1.03, font_bold=False, font_name='方正兰亭黑_GBK', font_color='black',
             alignment='居中',
             word_wrap=False)

    # 增加图片
    img_path = os.path.abspath(r'.\icon\logo.png')
    add_picture(img_path, new_ppt_path, page_num=0, left=23.25, top=0.12, width=1.7)

    # 增加表格
    table_Nrows_17cols(new_ppt_path, page_num=0,
                       title_list=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
                       col_width=[1.15, 2, 5.2, 1, 1.4, 1.4, 1, 1, 1, 1, 1.4, 1, 1, 1, 1, 1, 1], row_height=0.56,
                       fontname='方正兰亭黑_GBK',
                       fontsize=6, leftx=0.55, topx=2.85,
                       df=df_table_data.copy()
                       )
    # 增加柱状图
    chart_clustered_bar_self_color(new_ppt_path, page_num=0, left=0.9, top=7.14, width=23.2, height=4.46,
                                   font_size=6,
                                   has_legend=True, value_axis_maximum_scale=None, data_position='居中',
                                   value_axis_minimum_scale=None,
                                   has_data_labels=True,
                                   df=df_chart.copy(), self_chart_style='2_orange_green',
                                   y_axis_visible=True,
                                   legend_font_size='',
                                   data_labels_font_size='', data_percent=False)

10.4调用函数

在 if __name__ == '__main__': 中调用 generate_ppt 函数,并传入相应的参数:

if __name__ == '__main__':
    text1 = '部门报告'
    text2 = '■部门商品库存记录'
    text3 = '■部门商品销售记录'
    text4 = '■总结'
    text5 = '红灯'
    text6 = '绿灯'

    # 表格数据
    df_table_data = pd.DataFrame({
        f'col{i}': range(5) for i in range(17)  # 每列数据为 0 到 4
    })

    # 柱状图数据
    df_chart = pd.DataFrame(
        {'区域1': ['9', '11'], '区域2': ['6', '9'], '区域3': ['13', '7'],
         '区域4': ['9', '11'],
         '区域5': ['6', '9'],
         '区域6': ['13', '7']},
        index=['主题1', '主题2'])

    generate_ppt(text1, text2, text3, text4, text5, text6, df_table_data, df_chart)

分享上述完整代码路径:
链接: https://pan.baidu.com/s/13GpH2zDegOXCsLPBNbQN9g?pwd=et2p 提取码: et2p

11总结

感谢大家看到最后,本文通过一个具体的案例,展示了如何利用 Python 自动化生成 PPT 报告。介绍了 python-pptx 模块的基本用法,还通过一个完整的项目案例,详细讲解了如何从零开始构建一个自动化生成 PPT 的工具。通过模块化的设计和代码封装,文章展示了如何提高代码的复用性和可维护性,最终实现高效、准确的 PPT 报告生成。对于需要频繁生成 PPT 报告的职场人士来说,提供了一个非常实用的解决方案,能够显著提高工作效率,减少重复性劳动。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值