Python печать в pdf

Автоматизируем печать документов с помощью Python

Каждый день, я готовлю однообразные документы, в которых нужно печатать страницы — одинаково (однообразно):
1 (ую) и 2 (ую) страницы, двойной печатью по длинному краю;
3 (ью) и 4 (ую) по короткому краю (эти листы горизонтальные);
5 (ую) страницу отдельно (только 1 лист).

Каждый день, из раза в раз, нужно было настраивать диапазон для печатати. И в один момент (спустя 3 дня) мне это надоело и я решил написать программу, с помощью которой можно будет распечатать этот документ — одним нажатием мыши.

Спойлер — мне удалось. Но пришлось поискать информацию, а информации на русском не очень много, поэтому искал преимущественно в английских источниках.

Задача

В начале у меня были Word документы и их нужно распечатать максимально экономно и этично, чтобы не просто печатать весь документ в разнобой, а используя свои подходы на печать.

Решение

Из Word в PDF

Для начала преобразуем Word документы в отдельные PDF файлы, для этого устанавливаем следящую библиотеку:

И пишем код для конвертации. Для этого собираем все «.docx» файлы в папке, преобразуем их в PDF и нам требуется условие на проверку файла.

Если «.docx» есть в названии файла, то конвертируем, иначе пропускаем файлы. Нужно для того, чтобы сами pdf файлы не конвертировались в pdf (вылезет ошибка).

from docx2pdf import convert import os def word_convert(arr): out = [] for file in arr: if '.docx' in file: out.append(file) return out indir = '\\input' #ваша директория, где находятся .docx файлы all_files = next(os.walk(indir))[2] # все файлы в вашей директории в массиве input_files = word_convert(all_files) # входные .dock файлы #проходимся циклом по директории и конвертируем for file in input_files: path_file = indir + file # путь до файла convert(path_file)

Систематизация страниц

Далее устанавливаем библиотеку для редактирования страниц в pdf:

Пишем функцию для чтения и систематизации документа на под файлы т.к используя эту библиотеку, мы будет удалять из нашего файла страницы, то пишем функцию для более удобного удаления:

def del_pages(pdf, arr, num_pages=16): max = arr[1] min = arr[0] - 1 del pdf.pages[max:num_pages] del pdf.pages[0:min] return pdf # -1 для того, чтобы вы писали с 1 страницы, а не с 0. #В начале это не мешает, но если страниц 20, то в конце можно запутаться. 

Сохранение новых файлов

# Теперь пишем функцию для чтения и систематизации: outdir = '\\output' def doc_crushing(doc_path, arr, outpdf): with pikepdf.open(doc_path) as pdf: # Смотрим сколько страниц в pdf num_pages = len(pdf.pages) # Удаляем страницы из pdf del_pages(pdf, arr, num_pages) pdf.save(outdir + outpdf) #Пример doc = 'Договор.pdf' # Название вашего файла (тут для примера без цикла) doc_path = indir + doc # Путь до файла #doc_crushing(входной файл, масив с нужными срезом страниц, новое название) doc_crushing(doc_path, [1,2], 'Титульный лист.pdf') doc_crushing(doc_path, [3,4], 'Экзаменационный лист с фото.pdf') doc_crushing(doc_path, [5,6], 'Заявление на поступление.pdf') 

Т.е из документа «doc_path», мы оставляем промежуток страниц с 1 по 2 и сохраняем с именем ‘Титульный лист.pdf’ и так для каждого файла

Читайте также:  Css animation with scroll

Печать документов

Для работы с принтерами установим следующую библиотеку

Далее пишем функцию для печати т.к мы ее будем вызывать для каждого нужного файла

