Модуль python-docx
предназначен для создания и обновления файлов с расширением .docx
— Microsoft Word. Этот модуль имеет одну зависимость: сторонний модуль lxml
.
Модуль python-docx
размещен на PyPI, поэтому установка относительно проста.
# создаем виртуальное окружение, если нет $ python3 -m venv .venv --prompt VirtualEnv # активируем виртуальное окружение $ source .venv/bin/activate # ставим модуль python-docx (VirtualEnv):~$ python3 -m pip install -U python-docx
Основы работы с файлами Microsoft Word на Python.
- Открытие/создание документа;
- Добавление заголовка документа;
- Добавление абзаца;
- Применение встроенного стиля в Microsoft Word к абзацу;
- Жирный, курсив и подчеркнутый текст в абзаце;
- Применение стилей Microsoft Word к символам текста (к прогону);
- Пользовательский стиль символов текста;
- Добавление разрыва страницы;
- Добавление картинки в документ;
- Чтение документов MS Word.
Открытие/создание документа.
Первое, что вам понадобится, это документ, над которым вы будете работать. Самый простой способ:
from docx import Document # создание документа document = Document() # открытие документа document = Document('/path/to/document.docx')
При этом создается пустой документ, основанный на «шаблоне» по умолчанию. Другими словами, происходит примерно то же самое, когда пользователь нажимает на иконку в Microsoft Word «Новый документ» с использованием встроенных значений по умолчанию.
При этом шрифт документа и его размер по умолчанию для всего документа можно задать следующим образом:
from docx import Document from docx.shared import Pt doc = Document() # задаем стиль текста по умолчанию style = doc.styles['Normal'] # название шрифта style.font.name = 'Arial' # размер шрифта style.font.size = Pt(14) document.add_paragraph('Текст документа')
Так же, можно открывать существующий документ Word и работать с ним при помощи модуля python-docx
. Для этого, в конструктор класса Document()
необходимо передать путь к существующему документу Microsoft Word.
Добавление заголовка документа.
В любом документе, основной текст делится на разделы, каждый из которых начинается с заголовка. Название таких разделов можно добавить методом Document.add_heading()
:
# без указания аргумента `level` # добавляется заголовок "Heading 1" head = document.add_heading('Основы работы с файлами Microsoft Word на Python.') from docx.enum.text import WD_ALIGN_PARAGRAPH # выравнивание посередине head.alignment = WD_ALIGN_PARAGRAPH.CENTER
По умолчанию, добавляется заголовок верхнего уровня, который отображается в Word как «Heading 1». Если нужен заголовок для подраздела, то просто указываем желаемый уровень в виде целого числа от 1 до 9:
document.add_heading('Добавление заголовка документа', level=2)
Если указать level=0
, то будет добавлен текст с встроенным стилем титульной страницы. Такой стиль может быть полезен для заголовка относительно короткого документа без отдельной титульной страницы.
Так же, заголовки разделов можно добавлять методом document.add_paragraph().add_run()
, с указанным размером шрифта.
Например:
from docx import Document from docx.shared import Pt doc = Document() # добавляем текст прогоном run = doc.add_paragraph().add_run('Заголовок, размером 24 pt.') # размер шрифта run.font.size = Pt(24) run.bold = True doc.save('test.docx')
Добавление абзаца.
Абзацы в Word имеют основополагающее значение. Они используются для добавления колонтитулов, основного текста, заголовков, элементов списков, картинок и т.д.
Смотрим самый простой способ добавить абзац/параграф:
p = document.add_paragraph('Абзацы в Word имеют основополагающее значение.')
Метод Document.add_paragraph()
возвращает ссылку на только что добавленный абзац (объект Paragraph
). Абзац добавляется в конец документа. Эту ссылку можно использовать в качестве своеобразного «курсора» и например, вставить новый абзац прямо над ним:
prior_p = p.insert_paragraph_before( 'Объект `paragraph` - это ссылка на только что добавленный абзац.')
Такое поведение позволяет вставить абзац в середину документа, это важно при изменении существующего документа, а не при его создании с нуля.
Ссылка на абзац, так же используется для его форматирования встроенными в MS Word стилями или для кастомного/пользовательского форматирования.
Пользовательское форматирование абзаца.
Форматирование абзацев происходит при помощи объекта ParagraphFormat
.
Простой способ форматировать абзац/параграф:
from docx import Document from docx.shared import Mm from docx.enum.text import WD_ALIGN_PARAGRAPH doc = Document() # Добавляем абзац p = doc.add_paragraph('Новый абзац с отступами и красной строкой.') # выравниваем текст абзаца p.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY # получаем объект форматирования fmt = p.paragraph_format # Форматируем: # добавляем отступ слева fmt.first_line_indent = Mm(15) # добавляем отступ до fmt.space_before = Mm(20) # добавляем отступ слева fmt.space_after = Mm(10) doc.add_paragraph('Новый абзац.') doc.add_paragraph('Еще новый абзац.') doc.save('test.docx')
Чтобы узнать, какие параметры абзаца еще можно настроить/изменить, смотрите материал «Объект ParagraphFormat
»
Очень часто в коде, с возвращенной ссылкой (в данном случае p
) ничего делать не надо, следовательно нет смысла ее присваивать переменной.
Применение встроенного стиля в Microsoft Word к абзацу.
Стиль абзаца — это набор правил форматирования, который заранее определен в Microsoft Word, и храниться в редакторе в качестве переменной. По сути, стиль позволяет сразу применить к абзацу целый набор параметров форматирования.
Можно применить стиль абзаца, прямо при его создании:
document.add_paragraph('Стиль абзаца как цитата', style='Intense Quote') document.add_paragraph('Стиль абзаца как список.', style='List Bullet')
В конкретном стиле 'List Bullet'
, абзац отображается в виде маркера. Также можно применить стиль позже. Две строки, в коде ниже, эквивалентны примеру выше:
document.add_paragraph('Другой стиль абзаца.').style = 'List Number' # Эквивалентно paragraph = document.add_paragraph('Другой стиль абзаца.') # применяем стиль позже paragraph.style = 'List Number'
Стиль указывается с использованием его имени, в этом примере имя стиля — 'List'
. Как правило, имя стиля точно такое, как оно отображается в пользовательском интерфейсе Word.
Обратите внимание, что можно установить встроенный стиль прямо на результат document.add_paragraph()
, без использования возвращаемого объекта paragraph
Жирный, курсив и подчеркнутый текст в абзаце.
Разберемся, что происходит внутри абзаца:
- Абзац содержит все форматирование на уровне блока, такое как — отступ, высота строки, табуляции и так далее.
- Форматирование на уровне символов, например полужирный и курсив, применяется на уровне прогона
paragraph.add_run()
. Все содержимое абзаца должно находиться в пределах цикла, но их может быть больше одного. Таким образом, для абзаца с полужирным словом посередине требуется три прогона: обычный, полужирный — содержащий слово, и еще один нормальный для текста после него.
Когда создается абзац методом Document.add_paragraph()
, то передаваемый текст добавляется за один прогон Run
. Пустой абзац/параграф можно создать, вызвав этот метод без аргументов. В этом случае, наполнить абзац текстом можно с помощью метода Paragraph.add_run()
. Метод абзаца .add_run()
можно вызывать несколько раз, тем самым добавляя информацию в конец данного абзаца:
paragraph = document.add_paragraph('Абзац содержит форматирование ') paragraph.add_run('на уровне блока.')
В результате получается абзац, который выглядит так же, как абзац, созданный из одной строки. Если не смотреть на полученный XML, то не очевидно, где текст абзаца разбивается на части. Обратите внимание на конечный пробел в конце первой строки. Необходимо четко указывать, где появляются пробелы в начале и в конце прогона, иначе текст будет слитный (без пробелов). Они (пробелы) автоматически не вставляются между прогонами paragraph.add_run()
. Метод paragraph.add_run()
возвращает ссылку на объект прогона Run
, которую можно использовать, если она нужна.
Объекты прогонов имеют следующие свойства, которые позволяют установить соответствующий стиль:
.bold
: полужирный текст;.underline
: подчеркнутый текст;.italic
: курсивный (наклонный) текст;.strike
: зачеркнутый текст.
paragraph = document.add_paragraph('Абзац содержит ') paragraph.add_run('форматирование').bold = True paragraph.add_run(' на уровне блока.')
Получится текст, что то вроде этого: «Абзац содержит форматирование на уровне блока».
Обратите внимание, что можно установить полужирный или курсив прямо на результат paragraph.add_run()
, без использования возвращаемого объекта прогона:
paragraph.add_run('форматирование').bold = True # или run = paragraph.add_run('форматирование') run.bold = True
Передавать текст в метод Document.add_paragraph()
не обязательно. Это может упростить код, если строить абзац из прогонов:
paragraph = document.add_paragraph() paragraph.add_run('Абзац содержит ') paragraph.add_run('форматирование').bold = True paragraph.add_run(' на уровне блока.')
Пользовательское задание шрифта прогона.
from docx import Document from docx.shared import Pt, RGBColor # создание документа doc = Document() # добавляем текст прогоном run = doc.add_paragraph().add_run('Заголовок, размером 24 pt.') # название шрифта run.font.name = 'Arial' # размер шрифта run.font.size = Pt(24) # цвет текста run.font.color.rgb = RGBColor(0, 0, 255) # + жирный и подчеркнутый run.font.bold = True run.font.underline = True doc.save('test.docx')
Применение стилей Microsoft Word к символам текста (к прогону).
В дополнение к встроенным стилям абзаца, которые определяют группу параметров уровня абзаца, Microsoft Word имеет стили символов, которые определяют группу параметров уровня прогона paragraph.add_run()
. Другими словами, можно думать о стиле текста как об указании шрифта, включая его имя, размер, цвет, полужирный, курсив и т. д.
Подобно стилям абзацев, стиль символов текста будет определен в документе, который открывается с помощью вызова Document()
(см. Общие сведения о стилях).
Стиль символов можно указать при добавлении нового прогона:
paragraph = document.add_paragraph('Обычный текст, ') paragraph.add_run('текст с акцентом.', 'Emphasis')
Также можете применить стиль к прогону после его добавления. Этот код дает тот же результат, что и строки выше:
paragraph = document.add_paragraph() paragraph.add_run('Обычный текст, ') paragraph.add_run('текст с акцентом.').style = 'Emphasis'
Как и в случае со стилем абзаца, имя стиля текста такое, как оно отображается в пользовательском интерфейсе Word.
Пользовательский стиль символов текста.
from docx import Document from docx.shared import Pt, RGBColor # создание документа doc = Document() # задаем стиль текста по умолчанию style = doc.styles['Normal'] # название шрифта style.font.name = 'Calibri' # размер шрифта style.font.size = Pt(14) p = doc.add_paragraph('Пользовательское ') # добавляем текст прогоном run = p.add_run('форматирование ') # размер шрифта run.font.size = Pt(16) # курсив run.font.italic = True # добавляем еще текст прогоном run = p.add_run('символов текста.') # Форматируем: # название шрифта run.font.name = 'Arial' # размер шрифта run.font.size = Pt(18) # цвет текста run.font.color.rgb = RGBColor(255, 0, 0) # + жирный и подчеркнутый run.font.bold = True run.font.underline = True doc.save('test.docx')
Добавление разрыва страницы.
При создании документа, время от времени нужно, чтобы следующий текст выводился на отдельной странице, даже если последняя не заполнена. Жесткий разрыв страницы можно сделать следующим образом:
document.add_page_break()
Если вы обнаружите, что используете это очень часто, это, вероятно, знак того, что вы могли бы извлечь выгоду, лучше разбираясь в стилях абзацев. Одно свойство стиля абзаца, которое вы можете установить, — это разрыв страницы непосредственно перед каждым абзацем, имеющим этот стиль. Таким образом, вы можете установить заголовки определенного уровня, чтобы всегда начинать новую страницу. Подробнее о стилях позже. Они оказываются критически важными для получения максимальной отдачи от Word.
Жесткий разрыв страницы можно привязать к стилю абзаца, и затем применять его для определенных абзацев, которые должны начинаться с новой страницы. Так же можно установить жесткий разрыв на стиль заголовка определенного уровня, чтобы с него всегда начинать новую страницу. В общем, стили, оказываются критически важными для того, чтобы получить максимальную отдачу от модуля python-docx
.
Добавление картинки в документ.
Microsoft Word позволяет разместить изображение в документе с помощью пункта меню «Вставить изображение«. Вот как это сделать при помощи модуля python-docx
:
document.add_picture('/path/to/image-filename.png')
В этом примере используется путь, по которому файл изображения загружается из локальной файловой системы. В качестве пути можно использовать файловый объект, по сути, любой объект, который действует как открытый файл. Такое поведение может быть полезно, если изображение извлекается из базы данных или передается по сети.
Размер изображения.
По умолчанию, изображение добавляется с исходными размерами, что часто не устраивает пользователя. Собственный размер рассчитывается как px/dpi
. Таким образом, изображение размером 300×300 пикселей с разрешением 300 точек на дюйм появляется в квадрате размером один дюйм. Проблема в том, что большинство изображений не содержат свойства dpi
, и по умолчанию оно равно 72 dpi. Следовательно, то же изображение будет иметь одну сторону, размером 4,167 дюйма, что означает половину страницы.
Чтобы получить изображение нужного размера, необходимо указывать его ширину или высоту в удобных единицах измерения, например, в миллиметрах или сантиметрах:
from docx.shared import Mm document.add_picture('/path/to/image-filename.png', width=Mm(35))
Если указать только одну из сторон, то модуль python-docx
использует его для вычисления правильно масштабированного значения другой стороны изображения. Таким образом сохраняется соотношение сторон и изображение не выглядит растянутым.
Классы Mm()
и Cm()
предназначены для того, чтобы можно было указывать размеры в удобных единицах. Внутри python-docx
используются английские метрические единицы, 914400 дюймов. Так что, если просто указать размер, что-то вроде width=2
, то получится очень маленькое изображение. Классы Mm()
и Cm()
импортируются из подпакета docx.shared
. Эти классы можно использовать в арифметике, как если бы они были целыми числами. Так что выражение, width=Mm(38)/thing_count, работает нормально.
Чтение документов Microsoft Word.
В модуле python-docx
, структура документа Microsoft Word представлена тремя различными типами данных. На самом верхнем уровне объект Document()
представляет собой весь документ. Объект Document()
содержит список объектов Paragraph()
, которые представляют собой абзацы документа. Каждый из абзацев содержит список, состоящий из одного или нескольких объектов Run()
, представляющих собой фрагменты текста с различными стилями форматирования.
Например:
>>> from docx import Document >>> doc = Document('/path/to/example.docx') # количество абзацев в документе >>> len(doc.paragraphs) # текст первого абзаца в документе >>> doc.paragraphs[0].text # текст второго абзаца в документе >>> doc.paragraphs[1].text # текст первого прогона второго абзаца >>> doc.paragraphs[1].runs[0].text
Используя следующий код, можно получить весь текст документа:
text = [] for paragraph in doc.paragraphs: text.append(paragraph.text) print('nn'.join(text))
А так можно получить стили всех параграфов:
styles = [] for paragraph in doc.paragraphs: styles.append(paragraph.style)
Использовать полученные стили можно следующим образом:
# изменим стиль 1 параграфа на # стиль взятый из 3 параграфа doc.paragraphs[0].style = styles[2]
Время на прочтение
2 мин
Количество просмотров 70K
Исполняем обязанности по получению сведений о своих бенефициарных владельцах
Небольшая вводная
Начиная с 21 декабря 2016 года вступили изменения в ФЗ РФ «О противодействии легализации (отмыванию) доходов, полученных преступным путем, и финансированию терроризма», касательно обязанности юридического лица по раскрытию информации о своих бенефициарных владельцах. В связи с этим, многие компании направляют запросы по цепочке владения с целью выяснения своих бенефициарных владельцев. Кто-то формирует запросы на бумаге, кто-то рассылает электронные письма.
На наш взгляд, надлежащим доказательством исполнения обязанности «знай своего бенефициарного владельца» является наличие письма на бумаге с отметкой об отправке/вручении. Данные письма в идеале должны готовиться не реже одного раза в год. Если в ведении юриста находится всего несколько компаний, то составление писем не составляет особого труда. Но, если компаний больше 3-х десятков, составление писем превращается в уничтожающую позитив рутину. Дело усугубляется тем, что реквизиты писем постоянно меняются: подписанты увольняются, компании перерегистрируются, меняя адреса. Все это надо учитывать. Как здесь могут помочь навыки программирования на python?
Очень просто — хорошо бы иметь программу, которая сама будет подставлять в письма необходимые реквизиты. В том числе формировать сами письма, не заставляя создавать документ за документом вручную. Попробуем.
Структура письма в word. Модуль python docxtpl
Перед написанием кода программы посмотрим как должен выглядеть шаблон письма, в который мы будем помещать наши данные.
Текст письма от общества своему участнику/акционеру будет примерно следующим:
Напишем простую программу, которая заполнит для начала одно поле в нашем шаблоне, чтобы понять принцип работы.
Для начала в самом шаблоне письма Word вместо одного из полей, например, подписанта поставим переменную. Данная переменная должна быть на либо на англ. языке, либо на русском, но в одно слово.Также переменная должна быть обязательно заключена в двойные фигурные скобки. Выглядеть это будет примерно так:
Сама программа будет иметь следующий вид:
from docxtpl import DocxTemplate
doc = DocxTemplate("шаблон.docx")
context = { 'director' : "И.И.Иванов"}
doc.render(context)
doc.save("шаблон-final.docx")
Вначале мы импортируем модуль для работы с документами формата Word. Далее мы открываем шаблон, и в поле директор, которое бы обозначили ранее в самом шаблоне, вносим ФИО директора. В конце документ сохраняется под новым именем.
Таким образом, чтобы заполнить все поля в файле-шаблоне Word нам для начала необходимо определить все поля ввода в самом шаблоне скобками {} вместе с переменными и потом написать программу. Код будет примерно следующим:
from docxtpl import DocxTemplate
doc = DocxTemplate("шаблон.docx")
context = { 'emitent' : 'ООО Ромашка', 'address1' : 'г. Москва, ул. Долгоруковская, д. 0', 'участник': 'ООО Участник', 'адрес_участника': 'г. Москва, ул. Полевая, д. 0', 'director': 'И.И. Иванов'}
doc.render(context)
doc.save("шаблон-final.docx")
На выходе при исполнении программы мы получим готовый заполненный документ.
Скачать готовый шаблон Word можно здесь.
Getting started with |docx| is easy. Let’s walk through the basics.
Opening a document
First thing you’ll need is a document to work on. The easiest way is this:
from docx import Document document = Document()
This opens up a blank document based on the default «template», pretty much
what you get when you start a new document in Word using the built-in
defaults. You can open and work on an existing Word document using |docx|,
but we’ll keep things simple for the moment.
Adding a paragraph
Paragraphs are fundamental in Word. They’re used for body text, but also for
headings and list items like bullets.
Here’s the simplest way to add one:
paragraph = document.add_paragraph('Lorem ipsum dolor sit amet.')
This method returns a reference to a paragraph, newly added paragraph at the
end of the document. The new paragraph reference is assigned to paragraph
in this case, but I’ll be leaving that out in the following examples unless
I have a need for it. In your code, often times you won’t be doing anything
with the item after you’ve added it, so there’s not a lot of sense in keep
a reference to it hanging around.
It’s also possible to use one paragraph as a «cursor» and insert a new
paragraph directly above it:
prior_paragraph = paragraph.insert_paragraph_before('Lorem ipsum')
This allows a paragraph to be inserted in the middle of a document, something
that’s often important when modifying an existing document rather than
generating one from scratch.
Adding a heading
In anything but the shortest document, body text is divided into sections, each
of which starts with a heading. Here’s how to add one:
document.add_heading('The REAL meaning of the universe')
By default, this adds a top-level heading, what appears in Word as ‘Heading 1’.
When you want a heading for a sub-section, just specify the level you want as
an integer between 1 and 9:
document.add_heading('The role of dolphins', level=2)
If you specify a level of 0, a «Title» paragraph is added. This can be handy to
start a relatively short document that doesn’t have a separate title page.
Adding a page break
Every once in a while you want the text that comes next to go on a separate
page, even if the one you’re on isn’t full. A «hard» page break gets this
done:
document.add_page_break()
If you find yourself using this very often, it’s probably a sign you could
benefit by better understanding paragraph styles. One paragraph style property
you can set is to break a page immediately before each paragraph having that
style. So you might set your headings of a certain level to always start a new
page. More on styles later. They turn out to be critically important for really
getting the most out of Word.
Adding a table
One frequently encounters content that lends itself to tabular presentation,
lined up in neat rows and columns. Word does a pretty good job at this. Here’s
how to add a table:
table = document.add_table(rows=2, cols=2)
Tables have several properties and methods you’ll need in order to populate
them. Accessing individual cells is probably a good place to start. As
a baseline, you can always access a cell by its row and column indicies:
cell = table.cell(0, 1)
This gives you the right-hand cell in the top row of the table we just created.
Note that row and column indicies are zero-based, just like in list access.
Once you have a cell, you can put something in it:
cell.text = 'parrot, possibly dead'
Frequently it’s easier to access a row of cells at a time, for example when
populating a table of variable length from a data source. The .rows
property of a table provides access to individual rows, each of which has a
.cells
property. The .cells
property on both Row
and Column
supports indexed access, like a list:
row = table.rows[1] row.cells[0].text = 'Foo bar to you.' row.cells[1].text = 'And a hearty foo bar to you too sir!'
The .rows
and .columns
collections on a table are iterable, so you
can use them directly in a for
loop. Same with the .cells
sequences
on a row or column:
for row in table.rows: for cell in row.cells: print(cell.text)
If you want a count of the rows or columns in the table, just use len()
on
the sequence:
row_count = len(table.rows) col_count = len(table.columns)
You can also add rows to a table incrementally like so:
row = table.add_row()
This can be very handy for the variable length table scenario we mentioned
above:
# get table data ------------- items = ( (7, '1024', 'Plush kittens'), (3, '2042', 'Furbees'), (1, '1288', 'French Poodle Collars, Deluxe'), ) # add table ------------------ table = document.add_table(1, 3) # populate header row -------- heading_cells = table.rows[0].cells heading_cells[0].text = 'Qty' heading_cells[1].text = 'SKU' heading_cells[2].text = 'Description' # add a data row for each item for item in items: cells = table.add_row().cells cells[0].text = str(item.qty) cells[1].text = item.sku cells[2].text = item.desc
The same works for columns, although I’ve yet to see a use case for it.
Word has a set of pre-formatted table styles you can pick from its table style
gallery. You can apply one of those to the table like this:
table.style = 'LightShading-Accent1'
The style name is formed by removing all the spaces from the table style name.
You can find the table style name by hovering your mouse over its thumbnail in
Word’s table style gallery.
Adding a picture
Word lets you place an image in a document using the Insert > Photo > Picture
menu item. Here’s how to do it in |docx|:
from file...
document.add_picture('image-filename.png')
This example uses a path, which loads the image file from the local filesystem.
You can also use a file-like object, essentially any object that acts like an
open file. This might be handy if you’re retrieving your image from a database
or over a network and don’t want to get the filesystem involved.
Image size
By default, the added image appears at native size. This is often bigger than
you want. Native size is calculated as pixels / dpi
. So a 300×300 pixel
image having 300 dpi resolution appears in a one inch square. The problem is
most images don’t contain a dpi property and it defaults to 72 dpi. This would
make the same image appear 4.167 inches on a side, somewhere around half the
page.
To get the image the size you want, you can specify either its width or height
in convenient units, like inches or centimeters:
from docx.shared import Inches document.add_picture('image-filename.png', width=Inches(1.0))
You’re free to specify both width and height, but usually you wouldn’t want to.
If you specify only one, |docx| uses it to calculate the properly scaled value
of the other. This way the aspect ratio is preserved and your picture doesn’t
look stretched.
The Inches
and Cm
classes are provided to let you specify measurements
in handy units. Internally, |docx| uses English Metric Units, 914400 to the
inch. So if you forget and just put something like width=2
you’ll get an
extremely small image :). You’ll need to import them from the docx.shared
sub-package. You can use them in arithmetic just like they were an integer,
which in fact they are. So an expression like width = Inches(3)
works just fine.
/ thing_count
Applying a paragraph style
If you don’t know what a Word paragraph style is you should definitely check it
out. Basically it allows you to apply a whole set of formatting options to
a paragraph at once. It’s a lot like CSS styles if you know what those are.
You can apply a paragraph style right when you create a paragraph:
document.add_paragraph('Lorem ipsum dolor sit amet.', style='ListBullet')
This particular style causes the paragraph to appear as a bullet, a very handy
thing. You can also apply a style afterward. These two lines are equivalent to
the one above:
paragraph = document.add_paragraph('Lorem ipsum dolor sit amet.') paragraph.style = 'List Bullet'
The style is specified using its style name, ‘List Bullet’ in this example.
Generally, the style name is exactly as it appears in the Word user interface
(UI).
Applying bold and italic
In order to understand how bold and italic work, you need to understand
a little about what goes on inside a paragraph. The short version is this:
- A paragraph holds all the block-level formatting, like indentation, line
height, tabs, and so forth. - Character-level formatting, such as bold and italic, are applied at the
run level. All content within a paragraph must be within a run, but there
can be more than one. So a paragraph with a bold word in the middle would
need three runs, a normal one, a bold one containing the word, and another
normal one for the text after.
When you add a paragraph by providing text to the .add_paragraph()
method,
it gets put into a single run. You can add more using the .add_run()
method
on the paragraph:
paragraph = document.add_paragraph('Lorem ipsum ') paragraph.add_run('dolor sit amet.')
This produces a paragraph that looks just like one created from a single
string. It’s not apparent where paragraph text is broken into runs unless you
look at the XML. Note the trailing space at the end of the first string. You
need to be explicit about where spaces appear at the beginning and end of
a run. They’re not automatically inserted between runs. Expect to be caught by
that one a few times :).
|Run| objects have both a .bold
and .italic
property that allows you to
set their value for a run:
paragraph = document.add_paragraph('Lorem ipsum ') run = paragraph.add_run('dolor') run.bold = True paragraph.add_run(' sit amet.')
which produces text that looks like this: ‘Lorem ipsum dolor sit amet.’
Note that you can set bold or italic right on the result of .add_run()
if
you don’t need it for anything else:
paragraph.add_run('dolor').bold = True # is equivalent to: run = paragraph.add_run('dolor') run.bold = True # except you don't have a reference to `run` afterward
It’s not necessary to provide text to the .add_paragraph()
method. This can
make your code simpler if you’re building the paragraph up from runs anyway:
paragraph = document.add_paragraph() paragraph.add_run('Lorem ipsum ') paragraph.add_run('dolor').bold = True paragraph.add_run(' sit amet.')
Applying a character style
In addition to paragraph styles, which specify a group of paragraph-level
settings, Word has character styles which specify a group of run-level
settings. In general you can think of a character style as specifying a font,
including its typeface, size, color, bold, italic, etc.
Like paragraph styles, a character style must already be defined in the
document you open with the Document()
call (see
:ref:`understanding_styles`).
A character style can be specified when adding a new run:
paragraph = document.add_paragraph('Normal text, ') paragraph.add_run('text with emphasis.', 'Emphasis')
You can also apply a style to a run after it is created. This code produces
the same result as the lines above:
paragraph = document.add_paragraph('Normal text, ') run = paragraph.add_run('text with emphasis.') run.style = 'Emphasis'
As with a paragraph style, the style name is as it appears in the Word UI.
С помощью модуля python-docx можно создавать и изменять документы MS Word с расширением .docx. Чтобы установить этот модуль, выполняем команду
> pip install python-docx
При установке модуля надо вводить python-docx
, а не docx
(это другой модуль). В то же время при импортировании модуля python-docx
следует использовать import docx
, а не import python-docx
.
Чтение документов MS Word
Файлы с расширением .docx обладают развитой внутренней структурой. В модуле python-docx эта структура представлена тремя различными типами данных. На самом верхнем уровне объект Document
представляет собой весь документ. Объект Document
содержит список объектов Paragraph
, которые представляют собой абзацы документа. Каждый из абзацев содержит список, состоящий из одного или нескольких объектов Run
, представляющих собой фрагменты текста с различными стилями форматирования.
import docx doc = docx.Document('example.docx') # количество абзацев в документе print(len(doc.paragraphs)) # текст первого абзаца в документе print(doc.paragraphs[0].text) # текст второго абзаца в документе print(doc.paragraphs[1].text) # текст первого Run второго абзаца print(doc.paragraphs[1].runs[0].text)
6 Название документа Простой абзац с жирным и курсивным текстом Простой абзац с
Получаем весь текст из документа:
text = [] for paragraph in doc.paragraphs: text.append(paragraph.text) print('n'.join(text))
Название документа Простой абзац с жирным и курсивным текстом Заголовок, уровень 1 Выделенная цитата Первый элемент маркированного списка Первый элемент нумерованного списка
Стилевое оформление
В документах MS Word применяются два типа стилей: стили абзацев, которые могут применяться к объектам Paragraph
, стили символов, которые могут применяться к объектам Run
. Как объектам Paragraph
, так и объектам Run
можно назначать стили, присваивая их атрибутам style
значение в виде строки. Этой строкой должно быть имя стиля. Если для стиля задано значение None
, то у объекта Paragraph
или Run
не будет связанного с ним стиля.
Стили абзацев
Normal
Body Text
Body Text 2
Body Text 3
Caption
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Heading 6
Heading 7
Heading 8
Heading 9
Intense Quote
List
List 2
List 3
List Bullet
List Bullet 2
List Bullet 3
List Continue
List Continue 2
List Continue 3
List Number
List Number 2
List Number 3
List Paragraph
Macro Text
No Spacing
Quote
Subtitle
TOCHeading
Title
Стили символов
Emphasis
Strong
Book Title
Default Paragraph Font
Intense Emphasis
Subtle Emphasis
Intense Reference
Subtle Reference
paragraph.style = 'Quote' run.style = 'Book Title'
Атрибуты объекта Run
Отдельные фрагменты текста, представленные объектами Run
, могут подвергаться дополнительному форматированию с помощью атрибутов. Для каждого из этих атрибутов может быть задано одно из трех значений: True
(атрибут активизирован), False
(атрибут отключен) и None
(применяется стиль, установленный для данного объекта Run
).
bold
— Полужирное начертаниеunderline
— Подчеркнутый текстitalic
— Курсивное начертаниеstrike
— Зачеркнутый текст
Изменим стили для всех параграфов нашего документа:
import docx doc = docx.Document('example.docx') # изменяем стили для всех параграфов for paragraph in doc.paragraphs: paragraph.style = 'Normal' doc.save('restyled.docx')
А теперь восстановим все как было:
import docx os.chdir('C:\example') doc1 = docx.Document('example.docx') doc2 = docx.Document('restyled.docx') # получаем из первого документа стили всех абзацев styles = [] for paragraph in doc1.paragraphs: styles.append(paragraph.style) # применяем стили ко всем абзацам второго документа for i in range(len(doc2.paragraphs)): doc2.paragraphs[i].style = styles[i] doc2.save('restored.docx')
Изменим форматирвание объектов Run
второго абзаца:
import docx doc = docx.Document('example.docx') # добавляем стиль символов для runs[0] doc.paragraphs[1].runs[0].style = 'Intense Emphasis' # добавляем подчеркивание для runs[4] doc.paragraphs[1].runs[4].underline = True doc.save('restyled2.docx')
Запись докуменов MS Word
Добавление абзацев осуществляется вызовом метода add_paragraph()
объекта Document
. Для добавления текста в конец существующего абзаца, надо вызвать метод add_run()
объекта Paragraph
:
import docx doc = docx.Document() # добавляем первый параграф doc.add_paragraph('Здравствуй, мир!') # добавляем еще два параграфа par1 = doc.add_paragraph('Это второй абзац.') par2 = doc.add_paragraph('Это третий абзац.') # добавляем текст во второй параграф par1.add_run(' Этот текст был добавлен во второй абзац.') # добавляем текст в третий параграф par2.add_run(' Добавляем текст в третий абзац.').bold = True doc.save('helloworld.docx')
Оба метода, add_paragraph()
и add_run()
принимают необязательный второй аргумент, содержащий строку стиля, например:
doc.add_paragraph('Здравствуй, мир!', 'Title')
Добавление заголовков
Вызов метода add_heading()
приводит к добавлению абзаца, отформатированного в соответствии с одним из возможных стилей заголовков:
doc.add_heading('Заголовок 0', 0) doc.add_heading('Заголовок 1', 1) doc.add_heading('Заголовок 2', 2) doc.add_heading('Заголовок 3', 3) doc.add_heading('Заголовок 4', 4)
Аргументами метода add_heading()
являются строка текста и целое число от 0 до 4. Значению 0 соответствует стиль заголовка Title
.
Добавление разрывов строк и страниц
Чтобы добавить разрыв строки (а не добавлять новый абзац), нужно вызвать метод add_break()
объекта Run
. Если же требуется добавить разрыв страницы, то методу add_break()
надо передать значение docx.enum.text.WD_BREAK.PAGE
в качестве единственного аргумента:
import docx doc = docx.Document() doc.add_paragraph('Это первая страница') doc.paragraphs[0].runs[0].add_break(docx.enum.text.WD_BREAK.PAGE) doc.add_paragraph('Это вторая страница') doc.save('pages.docx')
Добавление изображений
Метод add_picture()
объекта Document
позволяет добавлять изображения в конце документа. Например, добавим в конец документа изображение kitten.jpg
шириной 10 сантиметров:
import docx doc = docx.Document() doc.add_paragraph('Это первый абзац') doc.add_picture('kitten.jpg', width = docx.shared.Cm(10)) doc.save('picture.docx')
Именованные аргументы width
и height
задают ширину и высоту изображения. Если их опустить, то значения этих аргументов будут определяться размерами самого изображения.
Добавление таблицы
import docx doc = docx.Document() # добавляем таблицу 3x3 table = doc.add_table(rows = 3, cols = 3) # применяем стиль для таблицы table.style = 'Table Grid' # заполняем таблицу данными for row in range(3): for col in range(3): # получаем ячейку таблицы cell = table.cell(row, col) # записываем в ячейку данные cell.text = str(row + 1) + str(col + 1) doc.save('table.docx')
import docx doc = docx.Document('table.docx') # получаем первую таблицу в документе table = doc.tables[0] # читаем данные из таблицы for row in table.rows: string = '' for cell in row.cells: string = string + cell.text + ' ' print(string)
11 12 13 21 22 23 31 32 33
Дополнительно
- Документация python-docx
Поиск:
MS • Python • Web-разработка • Word • Модуль
Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
In this Python Tkinter tutorial, we will learn about how to create a word document in python tkinter. We will create an application using Python Tkinter that will generate a word document with dynamic values.
- Create word document in Python Tkinter – Overview
- Tkinter Module in Python
- Python-docx module in Python
- Overview of the python tkinter application
- Source code of python tkinter application
- Output of python tkinter application
Recently, we got a requirement to generate an experience certificate for employees who are leaving the organization using Python Tkinter.
So we created a complete application using Python Tkinter that will take inputs like below:
User Inputs | Tkinter Widget |
---|---|
Employee ID | Entry widget |
Employee Name | Entry Widget |
Designation | Entry Widget |
Joining Date | Entry Widget |
End Date | Entry Widget |
Gender | OptionMenu Widget |
Then when the user will fill the form and click on Generate Word button, it will create an experience certificate (word document) with the dynamic values provided by the user.
The word document will also have the company logo, signature, etc.
The form looks like below:
The output will come like below:
Also read, How to convert Python file to exe using Pyinstaller
Tkinter Module in Python
Using the Tkinter module in python we can create a graphical user interface (GUI) of any application. It is a popular and easy-to-use python module that can help you convert your command-line-based application into an interactive GUI-based program.
We have a dedicated tutorial on our website for learning Python Tkinter with Examples.
In this section, we will discuss all the python Tkinter widgets that we have used in creating the Tkinter application for generating experience certificate word files.
User Inputs | Tkinter Widget |
---|---|
Employee ID | Entry widget |
Employee Name | Entry Widget |
Designation | Entry Widget |
Joining Date | Entry Widget |
End Date | Entry Widget |
Gender | OptionMenu Widget |
- Gender is tkinter OptionMenu widget, user can select the gender using the dropdown. This information is used for declaring subject pronoun.
- Using gender information, we have specified he, she, him, his, her in the body text of the message.
- Python Tkinter Entry widget is used to take String based inputs from the user.
- All other tkinter widgets except gender are python tkinter entry widgets. We have a dedicated blog on Python Tkinter Entry widget and Python Tkinter Optionmenu widget.
Python-docx module in Python
Python-docx module allows us to create word document(s) using python Tkinter. This is a powerful python module that allows the creation of a new word document or updating the existing ones.
Python-docx can be installed using pip and conda package manager with the following command.
# using pip
pip install python-docx
# using anaconda
conda install -c conda-forge python-docx
Word document has so many features that help the user in writing & formatting the data. Using the python-docx module we can work with all those features. Below is the picture of a word document with marked features.
- Each feature has dedicated method in python-docx. Few widely used methods of python-docx are add_paragraph(), add_picture(), add_heading(), add_page_break(), add_table(), etc.
- First step in the process of creating word document using python is creating word object. All the above methods are the part of the Document object.
from docx import Document
doc = Document()
Moving forward, we will discuss common methods of a python-docx module using which you can create a sample word document in python.
docx.styles()
If you want to save time from manually formatting each row of a word document then you can apply a bundle of pre-formatted styles using this feature in a python-docx module.
The image below shows the styles option on word document:
- Other than this, you can modify the style by adding bullet points, changing font weight to bold, italices, underline, etc.
Example:
This example, demonstrate how to create style in the python docx module also shows how to use the style on a paragraph in the python docx module.
# style created
new_style = doc.styles['Heading 1']
# style applied
doc.add_paragraph(style=new_style)
docx.add_heading()
Heading specifies the short description of the topic or content. A good heading is always short and self-explanatory. In this section, we will learn how to add heading using python.
- Every sub-heading is smaller than parent heading and this way they form a heirarchy of 1-9 levels where 1 is the highest level and 9 is the lowest.
- By default, python-docx picks 1 has the default text for heading and on changing level to 0 changes the category from ‘Heading’ to ‘Title’.
doc.add_heading('United States of America', level=1)
- Change the level value to modify the heading size in python docx.
docx.add_paragraph()
The paragraph is the widely used method as this will require every time you want to add text on the word document using python module python-docx.
- Each paragraph adds a single run in the word document using python module python-docx.
- If you want to add more than one run in a row then use add_run() method on add_paragraph().
- Method add_run() is very useful when you want to apply two things at the same time. for example, you want to add a paragraph with your country name in bold letters.
Example:
This example demonstrate the use of add_paragraph() method with add_run() method in python-docx module of python.
In this code, we have added a paragraph: ‘Best Country’ and using run object added country name: the United States of America and then applied bold formatting on the country name. This way we have applied 3 activities instead of one, this is the benefit of using the add_run() method.
# one-liner
doc.add_paragraph('Best Country').add_run('United States of America').bold = True
# same thing in 2 lines to make it look good
nomination = doc.add_paragraph('Best Country')
nomination.add_run('United States of America').bold =True
docx.add_picture()
Using the add_picture() method in python-docx you can add an image on the word document. The below picture shows the column available for uploading images on a word document.
- Python docx add_picture() methods provides option to add picture in the word file. You can control the size of the image by defining height and width of the image.
- Heigth and width value can either be in Inches or Centemeters (cm). Inorder to use either of them you have to import Inches or cm from docx.shared.
Syntax:
Height and width are optional to provide but it will be either in Inches or cm (centimeter). We recommend keeping the image in the same folder where the main project is but in case it is not possible then provide the complete path in place of <image_path>.
from docx.shared import Inches
doc = Document()
doc.add_picture(<image_path>, width=Inches(val), height=Inches(val))
Example:
The below example, demonstrate use of docx.add_image() in python docx module. In this example, we have added an image file to the word document.
# import modules
from docx import Document
from docx.shared import Inches
# create an instance
doc = Document()
# add image
doc.add_picture('logo.png', height=Inches(0.81), width=Inches(2.52))
# save file
doc.save('word.docx')
With this, we have concluded a few important and widely used methods of the python docx module. There are many more functions that you can explore on the official website of python-docx.
If you need an explanation of any method or function please write us and we will share the best tutorial for the same.
Read How to make a calculator in Python
Source code of tkinter application
In this section, we have provided source code for creating an application for generating experience certificates for employees who are leaving the organization.
- In this python application, graphical user interface (GUI) is created using Python library Tkinter.
- With the interactive interface user can fill in the employee(s) informations like employee id, name, date of joining, etc.
- The python program will use these information to generate experience certificate in the word format.
PermissionError: [Errno 13] Permission denied: 'word.docx'
Please note: The word file must be closed before clicking on the ‘Generate Word‘ button again. If you are seeing the above permission error that means the file is open. Close the file and try again to fix this error.
We have provided the source code for:
Python Tkinter Code (GUI Development)
Here is the source code for creating Graphical User Interface (GUI) for the Experience Letter generating application in python.
# modules
from tkinter import *
# clear function
def clear_inputs():
eid.delete(0, 'end')
ename.delete(0, 'end')
desig.delete(0, 'end')
jd.delete(0, 'end')
ed.delete(0, 'end')
ws = Tk()
ws.title('Service Certificate Generator')
ws.geometry('400x300')
ws.config(bg='#456')
f = ('sans-serif', 13)
btn_font = ('sans-serif', 10)
bgcolor = '#BF5517'
genvar = StringVar()
genopt = ['Male', 'Female']
genvar.set('Male')
# frames
frame = Frame(ws, padx=20, pady=20, bg=bgcolor)
frame.pack(expand=True, fill=BOTH)
# label widgets
Label(
frame,
text="Employee ID",
font=f,
bg=bgcolor
).grid(row=0, column=0, sticky='w')
Label(
frame,
text="Employee Name",
font=f,
bg=bgcolor
).grid(row=1, column=0, sticky='w')
Label(
frame,
text="Designation",
font=f,
bg=bgcolor
).grid(row=2, column=0, sticky='w')
Label(
frame,
text="Joining Date",
font=f,
bg=bgcolor
).grid(row=3, column=0, sticky='w')
Label(
frame,
text="End Date",
font=f,
bg=bgcolor
).grid(row=4, column=0, sticky='w')
Label(
frame,
text='Gender',
font=f,
bg=bgcolor
).grid(row=5, column=0, sticky='w')
# entry widgets
eid = Entry(frame, width=20, font=f)
eid.grid(row=0, column=1)
ename = Entry(frame, width=20, font=f)
ename.grid(row=1, column=1)
desig = Entry(frame, width=20, font=f)
desig.grid(row=2, column=1)
jd = Entry(frame, width=20, font=f)
jd.grid(row=3, column=1)
ed = Entry(frame, width=20, font=f)
ed.grid(row=4, column=1)
gender = OptionMenu(
frame,
genvar,
*genopt
)
gender.grid(row=5, column=1, pady=(5,0))
gender.config(width=15, font=f)
btn_frame = Frame(frame, bg=bgcolor)
btn_frame.grid(columnspan=2, pady=(50, 0))
# default inputs for testing
eid.insert(0,'E1008')
ename.insert(0, 'Vineet Singh')
desig.insert(0, 'Python Developer')
jd.insert(0, 'Aug 3rd, 2020')
ed.insert(0, 'July 31st, 2021')
# action buttons
submit_btn = Button(
btn_frame,
text='Generate Word',
command=None, #generate,
font=btn_font,
padx=10,
pady=5
)
submit_btn.pack(side=LEFT, expand=True, padx=(15, 0))
clear_btn = Button(
btn_frame,
text='Clear',
command=clear_inputs,
font=btn_font,
padx=10,
pady=5,
width=7
)
clear_btn.pack(side=LEFT, expand=True, padx=15)
exit_btn = Button(
btn_frame,
text='Exit',
command=lambda:ws.destroy(),
font=btn_font,
padx=10,
pady=5
)
exit_btn.pack(side=LEFT, expand=True)
# mainloop
ws.mainloop()
Source code for Creating Word File using Python (command-line)
Here, is the fully functional python source code for creating a word file using python. This code, uses python-docx modules and it do not have GUI that means you have to put the information in the code itself.
# modules
from docx import Document
from docx.opc.coreprops import CoreProperties
from docx.enum.style import WD_STYLE_TYPE
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.shared import Inches, Pt
# user inputs
logo = 'files/tsinfo_logo.jpg'
output = 'Experience_letter1.docx'
sign = 'files/signature.png'
ceo_sig_text = '''Adarshnath Singh nDirector'''
heading = 'Service Certificate'
emp_id = 'E1001' #eid.get()
emp_name = 'Vineet Singh' # ename.get()
designation = 'Software Engineer' #desig.get()
joining_date = 'August 20, 2019' #jd.get()
end_date = 'July 31, 2021' #ed.get()
comp_detail = '''TSInfo Technologies (OPC) Pvt Ltd
Flat G-115, SJR Residency, Devarabeesanahalli, Bellandur, Bangalore, 560103
Email: info@tsinfotechnologies.com, Phone: +91-9916854253
'''
gen = 'He' # who.get()
# subject pronoun
gen2 = 'his' # her
gen3 = 'him' # her
if gen.lower() == 'he':
gen2 = 'his'
gen3 = 'him'
elif gen.lower() == 'she':
gen2 = 'her'
gen3 = 'her'
else:
print('Error: accept He/She only')
# certificate template
body_text = f'''This is to certify that {emp_name} has worked with TSInfo Technologies (OPC) Pvt Ltd from {joining_date} to {end_date}, and was designated as {designation} at the time of {gen2} leaving the organization.
{gen.capitalize()} is hardworking and a good team player.
We wish {gen3} all the success in his future endeavor.
'''
# create instance
doc = Document()
# declare margin
sections = doc.sections
for section in sections:
section.top_margin = Inches(0.04)
section.bottom_margin = Inches(0.19)
section.left_margin = Inches(0.93)
section.right_margin = Inches(0.89)
section = doc.sections[0]
# logo image placement
logo = doc.add_picture(logo, width=Inches(2.52), height=Inches(0.81))
logo_placement = doc.paragraphs[-1]
logo_placement.alignment = WD_ALIGN_PARAGRAPH.CENTER
# line space
for _ in range(1):
linespace_style = doc.styles['Body Text']
linespace = doc.add_paragraph(style=linespace_style).add_run(' ')
linespace_style.font.size = Pt(10)
# employee Id
empid_style = doc.styles['Normal']
empid = doc.add_paragraph(style=empid_style).add_run(f'{emp_id}')
empid.font.bold = True
# line space
for _ in range(1):
linespace_style = doc.styles['Body Text']
linespace = doc.add_paragraph(style=linespace_style).add_run()
linespace.font.size = 10
# Header
heading_style = doc.styles['Body Text']
head=doc.add_paragraph(style=heading_style).add_run(f'{heading}')
doc.paragraphs[-1].alignment = WD_ALIGN_PARAGRAPH.CENTER
head.font.size = Pt(20)
head.font.bold = True
# body text
body_style = doc.styles['Body Text']
body = doc.add_paragraph(style=body_style).add_run(f'{body_text}')
body.font.size = Pt(14)
body.font.name = 'Times New Roman'
#line space
for _ in range(2):
linespace_style = doc.styles['Body Text']
linespace = doc.add_paragraph(style=linespace_style).add_run()
linespace.font.size = 10
# signature image & text
ceo_sign = doc.styles['Body Text']
doc.add_picture(sign, width=Inches(1.57), height=Inches(0.43))
doc.add_paragraph(style=ceo_sign).add_run(f'{ceo_sig_text}')
ceo_sign.font.size = Pt(14)
# line space
for _ in range(4):
linespace_style = doc.styles['Body Text']
linespace = doc.add_paragraph(style=linespace_style)
# footer text : company description
company_text = doc.styles['Normal']
company_text.paragraph_format.space_before = Pt(12)
doc.add_paragraph(style=company_text).add_run(f'{comp_detail}')
center_align = doc.paragraphs[-1]
center_align.alignment = WD_ALIGN_PARAGRAPH.CENTER
# saving file to word document
doc.save(output)
Read Python Tkinter ToDo List
Complete Source code of creating word document using python tkinter
Here is the source code of the complete application that will generate the experience letter of an employee. It accepts the information through a graphical user interface created using tkinter module in python.
And then, it creates a word document with the provided information. It uses python-docx module to interact with the word document.
Use the following steps to setup the project on your device:
- Create a folder where you want to keep this project.
- Create and activate the virtual environment.
- Install python-docx module in the virtual environment.
- Create main.py and paste the below code in that file.
- Create folders with the name files and output. Add images inside the files folder.
- run the program, Experience Letter will be generated inside the output folder.
# modules
from docx import Document
from docx.opc.coreprops import CoreProperties
from docx.enum.style import WD_STYLE_TYPE
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.shared import Inches, Pt
from tkinter import *
from tkinter import messagebox
ws = Tk()
ws.title('Service Certificate Generator')
ws.geometry('400x300')
ws.config(bg='#456')
f = ('sans-serif', 13)
btn_font = ('sans-serif', 10)
bgcolor = '#BF5517'
genvar = StringVar()
genopt = ['Male', 'Female']
genvar.set('Male')
def clear_inputs():
eid.delete(0, 'end')
ename.delete(0, 'end')
desig.delete(0, 'end')
jd.delete(0, 'end')
ed.delete(0, 'end')
def generate():
# data variables
logo = 'files/tsinfo_logo.jpg'
output = 'output/Experience_letter.docx'
sign = 'files/signature.png'
ceo_sig_text = '''Adarshnath Singh nDirector'''
heading = 'Service Certificate'
emp_id = eid.get()
emp_name = ename.get()
designation = desig.get()
joining_date = jd.get()
end_date = ed.get()
comp_detail = '''
TSInfo Technologies (OPC) Pvt Ltd
Flat G-115, SJR Residency, Devarabeesanahalli, Bellandur, Bangalore, 560103
Email: info@tsinfotechnologies.com, Phone: +91-9916854253
'''
# gender specification
gen1 = 'He' # she
gen2 = 'his' # her
gen3 = 'him' # her
if genvar.get() == 'Male':
gen1 = 'He'
gen2 = 'his'
gen3 = 'him'
elif genvar.get() == 'Female':
gen1 = 'She'
gen2 = 'her'
gen3 = 'her'
else:
messagebox.showerror('Error', 'Incorrect gender Selection!')
# experience certificate template
body_text = f'''
This is to certify that {emp_name} has worked with TSInfo Technologies (OPC) Pvt Ltd from {joining_date} to {end_date}, and was designated as {designation} at the time of {gen2} leaving the organization.
{gen1} is hardworking and a good team player.
We wish {gen3} all the success in {gen2} future endeavor.
'''
# create object(s)
doc = Document()
sections = doc.sections
# declare margin
for section in sections:
section.top_margin = Inches(0.04)
section.bottom_margin = Inches(0.19)
section.left_margin = Inches(0.93)
section.right_margin = Inches(0.89)
section = doc.sections[0]
# logo image placement
logo = doc.add_picture(logo, width=Inches(2.52), height=Inches(0.81))
logo_placement = doc.paragraphs[-1]
logo_placement.alignment = WD_ALIGN_PARAGRAPH.CENTER
# line space
for _ in range(1):
linespace_style = doc.styles['Body Text']
linespace = doc.add_paragraph(style=linespace_style).add_run(' ')
linespace_style.font.size = Pt(10)
# employee Id
empid_style = doc.styles['Normal']
empid = doc.add_paragraph(style=empid_style).add_run(f'{emp_id}')
empid.font.bold = True
# line space
for _ in range(1):
linespace_style = doc.styles['Body Text']
linespace = doc.add_paragraph(style=linespace_style).add_run()
linespace.font.size = 10
# Header
heading_style = doc.styles['Body Text']
head = doc.add_paragraph(style=heading_style).add_run(f'{heading}')
doc.paragraphs[-1].alignment = WD_ALIGN_PARAGRAPH.CENTER
head.font.size = Pt(20)
head.font.bold = True
# body text
body_style = doc.styles['Body Text']
body = doc.add_paragraph(style=body_style).add_run(f'{body_text}')
body.font.size = Pt(14)
body.font.name = 'Times New Roman'
#line space
for _ in range(2):
linespace_style = doc.styles['Body Text']
linespace = doc.add_paragraph(style=linespace_style).add_run()
linespace.font.size = 10
# signature image & text
ceo_sign = doc.styles['Body Text']
doc.add_picture(sign, width=Inches(1.57), height=Inches(0.43))
doc.add_paragraph(style=ceo_sign).add_run(f'{ceo_sig_text}')
ceo_sign.font.size = Pt(14)
# line space
for _ in range(4):
linespace_style = doc.styles['Body Text']
linespace = doc.add_paragraph(style=linespace_style)
# linespace.font.size = Pt(10)
# footer text : company description
company_text = doc.styles['Normal']
company_text.paragraph_format.space_before = Pt(12)
doc.add_paragraph(style=company_text).add_run(f'{comp_detail}')
center_align = doc.paragraphs[-1]
center_align.alignment = WD_ALIGN_PARAGRAPH.CENTER
doc.save(output)
# frames
frame = Frame(ws, padx=20, pady=20, bg=bgcolor)
frame.pack(expand=True, fill=BOTH)
# label widgets
Label(
frame,
text="Employee ID",
font=f,
bg=bgcolor
).grid(row=0, column=0, sticky='w')
Label(
frame,
text="Employee Name",
font=f,
bg=bgcolor
).grid(row=1, column=0, sticky='w')
Label(
frame,
text="Designation",
font=f,
bg=bgcolor
).grid(row=2, column=0, sticky='w')
Label(
frame,
text="Joining Date",
font=f,
bg=bgcolor
).grid(row=3, column=0, sticky='w')
Label(
frame,
text="End Date",
font=f,
bg=bgcolor
).grid(row=4, column=0, sticky='w')
Label(
frame,
text='Gender',
font=f,
bg=bgcolor
).grid(row=5, column=0, sticky='w')
# entry widgets
eid = Entry(frame, width=20, font=f)
eid.grid(row=0, column=1)
ename = Entry(frame, width=20, font=f)
ename.grid(row=1, column=1)
desig = Entry(frame, width=20, font=f)
desig.grid(row=2, column=1)
jd = Entry(frame, width=20, font=f)
jd.grid(row=3, column=1)
ed = Entry(frame, width=20, font=f)
ed.grid(row=4, column=1)
gender = OptionMenu(
frame,
genvar,
*genopt
)
gender.grid(row=5, column=1, pady=(5,0))
gender.config(width=15, font=f)
btn_frame = Frame(frame, bg=bgcolor)
btn_frame.grid(columnspan=2, pady=(50, 0))
# default inputs for testing
eid.insert(0,'E1008')
ename.insert(0, 'Vineet Singh')
desig.insert(0, 'Python Developer')
jd.insert(0, 'Aug 3rd, 2020')
ed.insert(0, 'July 31st, 2021')
submit_btn = Button(
btn_frame,
text='Generate Word',
command=generate,
font=btn_font,
padx=10,
pady=5
)
submit_btn.pack(side=LEFT, expand=True, padx=(15, 0))
clear_btn = Button(
btn_frame,
text='Clear',
command=clear_inputs,
font=btn_font,
padx=10,
pady=5,
width=7
)
clear_btn.pack(side=LEFT, expand=True, padx=15)
exit_btn = Button(
btn_frame,
text='Exit',
command=lambda:ws.destroy(),
font=btn_font,
padx=10,
pady=5
)
exit_btn.pack(side=LEFT, expand=True)
# mainloop
ws.mainloop()
Read Python Tkinter Canvas
Output of Python Tkinter Application
In this output, there is a form that accepts various information about an employee. Once information is filled, on clicking the ‘Generate Word’ button a word file will be generated.
That word file will have a template of experience certificate with the employee information (Id, name, joining date, etc) dynamically allocated at the respective place.
- Clear button will clear the enteries and exit button will terminate the program.
- This application form is created using python tkinter and it is using python-docx module to interact with the word file.
- Below is the picture of generated service certificate. This is a word file with dynamic values highlighted in yellow. All these yellow values are provided by the user in the above image.
- highlighted yellow is for demonstration purpose only, while executing the program this won’t appear.
This is how to create a word document in Python by using Python Tkinter.
Related Python Tkinter tutorials:
- Python Tkinter Stopwatch
- BMI Calculator Using Python Tkinter
- Expense Tracking Application Using Python Tkinter
- How to Create Countdown Timer using Python Tkinter
- Upload a File in Python Tkinter
- Python Tkinter drag and drop
Python is one of the most popular languages in the United States of America. I have been working with Python for a long time and I have expertise in working with various libraries on Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… I have experience in working with various clients in countries like United States, Canada, United Kingdom, Australia, New Zealand, etc. Check out my profile.