הדפסת קובץ PDF בפייתון (windows)
-
שאלה פשוטה עם תשובה מסובכת:
אני מחפש דרך לשליחת קובץ pdf להדפסה שתעבוד ללא תלות בתוכנות המותקנות במחשב.
יש את הדרך win32api:win32api.ShellExecute(0, "print", f, None, ".", 0)
החיסרון בזה- הוא עובד רק אם יש קורא PDF שיש לו api מתאים (כגון foxit). לא מתאים לי מכיון שזה מיועד לשימוש ציבורי והרבה אנשים משתמשים רק בedge כקורא pdf ואין לו את הapi המתאים.
קראתי את המאמר הזה ולמעשה יצאתי בידיים ריקות... -
@הפצת-אנקי
גילוי נאות: אינני מכיר את פייתון כללאשקף את הבנתי מהשאלה
הינך מעוניין שלחיצה על 'הדפס' תשלח ישירות את הקובץ להדפסה
במדפסת ברירת מחדל של המשתמשראה כאן
(חיפוש בגוגל: Python how to print file directly to default printer)
-
@הפצת-אנקי אין תמיכה מובנית בווינדוס להדפסת PDF.
אם זה היה קובץ XPS או קובץ EMF אולי המצב היה שונה, נראה לי שבשני המקרים האלו היה לך אפשרות לשלוח ישירות למדפסת כי זה פורמט שווינודס מבין
אבל במקרה של קובץ PDF זה קופסה שחורה עבור ווינדוס וצריך קודם להמיר אותו למשהו שווינדוס או המדפסת מבינים.
אם זה משהו שווינדוס מבין הוא יודע לתרגם את זה לשפה של המדפסת, ואם המדפסת מבין, אז אפשר לשלוח את זה ישירות למדפסת
אבל במקרה הזה שלא ווינדוס ולא המדפסת מבינים את הפורמט, חייבים תוכנה באמצע לתרגם
האפשרות היחידה שאני רואה פה זה ספריית פייתון שיודע לרנדר PDF, ואז אולי כמו שהוא ידע לרנדר אותו למסך הוא גם יתן לך API לרנדר למדפסתאפשרות נוספת, להמיר לפורמט שיש לו תוכנה מובנית בווינדוס שמקבל פרמטר שאומר לו להדפיס. כנראה שזה יהיה חייב להיות קובץ תמונה, זה לא הפורמט הכי טוב עבור הדפסה של PDF, אבל יותר טוב מכלום
-
@הפצת-אנקי
מקווה שאני לא 'מספים' לך את השאלה המקוריתלפי דברי @yossiz
אולי ניתן לעשות מיד אחרי הלחיצה - בדיקה האם מותקן במחשב מדפסת PDF
(יוצא מתוך הנחה שכל מדפסת PDF מופיע בשם המדפסת האותיות PDF)במידה וקיים - תדפיס ישירות כדלעיל
במידה ולא קיים - תציע למשתמש התקנה של מדפסת PDF כלשהיא -
@mekev אני לא חושב שיעזור פה מדפסת PDF
א. בד״כ הם רשומים במערכת כמדפסות postscript והם ממירים את ה-postscript שווינדוס שולח להם ל-PDF, אני לא חושב שאפשר לשלוח להם ישירות קבצי PDF, וגם אלה שלא עובדים כמדפסות postscript - כמו זה של pdfXchange מכל מקום מסופקני מאוד אם הם יסכימו לקבל קובץ PDF
ב. גם אם הם יקבלו קובץ pdf הם יפלטו קובץ pdf אבל השואל רוצה להדפיס למדפסת נייר.האם לא הבנתי את הצעתך בצורה נכונה?
מה שכן אפשר: לקבל רשימת התוכנות שמטפלות בסיומת PDF ולבחור מתוכם באחד שתומך גם בהדפסה
-
@הפצת-אנקי מה באמת המטרה שלך? למה אתה רוצה לתת אפשרות להדפיס קובץ בלי להציג אותו? ואם אתה מציג אותו אז התוכנה שמציגה נותנת בד״כ אפשרות להדפיס ג״כ
-
@WWW אם כבר, אז התעוררתי בדבריך שלכאורה אפשר להשתמש ב-ghostscript להמיר ל-emf ואז להדפיס.
צריך עוד עיון אם זה באמת אפשרותעריכה: בינתיים לא נראה לי שיש אפשרות לפלט emf או xps ב-ghostscript.
עריכה2: יש XPS: https://ghostscript.com/doc/current/VectorDevices.htm#XPS -
ראשית, תודה לכל המשיבים
@yossiz אפרט הכל מהתחלה:
ברמת העיקרון, השאלות בתוכנת אנקי הן בעצם מסמכי html וכתובות בקוד html ותומכות גם בjs וכל הנלווה.
התוכנה מתפקדת כדפדפן שמציג את השאלות. הדפדפן הוא יישום מהספריה Qt הנקרא QtWebEngine שמבוסס על כרום.
כדי להדפיס את השאלות לפי קריטריונים מסוימים כתבתי קוד שאוסף את השאלות לפי הפרמטרים שהמשתמש מכניס. הפלט הוא דף html.
מהhtml הזה אני מתקדם הלאה לצורך המרה לוורד (למתעניינים: על ידי הAPI של וורד), שמירה כpdf (אופציה מובנה בpyqt6) והדפסה.
(מכאן ואילך העיקר)
עד הגירסאות האחרונות תוכנת אנקי היתה מבוססת על pyqt5 ושם השתמשתי בקוד מוכן כדי להדפיס. כעת הגירסא העדכנית עברה לPyqt6 ושם נעשו הרבה שינויים במחלקות שקשורות להדפסה (QPrintSupport ונספחיה) עם כמעט אפס תיעוד.
בתחילה ניסיתי להמיר את הקוד ללא הצלחה. השלב הבא היה לחפש דרכים אחרות. במהלך החיפושים גיליתי שההדפסה דרך Qt איטית בצורה משמעותית מאשר להדפיס בדרכים אחרות מלבד מה שאין אינדיקציה כמה דפים יצאו מהמדפסת בסופו של דבר. הדרך היותר מהירה הייתה לבצע המרת ביניים לpdf ומשם להדפיס.
התצוגה המקדימה של ההדפסה היא בסך הכל דף html ארוך ללא שום קשר לתוצאה הסופית. אני מעדיף לא ליצור עוד מידי הרבה תיבות דו שיח כדי לא להכביד.
כנראה שמה שהכי יעיל יהיה להמיר לתמונה ומשם להדפיס (?). -
למעשה, לבעיה שלי מצאתי פתרון הדפסה ישירות מהhtml עם תצוגה מקדימה שנראית ככה:
אם אי פעם יהיה למישהו צורך בקוד (או למקרה שיש צורך דחוף להדפיס את הדף הזה דרך Pyqt6 דווקא...):
import sys from PyQt6.QtCore import QCoreApplication, QUrl, pyqtSlot, QEventLoop from PyQt6.QtPrintSupport import QPrintPreviewDialog, QPrinter from PyQt6.QtWebEngineWidgets import QWebEngineView from PyQt6.QtWidgets import QApplication class PDFPage(QWebEngineView): def __init__(self, url, filename): super(PDFPage, self).__init__() self.url = QUrl.fromUserInput(url) self.filename = filename self.loadFinished.connect(self.load_finished) self.m_printer = QPrinter(QPrinter.PrinterMode.HighResolution) self.m_waitForResult = QEventLoop() self.printFinished.connect(self.print_finished) def start(self): self.load(self.url) def load_finished(self, ok): if ok: self.QPrintPreviewDialog = QPrintPreviewDialog(self.m_printer) self.QPrintPreviewDialog.paintRequested.connect(self.printDocument) self.QPrintPreviewDialog.exec() else: QCoreApplication.exit(-1) def printDocument(self, printer): self.print(printer) self.m_waitForResult.exec() def print_finished(self): self.m_waitForResult.quit() def pdf_from_url(url, filename): app = QApplication(sys.argv) page = PDFPage(url, filename) page.start() ret = app.exec() return ret == 0 sucess = pdf_from_url("https://tchumim.com/topic/13945/%D7%94%D7%93%D7%A4%D7%A1%D7%AA-%D7%A7%D7%95%D7%91%D7%A5-pdf-%D7%91%D7%A4%D7%99%D7%99%D7%AA%D7%95%D7%9F-windows/13?_=1662075589691", "test.pdf") if sucess: print("PDF has been generated")
לגופו של עניין, כנראה שהתשובה תהיה באמת להמיר את הpdf לתמונה באמצעות pdf2image ואחר כך להדפיס באמצעות win32print. דוגמא מובאת למעלה בקישור שבהודעה הראשונה שלי.
תודה לכל העוזרים ובפרט ל @yossiz המיוחד...
-
-