当前位置: 首页 > news >正文

使用PyMuPDF库的PDF合并和分拆程序

PDF工具应用程序是一个使用wxPython和PyMuPDF库编写的简单工具,用于合并和分拆PDF文件。它提供了一个用户友好的图形界面,允许用户选择源文件夹和目标文件夹,并对PDF文件进行操作。
C:\pythoncode\blog\pdfmergandsplit.py
在这里插入图片描述

功能特点

  • 选择文件夹:用户可以通过应用程序界面轻松选择源文件夹和目标文件夹。
  • 合并PDF文件:应用程序允许用户选择要合并的PDF文件,并将它们合并成一个单独的PDF文件。
  • 分拆PDF文件:用户可以选择一个PDF文件,将其分拆成多个单独的PDF文件,每个文件包含一个页面。

程序实现

该应用程序使用了以下库和模块:

  • wxPython:用于创建应用程序的图形用户界面。
  • PyMuPDF:用于处理PDF文件的库。

应用程序的主要部分是一个继承自wxPython的wx.Frame类的主窗口。窗口包含以下组件:

  • 选择源文件夹和目标文件夹的按钮。
  • PDF文件列表框,显示源文件夹中的PDF文件。
  • 合并和分拆按钮,用于执行相应的操作。

当用户点击选择源文件夹按钮时,应用程序显示一个文件夹选择对话框,用户可以选择源文件夹。选择后,应用程序获取文件夹路径,并列出文件夹中的PDF文件。然后,合并和分拆按钮变为可用状态,用户可以执行相应的操作。

合并按钮的点击事件会弹出一个文本输入对话框,要求用户输入合并后的文件名。用户输入后,应用程序调用PyMuPDF库合并选定的PDF文件,并将合并后的PDF文件保存到目标文件夹中。

分拆按钮的点击事件会遍历选定的PDF文件,并使用PyMuPDF库将每个页面保存为单独的PDF文件。

代码示例

以下是应用程序的代码示例:

import os
import wx
import fitzclass PDFToolApp(wx.Frame):def __init__(self, parent, title):super(PDFToolApp, self).__init__(parent, title=title, size=(400, 400))self.panel = wx.Panel(self)self.source_folder_btn = wx.Button(self.panel, -1, "选择源文件夹")self.target_folder_btn = wx.Button(self.panel, -1, "选择目标文件夹")self.pdf_list = wx.CheckListBox(self.panel, -1, choices=[], style=wx.LB_MULTIPLE)self.merge_btn = wx.Button(self.panel, -1, "合并")self.split_btn = wx.Button(self.panel, -1, "分拆")self.merge_btn.Disable()self.split_btn.Disable()self.source_folder_btn.Bind(wx.EVT_BUTTON, self.on_select_source_folder)self.target_folder_btn.Bind(wx.EVT_BUTTON, self.on_select_target_folder)self.merge_btn.Bind(wx.EVT_BUTTON, self.on_merge)self.split_btn.Bind(wx.EVT_BUTTON, self.on_split)sizer = wx.BoxSizer(wx.VERTICAL)sizer.Add(self.source_folder_btn, 0, wx.ALIGN_CENTER | wx.ALL, 10)sizer.Add(self.target_folder_btn, 0, wx.ALIGN_CENTER | wx.ALL, 10)sizer.Add(self.pdf_list, 1, wx.EXPAND | wx.ALL, 10)sizer.Add(self.merge_btn, 0, wx.ALIGN_CENTER | wx.ALL, 10)sizer.Add(self.split_btn, 0, wx.ALIGN_CENTER | wx.ALL, 10)self.panel.SetSizer(sizer)self.Show()def on_select_source_folder(self, event):dlg = wx.DirDialog(self, "选择源文件夹", style=wx.DD_DEFAULT_STYLE)if dlg.ShowModal() == wx.ID_OK:source_folder_path = dlg.GetPath()self.pdf_list.Set(self.get_pdf_files(source_folder_path))self.merge_btn.Enable()self.split_btn.Enable()dlg.Destroy()def on_select_target_folder(self, event):dlg = wx.DirDialog(self, "选择目标文件夹", style=wx.DD_DEFAULT_STYLE)if dlg.ShowModal() == wx.ID_OK:self.target_folder_path = dlg.GetPath()dlg.Destroy()def on_merge(self, event):selected_items = self.pdf_list.GetCheckedItems()if len(selected_items) > 0:dlg = wx.TextEntryDialog(self, "请输入合并后的文件名(不带扩展名):", "合并文件")if dlg.ShowModal() == wx.ID_OK:output_filename = dlg.GetValue()output_filepath = os.path.join(self.target_folder_path, output_filename + ".pdf")self.merge_pdfs(selected_items, output_filepath)wx.MessageBox("PDF文件合并完成!", "完成", wx.OK | wx.ICON_INFORMATION)dlg.Destroy()def on_split(self, event):selected_items = self.pdf_list.GetCheckedItems()if len(selected_items) > 0:for index in selected_items:pdf_filename = self.pdf_list.GetString(index)pdf_filepath = os.path.join(self.target_folder_path, pdf_filename)self.split_pdf(pdf_filename, pdf_filepath)wx.MessageBox("PDF文件分拆完成!", "完成", wx.OK | wx.ICON_INFORMATION)def merge_pdfs(self, selected_items, output_filepath):pdf_merger = fitz.open()for index in selected_items:pdf_filename = self.pdf_list.GetString(index)pdf_filepath = os.path.join(self.target_folder_path, pdf_filename)pdf = fitz.open(pdf_filepath)pdf_merger.insert_pdf(pdf)pdf_merger.save(output_filepath)pdf_merger.close()def split_pdf(self, pdf_filename, pdf_filepath):pdf = fitz.open(pdf_filepath)num_pages = pdf.page_countfor i in range(num_pages):output_filename = f"{pdf_filename[:-4]}_{i+1}.pdf"output_filepath = os.path.join(self.target_folder_path, os.path.basename(output_filename) )print("output_filename:"+output_filename)page = pdf[i]new_pdf = fitz.open()new_pdf.insert_pdf(pdf, from_page=i, to_page=i)new_pdf.save(output_filepath)print("self.target_folder_path:"+self.target_folder_path)print("output_filepath:"+output_filepath)new_pdf.close()pdf.close()def get_pdf_files(self, folder_path):pdf_files = []for filename in os.listdir(folder_path):if filename.endswith(".pdf"):pdf_files.append(folder_path+'/'+filename)return pdf_filesif __name__ == "__main__":app = wx.App()PDFToolApp(None, "PDF工具")app.MainLoop()

