Apr-02-2023, 09:49 PM
Hi,
I have a task: I have an XLSX document with data such as name, surname, class, school ID, etc. I also have a template for the Certificate of Appreciation. My goal is to read the data from the XLSX file, generate new documents using this data and the template, and merge all new documents into one.
Now I have this code. (Sorry, this is only my second Python script, and it might be messy)
I have a task: I have an XLSX document with data such as name, surname, class, school ID, etc. I also have a template for the Certificate of Appreciation. My goal is to read the data from the XLSX file, generate new documents using this data and the template, and merge all new documents into one.
Now I have this code. (Sorry, this is only my second Python script, and it might be messy)
import os
import sys
import time
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'
gbou_name = './tpl/gbou.txt'
docx_tpl = './tpl/tpl3.docx'
# Отступы в docx шаблоне
top = 0.75
bottom = 0.5
left = 1.27
right = 1.27
###########################################################################
if len(sys.argv) > 1:
xls_name = sys.argv[1]
else:
xls_name = "data.xlsx"
def chk_dir():
if not os.path.exists(destination_folder):
os.makedirs(destination_folder)
def xls2doc():
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)
tpl.save(f'./Result/{full_name}_{discipline}.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)
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():
chk_dir()
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("Файлов для объединения не найдено")
time.sleep(3)
if __name__ == "__main__":
main()As far as I can see, this code works fine for single pages. However, after merging the DOCX files, I encounter a strange bug. The first page is okay, but after the first page, all the text moves up. For example, I have attached screenshots from the bottom of the first page and the eighth page. Can someone please tell me what I did wrong?
