Created
March 3, 2021 10:30
-
-
Save pylixm/5e4d3ab547c1ef8f0118e969237950c4 to your computer and use it in GitHub Desktop.
pdf_pyqt5.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # read docs : https://www.learnpyqt.com/examples/python-pdf-report-generator/ | |
| from PyQt5.QtWidgets import QPushButton, QLineEdit, QApplication, QFormLayout, QWidget, QTextEdit, QMessageBox, QSpinBox | |
| from PyQt5.QtCore import QObject, QRunnable, QThreadPool, pyqtSignal, pyqtSlot | |
| from reportlab.pdfgen.canvas import Canvas | |
| import os | |
| import textwrap | |
| from datetime import datetime | |
| from pdfrw import PdfReader | |
| from pdfrw.buildxobj import pagexobj | |
| from pdfrw.toreportlab import makerl | |
| class WorkerSignals(QObject): | |
| """ | |
| Defines the signals available from a running worker thread. | |
| """ | |
| error = pyqtSignal(str) | |
| file_saved_as = pyqtSignal(str) | |
| class Generator(QRunnable): | |
| """ | |
| Worker thread | |
| Inherits from QRunnable to handle worker thread setup, signals | |
| and wrap-up. | |
| :param data: The data to add to the PDF for generating. | |
| """ | |
| def __init__(self, data): | |
| super().__init__() | |
| self.data = data | |
| self.signals = WorkerSignals() | |
| @pyqtSlot() | |
| def run(self): | |
| try: | |
| outfile = "result.pdf" | |
| template = PdfReader("template.pdf", decompress=False).pages[0] | |
| template_obj = pagexobj(template) | |
| canvas = Canvas(outfile) | |
| xobj_name = makerl(canvas, template_obj) | |
| canvas.doForm(xobj_name) | |
| ystart = 443 | |
| # Prepared by | |
| canvas.drawString(170, ystart, self.data['name']) | |
| # Date: Todays date | |
| today = datetime.today() | |
| canvas.drawString(410, ystart, today.strftime('%F')) | |
| # Device/Program Type | |
| canvas.drawString(230, ystart-28, self.data['program_type']) | |
| # Product code | |
| canvas.drawString(175, ystart-(2*28), self.data['product_code']) | |
| # Customer | |
| canvas.drawString(315, ystart-(2*28), self.data['customer']) | |
| # Vendor | |
| canvas.drawString(145, ystart-(3*28), self.data['vendor']) | |
| ystart = 250 | |
| # Program Language | |
| canvas.drawString(210, ystart, "Python") | |
| canvas.drawString(430, ystart, self.data['n_errors']) | |
| comments = self.data['comments'].replace('\n', ' ') | |
| if comments: | |
| lines = textwrap.wrap(comments, width=65) # 45 | |
| first_line = lines[0] | |
| remainder = ' '.join(lines[1:]) | |
| lines = textwrap.wrap(remainder, 75) # 55 | |
| lines = lines[:4] # max lines, not including the first. | |
| canvas.drawString(155, 223, first_line) | |
| for n, l in enumerate(lines, 1): | |
| canvas.drawString(80, 223 - (n*28), l) | |
| canvas.save() | |
| except Exception as e: | |
| self.signals.error.emit(str(e)) | |
| return | |
| self.signals.file_saved_as.emit(outfile) | |
| class Window(QWidget): | |
| def __init__(self): | |
| super().__init__() | |
| self.threadpool = QThreadPool() | |
| self.name = QLineEdit() | |
| self.program_type = QLineEdit() | |
| self.product_code = QLineEdit() | |
| self.customer = QLineEdit() | |
| self.vendor = QLineEdit() | |
| self.n_errors = QSpinBox() | |
| self.n_errors.setRange(0, 1000) | |
| self.comments = QTextEdit() | |
| self.generate_btn = QPushButton("Generate PDF") | |
| self.generate_btn.pressed.connect(self.generate) | |
| layout = QFormLayout() | |
| layout.addRow("Name", self.name) | |
| layout.addRow("Program Type", self.program_type) | |
| layout.addRow("Product Code", self.product_code) | |
| layout.addRow("Customer", self.customer) | |
| layout.addRow("Vendor", self.vendor) | |
| layout.addRow("No. of Errors", self.n_errors) | |
| layout.addRow("Comments", self.comments) | |
| layout.addRow(self.generate_btn) | |
| self.setLayout(layout) | |
| def generate(self): | |
| self.generate_btn.setDisabled(True) | |
| data = { | |
| 'name': self.name.text(), | |
| 'program_type': self.program_type.text(), | |
| 'product_code': self.product_code.text(), | |
| 'customer': self.customer.text(), | |
| 'vendor': self.vendor.text(), | |
| 'n_errors': str(self.n_errors.value()), | |
| 'comments': self.comments.toPlainText() | |
| } | |
| g = Generator(data) | |
| g.signals.file_saved_as.connect(self.generated) | |
| g.signals.error.connect(print) # Print errors to console. | |
| self.threadpool.start(g) | |
| def generated(self, outfile): | |
| self.generate_btn.setDisabled(False) | |
| try: | |
| os.startfile(outfile) | |
| except Exception: | |
| # If startfile not available, show dialog. | |
| QMessageBox.information(self, "Finished", "PDF has been generated") | |
| app = QApplication([]) | |
| w = Window() | |
| w.show() | |
| app.exec_() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment