将一份ppt的每一页字体、大小、是否加粗都统一,是一个常见需求。特别是字体统一是高频、热点需求。在python操控ppt常用库python-pptx中有一个bug,对字体的修改只能修改数字和英文字母,无法修改汉字。即 run.font.namet属性只能修改英文和数字,并且 run.font.name识别的也是英文和数字的名称。如文本框中英文和数字是’arial’汉字是宋体,则会返回’arial’。因为这个包,没有针对汉字的api,而且这个包很久没更新了,开发者提供了解决思路是修改office文件的底层xml来实现,修改xml中的a:ea的typeface属性,网上已经有人用 pptx_ea_font 这个包实现了该功能。
首先安装对应的包
pptx和docx的包为,注意不是pptx和docx
pip install python-pptx pip install python-docx
pptx_ea_font 安装方法为
pip install pptx_ea_font
导入相应模块
from pptx import presentation import pptx_ea_font from docx import document from pptx.util import cm, pt
一、修改ppt中每一页的字体
python修改
1、可以修改字体、大小、是否加粗
2、图形、图表、表格的汉字还不能修改,需要下一步增加该功能
函数如下:
def change_ppt_font(ppt_file, new_font,new_size=none,bold=none,line_spacing=none): # 打开ppt文件 presentation = presentation(ppt_file) # 循环遍历每个slide for slide in presentation.slides: # 循环遍历slide中的每个shape for shape in slide.shapes: # 检查shape类型是否为文本框 if shape.has_text_frame: # 获取文本框中的文字 text_frame = shape.text_frame for paragraph in text_frame.paragraphs: if line_spacing is not none: paragraph.line_spacing = line_spacing for run in paragraph.runs: # 修改字体 pptx_ea_font.set_font(run,new_font) #以下方法只能修改数字和英文 #run.font.name = new_font if new_size : run.font.size = pt(new_size) if bold is not none: run.font.bold = bold # 保存修改后的ppt文件 new_ppt_file = ppt_file.replace(".pptx", "_new.pptx") presentation.save(new_ppt_file) print("字体修改完毕!")
以上代码只能修改文本框,因为图形或者组合过的图像是个msogroup对象。
vba代码库—修改文本框和图表字体为微软雅黑和1.5倍(常用)
以下代码更全面可以修改表格和图形的,但是不能修改图表的和文本框聚合的图形中的文字。
sub changefontinallslides() dim oslide as slide dim oshape as shape dim otable as table dim orow as row dim ocell as cell dim otxtrange as textrange dim ogroup as shapes dim ochildshape as shape ' 遍历演示文稿中的所有幻灯片 for each oslide in activepresentation.slides ' 遍历幻灯片中的所有形状 for each oshape in oslide.shapes ' 如果形状包含文本框 if oshape.hastextframe then set otxtrange = oshape.textframe.textrange ' 设置文本框中文本的字体属性 with otxtrange.font .name = "微软雅黑" '.size = 14 '.color.rgb = rgb(255, 0, 0) '.bold = true .italic = false .underline = false end with ' 行距1.5 otxtrange.paragraphformat.spacewithin = 1.5 end if ' 如果形状是组合图形 if oshape.type = msogroup then ' 直接遍历组合图形内的子形状 for i = 1 to oshape.groupitems.count set ochildshape = oshape.groupitems.item(i) ' 如果子形状包含文本框 if ochildshape.hastextframe then set otxtrange = ochildshape.textframe.textrange ' 设置文本框中文本的字体属性 with otxtrange.font .name = "微软雅黑" '.size = 14 '.color.rgb = rgb(255, 0, 0) '.bold = true .italic = false .underline = false end with ' 行距1.5 otxtrange.paragraphformat.spacewithin = 1.5 end if next i end if ' 如果形状包含表格 if oshape.hastable then set otable = oshape.table ' 遍历表格中的所有行和单元格 for each orow in otable.rows for each ocell in orow.cells if ocell.shape.hastextframe then set otxtrange = ocell.shape.textframe.textrange ' 设置表格单元格中文本的字体属性 with otxtrange.font .name = "微软雅黑" '.size = 20 '.color.rgb = rgb(255, 0, 0) '.bold = true .italic = false .underline = false end with end if next ocell next orow end if next oshape next oslide end sub
二、ppt转word—将文本框中的字都放到word里
from pptx import presentation from docx import document def extract_text_from_shape(shape): text = "" if hasattr(shape, "text"): text += shape.text + " " elif shape.shape_type == 6: # 6 corresponds to group_shape for subshape in shape.shapes: text += extract_text_from_shape(subshape) return text def ppt_to_word(presentation_path, output_path): # 打开ppt presentation = presentation(presentation_path) # 创建word文档 doc = document() # 遍历ppt中的每一张幻灯片 for slide in presentation.slides: # 提取幻灯片的文本内容 slide_text = "" for shape in slide.shapes: slide_text += extract_text_from_shape(shape) # 在word文档中插入文本内容 doc.add_paragraph(slide_text) # 保存word文档 doc.save(output_path) if __name__ == '__main__': s = r"" t = r"" ppt_to_word(s, t)
三、ppt插入图片和修改位置
1、python ppt插入图片 —推荐
1、使用get_image_list(img_dir)函数获取ppt文件路径列表,方便对列表操作以控制插入ppt的图片的顺序,如对列表进行翻转、排序等,可以让图片反序、按一定序列插入ppt。
2、使用create_ppt_with_images函数将图片插入ppt,其中slide.shapes.add_picture(img_file, left, top, width, height)代码进行插入,img_file是要插入的图片, left, top, width, height是插入的坐标和大小,left, top表示插入位置,手工设定。 width, height是插入图片的大小,可以手工设定也可以通过 width ,height = prs.slide_width, prs.slide_height的方式获取幻灯片的大小,然后按比例输入图片的大小。
import os from pptx import presentation from pptx.util import inches def get_image_list(img_dir): """ 读取文件夹中的图片文件名并返回一个列表。 """ img_files = os.listdir(img_dir) img_path = [os.path.join(img_dir, f) for f in img_files if f.endswith('.jpg') or f.endswith('.png')] # 你可以根据需要修改这里,只选择你需要的图片格式 return img_path def create_ppt_with_images(img_list, output_ppt_path): """ 将给定的图片列表按顺序插入到一个新的ppt演示文稿中。 """ prs = presentation() for i, img_file in enumerate(img_list): slide = prs.slides.add_slide(prs.slide_layouts[6]) # 使用标题和内容布局,你可以根据需要选择其他布局 # 设置图片位置和大小,使其铺满整个幻灯片 left = top = 0 width ,height = prs.slide_width, prs.slide_height pic = slide.shapes.add_picture(img_file, left, top, width, height) prs.save(output_ppt_path) if __name__ == '__main__': # 请将 'path_to_your_images' 替换为你的图片文件夹路径,将 'output.pptx' 替换为你想要保存ppt的路径和文件名 path_img=r"xx" path_out=r"output.pptx" list_img=get_image_list(path_img) create_ppt_with_images(list_img,path_out)
2、vba ppt插入图片
sub insertpicturestoppt() dim sld as slide dim shp as shape dim i, count, numpictureperslide, curslide as long dim slidewidth, slideheight as single dim autoaddslide as boolean curslide = activewindow.view.slide.slideindex '用这个变量设置每页 ppt 要插入的图片数量 numpictureperslide = 1 '用这个变量设置是否在页数不足时自动添加新的 ppt 页来插入所有选中的图片,设置为 false 来取消该功能 autoaddslide = true fd = split(filedialogopen, vblf) if left(fd(0), 1) = "-" then debug.print "canceled" exit sub end if slidewidth = activepresentation.pagesetup.slidewidth slideheight = activepresentation.pagesetup.slideheight if autoaddslide then if (activepresentation.slides.count - curslide + 1) * numpictureperslide < ubound(fd) - lbound(fd) + 1 then total = int((ubound(fd) - lbound(fd) + 1) / numpictureperslide - activepresentation.slides.count + curslide - 1 + 0.5) for i = activepresentation.slides.count + 1 to activepresentation.slides.count + total ' 在末尾添加空白页 'activepresentation.slides.add i, pplayoutblank ' 在当前页之后添加空白页 ' activepresentation.slides.add curslide, pplayoutblank ' activepresentation.slides(cursldie - 1).select ' 在当前页之后复制当前页 activepresentation.slides(curslide).duplicate next i end if end if count = 0 for each sld in activepresentation.slides ' 跳过隐藏的 ppt 页,并跳过在当前页之前的页 debug.print sld.slideindex & " >= " & curslide if sld.slideshowtransition.hidden = msofalse and sld.slideindex >= curslide then if count + lbound(fd) > ubound(fd) then ' no picture to insert exit for end if for i = 1 to numpictureperslide if count + lbound(fd) <= ubound(fd) then set shp = sld.shapes.addpicture( _ filename:=fd(count + lbound(fd)), _ linktofile:=msofalse, _ savewithdocument:=msotrue, _ left:=0, _ top:=0, _ width:=-1, _ height:=-1 _ ) with shp .lockaspectratio = msotrue ' 锁定纵横比 '.scaleheight 0.75, msotrue .left = slidewidth / numpictureperslide * i - .width / 2 .top = (slideheight - .height) / 2 '.zorder msosendtoback ' 将图片设置为最底层 end with count = count + 1 else exit for end if next i end if next sld 'msgbox "processing finished. inserted (" & count & ") pictures in total" msgbox "插入图片完成,共插入 " & count & " 张图片" end sub function filedialogopen() as string #if mac then ' 默认路径 mypath = macscript("return (path to desktop folder) as string") smacscript = "set applescript's text item delimiters to "","" " & vbnewline & _ "try " & vbnewline & _ "set thefiles to (choose file of type {""png"", ""jpg"", ""jpeg"", ""svg"", ""tiff"", ""gif""}" & _ "with prompt ""请选择一个或多个要插入的图片"" default location alias """ & _ mypath & """ multiple selections allowed true)" & vbnewline & _ "set applescript's text item delimiters to """" " & vbnewline & _ "on error errstr number errornumber" & vbnewline & _ "return errornumber " & vbnewline & _ "end try " & vbnewline & _ "repeat with i from 1 to length of thefiles" & vbnewline & _ "if i = 1 then" & vbnewline & _ "set fpath to posix path of item i of thefiles" & vbnewline & _ "else" & vbnewline & _ "set fpath to fpath & """ & vbnewline & _ """ & posix path of item i of thefiles" & vbnewline & _ "end if" & vbnewline & _ "end repeat" & vbnewline & _ "return fpath" filedialogopen = macscript(smacscript) #else with application.filedialog(msofiledialogopen) .allowmultiselect = true .title = "请选择要一个或多个要插入的图片" .filters.add "图片", "*.png; *.jpg; *.jpeg; *.svg; *.tiff; *.gif", 1 if .show = -1 then filedialogopen = "" for i = 1 to .selecteditems.count if i = 1 then filedialogopen = .selecteditems.item(i) else filedialogopen = filedialogopen & vblf & .selecteditems.item(i) end if next else filedialogopen = "-" end if end with #end if end function
3、ppt中图片修改位置
sub test() '获取所有ppt页面 for each currentslide in activepresentation.slides '循环每个页面 for each shp in currentslide.shapes 'type = 13是图片 17是文本框 if shp.type = 13 then shp.top = 10 '设置top位置 shp.left = 10 '设置left位置 shp.height = 10000 '设置图片高度位置 shp.width = 600 end if next shp next currentslide end sub
四、合并文件夹下多个ppt
注意:
1、不能用pptx库来实现,会设计页面内容复制等,非常麻烦
使用win32com.client实现
2、使用new_ppt.saveas而不是save 方法。save 方法并不接受路径作为参数;它默认会在 powerpoint 打开时指定的默认位置保存文件。
import win32com.client as win32 import os import re def merge_ppt(path:str): """ :param path: ppt所在文件路径 :return: none """ files = os.listdir(path) application = win32.gencache.ensuredispatch("powerpoint.application") application.visible = 1 new_ppt = application.presentations.add() for file in files: abs_path = os.path.join(path, file) exit_ppt = application.presentations.open(abs_path) print(abs_path) page_num = exit_ppt.slides.count exit_ppt.close() new_ppt.slides.insertfromfile(abs_path, new_ppt.slides.count, 1, page_num) new_ppt.saveas(os.path.join(path, 'merged.pptx')) # 保存在c:\users\administrator\documents\下 application.quit() path=r"c:\xx" merge_ppt(path)
五、ppt中插入形状中的图形—python绘制复杂图形
- 通过在纸上手绘或者drawio中画系统框图,然后把图片传给多模态大模型
- 让大模型生成ppt图形python代码
- 运行代码生成图形
1、插入矩形
from pptx import presentation from pptx.util import inches, pt from pptx.enum.shapes import mso_shape from pptx.dml.color import rgbcolor # 创建一个新的空白ppt presentation = presentation() # 创建一个新的幻灯片 slide_layout = presentation.slide_layouts[0] slide = presentation.slides.add_slide(slide_layout) # 在幻灯片上添加一个矩形形状 left = top = inches(1) width = height = inches(2) shape = slide.shapes.add_shape( mso_shape.rectangle, left, top, width, height ) # 设置矩形形状的填充颜色和轮廓线颜色 fill = shape.fill fill.solid() fill.fore_color.rgb = rgbcolor(0x00, 0x00, 0x00) # 黑色 line = shape.line line.color.rgb = rgbcolor(0xff, 0x00, 0x00) # 红色 line.width = pt(3) # 设置轮廓线的宽度 # 保存ppt文件 presentation.save('example.pptx')
2、将矩形改为三维的
sub convertrectanglesto3d() dim slide as slide dim shape as shape dim idepth as integer ' 设定三维深度,可根据需要调整 ' 选择要处理的幻灯片,这里以当前幻灯片为例 set slide = application.activewindow.view.slide ' 设置三维深度 idepth = 50 ' 示例值,可以根据需要调整 ' 遍历幻灯片上的所有形状 for each shape in slide.shapes ' 检查形状是否为矩形 if shape.type = msoshaperectangle then ' 应用三维格式 with shape.threed .visible = true .depth = idepth ' 可以根据需要调整其他三维属性,例如旋转角度等 end with end if next shape msgbox "完成!所有矩形已转换为三维。" end sub
3、画系统框图
from pptx import presentation from pptx.util import inches, pt from pptx.enum.shapes import mso_shape from pptx.dml.color import rgbcolor from pptx.enum.text import pp_align def hex_to_rgb(hex_color): """converts a hex color string to an rgbcolor object.""" hex_color = hex_color.lstrip('#') return rgbcolor(*tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))) def single_line(presentation, slide, box_contents, box_height, total_length, start_position, color,fontname= 'microsoft yahei' ): # 设置方框的总长度和高度 total_length_in = inches(total_length) box_height_in = inches(box_height) # 计算每个方框的宽度 num_boxes = len(box_contents) box_width_in = total_length_in / num_boxes # 设置线条颜色为白色 line_color = rgbcolor(255, 255, 255) # 判断颜色输入类型并转换为rgbcolor if isinstance(color, str) and color.startswith('#'): fill_color = hex_to_rgb(color) elif isinstance(color, (tuple, list)) and len(color) == 3: fill_color = rgbcolor(*color) else: raise valueerror("invalid color format") # 设置起始位置 start_left = inches(start_position[0]) start_top = inches(start_position[1]) # 循环添加方框 for i, content in enumerate(box_contents): # 计算当前方框的位置 left = start_left + i * box_width_in top = start_top # 在幻灯片上添加矩形形状 shape = slide.shapes.add_shape( mso_shape.rectangle, left, top, box_width_in, box_height_in ) # 设置填充颜色 fill = shape.fill fill.solid() fill.fore_color.rgb = fill_color # 设置线条颜色 line = shape.line line.color.rgb = line_color line.width = pt(1) # 添加文本到方框内并设置居中对齐 if content: tf = shape.text_frame p = tf.paragraphs[0] p.text = content p.alignment = pp_align.center # 添加字体设置 run = p.runs[0] font = run.font font.name =fontname # 设置字体为微软雅黑 #font.size = pt(14) # 可以根据需要调整字体大小 # 创建多行矩形 #rectangle_rows 配置字典, step = 0.2每行之间的间隔是0.2英寸 def multi_line(rectangle_rows, step,output_filename='example.pptx'): presentation = presentation() slide_layout = presentation.slide_layouts[6] slide = presentation.slides.add_slide(slide_layout) y_offset = 0 for row_id, row_config in rectangle_rows.items(): start_position = (row_config['start_position'][0], row_config['start_position'][1] - y_offset) single_line(presentation, slide, row_config['box_contents'], row_config['box_height'], row_config['total_length'], start_position, row_config['color']) y_offset += row_config['box_height'] + step print("确保无同文件路径ppt打开") presentation.save(output_filename) if __name__ == "__main__": # 定义一个字典,用于存储每一行的配置, """ #1表示是第一行 1: { # 每个矩形内显示的内容列表 'box_contents': ['box 1', 'box 2', 'box 3', 'box 4'], # 每个矩形的高度(单位通常是英寸) 'box_height': 0.8, # 整行矩形的总长度(单位通常是英寸),这决定了矩形的宽度和它们之间的间距 'total_length': 8, # 该行第一个矩形的起始位置坐标(x, y),单位是英寸 # x坐标是水平方向的位置,y坐标是垂直方向的位置 'start_position': (1.4, 1.4), # 矩形的填充颜色,使用十六进制颜色代码 'color': '#1abc9c' # 这是一种浅绿色 }, """ rectangle_rows ={ 1: { 'box_contents': ['box 1', 'box 2', 'box 3', 'box 4'], 'box_height': 0.8, 'total_length': 8, 'start_position': (1, 4.8), 'color': '#1abc9c' }, 2: { 'box_contents': ['box 1', 'box 2', 'box 3', 'box 4', 'box 5'], 'box_height': 0.8, 'total_length': 8, 'start_position': (1, 4.8), 'color': '#00cc99' }, 3: { 'box_contents': ['box 1', 'box 2', 'box 3', 'box 4', 'box 5'], 'box_height': 0.8, 'total_length': 8, 'start_position': (1, 4.8), 'color': '#009dc4' }, 4: { 'box_contents': ['box 1', 'box 2', 'box 3', 'box 4', 'box 5'], 'box_height': 0.8, 'total_length': 8, 'start_position': (1, 4.8), 'color': '#0d98ba' }, 5: { 'box_contents': ['box 1', 'box 2', 'box 3', 'box 4', 'box 5'], 'box_height': 0.8, 'total_length': 8, 'start_position': (1, 4.8), 'color': '#00c5cd' }, 6: { 'box_contents': ['box 1', 'box 2', 'box 3', 'box 4', 'box 5'], 'box_height': 0.8, 'total_length': 8, 'start_position': (1, 4.8), 'color': '#00ced1' } } #每行的间隔 step = 0.05 multi_line(rectangle_rows, step ,output_filename='系统框图.pptx')
六、ppt修改标题文本框的格式
用母版修改最合适,但是母版修改完之后总有部分框不改变格式,通感python 定位标题文本框
判断标题的逻辑为:获取第一个文本框且位于顶端(距离顶端小于页面的1/20)。
from pptx import presentation from pptx.util import pt from pptx.enum.text import pp_align from pptx.dml.color import rgbcolor def modify_ppt_title_format(ppt_path, font_name, font_size, font_color): """ 修改ppt文件中所有幻灯片标题的格式。 参数: ppt_path (str): ppt文件的路径。 font_name (str): 标题字体。 font_size (int): 字号。 font_color (tuple): 颜色rgb值。 """ # 打开现有的ppt文件 presentation = presentation(ppt_path) # 获取幻灯片的高度 slide_height = presentation.slide_height top_threshold = slide_height / 20 # 定义顶端的阈值 # 遍历每一张幻灯片 for slide in presentation.slides: # 查找标题形状(通常第一个形状是标题) if slide.shapes: first_shape = slide.shapes[0] if first_shape.has_text_frame and first_shape.text.strip(): # 确保形状有文本框并且不为空 # 检查第一个形状是否位于顶端 if first_shape.top < top_threshold: text_frame = first_shape.text_frame if len(text_frame.paragraphs) > 0: # 确保段落存在 paragraph = text_frame.paragraphs[0] # 假设标题是第一个段落 # 修改文本内容(可选) # paragraph.text = "新的标题" # 如果需要修改标题文本,取消注释这行 # 设置字体大小、颜色等属性 for run in paragraph.runs: font = run.font font.name = font_name # 更改字体 font.size = pt(font_size) # 更改字号 font.color.rgb = rgbcolor(*font_color) # 设置颜色 # 设置对齐方式(可选) paragraph.alignment = pp_align.center # 居中对齐 # 保存修改后的ppt到一个新的文件 modified_ppt_path = 'modifiedppt.pptx' presentation.save(modified_ppt_path) print(f"ppt已保存至:{modified_ppt_path}") path=r" " # 示例调用 modify_ppt_title_format(path, font_name='arial', font_size=36, font_color=(0, 0, 0))
七、基础知识
1、prs.slide_layouts[6]指定幻灯片布局,其中slide_layouts[6]是第6种布局,是一个白板。
以上就是使用python进行批量操作ppt的示例详解的详细内容,更多关于python操作ppt的资料请关注代码网其它相关文章!
发表评论