Сообщить об ошибке.

Работа с текстом, модуль python-docx

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

Содержание:


Блочные и встроенные текстовые объекты документа DOCX.

Абзац Paragraph - это основной объект уровня блока в MS Word. Таблица Table также является объектом блочного уровня.

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

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

  • Атрибуты элемента уровня блока определяют его размещение на странице, например отступы и пробелы до и после абзаца.
  • Атрибуты встроенного элемента обычно определяют шрифт, в котором отображается содержимое, такие как гарнитура, размер шрифта, полужирный и курсив.

Какие свойства есть у абзаца документа DOCX.

Абзац Paragraph имеет множество свойств, которые определяют его размещение в контейнере (обычно на странице) и способ разделения его содержимого на отдельные строки.

Лучше всего определить стиль абзаца, объединяющий эти атрибуты в какую-то группу и применять соответствующий стиль к каждому абзацу, а не применять по отдельности каждое свойства непосредственно к каждому абзацу. Такое поведение можно сравнить с применением свойств CSS к HTML. Все описанные здесь свойства абзаца можно установить с помощью стиля, а также применить непосредственно к абзацу.

Доступ к свойствам форматирования абзаца осуществляется с помощью объекта ParagraphFormat, доступного с помощью свойства абзаца Paragraph.paragraph_format.

Горизонтальное выравнивание абзаца.

Горизонтальное выравнивание абзаца может быть установлено по левому краю, по центру, по правому краю или полностью выровнено (с выравниванием по левой и правой сторонам) с использованием значений из перечисления WD_PARAGRAPH_ALIGNMENT:

>>> from docx.enum.text import WD_ALIGN_PARAGRAPH
>>> document = Document()
>>> paragraph = document.add_paragraph()
>>> p_fmt = paragraph.paragraph_format
# выравнивание наследуется от иерархии стилей
>>> p_fmt.alignment
# None
>>> p_fmt.alignment = WD_ALIGN_PARAGRAPH.CENTER
>>> p_fmt.alignment
# CENTER (1)

Отступы абзаца.

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

Отступ задается с помощью значения Length, например классами Mm() или Cm(). Отрицательные значения допустимы и приводят к тому, что абзац перекрывает поле на указанную величину. Значение None указывает, что значение отступа унаследовано от иерархии стилей. Присвоение None свойству отступа удаляет все напрямую применяемые параметры отступа и восстанавливает наследование из иерархии стилей:

>>> from docx.shared import Mm
>>> paragraph = document.add_paragraph()
>>> p_fmt = paragraph.paragraph_format
# отступ наследуется от иерархии стилей
>>> p_fmt.left_indent
# None
>>> p_fmt.left_indent = Mm(15)
>>> p_fmt.left_indent.mm
# 15

Отступ справа работает аналогично:

>>> from docx.shared import Cm
>>> p_fmt.right_indent
# None
>>> p_fmt.right_indent = Cm(1.5)
>>> p_fmt.right_indent.cm
# 1.5

Отступ первой (красной) строки указывается с помощью свойства ParagraphFormat.first_line_indent и интерпретируется относительно левого отступа. Отрицательное значение указывает на выступ:

>>> p_fmt.first_line_indent
# None
>>> p_fmt.first_line_indent = Cm(-1.0)
>>> p_fmt.first_line_indent.inches
# -1.0

Интервал между абзацами.

Свойства ParagraphFormat.space_before и ParagraphFormat.space_after определяют интервал между последующими абзацами, регулируя интервал до и после абзаца соответственно. Интервал между абзацами сворачивается во время компоновки страницы, это означает, что интервал между двумя абзацами равен максимальному значению пробела после первого абзаца и пробела перед вторым абзацем. Интервал между абзацами указывается как значение длины, часто с использованием пунктов Pt():

# интервалы по умолчанию - наследуется 
>>> p_fmt.space_before, p_fmt.space_after
# (None, None)
>>> p_fmt.space_before = Pt(18)
>>> p_fmt.space_before.pt
# 18.0
>>> p_fmt.space_after = Pt(12)
>>> p_fmt.space_after.pt
# 12.0

Межстрочный интервал.

Межстрочный интервал - это расстояние между последующими базовыми линиями в строках абзаца. Межстрочный интервал может быть задан либо как абсолютное расстояние, либо относительно высоты строки (по сути, размера используемого шрифта). Типичный абсолютный показатель составлял бы 18 пунктов. Типичной относительной мерой будет двойной интервал (высота линии 2,0). Межстрочный интервал по умолчанию - одинарный (высота строки 1,0).

Межстрочный интервал регулируется взаимодействием свойств ParagraphFormat.line_spacing и ParagraphFormat.line_spacing_rule. Свойство .line_spacing - это либо значение объекта Length, либо (небольшое) значение float, либо None.

  • Значение Length указывает абсолютное расстояние.
  • Значение float указывает количество высот линий.
  • None указывает на то, что межстрочный интервал наследуется.

