支持两种分割方式
1.可将pdf文件按固定页数分割,例如:100页的PDF文件,按固定页数30进行分割,则实际分割为1-30,31-60,61-90,91-100

微信图片_20210418221623.png
2.可将pdf文件按指定页码分割,例如:100页的PDF文件,按指定页码20,50,100进行分割,则实际分割为1-20,21-50,51-100

微信图片_20210418221803.png
分割成功后,输出到源文件同目录下的新目录中(新目录与源文件名相同)
3.完整代码如下:
from PyPDF2 import PdfFileReader, PdfFileWriter
import PySimpleGUI as sg
import os
import math
import re
import pyperclip
global_option = 1
# 按指定固定页数分割PDF
def pdfSplitOp1(input_path_file, output_path, file_size):
try:
fine_name = os.path.splitext(os.path.basename(input_path_file))[0]
pdf = PdfFileReader(input_path_file, False)
idx = 0
for page in range(pdf.getNumPages()):
# 初始化
if((page % file_size) == 0):
idx = idx + 1
pdf_writer = PdfFileWriter()
output_path_file = os.path.join(output_path, '{}-{}.pdf'.format(fine_name, idx))
pdf_writer.addPage(pdf.getPage(page))
with open(output_path_file, 'wb') as out:
pdf_writer.write(out)
return 'success'
except Exception as e:
return repr(e)
# 按指定页码分割PDF
def pdfSplitOp2(input_path_file, output_path, list_number):
try:
fine_name = os.path.splitext(os.path.basename(input_path_file))[0]
pdf = PdfFileReader(input_path_file, False)
idx = 0
start_page = 0
for num in list_number:
idx = idx + 1
end_page = int(num)
pdf_writer = PdfFileWriter()
output_path_file = os.path.join(output_path, '{}-{}.pdf'.format(fine_name, idx))
for page in range(start_page, end_page):
pdf_writer.addPage(pdf.getPage(page))
with open(output_path_file, 'wb') as out:
pdf_writer.write(out)
start_page = int(num)
return 'success'
except Exception as e:
return repr(e)
# 提示对话框,用户知悉即可
def infoDialog(info):
sg.popup('', info, '',
title='提示',
custom_text=' 知道了 ',
background_color='gray',
text_color='black',
button_color='#9FB8AD')
# 继续执行对话框,用户点击下一步可继续执行
def nextDialog(info):
return sg.popup('', info, '',
title='询问',
custom_text=(' 分割 ', ' 取消 '),
background_color='gray',
text_color='black',
button_color='#9FB8AD')
def openFolderDialog(info):
return sg.popup('', info, '',
title='询问',
custom_text=(' 打开 ', ' 不用 '),
background_color='green',
text_color='black',
button_color='#9FB8AD')
# 错误对话框,用户知悉异常详细信息
def exceptionDialog(info):
return sg.popup('', info, '',
title='异常',
custom_text=(' 知道了 ', ' 复制异常信息 '),
background_color='red',
text_color='black',
button_color='#9FB8AD')
# 检查固定页数填写值是否符合格式要求
def checkFileSize(fileSize):
if re.match(r"^\+?[1-9][0-9]*$", fileSize) is None:
return False
else:
return True
# 检查指定页码填写值是否符合格式要求
def checkSizeList(sizeList):
print(sizeList)
if re.match(r"^([0-9]+)(,([0-9]+))*$", sizeList) is None:
return False
else:
return True
# 设置应用程序的主题
sg.theme('DarkAmber')
layout = [
[sg.Text('1. 请选择PDF文件')],
[sg.FileBrowse('选择...', size=(10, 1), file_types=(('PDF Files', '*.pdf'),)),
sg.Input(size=(100, 1), key='_INPUT_PATH_FILE_')],
[sg.Text('_'*30)],
[sg.Text('2. 请选择分割方式')],
[sg.Radio('固定页数', 'S1', enable_events=True, key='_OP01_', default=True),
sg.Radio('指定页码', 'S1', enable_events=True, key='_OP02_')],
[sg.Text('按固定页数', key='_INFO1_'),
sg.Input('', size=(16, 1), key='_INFO2_'),
sg.Text('进行分割(例如:100页的PDF文件,按固定页数30进行分割,则实际分割为1-30,31-60,61-90,91-100)', size=(80, 1), key='_INFO3_')],
[sg.Button('分割PDF文件', size=(16,1), key='_SPLIT_PDF_'),
sg.Button('退出', size=(16,1), key='_CANCEL_')]
]
window = sg.Window('PDF分割工具', layout)
while True:
event, values = window.read()
if event == '_OP01_':
# 选择了按固定页数分割
global_option = 1
window['_INFO1_'].update('按固定页数')
window['_INFO2_'].update('')
window['_INFO3_'].update('进行分割(例如:100页的PDF文件,按固定页数30进行分割,则实际分割为1-30,31-60,61-90,91-100)')
elif event == '_OP02_':
# 选择了按指定页码分割
global_option = 2
window['_INFO1_'].update('按指定页码')
window['_INFO2_'].update('')
window['_INFO3_'].update('进行分割(例如:100页的PDF文件,按指定页码20,50,100进行分割,则实际分割为1-20,21-50,51-100)')
elif event == '_SPLIT_PDF_':
# 点击了分割PDF按钮
# 校验输入信息
inputPathFile = values['_INPUT_PATH_FILE_']
try:
pageCount = PdfFileReader(inputPathFile, False).getNumPages()
except FileNotFoundError:
# 源文件不存在
info = '源文件不存在,请选择需要分割的PDF文件。'
infoDialog(info)
continue
if(1 == global_option):
# 如果选择了按指定页码分割
fileSize = values['_INFO2_']
# 检查参数
if checkFileSize(fileSize):
# 如果参数格式正确
iFileSize = int(values['_INFO2_'])
if(iFileSize >= pageCount):
# 如果参数值不正确
info = '设置的固定页数(%s)不能大于或等于源文件的总页数(%s)' % (iFileSize, pageCount)
infoDialog(info)
continue
else:
# 如果参数值正确,提示是否执行分割
fileCount = math.ceil(pageCount / iFileSize)
info = '源文件总计%s页,每份文件%s页,可以分割成%s份文件。\r\n\r\n是否分割PDF文件?' % (pageCount, iFileSize, fileCount)
rtn = nextDialog(info)
if(rtn is not None and '分割' == rtn.strip()):
# 点击了分割按钮
# 执行分割文件
inputPathFile = values['_INPUT_PATH_FILE_']
inputPath = os.path.abspath(os.path.dirname(inputPathFile) + os.path.sep + ".")
inputFile = os.path.splitext(os.path.basename(inputPathFile))[0].split('.')[0]
outputPath = '{}\\{}'.format(inputPath, inputFile)
# 创建输出文件夹,先判断是否存在,存在则不创建,不存在则新建,使用源文件名称作为文件夹名称
try:
if(not os.path.exists(outputPath)):
os.mkdir(outputPath)
except OSError:
# 创建输出文件夹失败
rtn = exceptionDialog('创建输出文件夹失败!\r\n\r\n异常信息:%s' % OSError)
if (rtn is not None and '复制异常信息' == rtn.strip()):
pyperclip.copy(exceptionInfo)
continue
else:
continue
rtn = pdfSplitOp1(inputPathFile, outputPath, iFileSize)
if('success' == rtn):
rtn = openFolderDialog('分割成功!\r\n\r\n是否打开文件夹?\t\t\t\t\t')
if(rtn is not None and '打开' == rtn.strip()):
os.system("explorer.exe %s" % outputPath)
else:
continue
else:
exceptionInfo = rtn
rtn = exceptionDialog('执行失败!\r\n\r\n异常信息:%s' % exceptionInfo)
if (rtn is not None and '复制异常信息' == rtn.strip()):
pyperclip.copy(exceptionInfo)
continue
else:
continue
continue
elif(rtn is not None and '取消' == rtn.strip()):
# 点击了取消按钮
continue
else:
# 点击了标题栏的关闭(X)
continue
else:
# 如果参数格式不正确
info = '请输入正确的固定页数(大于等于1的整数)。'
infoDialog(info)
continue
elif(2 == global_option):
# 如果选择了按指定页码分割
sizeList = values['_INFO2_']
# 检查参数格式,是否按英文逗号分割数字
if checkSizeList(sizeList):
# 将其转为列表list
listSize = sizeList.split(",")
# 校验参数值是否正确
valFlg = True
start_num = 1
for num in listSize:
if (int(num) < start_num):
# 如果参数值不正确,校验数值是否正确:一个比一个大
valFlg = False
info = '指定页码需大于1,且越来越大。'
infoDialog(info)
break
elif (int(num) > pageCount):
# 如果参数值不正确,最大的数不能大于pageCount
valFlg = False
info = '最大的指定页码不能超过总页数({})。'.format(pageCount)
infoDialog(info)
break
start_num = int(num) + 1
start_num = 1
if(valFlg):
#如果参数值正确,则允许分割
# 提示是否执行分割
splitInfo = []
for num in listSize:
splitInfo.append(str(start_num) + '-' + str(num))
start_num = int(num) + 1
info = '源文件总计%s页,可以分割成%s份文件:%s。\r\n\r\n是否分割PDF文件?' % (pageCount, len(listSize), splitInfo)
rtn = nextDialog(info)
if(rtn is not None and '分割' == rtn.strip()):
# 点击了分割按钮
# 执行分割文件
inputPathFile = values['_INPUT_PATH_FILE_']
inputPath = os.path.abspath(os.path.dirname(inputPathFile) + os.path.sep + ".")
inputFile = os.path.splitext(os.path.basename(inputPathFile))[0].split('.')[0]
outputPath = '{}\\{}'.format(inputPath, inputFile)
# 创建输出文件夹,先判断是否存在,存在则不创建,不存在则新建,使用源文件名称作为文件夹名称
try:
if(not os.path.exists(outputPath)):
os.mkdir(outputPath)
except OSError:
# 创建输出文件夹失败
rtn = exceptionDialog('创建输出文件夹失败!\r\n\r\n异常信息:%s' % OSError)
if (rtn is not None and '复制异常信息' == rtn.strip()):
pyperclip.copy(exceptionInfo)
continue
else:
continue
rtn = pdfSplitOp2(inputPathFile, outputPath, listSize)
if('success' == rtn):
rtn = openFolderDialog('分割成功!\r\n\r\n是否打开文件夹?\t\t\t\t\t')
if(rtn is not None and '打开' == rtn.strip()):
os.system("explorer.exe %s" % outputPath)
else:
continue
else:
exceptionInfo = rtn
rtn = exceptionDialog('执行失败!\r\n\r\n异常信息:%s' % exceptionInfo)
if (rtn is not None and '复制异常信息' == rtn.strip()):
pyperclip.copy(exceptionInfo)
continue
else:
continue
continue
elif(rtn is not None and '取消' == rtn.strip()):
# 点击了取消按钮
continue
else:
# 点击了标题栏的关闭(X)
continue
else:
# 如果参数格式不正确
info = '请输入正确的指定页码(如:3,10,27)。'
infoDialog(info)
continue
elif event == sg.WIN_CLOSED or event == '_CANCEL_':
break
window.close()