Я использую модуль python-docx-template для генерации файлов docx по шаблону.
Подробнее о модуле можно почитать здесь.
Модуль содержит функционал для вставки в документ внешних ссылок, но когда мне понадобилось создавать по шаблону внутренние ссылки (на конкретное место в документе), такого функционала не нашлось, поиск в сети тоже ничего не дал.
Здесь я предлагаю свой способ вставки закладок (bookmarks) и ссылок (hyperlinks) на них при помощи python-docx-template.
Решение
В состав модуля входит объект RichText(). Метод add(string) этого объекта создает xml код, который помещается в RichText().xml и далее вставляется как есть в документ docx.
Например:
rt = RichText()
rt.add('TEST')
print(rt.xml)
# <w:r><w:t xml:space="preserve">TEST</w:t></w:r>
Я решил самостоятельно генерировать и напрямую помещать нужный мне код xml в RichText().xml и это сработало.
Ниже пример кода:
from docxtpl import DocxTemplate, RichText
def add_bookmarks_and_links(data):
for i, item in enumerate(data['articles']):
# создаем закладку
bookmark_name = f'article_{i}'
bookmark = RichText(item["title"])
bookmark.xml = f'<w:bookmarkStart w:id="" w:name="{bookmark_name}"/>' + \
bookmark.xml + \
'<w:bookmarkEnd w:id=""/>'
item['title_with_bookmark'] = bookmark
# создаем ссылку на закладку
hyperlink_start = RichText()
hyperlink_end = RichText()
hyperlink_start.xml = f'<w:hyperlink w:anchor="{bookmark_name}" w:history="1">'
hyperlink_end.xml = '</w:hyperlink>'
item['hyperlink_start'] = hyperlink_start
item['hyperlink_end'] = hyperlink_end
data = {'report_title': 'Report title',
'articles': [{'title': 'Title Article 1',
'description': 'Description Article 1',
'body': 'Body Article 1'},
{'title': 'Title Article 2',
'description': 'Description Article 2',
'body': 'Body Article 2'}
]
}
template_filename = 'template.docx'
result_filename = 'result.docx'
add_bookmarks_and_links(data)
tpl = DocxTemplate(template_filename)
tpl.render(data)
tpl.save(result_filename)
Файл шаблона docx выглядит примерно так:
{{ report_title }}
Дайджест
{% for article in articles %}
{{r article.hyperlink_start }}{{ article.title }}{{r article.hyperlink_end }}
{{ article.description }}
{% endfor %}
Полные тексты статей
{% for article in articles %}
{{ article.title_with_bookmark }}
{{ article.description }}
{{ article.body }}
{% endfor %}
В результате выполнения кода получаем документ с разделом дайджестов статей, с ссылками в заголовках, которые ведут на полные тексты статей:
Аналогичным образом можно вставлять в поля шаблона любой другой неподдерживаемый модулем python-docx-template xml-код.
Спасибо за внимание.