Свойство .line_spacing_rule является членом перечисления WD_LINE_SPACING или None:

>>> from docx.shared import Length
>>> p_fmt.line_spacing
# None
>>> p_fmt.line_spacing_rule
# None
>>> p_fmt.line_spacing = Pt(18)
>>> isinstance(p_fmt.line_spacing, Length)
# True
>>> p_fmt.line_spacing.pt
# 18.0
>>> p_fmt.line_spacing_rule
# EXACTLY (4)
>>> p_fmt.line_spacing = 1.75
>>> p_fmt.line_spacing
# 1.75
>>> p_fmt.line_spacing_rule
# MULTIPLE (5)

Свойства разбивки на страницы.

Аспектами поведения абзаца вблизи границ страницы управляют четыре свойства абзаца:

  • ParagraphFormat.keep_together заставляет весь абзац отображаться на одной странице, выдавая разрыв страницы перед абзацем, в противном случае он был бы разбит на две страницы.
  • ParagraphFormat.keep_with_next сохраняет абзац на той же странице, что и последующий абзац. Это можно использовать, например, чтобы сохранить заголовок раздела на той же странице, что и первый абзац раздела.
  • ParagraphFormat.page_break_before заставляет абзац размещаться вверху новой страницы. Это можно использовать для заголовке главы, чтобы главы начинались с новой страницы.
  • ParagraphFormat.widow_control разбивает страницу, чтобы первая или последняя строка абзаца не помещалась на отдельной странице от остальной части абзаца.

Все четыре свойства являются трехуровневыми, что означает, что они могут принимать значения True, False или None.

  • None означает, что значение свойства унаследовано от иерархии стилей.
  • True означает - "включено".
  • False означает "выключено".
# наследуются по умолчанию
>>> p_fmt.keep_together
# None
>>> p_fmt.keep_with_next = True
>>> p_fmt.keep_with_next
# True
>>> p_fmt.page_break_before = False
>>> p_fmt.page_break_before
# `False

Форматирование слов/символов абзаца.

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

Объект Run имеет свойство шрифта только для чтения, обеспечивающее доступ к объекту Font. Объект Font прогона предоставляет свойства для получения и установки форматирования символов для этого прогона.

Здесь приведены несколько примеров. Полный набор доступных свойств, смотрите в документации по объекту Font.

Доступ к шрифту для прогона можно получить следующим образом:

>>> from docx import Document
>>> document = Document()
>>> run = document.add_paragraph().add_run()
>>> r_fmt = run.font

Гарнитура шрифта и размер устанавливаются так:

>>> from docx.shared import Pt
>>> r_fmt.name = 'Calibri'
>>> r_fmt.size = Pt(12)

Многие свойства шрифта имеют три состояния, это означает, что они могут принимать значения True, False и None.

  • True означает, что свойство "включено",
  • False означает, что оно "выключено".
  • None означает, что значение "унаследовано".

Прогон существует в иерархии наследования стилей и по умолчанию наследует форматирование символов из этой иерархии. Любое форматирование символов, применяемое напрямую с помощью объекта Font, переопределяет унаследованные значения.

Полужирный шрифт и курсив - это свойства с тремя состояниями, как и заглавные буквы, зачеркивание, надстрочный индекс и многие другие. Полный список смотрите в документации по объекту Font.

>>> r_fmt.bold, r_fmt.italic
# (None, None)
>>> r_fmt.italic = True
>>> r_fmt.italic
# True
>>> r_fmt.italic = False
>>> r_fmt.italic
# False
>>> r_fmt.italic = None
>>> r_fmt.italic
# None

Подчеркивание - это особый случай. Это гибрид свойства с тремя состояниями и свойств перечисления. Значение True означает одно подчеркивание, этот вариант использования наиболее распространен. Значение False означает отсутствие подчеркивания, но чаще значение None является правильным выбором, если подчеркивание не требуется. Другие формы подчеркивания, такие как двойное или пунктирное, указываются с помощью члена перечисления WD_UNDERLINE:

>>> r_fmt.underline
# None
>>> r_fmt.underline = True
>>> # или, может быть
>>> r_fmt.underline = WD_UNDERLINE.DOT_DASH

Цвет шрифта.

Каждый объект Font имеет объект ColorFormat, который обеспечивает доступ к цвету символов шрифта. Доступ к цвету осуществляется через свойство Font.color (только для чтения).

Применим к шрифту определенный цвет RGB:

>>> from docx.shared import RGBColor
>>> r_fmt.color.rgb = RGBColor(0x42, 0x24, 0xE9)

Шрифту также можно задать цвет темы, назначив элемент перечисления MSO_THEME_COLOR_INDEX (не описывается, т.к. практически ни кем не используется):

>>> from docx.enum.dml import MSO_THEME_COLOR
>>> r_fmt.color.theme_color = MSO_THEME_COLOR.ACCENT_1

Цвет шрифта можно восстановить до значения по умолчанию (унаследованного), присвоив None атрибуту .rgb или .theme_color:

>>> font.color.rgb = None