import win32print import win32api #print_pdf (входной pdf, режим печати, какой принтер) #режим печати: 1 - односторонняя, 2 двойная по длинному краю, 3 - по короткому def print_pdf(input_pdf, mode=2, printer=1): # тут мои принтеры, для своихузнаем имя дефолтного принтера через метод win32print.GetDefaultPrinter() if int(printer) == 2: name = "\\\\buh\\BUH DCP-L5500DN series (копия 1)" #win32print.GetDefaultPrinter() elif int(printer) == 1: name = "Brother DCP-L2540DN series Printer" #win32print.GetDefaultPrinter() try: # Устанавливаем дефолтный принтер win32print.SetDefaultPrinterW(name) win32print.SetDefaultPrinter(name) finally: # Если не получилось или получилось -> устанавливаем этот принтер стандартом name = win32print.GetDefaultPrinter() # оставляем без изменений ## тут нужные права на использование принтеров printdefaults = ## начинаем работу с принтером ("открываем" его) handle = win32print.OpenPrinter(name, printdefaults) ## Если изменить level на другое число, то не сработает level = 2 ## Получаем значения принтера attributes = win32print.GetPrinter(handle, level) ## Настройка двухсторонней печати attributes['pDevMode'].Duplex = mode #flip over 3 - это короткий 2 - это длинный край ## Передаем нужные значения в принтер win32print.SetPrinter(handle, level, attributes, 0) win32print.GetPrinter(handle, level)['pDevMode'].Duplex ## Предупреждаем принтер о старте печати win32print.StartDocPrinter(handle, 1, [input_pdf, None, "raw"]) ## 2 в начале для открытия pdf и его сворачивания, для открытия без сворачивания поменяйте на 1 win32api.ShellExecute(2,'print', input_pdf,'.','/manualstoprint',0) ## "Закрываем" принтер win32print.ClosePrinter(handle) ## Меняем стандартный принтер на часто используемый win32print.SetDefaultPrinterW("Brother DCP-L2540DN series Printer") win32print.SetDefaultPrinter("Brother DCP-L2540DN series Printer") # Пример inputs_print = next(os.walk(outdir))[2] # Берем все файлы в папке outdir # Печатаем документы for input_print in inputs_print: # Путь до файла, который нужно расспечатать path_print = outdir + input_print # Если в названии файла есть 'Экзаменационный', то печатаем по короткому краю if 'Экзаменационный' in input_print: print_pdf(path_print, 3, num) else: print_pdf(path_print, 2, num)
from docx2pdf import convert import win32print import win32api import pikepdf import shutil import time import sys import os #Мой код запускается сразу с определными значениями if sys.argv[7]: lastname = sys.argv[1] name = sys.argv[2] fname = sys.argv[3] name1 = sys.argv[4] today = sys.argv[5] num = sys.argv[6] level_stydy = sys.argv[7] else: lastname = sys.argv[1] name = sys.argv[2] fname = sys.argv[3] today = sys.argv[4] num = sys.argv[5] level_stydy = sys.argv[6] #Если значения передавались, то изменяем директорию if lastname: dir = os.path.abspath(os.curdir) + "\\py\\" + f"  " else: dir = os.path.abspath(os.curdir) indir = dir + "\\input\\" outdir = dir + "\\output\\" #Получаем все файлы в дикетории -> выдаем docx файлы def tackword(arr): out = [] for file in arr: if '.docx' in file: out.append(file) return out #Функция для копирования сгенерированых файлов в мою директорию def copy_in_input(indir, name1): dir = os.path.abspath(os.curdir) + '\\iles\\' input_files = tackword(next(os.walk('.\\files'))[2]) for file in input_files: if name1 in file and today in file: src = dir + file ind = indir + file shutil.copyfile(src, ind) def del_pages(pdf, arr, num_pages=16): max = arr[1] min = arr[0] - 1 del pdf.pages[max:num_pages] del pdf.pages[0:min] return pdf def doc_crushing(doc_path, arr, outpdf): with pikepdf.open(doc_path) as pdf: num_pages = len(pdf.pages) #Удаляем страницы из pdf del_pages(pdf, arr, num_pages) pdf.save(outdir+outpdf) def print_pdf(input_pdf, mode=2, printer=1): if int(printer) == 2: name = "\\buh\BUH DCP-L5500DN series (копия 1)" #win32print.GetDefaultPrinter() elif int(printer) == 1: name = "Brother DCP-L2540DN series Printer" #win32print.GetDefaultPrinter() win32print.SetDefaultPrinterW(name) win32print.SetDefaultPrinter(name) name = win32print.GetDefaultPrinter() print(name) print("<bk>") drivers = win32print.EnumPrinterDrivers(None, None, 2) for drive in drivers: print(drive['Name']) printdefaults = handle = win32print.OpenPrinter(name, printdefaults) level = 2 attributes = win32print.GetPrinter(handle, level) attributes['pDevMode'].Duplex = mode #flip over 3 - это короткий 2 - это длинный край win32print.SetPrinter(handle, level, attributes, 0) win32print.GetPrinter(handle, level)['pDevMode'].Duplex r = win32print.StartDocPrinter(handle, 1, [input_pdf, None, "raw"]) print(r) win32api.ShellExecute(2,'print', input_pdf,'.','/manualstoprint',0) # win32print.ClosePrinter(handle) # win32print.SetDefaultPrinterW("Brother DCP-L2540DN series Printer") # win32print.SetDefaultPrinter("Brother DCP-L2540DN series Printer") def main(): # проверяем есть ли директория, если нету, то делаем if not os.path.exists(dir): os.mkdir(dir) os.mkdir(dir + '\\input') os.mkdir(dir + '\\output') # копируем из файлы имеющие имя в файле copy_in_input(indir, name1) # берем docx скопированные файлы input_files = tackword(next(os.walk(indir))[2]) for file in input_files: convert(indir+file) input_pds = next(os.walk(indir))[2] doc = '' rec = '' outs = [] # Если я хочу изменять pdf файл, то записываю его в переменную for file in input_pds: if '.pdf' in file: if 'Договор' in file: doc = file elif 'Реквизиты' in file: rec = file else: outs.append(file) # Открываем договор pdf, если он есть if doc != '': doc_path = indir + doc # 1 - БАК; 2 - МАГ; 3 - СПО if level_stydy == 1: doc_crushing(doc_path, [1,2], 'Титульный лист.pdf') doc_crushing(doc_path, [3,4], 'Экзаменационный лист с фото.pdf') doc_crushing(doc_path, [5,6], 'Заявление на поступление.pdf') doc_crushing(doc_path, [7,7], 'Согласие на зачисление.pdf') doc_crushing(doc_path, [8,9], 'Согласие на обработку персональных данных.pdf') doc_crushing(doc_path, [10,16], 'Договор.pdf') elif level_stydy == 2: doc_crushing(doc_path, [1,2], 'Титульный лист.pdf') doc_crushing(doc_path, [3,4], 'Экзаменационный лист с фото.pdf') doc_crushing(doc_path, [5,6], 'Заявление на поступление.pdf') doc_crushing(doc_path, [7,7], 'Согласие на зачисление.pdf') doc_crushing(doc_path, [8,9], 'Согласие на обработку персональных данных.pdf') doc_crushing(doc_path, [10,14], 'Договор.pdf') elif level_stydy == 3: doc_crushing(doc_path, [1,2], 'Титульный лист.pdf') doc_crushing(doc_path, [3,4], 'Заявление на поступление.pdf') doc_crushing(doc_path, [5,5], 'Согласие на зачисление.pdf') doc_crushing(doc_path, [6,7], 'Согласие на обработку персональных данных.pdf') doc_crushing(doc_path, [8,12], 'Договор.pdf') if rec != '': rec_path = indir + rec with pikepdf.open(rec_path) as pdf: num_pages = len(pdf.pages) if num_pages != 1: del_pages(pdf, [1,1], num_pages) pdf.save(outdir+'Реквизиты на оплату.pdf') if outs: for out in outs: with pikepdf.open(indir+out) as pdf: pdf.save(outdir+out) files_to_print = [] inputs_print = next(os.walk(outdir))[2] #Печатаем документы for input_print in inputs_print: path_print = outdir + input_print if 'Экзаменационный' in input_print: print_pdf(path_print, 3, num) else: print_pdf(path_print, 2, num) # #Удаляем файлы # time.sleep(100) # for file in os.scandir(indir): # if file.name.endswith(".pdf") or file.name.endswith(".docx"): # os.unlink(file.path) # for file in os.scandir(outdir): # if file.name.endswith(".pdf") or file.name.endswith(".docx"): # os.unlink(file.path) if name == 'main': main()

