從PPTX轉(zhuǎn)PDF的方式很多,通過(guò)ppt自帶的工具即可實(shí)現(xiàn)快速而精確的轉(zhuǎn)換。但從PDF轉(zhuǎn)PPTX的轉(zhuǎn)換卻缺乏簡(jiǎn)單便捷的方式。
該問(wèn)題的需求在于:
ppt編輯公式比較繁瑣,且需要花費(fèi)大量的時(shí)間用來(lái)調(diào)節(jié)字體等格式,且不美觀
latex編輯公式較為方便,但生成的PDF與課堂白板sewoo并不兼容,無(wú)法很好地利用畫筆在課件上進(jìn)行標(biāo)記,給授課帶來(lái)不遍。
一個(gè)簡(jiǎn)單的想法是看看有無(wú)現(xiàn)有的工具將PDF直接導(dǎo)出為PPTX,但發(fā)現(xiàn)無(wú)論是adobe acrobat還是foxit pdf reader,亦或者PDF24 tools均喜歡做額外的工作,進(jìn)行OCR識(shí)別,效果還不甚理想。直接轉(zhuǎn)化為圖片再拼接成PPTX不香么!多此一舉!
好在PDF24 tools可以將PDF拆分成圖片,而PPT又可以很方便地導(dǎo)入圖片。


