Как объединить пдф используя python
Как объединить несколько .pdf файлов в один , количество файлов которые надо объединить разное и чаще всего находятся в разных директориях, поэтому хотелось бы реализовать окно выбора файлов.
Пробовал таким способом, чтобы открывалось окно выбора файла и разрешало выбирать сразу несколько файлов.
merger = PdfFileMerger()
doc1 = merger.append(Path(filedialog.askopenfilename()))
merger.append(filedialog.askopenfilenames()) merger.write(filedialog.asksaveasfilename(initialfile=doc1.name, defaultextension=('.pdf'), filetypes=(("pdf file", "*.pdf"),("All Files", "*.*")) ))
merger.close()
Но появляется данная ошибка
AttributeError: 'WindowsPath' object has no attribute 'seek'
Пробовал еще таким способом
merger = PdfFileMerger()
doc1 = merger.append(FileIO(Path(filedialog.askopenfilename())))
merger.append(FileIO(filedialog.askopenfilenames()))
merger.write(filedialog.asksaveasfilename(initialfile=doc1.name, defaultextension=('.pdf'), filetypes=(("pdf file", "*.pdf"),("All Files", "*.*")) ))
merger.close()
в этом случае появляется уже такая ошибка
TypeError: expected str, bytes or os.PathLike object, not tuple
Модули которые участвовали
from pathlib import Path
import PyPDF2
from PyPDF2 import PdfFileReader, PdfFileWriter, PdfFileMerger
Ответы (2 шт):
Попробуйте это. На Ubuntu работает.
Пользоваться следующим образом:
- Диалоговые окна для выбора pdf файлов выводятся до нажатия кнопки
Cancel. То есть: запускаем программу, выскакивает первое окно, выбираем в нём файл (или файлы через Ctrl), жмёмOpen. Операция повторяется - опять выскакивает диалоговое окно выбора файлов, опять выбираем файл, жмёмOpen. В названии диалогового окна отображается количество выбранных файлов. Для завершения выбора файлов жмёмCancelв очередном диалоговом окне. - После того, как все нужные pdf файлы выбраны, появляется диалоговое окно сохранения.
import tkinter as tk
import tkinter.filedialog
from PyPDF2 import PdfFileMerger
# Скрываем главное окно за ненадобностью
tk.Tk().withdraw()
pdfs = []
cnt = 0
while True:
selected_pdfs = tk.filedialog.askopenfilenames(
title=f"PDF merge, {cnt} file(s) were selected",
filetypes=[("PDF files", '.pdf')]
)
if not selected_pdfs:
break
pdfs.extend(selected_pdfs)
# Увеличиваем счётчик на количество файлов выбранных в текущей итерации
cnt += len(selected_pdfs)
merger = PdfFileMerger()
for pdf in pdfs:
merger.append(pdf)
filename_to_save = tk.filedialog.asksaveasfilename(
title=f"Merge {cnt} pdfs to: ",
defaultextension=('.pdf'),
filetypes=[("PDF files", '.pdf')]
)
if filename_to_save:
merger.write(filename_to_save)
merger.close()
Разработка настольного приложения для объединения PDF-файлов с Python и PyQt5.
Прежде чем запустить мой пример, убедитесь, что вы установили PyQt5
pip install PyQt5
pip install pyqt5-tools
PyQt — реализация фреймворка Qt для языка Python.
Запускает приложуние: python main.py
Нажмите на кнопку
Save To- задайте.pdfфайл результирующий.Перетащите файл/файлы с любых директорий.
Нажмите на кнопку
Merge- готово.
main.py
import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QLabel, QLineEdit,
QPushButton, QListWidget, QVBoxLayout, QHBoxLayout, QGridLayout,
QDialog, QFileDialog, QMessageBox, QAbstractItemView)
from PyQt5.QtCore import Qt, QUrl, QSize
from PyQt5.QtGui import QIcon
from PyPDF2 import PdfFileMerger
class ListWidget(QListWidget):
def __init__(self, parent=None):
super().__init__(parent=None)
self.setAcceptDrops(True)
self.setStyleSheet('''font-size:25px''')
self.setDragDropMode(QAbstractItemView.InternalMove)
self.setSelectionMode(QAbstractItemView.ExtendedSelection)
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
event.accept()
else: return super().dragEnterEvent(event)
def dragMoveEvent(self, event):
if event.mimeData().hasUrls():
event.setDropAction(Qt.CopyAction)
event.accept()
else: return super().dragMoveEvent(event)
def dropEvent(self, event):
if event.mimeData().hasUrls():
event.setDropAction(Qt.CopyAction)
event.accept()
pdfFiles = []
for url in event.mimeData().urls():
if url.isLocalFile():
if url.toString().endswith('.pdf'):
pdfFiles.append(str(url.toLocalFile()))
self.addItems(pdfFiles)
else: return super().dropEvent(event)
class OutputField(QLineEdit):
def __init__(self):
super().__init__()
self.height = 45
self.setStyleSheet('''font-size: 20px;''')
self.setFixedHeight(self.height)
def dragEnterEvent(self, event):
if event.mimeData().hasUrls:
event.accept()
else: event.ignore()
def dragMoveEvent(self, event):
if event.mimeData().hasUrls:
event.setDropAction(Qt.CopyAction)
event.accept()
else: event.ignore()
def dropEvent(self, event):
if event.mimeData().hasUrls:
event.setDropAction(Qt.CopyAction)
event.accept()
if event.mimeData().urls():
self.setText(event.mimeData().urls()[0].toLocalFile())
else: event.ignore()
class Button(QPushButton):
def __init__(self, label_text):
super().__init__()
self.setText(label_text)
self.setStyleSheet('''
font-size: 20px;
width: 180px;
height: 50;
''')
class AppDemo(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('Слияние PDF-файлов')
self.setWindowIcon(QIcon('pdf.png'))
self.initUI()
def initUI(self):
self.outputFile = OutputField()
self.buttonBrowseOutputFile = Button('&Save To')
self.buttonBrowseOutputFile.clicked.connect(self.populateFileName)
self.buttonBrowseOutputFile.setFixedHeight(self.outputFile.height)
outputFolderRow = QHBoxLayout()
outputFolderRow.addWidget(self.outputFile)
outputFolderRow.addWidget(self.buttonBrowseOutputFile)
self.pdfListWidget = ListWidget(self)
# Buttons
buttonLayout = QHBoxLayout()
self.buttonDeleteSelect = Button('&Delete')
self.buttonDeleteSelect.clicked.connect(self.deleteSelected)
buttonLayout.addWidget(self.buttonDeleteSelect, 1, Qt.AlignRight)
self.buttonMerge = Button('&Merge')
self.buttonMerge.setIcon(QIcon('play_button.jpg'))
self.buttonMerge.setIconSize(QSize(30, 30))
self.buttonMerge.clicked.connect(self.mergeFile)
buttonLayout.addWidget(self.buttonMerge)
self.buttonClose = Button('&Exit')
self.buttonClose.clicked.connect(QApplication.quit)
buttonLayout.addWidget(self.buttonClose)
self.buttonReset = Button('&Reset')
self.buttonReset.clicked.connect(self.clearQueue)
buttonLayout.addWidget(self.buttonReset)
mainLayout = QVBoxLayout()
mainLayout.addLayout(outputFolderRow)
mainLayout.addWidget(self.pdfListWidget)
mainLayout.addLayout(buttonLayout)
self.setLayout(mainLayout)
def deleteSelected(self):
items = self.pdfListWidget.selectedItems()
if items:
for item in items:
self.pdfListWidget.takeItem(self.pdfListWidget.row(item))
else:
self.dialogMessage(
'''<h2 style="color: red;">Нечего удалять.<br> Выберите файл/ы для удаления!</h2>'''
)
def clearQueue(self):
self.pdfListWidget.clear()
self.outputFile.setText('')
def populateFileName(self):
path = self._getSaveFilePath()
if path:
self.outputFile.setText(path)
def dialogMessage(self, message):
dlg = QMessageBox(self)
dlg.setWindowTitle('PDF Manager')
dlg.setIcon(QMessageBox.Information)
dlg.setText(message)
dlg.show()
def _getSaveFilePath(self):
file_save_path, _ = QFileDialog.getSaveFileName(
self, 'Save PDF file', '.', 'PDF file (*.pdf)'
)
return file_save_path
def mergeFile(self):
if not self.outputFile.text():
# надо выбрать outputFile!
self.populateFileName()
return
if self.pdfListWidget.count() > 0:
pdfMerger = PdfFileMerger()
try:
for i in range(self.pdfListWidget.count()):
pdfMerger.append(self.pdfListWidget.item(i).text())
pdfMerger.write(self.outputFile.text())
pdfMerger.close()
self.pdfListWidget.clear()
self.dialogMessage('<h2 style="color: green;">Слияние PDF завершено!</h2>')
except Exception as e:
self.dialogMessage(f'Error: {e}')
else:
self.dialogMessage(
'''<h2 style="color: red;">Нечего объединять.<br> Добавьте файлы для слияни!</h2>'''
)
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyle("fusion")
app.setAttribute(Qt.AA_EnableHighDpiScaling, True)
demo = AppDemo()
demo.resize(600, 400)
demo.show()
sys.exit(app.exec_())