Вывод

Сразу про минусы:
принтеры не всегда меняются (т.е печатает, только, 1 принтер), разбираюсь почему.

Читайте также:  Java convert bytes to chars

Плюсы т.к мне не нужно постоянно вбивать диапазон страниц, освобождается куча времени, на саморазвитие)

Прощу, раскритиковать мой говнокод и поделится своим мнением о автоматизации печати (как вы это делали) или была ли моя статья полезно для вас

Это моя первая статья, поэтому давайте пожестче

P.S Документы генерирую на php форме с php сервера, на котором запускаю Python скрипт, с помощью php формы

Источник

How To Print PDF Files Using Python

Printing PDF files in Python is a valuable capability, enabling developers to work with documents in a platform-independent manner. PDFs are extensively utilized for storing and distributing files, making them essential for Python applications involving document management or workflows.

Python offers several methods for generating and printing PDF files, with one popular approach being the use of libraries that provide classes specifically designed for creating and manipulating PDF documents. This comprehensive How-to Guide focuses on utilizing the IronPDF library to effortlessly generate and print PDF files within Python scripts.

How to Print PDF Files using Python

IronPDF: Python PDF Library

IronPDF is a powerful Python library that empowers developers to generate, manipulate, and convert PDF documents. Inspired by the IronPDf C# .NET library, it offers a wide range of features suitable for the Python ecosystem.

With IronPDF, developers can leverage a high-level API that simplifies working with PDF files, eliminating the need to handle low-level intricacies. It provides convenient methods for common PDF operations, including creating new documents, adding content, formatting text, merging and splitting PDF files.

One standout feature of IronPDF is its ability to seamlessly convert HTML, CSS, and JavaScript code into PDF format. This functionality facilitates the effortless generation of PDF files from web pages or HTML templates. Furthermore, IronPDF includes support for printing PDF documents, adding to its versatility and utility.

Читайте также:  Python asyncio запуск нескольких задач

Install IronPDF via Pip

You can easily add the IronPDF library to your Python project using pip. Use the provided command below to install IronPDF via pip:

Add IronPDF package by using the following code:

Источник

Оцените статью