這種方式可以有效地解決我的需求。但我想更簡(jiǎn)單點(diǎn),有沒(méi)有一鍵完成的可能?
最初的想法是使用VBA,隨后導(dǎo)出為exe可執(zhí)行程序。但缺乏現(xiàn)有的教程指導(dǎo)。隨后查詢Github,找到了幾個(gè)pdf轉(zhuǎn)png的項(xiàng)目,結(jié)合網(wǎng)上的部分資源,耗時(shí)一個(gè)晚上,實(shí)現(xiàn)了一鍵tex->pdf->pngs->pptx的工作流。
# python
# windows
# pyinstaller -i pdf2pptx.ico --add-data=".\default.pptx;." -F -w pdf2pptx.py
# macOS
# pyinstaller -i pdf2pptx.ico --add-data=".\default.pptx:." -F pdf2pptx.py
# pipenv 下打包縮小體積
# pip install pyinstaller pymupdf python-pptx PyPDF2
import fitz # pip install pymupdf
import os
import sys
import shutil
import pptx #pip install python-pptx
import PyPDF2
#生成資源文件目錄訪問(wèn)路徑
def resource_path(relative_path):
if getattr(sys, 'frozen', False): #是否Bundle Resource
base_path = sys._MEIPASS
else:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
def pdf2pptx(pdf_name,zoom):
# pdf2pngs
pdf_name=os.path.abspath(pdf_name)
if pdf_name[-4:].lower() == '.pdf':
dir_name = os.path.dirname(pdf_name) # 獲得地址的父鏈接
base_name = os.path.basename(pdf_name)[0:-4] # 獲得地址的文件名
path = dir_name + os.sep + base_name
if not os.path.exists(path):
os.makedirs(path)
with open(pdf_name,'rb') as f:
pdfwidth=PyPDF2.PdfFileReader(f).getPage(0).mediaBox[2]
pdfheight=PyPDF2.PdfFileReader(f).getPage(0).mediaBox[3]
pdfscale=pdfheight/pdfwidth
pdfmode = 0
if pdfscale > 0.74 and pdfscale < 0.76:
pdfmode = 0
elif pdfscale > 0.5 and pdfscale < 0.6:
pdfmode = 1
else:
pdfmode = -1
pdf = fitz.open(pdf_name)
# pdfwidth=pdf[0].get_images()[0][2]
# pdfheight=pdf[0].get_images()[0][3]
# pdfscale=pdfheight/pdfwidth
# pdfmode = 0
# if pdfscale > 0.74 and pdfscale < 0.76:
# pdfmode = 0
# elif pdfscale > 0.5 and pdfscale < 0.6:
# pdfmode = 1
# else:
# pdfmode = -1
for pg in range(0, pdf.pageCount):
page = pdf[pg] # 獲得每一頁(yè)的對(duì)象
trans = fitz.Matrix(zoom, zoom).preRotate(0)
pm = page.getPixmap(matrix=trans, alpha=False) # 獲得每一頁(yè)的流對(duì)象
pm.writePNG(path + os.sep + base_name + '_' + '{:0>3d}.{}'.format(pg+1, 'png')) # 保存圖片
pdf.close()
print('PDF轉(zhuǎn)PNG成功!')
# pngs2pptx
pngs=os.listdir(path+os.sep)
template=resource_path(os.path.join("default.pptx"))
prs=pptx.Presentation(template)
if pdfmode == 0:
prs.slide_width = pptx.util.Inches(4)
prs.slide_height = pptx.util.Inches(3)
elif pdfmode == 1:
prs.slide_width = pptx.util.Inches(16)
prs.slide_height = pptx.util.Inches(9)
else:
print('請(qǐng)采用標(biāo)準(zhǔn)格式!')
prs.slide_width = pptx.util.Inches(4)
prs.slide_height = pptx.util.Inches(3)
layout=prs.slide_layouts[6]
for png in pngs:
slide=prs.slides.add_slide(layout)
slide.shapes.add_picture(path + os.sep + png,0,0,height=prs.slide_height)
prs.save(path + '.pptx')
print('PNG轉(zhuǎn)PPTX成功!')
shutil.rmtree(path)
else:
print('警告! 文件類型錯(cuò)誤,請(qǐng)打開pdf文件類型!')
if __name__=="__main__":
if len(sys.argv) == 2:
pdf2pptx(sys.argv[1],5)
elif len(sys.argv) > 2:
pdf2pptx(sys.argv[1],int(sys.argv[2]))
else:
print('請(qǐng)輸入要轉(zhuǎn)化的文件名')
在此過(guò)程中,又研究了如何將python源文件編譯為獨(dú)立的exe文件。
中途遇到了幾個(gè)問(wèn)題,列如下:
相對(duì)路徑和絕對(duì)路徑的問(wèn)題。為了避免前后不一致,在程序運(yùn)行前段將文件地址設(shè)定為絕對(duì)路徑。
獲取PDF文件的長(zhǎng)寬比。PPT文件有16:9和4:3兩種比例,通過(guò)或許原PDF的長(zhǎng)寬比,可以設(shè)定PPTX的長(zhǎng)寬。最初的方案直接利用fitz庫(kù)即可提取,但部分PDF會(huì)發(fā)生錯(cuò)誤。因而改用現(xiàn)有PyPDF2庫(kù)來(lái)提取該特征。此外,最初的想法是將長(zhǎng)寬比作為參數(shù)輸入,但后來(lái)覺(jué)得太蠢,還是通過(guò)上述方法來(lái)實(shí)現(xiàn),更能體現(xiàn)自動(dòng)化。
將python源文件編譯為exe后,找不到模板文件"default.pptx"。這一點(diǎn)經(jīng)常出現(xiàn)在pyinstaller編譯中,由于脫離了原python運(yùn)行環(huán)境,部分資源無(wú)法找到,會(huì)出現(xiàn)這種錯(cuò)誤。因而需要將"default.pptx"文件拷貝到工作目錄,并通過(guò)''pptx.Presentation("default.pptx")''的方式來(lái)調(diào)用。但這種方式會(huì)導(dǎo)致需要將該模板與exe文件綁定,既不方便,也不優(yōu)雅。隨后查閱pyinstaller手冊(cè),可以通過(guò)''--add-data''參數(shù),將該文件內(nèi)嵌到exe文件內(nèi)部。
程序運(yùn)行期間,會(huì)出現(xiàn)cmd窗口。 編譯命令中添加''-w''參數(shù)解決。
編譯生成的exe文件較大??梢钥紤]使用pipenv環(huán)境進(jìn)行編譯,可以降低空間占用。
環(huán)境配置。安裝fitz庫(kù),直接安裝pymupdf包即可。安裝pptx庫(kù),直接安裝python-pptx包。
完成以上步驟之后,將pdf文件用該可執(zhí)行文件打開,便可以轉(zhuǎn)化為pptx文件。
為了進(jìn)一步自動(dòng)化,每次在tex編譯生成pdf之后,自動(dòng)將pdf轉(zhuǎn)為pptx,查閱了vscode插件Latex Workshop的手冊(cè)。

注意到適當(dāng)調(diào)整占位符,即可完成自動(dòng)將pdf轉(zhuǎn)為pptx的過(guò)程。
隨后修改配置文件:
"latex-workshop.latex.tools": [
{
"name": "pdf2pptx",
"command": "pdf2pptx",
"args": [
"%DOCFILE%.pdf"
]
}
],
"latex-workshop.latex.recipes": [
{
"name": "xelatex",
"tools": [
"xelatex",
"pdf2pptx"
]
}
]
其中latex-workshop.latex.tools對(duì)應(yīng)latex-workshop.latex.recipes中的tools鍵.
至此,編輯tex文件之后,只需保存一下,即可自動(dòng)生成pdf和pptx文件。
程序:pdf2pptx.exe
Github項(xiàng)目地址:mission-young/PDF2PPTX (github.com)