pu369com

python实现docx转pptx(word文档转幻灯片)

以前都是手工将word内容复制粘贴到ppt中,实在受够了。

文心一言真是大忽悠,给的转换方案是用docx2pptx库,然而根本没有这个库,倒是可以用我下面的代码生成这个库:-)

网上很多方案是转成图片形式插入ppt,导致无法正常编辑ppt.

于是研究出以下方案:

1.先将word文档的页面设置改为自定义大小,使每一页文字可容纳于一张幻灯片

2.去掉word文档页码(否则后面读取时会把页码作为正文的一部分,还要处理),然后转换为pdf格式(以便于按页读取,因为用代码读取word文档的一页比较困难,参看我的上一篇文章:python 获取word页数 https://www.cnblogs.com/pu369/p/17757633.html)

3.读取pdf每一页的文字,粘贴到ppt中。(注意在代码中设置好文本框大小及字号,保证ppt的文本框比pdf页要大。否则会因段落的换行符而影响显示效果)

4.打开ppt选择设计模板。然后可以按正常的PPT进行编辑。

主要用到三个库:1.用docx2pdf将word转pdf  2.用 PyPDF2读取pdf    3.用pptx生成幻灯片

代码:

from pptx import Presentation
from pptx.enum.text import PP_PARAGRAPH_ALIGNMENT,MSO_ANCHOR
from pptx.util import Pt
from docx2pdf import convert
import PyPDF2

wordfile = "1.docx"
pdffile = "{}{}".format(wordfile[:-4],"pdf")
# 将Word文档转换为pdf 
convert(wordfile, pdffile)

# 创建一个Presentation对象  
prs = Presentation()
#打开pdf文件
with open(pdffile, 'rb') as file:
    # 创建一个PDF Reader对象
    pdf_reader = PyPDF2.PdfFileReader(file)
    # 获取PDF文件中页面的数量
    num_pages = pdf_reader.numPages   
    # 读取一页的内容
    for i in range(0,num_pages):
        page = pdf_reader.getPage(i)
        pdftext = page.extractText()#如有页码,则读出的第一个字符为页码
        # 在演示文稿中添加幻灯片
        slide_layout = prs.slide_layouts[5] # 5是标题幻灯片的布局  
        slide = prs.slides.add_slide(slide_layout)
        # 在幻灯片上添加一个shapge,并设置高度和宽度
        shapes0 =  slide.shapes[0]
        shapes0.height = Pt(450)
        shapes0.width = Pt(660)
        #左右边距
        shapes0.top = Pt(100)
        shapes0.left = Pt(100)
        #在shape里面添加文本
        txt_frame = slide.shapes[0].text_frame
        txt_frame.text = pdftext      
        #段落左对齐
        for p in txt_frame.paragraphs:
            p.alignment = 1
            p.font.size = Pt(25)
        #文本框顶端对齐
        txt_frame.vertical_anchor = MSO_ANCHOR.TOP      # 保存演示文稿  
    prs.save('1.pptx')  

注意:代码主要适用于文字 ,表格也会变成文字形式,图片我没有试。

 

 补充:上述代码直接双击运行不了,但在IDLE中正常,原因是:

collections.Container自 3.3 起已弃用并在 3.10 中删除,因此请检查您的 python 版本,检查该模块的更新版本是否可用

解决方法是导入模块集合和集合。导入pptx前的abc,例:

import collections
import collections.abc

好像IDLE会自动导入,所以运行时不会出错。

 

而且,还有个问题是pdf的一页显示文字是对齐的,但将文字转回ppt,就变得不整齐了。

所以还不如不绕弯子,直接读取word的段落,保存到列表中,并将字数太长的段落拆分开。

然后,将列表中的文字分别放到每一张幻灯片上:

代码:

from docx import Document
from pptx import Presentation
from pptx.enum.text import PP_PARAGRAPH_ALIGNMENT,MSO_ANCHOR
from pptx.util import Pt
 
file_path = '1.docx'  # 替换为实际word文件路径
#每页ppt允许的最多字数
NUM_PERPAGE = 200
#打开word
doc = Document(file_path)
# 创建一个Presentation对象,由于pptx无法设置主题及母版,
#所以我们先准备一个带主题的template.pptx作为模板,内容可以为空。
prs = Presentation("template.pptx")

#按段落读取word,并准备一个列表wordtexts保存所有段落内容,每个元素容纳一张ppt的文字
wordtexts = [] 
for paragraph in doc.paragraphs:    
    paratext = paragraph.text
    #空行就不要了
    if paratext.strip() != '':
        #若一张ppt超过规定字数perpage,则拆分开
        if len(paratext)> NUM_PERPAGE:
            splitparas = [paratext[i:i+NUM_PERPAGE] for i in range(0, len(paratext), NUM_PERPAGE)]
            wordtexts.extend(splitparas)
        else:
            wordtexts.append(paratext)
'''            
#如果两张ppt的文字加起来还不够半张ppt,则合并,结合存入wordtexts2
wordtexts2=[]
if  len(wordtexts) % 2 == 0:  #偶数
    numpage = len(wordtexts)
else:
    numpage = len(wordtexts) - 1
    
for i in range(0,numpage,2):
    nexti = i + 1
    if((len(wordtexts[i]) + len(wordtexts[nexti])) < NUM_PERPAGE ): #整除
        wordtexts2.append(wordtexts[i] + wordtexts[nexti])
    else:#字数够了,不用合并,直接追加两张ppt       
        wordtexts2.append(wordtexts[i])
        wordtexts2.append(wordtexts[nexti])
if len(wordtexts) % 2 == 1: #奇数张的最后一张ppt   
    wordtexts2.append(wordtexts[len(wordtexts) - 1])
'''        
for ppttext in wordtexts:
    # 在演示文稿中添加幻灯片
    slide_layout = prs.slide_layouts[5] # 5是标题幻灯片的布局  
    slide = prs.slides.add_slide(slide_layout)
    # 在幻灯片上添加一个shapge,并设置高度和宽度
    shapes0 =  slide.shapes[0]
    shapes0.height = Pt(450)
    shapes0.width = Pt(600)
    #左右边距
    shapes0.top = Pt(60)
    shapes0.left = Pt(60)
    #在shape里面添加文本
    txt_frame = slide.shapes[0].text_frame
    new_para = txt_frame.add_paragraph()  # 添加段落
    new_para.text = ppttext
    new_para.line_spacing = 1.5    # 1.5 倍的行距          
    #段落左对齐
    for p in txt_frame.paragraphs:
        p.alignment = 1
        p.font.size = Pt(25)
    #文本框顶端对齐
    txt_frame.vertical_anchor = MSO_ANCHOR.TOP
'''
#删除所有空shape。从最后面往前删,以避免循环过程中的顺序变化(这段代码在这个位置其实不起作用)
for i in range(len(prs.slides),0,-1):    
    for j in range(len(prs.slides[i-1].shapes),0, -1):
        shapej = prs.slides[i-1].shapes[j-1]
        if not  shapej.has_text_frame:
            prs.slides[i-1].shapes._spTree.remove(shapej._element)
'''          
# 保存演示文稿  
prs.save('1.pptx')

 

 

 

https://baijiahao.baidu.com/s?id=1664903484937508104&wfr=spider&for=pc

https://blog.csdn.net/naer_chongya/article/details/131429885

https://blog.csdn.net/programmerbug/article/details/127872706

posted on 2023-10-13 12:22  pu369com  阅读(230)  评论(0编辑  收藏  举报

导航