Анализ данных, Обработка документов

Заполняем PDF файлы с использованием Python: библиотека python-pptx

Время прочтения: 6 мин.

В прошлых статьях мы уже рассказывали о том, как достать информацию из PDF- файлов.

Сегодня рассмотрим обратный процесс – заполнение pdf файлов с использованием Python.

Это может помочь, к примеру, в автоматизации заполнения шаблонов презентаций: для ежеквартальный отчетов, выступлений, текущих задач и новых идей.

С одной стороны, создание слайдов – это творческий процесс и при автоматизации пропадает индивидуальный подход и творчество. Но это нет так. Рутинную работу мы передаем роботу, а творчество используем в создании умного шаблона. Преимущества: исключаем ошибки при переносе информации из одного формата (Excel, Word) в другой и отказываемся от ручного процесса переноса.

Впервые автозаполнение слайдов в Power Point с помощью Python — мы использовали для подготовки наградных документов  по результатам работы сотрудников за год. Так как номинаций было несколько – получился большой список сотрудников.

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

  • Какие инструменты использовали: Microsoft PowerPoint, Jupyter Notebook, MS Excel, Adobe Photoshop (или можно найти готовый шаблон в сети Интернет)
  • Язык программирования: Python
  1. Библиотеку для обработки файлов *.pptx устанавливаем через командную строку или Anaconda Prompt – pip install python-pptx
  2. С помощью Рhotoshop работаем с графическими элементами, создаем визуальное оформление. Несколько получившихся вариантов ниже.

3. Далее на фоновое изображение необходимо наложить текст и другие элементы, которые будут оставаться неизменными. Используем для этого — MS PowerPoint.

4. Информацию по всем сотрудникам, заявленным к награждению, мы вносим в файл Excel (его же будем использовать как источник данных).

5. Используя инструмент интерактивной разработки Jupyter Notebook импортируем библиотеку pptx и модули этой библиотеки. Для чтения excel импортируем библиотеку xlrd.

from pptx import Presentation
from pptx.enum.shapes import …
….
import os

import xlrd
workbook=xlrd.open_workbook('./Название файла, содержащего список ФИО награждаемых')

6. С помощью следующего блока программного кода читаем данные из Excel-листа в Python framework.

worksheet=workbook.sheet_by_index(4)

total_rows=worksheet.nrows
total_cols=worksheet.ncols

table=list()
record=list()
if total_rows > 0:
    for x in range(7,total_rows):    # не берем строки с 1 по 7, в которых текст и названия столбцов 
        for y in range(total_cols):
            record.append(worksheet.cell(x,y).value)        
        table.append(record) 
        record = [ ]
        x=x+1
else:
    print("Файл пустой")

7. Указываем место на локальном диске, в котором будет создана папка для наших наградных электронных документов
localpath=’c:\\папка_1\\папка_2\\’

8. Создаем функцию, c помощью которой обратим pptx-файл в pdf-файл.

def PPTtoPDF(inputFileName, outputFileName, formatType = 32):
    powerpoint = comtypes.client.CreateObject("Powerpoint.Application")
    powerpoint.Visible = 1

    if outputFileName[-3:] != 'pdf':
        outputFileName = outputFileName + ".pdf"
    deck = powerpoint.Presentations.Open(inputFileName)
    deck.SaveAs(outputFileName, formatType) # formatType = 32 for ppt to pdf
    deck.Close()
    powerpoint.Quit()

9. Соблюдаем правила орфографии и склонения с помощью следующего блока кода:

for i in range(total_rows-7): # не берем первые 7 строк (там "шапка")
    #print(i)  
    record=table[i]
    if record[0]!="": # если столбец "Кто номинирует" НЕ пустой (в таблице больше строк,чем внесено данных)
        company='ООО Ромащка '
        city= record[4]                    
        if city=='МСК':  city='г.Москва'
        companycity=company+city

10. Заполняем информацию по занятым местам:

mesto = str(record[2])
        
        if mesto=='1.0':
            mesto='I'
            _mesto=mesto   #для имени файла
            mesto1='     занявшее              в номинации'    # оставляем разное кол-во пробелов для печати места др.цветом
            mesto2=mesto+" место  "
        if mesto=='2.0':
            mesto='II'
            _mesto=mesto   #для имени файла
            mesto1='     занявшее               в номинации'
            mesto2=mesto+" место  "
        if mesto=='3.0':
            mesto='III'
            _mesto=mesto   #для имени файла
            mesto1='     занявшее                в номинации'    
            mesto2=mesto+" место  "
        if mesto=='1.5':
            mesto='I-II'
            _mesto=mesto   #для имени файла
            mesto1='     занявшее                 в номинации'            
            mesto2=mesto+" место  "
        if mesto=='2.5':
            mesto='II-III'
            _mesto=mesto   #для имени файла
            mesto1='     занявшее                   в номинации'            
            mesto2=mesto+" место  "
        if mesto=='3.5':
            mesto='III-IV'
            _mesto=mesto   #для имени файла
            mesto1='     занявшее                    в номинации'            
            mesto2=mesto+" место  "       
        if mesto=='': 
            _mesto='победитель' # для имени файла
            mesto1='победитель в номинации' 
            mesto2=''
            
        nom = record[1]
        za = record[3]

