Использование python-docx-template для динамического создания закладок и ссылок на них в документах Word

от автора

Я использую модуль python-docx-template для генерации файлов docx по шаблону.

Подробнее о модуле можно почитать здесь: https://docs-python.ru/packages/modul-python-docx-python/modul-docx-template/

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

Здесь я предлагаю свой способ вставки закладок (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-код.

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


ссылка на оригинал статьи https://habr.com/ru/articles/749706/