Я использую модуль 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-код.

Спасибо за внимание.

Комментарии (0)