11. Теперь формируем текст для печати, устанавливаем отступы, задаем цвет текстовым слоям:

if za!='':              #есть "за что"       
        #формируем текст для печати [1-company+city,2-mesto1,3-mesto2,4-nom,5-za]  
            dtop = {1: Cm(7.0), 2: Cm(8.5), 3: Cm(8.5), 4: Cm(10.0), 5: Cm(11.5)}
            dalign = {1:PP_ALIGN.CENTER,2:PP_ALIGN.CENTER,3:PP_ALIGN.CENTER,4:PP_ALIGN.CENTER,5:PP_ALIGN.CENTER}
            dfsize = {1: Pt(20),2: Pt(20),3: Pt(20),4: Pt(20), 5: Pt(20)}
            dfcolor = {1:RGBColor(38,38,38),2:RGBColor(38,38,38),3:RGBColor(9,137,55),4:RGBColor(38,38,38),5:RGBColor(38,38,38)}
            dfbold= {1:True,2:False,3:False,4:True,5:False}
            dtext = {1:companycity,2:mesto1,3:mesto2,4:nom,5:za}              
        else:                   # нет "за что"
        #формируем текст для печати [1-company+city,2-mesto1,3-mesto2,4-nom] 
            dtop = {1: Cm(7.5), 2: Cm(9.5),3: Cm(9.5), 4: Cm(11.5)}
            dalign = {1:PP_ALIGN.CENTER,2:PP_ALIGN.CENTER,3:PP_ALIGN.CENTER,4:PP_ALIGN.CENTER}
            dfsize = {1: Pt(20),2: Pt(20),3: Pt(20),4: Pt(20)}
            dfcolor = {1:RGBColor(38,38,38),2:RGBColor(38,38,38),3:RGBColor(9,137,55),4:RGBColor(38,38,38)}
            dfbold= {1:True,2:False,3:False, 4:True}
            dtext = {1:uvabank,2:mesto1,3:mesto2,4:nom}

12. Затем формируем итоговые pdf-файлы (устанавливаем шрифт, цвет, размер)

q=len(dtext)   # кол-во элементов для печати
        nameprs='ДИПЛОМ'  # ВНИМАНИЕ: шаблоны с именами должны лежать в каталоге вместе с программой
        prs=Presentation(nameprs + ".pptx")           
        slide = prs.slides[0]
        shapes = slide.shapes
        for j in range(1,q+1):
            shape = shapes.add_shape(MSO_SHAPE.RECTANGLE, Cm(1.25), dtop[j], Cm(25.0), Cm(2))
            shape.fill.background()
            shape.line.fill.background()
            shape.shadow.inherit = False
            text_frame = shape.text_frame
            text_frame.vertical_anchor = MSO_ANCHOR.TOP
            p = text_frame.paragraphs[0]
            p.alignment = dalign[j]
            run = p.add_run()
            font = run.font
            font.name = 'Arial'
            font.italic = None  # cause value to be inherited from theme
            font.bold=dfbold[j]
            #font.color.rgb=RGBColor(38,38,38)
            font.color.rgb=dfcolor[j]
            run.text = dtext[j]
            font.size = dfsize[j]
        fname=localpath + record[4] +'_'+'ДИПЛОМ'+'_'+ nom +'_'+_mesto+" "+str(i+8)   # ИМЯ ВЫХОДНОГО ФАЙЛА_"ДИПЛОМ"_номинация_место_№строки в файле
        prs.save(fname + '.pptx')
        PPTtoPDF(fname + '.pptx',fname + '.pdf')
        #os.remove(fname.replace('\\','/')+'.pptx')    не удаляем файл .pptx 
        
    i=i+1   # закончили формирование дипломов

Итоговый продукт выглядит следующим образом.

Вывод: если у вас также есть ежедневные/еженедельные задачи по кропотливому заполнению одних и тех же полей в слайдах Power Point, то создание умного шаблона поможет автоматизировать этот процесс.

Советуем почитать