Есть задача: брать данные из экселя, вставлять их в заранее подготовленную шаблон для награждения и потом готовые листы объединять в один документ. С грехом пополам, пользуясь разными источниками написал вот такой скрипт. Всё, вроде бы, нормально и отдельные листы выглядят как и было задумано. Но при объединении, дальше первого листа, весь текст начинает переезжать. Может кто-нибудь подсказать в чём может быть дело? Спасибо.
import openpyxl import os from docxtpl import DocxTemplate from docx import Document from docx.shared import Cm from docxcompose.composer import Composer from docx import Document as Document_compose from pathlib import Path ############################################################### source_folder = './result/' # Путь к папке с исходными файлами destination_folder = './result/сводные/' # Путь к папке, в которую будут сохранены сводные файлы final_doc_name = 'сводный.docx' xls_name = './tpl/real_data_cut.xlsx' gbou_name = './tpl/gbou.txt' docx_tpl = './tpl/tpl3.docx' # Отступы в docx шаблоне top = 0.75 bottom = 0.5 left = 1.27 right = 1.27 ################################################################## def xls2doc(): # загружаем файл excel workbook = openpyxl.load_workbook(xls_name) # выбираем первую страницу worksheet = workbook.active # открываем файл с названиями школ with open(gbou_name, encoding='utf-8') as f: schools = [line.strip().split(';') for line in f] # определяем номера столбцов по заголовкам header_row = 1 last_col = worksheet.max_column headers = {} for col in range(1, last_col+1): cell = worksheet.cell(row=header_row, column=col) if cell.value: headers[cell.value] = col # проходим по каждой строке данных for row in range(header_row+1, worksheet.max_row+1): # получаем значения всех полей last_name = worksheet.cell(row=row, column=headers['Фамилия']).value first_name = worksheet.cell(row=row, column=headers['Имя']).value middle_name = worksheet.cell(row=row, column=headers.get('Отчество')).value full_name = f'{last_name} {first_name}' if middle_name: full_name += f' {middle_name}' sex = worksheet.cell(row=row, column=headers['Пол']).value if sex and sex[0] in ['Ж', 'ж']: sex = 'учащаяся' elif sex and sex[0] in ['М', 'м']: sex = 'учащийся' else: sex = 'неизвестно' school_name = worksheet.cell(row=row, column=headers['Полное название общеобразовательного учреждения']).value school_num = '' if school_name: school_num = [s for s in school_name.split() if s.isdigit() or s == 'Морская'] if school_num: school_num = school_num[0] gbou = '' for school in schools: if school_num in school[0]: gbou = school[1] break discipline = worksheet.cell(row=row, column=headers['Предмет']).value class_num = worksheet.cell(row=row, column=headers['Класс обучения']).value status = worksheet.cell(row=row, column=headers['Статус участника']).value teacher = worksheet.cell(row=row, column=headers['Фамилия, Имя, Отчество учителя']).value # Открываем шаблон документа и рендерим его с помощью данных из строки tpl = DocxTemplate(docx_tpl) context = { 'full_name': full_name, 'sex': sex, 'class_num': class_num, 'gbou': gbou, 'status': status, 'discipline': discipline, 'teacher': teacher } tpl.render(context) # Сохраняем сгенерированный документ в файл с именем, соответствующим значению поля name tpl.save(f'./Result/{full_name}.docx') def create_master_docx(path: Path): # Создаем новый документ doc = Document() # Устанавливаем поля sections = doc.sections for section in sections: section.top_margin = Cm(top) section.bottom_margin = Cm(bottom) section.left_margin = Cm(left) section.right_margin = Cm(right) # Устанавливаем размер страницы в А4 section = sections[0] section.page_height = Cm(29.7) section.page_width = Cm(21.0) # Сохраняем сводный файл в папку назначения doc.save(os.path.join(destination_folder,final_doc_name)) def merge_docx(path_master: destination_folder, files: list): """ Открываем файл в который будем объединять все остальные. Создаем композитора. Запускаем цикл по списку файлов. Добавляем в композитор содержимое каждого файла из списка. Сохраняем итоговый документ. """ number_of_sections = len(files) master = Document_compose(path_master) composer = Composer(master) for i in range(0, number_of_sections): doc_temp = Document_compose(files[i]) composer.append(doc_temp) composer.save(path_master) def main(): """ Запрашиваем имя для объединенного файла. Запрашиваем путь к директории с файлами для объединения. Проверяем существование директории и является ли переданный путь путем к директории. Получаем список файлов в директории, формируем список файлов с полным путем к ним. Создаем новый документ. Объединяем документы из директории. """ xls2doc() path = Path.cwd() files = [Path(source_folder) / x for x in os.listdir(source_folder) if Path(x).suffix == ".docx"] if files: create_master_docx(destination_folder) merge_docx(os.path.join(destination_folder, final_doc_name), files) print(f"Объединение завершено. Объединенный файл -> {os.path.join(destination_folder, final_doc_name)} ") else: print("Файлов для объединения не найдено") if __name__ == "__main__": main()