总结

PDF工具应用程序是一个使用wxPython和PyMuPDF库编写的简单实用工具,可用于合并和分拆PDF文件。它提供了一个直观的图形界面,使用户能够轻松选择文件夹和执行操作。无论是处理大量PDF文件还是简单的分拆操作,该应用程序都能满足用户的需求。

相关文章:

使用PyMuPDF库的PDF合并和分拆程序

PDF工具应用程序是一个使用wxPython和PyMuPDF库编写的简单工具,用于合并和分拆PDF文件。它提供了一个用户友好的图形界面,允许用户选择源文件夹和目标文件夹,并对PDF文件进行操作。 C:\pythoncode\blog\pdfmergandsplit.py 功能特点 选择文…...

2023/8/18 - You need to rely on yourself to achieve the life you want

...

Data Abstract for .NET and Delphi Crack

Data Abstract for .NET and Delphi Crack .NET和Delphi的数据摘要是一套或RAD工具,用于在.NET、Delphi和Mono中编写多层解决方案。NET和Delphi的数据摘要是一个套件,包括RemObjects.NET和Delphi版本的数据摘要。RemObjects Data Abstract允许您创建访问…...

Eclipse集成MapStruct

Eclipse集成MapStruct 在Eclipse中添加MapStruct依赖配置Eclipse支持MapStruct①安装 m2e-aptEclipse Marketplace的方式安装Install new software的方式安装(JDK8用到) ②添加到pom.xml 今天拿到同事其他项目的源码,导入并运行的时候抛出了异…...

采用pycharm在虚拟环境使用pyinstaller打包python程序

一年多以前,我写过一篇博客描述了如何虚拟环境打包,这一次有所不同,直接用IDE pycharm构成虚拟环境并运行pyinstaller打包 之前的博文: 虚拟环境venu使用pyinstaller打包python程序_伊玛目的门徒的博客-CSDN博客 第一步&#xf…...

Rx.NET in Action 中文介绍 前言及序言

Rx 处理器目录 (Catalog of Rx operators) 目标可选方式Rx 处理器(Operator)创建 Observable Creating Observables直接创建 By explicit logicCreate Defer根据范围创建 By specificationRangeRepeatGenerateTimerInterval Return使用预设 Predefined primitivesThrow …...

Azure Blob存储使用

创建存储账户,性能选择标准即可,冗余选择本地冗余存储即可 容器选择类别选择专用即可 可以上传文件到blob中 打开文件可以看到文件的访问路径 4.编辑中可以修改文件 复制链接,尝试访问,可以看到没有办法访问,因为创建容器的时候选…...

mysql、redis面试题

mysql 相关 1、数据库优化查询方法 外键、索引、联合查询、选择特定字段等等2、简述mysql和redis区别 redis: 内存型非关系数据库,数据保存在内存中,速度快mysql:关系型数据库,数据保存在磁盘中,检索的话&…...

22、touchGFX学习Model-View-Presenter设计模式

touchGFX采用MVP架构,如下所示: 本文界面如下所示: 本文将实现两个操作: 1、触摸屏点击开关按键实现打印开关显示信息,模拟开关灯效果 2、板载案按键控制触摸屏LED灯的显示和隐藏 一、触摸屏点击开关按键实现打印开…...

