PDF格式文件作为一种使用广泛的文件,自诞生之始就被很多人使用。因为其各种原因,PDF成为几乎所有正式文件首选发布格式。无论是学生、社会机构、文本报告等等,都会使用的PDF文件。
其中,我们可能会涉及到一些问题:
文件由很多页,但是自己需要获取提交的就那几页(比如学校的志愿时数公布文件,我的名字就在其中一页,每一页都有正式题目和盖章)
有若干个PDF文件需要合并(比如我的英语电子版作业。。。)
这就要求我们去找能够进行PDF合并和分页的工具了。
一些客户端软件我倒是没看见几个可以免费的,线上工具,我就在使用ILovePDF。但是ILovePDF有一个重大的问题,不是有价格方案,对我来说免费额度够用,而是网络连接不稳定。
本篇文章写于“成功”后,对比了一下,本次编写的PDF工具合并并输出一个23MB的PDF文件用了不到2秒,而使用ILovePDF使用了近1分钟。
本次需要用到PyPDF2
库。一个完全免费开源、持续更新、高效的PDF处理库。为作者以及开发团队点赞!!!
本项目属于作者原创。借鉴了GitHub/TinUI上的tuxml.py
,翻版必究,但可以自行添加功能代码。
本项目使用的TinUI为我开源并维护在GitHub上的主文件——TinUI.py。当然,使用PYPI中下载安装的tinui也可以。
本次因为演示原因,分页主程序和合并主程序是分开来写的。
PDF文件的操作不是本篇文章的重点。关于PyPDF2的相关API,网络上有很多。
还记得我们之前完成的TinUIXml编辑器吗?现在可以拿出来用了。否则,光纯代码写TinUI界面就够我写十分钟了。使用TinUIXml编辑器后,不到三分钟就搞定了xml文件和IDO代码。
这是设计过程中的一张截图。
这样修改后可以立刻检查UI界面,并且完成后可以自动生成IDO部分代码,真的是超方便。
我自己手动写IDO其实也很烦躁。。。
pdf-fg.xml:
<tinui>
<line>
<title text='PDF分页器'>title>
line>
<line>
<label text='文件位置(无需引号)'>label>
<entry width='350'>origin_file_entryentry>
line>
<line>
<line>
<label text='分页页码填写'>label>
line>
<line>
<paragraph text='填写规则:
1. 单个页码每行一个数字
2. 连续分页例如:2-6 填写
3. 空行略过'>paragraph>
line>
<textbox width='350' height='300' scrollbar='True'>pages_textboxtextbox>
line>
<line>
<label text='输出目录(无需引号)'>label>
<entry width='350'>result_path_entryentry>
line>
<line>
<button text='开始分页PDF' command='self.funcs["start"]'>button>
<paragraph text='当前状态:'>paragraph>
<paragraph text='空闲'>stateparagraph>
line>
tinui>
from tkinter import Tk,Frame
import os
from tinui import *
from PyPDF2 import PdfFileReader, PdfFileWriter
def start(*e):
restate('分页中……')
u.update()
ofile=origin_file_entry[0].get()
fname=os.path.split(os.path.splitext(ofile)[0])[1]
rpath=result_path_entry[0].get()
if rpath[-1] not in ('\\','/'):
rpath+='\\'
pages_list=pages_textbox[0].get(1.0,'end').split('\n')
pagenum=list()
for i in pages_list:
if i=='':
continue
if '-' in i:
start,end=i.split('-')
start=int(start)
end=int(end)+1
for p in range(start,end):
pagenum.append(p)
else:
pagenum.append(int(i))
pdfreader=PdfFileReader(ofile)
pdfwriter=PdfFileWriter()
for page in pagenum:
pdfwriter.addPage(pdfreader.getPage(page-1))
with open(rpath+fname+'-分页结果.pdf','wb') as out:
pdfwriter.write(out)
restate('已生成 '+fname+'-分页结果.pdf')
u.after(5000,lambda:restate())
def restate(text='空闲'):
u.itemconfig(state,text=text)
pages_list=[]#输入框内容
ofile=None
rpath=None
root=Tk()
root.title('PDF分割')
root.geometry('600x500')
frame=Frame(root)
frame.pack(fill='y',side='left')
u=BasicTinUI(frame,height=580,width=580)
u.pack(fill='both',expand=True)
x=TinUIXml(u)
#in
x.funcs['start']=start
#during
with open('pdf-fg.xml',mode='r',encoding='utf-8') as f:
xml=f.read()
x.loadxml(xml)
#out
origin_file_entry = x.tags["origin_file_entry"]
pages_textbox = x.tags["pages_textbox"]
result_path_entry = x.tags["result_path_entry"]
state = x.tags["state"]
root.mainloop()
源PDF文件:
结果:
<tinui>
<line>
<title text='PDF合并器'>title>
line>
<line>
<line>
<label text='文件位置填写'>label>
line>
<line>
<paragraph text='填写规则:
1. 每行一个文件路径
2. 空行略过'>paragraph>
line>
<textbox width='350' height='300' scrollbar='True'>pages_textboxtextbox>
line>
<line>
<label text='输出目录(无需引号)'>label>
<entry width='350'>result_path_entryentry>
line>
<line>
<button text='开始合并PDF' command='self.funcs["start"]'>button>
<paragraph text='当前状态:'>paragraph>
<paragraph text='空闲'>stateparagraph>
line>
tinui>
from tkinter import Tk,Frame
import os
from tinui import *
from PyPDF2 import PdfFileReader, PdfFileWriter, PdfMerger
def start(*e):
restate('合并中……')
u.update()
files_list=pages_textbox[0].get(1.0,'end').split('\n')
files=list()
for i in files_list:
if i=='':
continue
else:
files.append(i)
fname=os.path.split(os.path.splitext(files[0])[0])[1]#取第一个文件名称
rpath=result_path_entry[0].get()
if rpath[-1] not in ('\\','/'):
rpath+='\\'
merger=PdfMerger()
for pdf in files:
merger.append(pdf)
merger.write(rpath+fname+'-合并结果.pdf')
merger.close()
restate('已生成 '+fname+'-分页结果.pdf')
u.after(5000,lambda:restate())
def restate(text='空闲'):
u.itemconfig(state,text=text)
files_list=[]#输入框内容
rpath=None
root=Tk()
root.title('PDF合并')
root.geometry('600x500')
frame=Frame(root)
frame.pack(fill='y',side='left')
u=BasicTinUI(frame,height=580,width=580)
u.pack(fill='both',expand=True)
x=TinUIXml(u)
#in
x.funcs["start"] = start
#during
with open('pdf-hb.xml',mode='r',encoding='utf-8') as f:
xml=f.read()
x.loadxml(xml)
#out
pages_textbox = x.tags["pages_textbox"]
result_path_entry = x.tags["result_path_entry"]
state = x.tags["state"]
现在,可以拿着写好的两个工具自己玩一会了,以后也用不找一要分割或合并PDF就去网络上找东西。本机够用的,也就没必要大费周章了。
这次有体验了一次使用TinUIXml的快乐。
🔆tkinter创新🔆