Python Opencv实践 - 图像高斯滤波(高斯模糊)

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_COLOR) rows,cols,channels img.shape print(rows,cols,channels)#为图像添加高斯噪声 #使用np.random.normal(loc0.0, scale1.0…...

使用 Qt 生成 Word 和 PDF 文档的详细教程

系列文章目录 文章目录 系列文章目录前言一、安装 Qt二、生成 Word 文档三、生成 PDF 文档四、运行代码并查看结果五、自定义文档内容总结 前言 Qt 是一个跨平台的应用程序开发框架,除了用于创建图形界面应用程序外,还可以用来生成 Word 和 PDF 文档。本…...

ssm+vue校园美食交流系统源码

ssmvue校园美食交流系统源码和论文026 开发工具:idea 数据库mysql5.7 数据库链接工具:navcat,小海豚等 技术:ssm 摘 要 随着现在网络的快速发展,网上管理系统也逐渐快速发展起来,网上管理模式很快融入到了许多商…...

电力系统基础知识(一)—电力系统概述

1、电压 也称作电势差或电位差,是衡量单位电荷在静电场中由于电势不同所产生的能量差的物理量。其大小等于单位正电荷因受电场力作用从A点移动到B点所做的功,电压的方向规定为从高电位指向低电位。其单位为伏特(V,简称伏),常用单位还有千伏(kV)、毫伏(mV)、微伏(uV…...

spring(15) SpringBoot启动过程

目录 一、过程简介二、过程流程图三、源码分析1、运行 SpringApplication.run() 方法2、确定应用程序类型3、加载所有的初始化器4、加载所有的监听器5、设置程序运行的主类6、开启计时器7、将 java.awt.headless 设置为 true8、获取并启用监听器9、设置应用程序参数10、准备环境…...

耕地单目标语义分割实践——Pytorch网络过程实现理解

一、卷积操作 (一)普通卷积(Convolution) (二)空洞卷积(Atrous Convolution) 根据空洞卷积的定义,显然可以意识到空洞卷积可以提取到同一输入的不同尺度下的特征图&…...

画质提升+带宽优化,小红书音视频团队端云结合超分落地实践

随着视频业务和短视频播放规模不断增长,小红书一直致力于研究:如何在保证提升用户体验质量的同时降低视频带宽成本? 在近日结束的音视频技术大会「LiveVideoStackCon 2023」上海站中,小红书音视频架构视频图像处理算法负责人剑寒向…...

【傅里叶级数与傅里叶变换】数学推导——3、[Part4:傅里叶级数的复数形式] + [Part5:从傅里叶级数推导傅里叶变换] + 总结

文章内容来自DR_CAN关于傅里叶变换的视频,本篇文章提供了一些基础知识点,比如三角函数常用的导数、三角函数换算公式等。 文章全部链接: 基础知识点 Part1:三角函数系的正交性 Part2:T2π的周期函数的傅里叶级数展开 P…...

第二章MyBatis入门程序

入门程序 创建maven程序 导入MyBatis依赖。pom.xml下导入如下依赖 <dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.6</version></dependency><dependen…...

AgentBench::AI智能体发展的潜在问题(二)

从历史上看&#xff0c;几乎每一种新技术的广泛应用都会在带来新机遇的同时引发很多新问题&#xff0c;AI智能体也不例外。从目前的发展看&#xff0c;AI智能体的发展可能带来的新问题可能包括如下方面&#xff1a; 第二是AI智能体的普及将有可能进一步加剧AI造成的技术性失业。…...

C++中的运算符总结(4):逻辑运算符(上)

C中的运算符总结&#xff08;4&#xff09;&#xff1a;逻辑运算符&#xff08;上&#xff09; 8、逻辑运算 NOT、 AND、 OR 和 XOR 逻辑 NOT 运算用运算符!表示&#xff0c;用于单个操作数。表 1是逻辑 NOT 运算的真值表&#xff0c;这种运算将提供的布尔标记反转&#xff1…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

书籍“之“字形打印矩阵(8)0609

题目 给定一个矩阵matrix&#xff0c;按照"之"字形的方式打印这个矩阵&#xff0c;例如&#xff1a; 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为&#xff1a;1&#xff0c;…...

AD学习(3)

1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分&#xff1a; &#xff08;1&#xff09;PCB焊盘&#xff1a;表层的铜 &#xff0c;top层的铜 &#xff08;2&#xff09;管脚序号&#xff1a;用来关联原理图中的管脚的序号&#xff0c;原理图的序号需要和PCB封装一一…...

JS红宝书笔记 - 3.3 变量

要定义变量&#xff0c;可以使用var操作符&#xff0c;后跟变量名 ES实现变量初始化&#xff0c;因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符&#xff0c;可以创建一个全局变量 如果需要定义…...