Найти - Пользователи
Полная версия: Объединение нескольких ворд документов
Начало » Python для новичков » Объединение нескольких ворд документов
1
crewdk
Добрый день.

Есть задача: брать данные из экселя, вставлять их в заранее подготовленную шаблон для награждения и потом готовые листы объединять в один документ. С грехом пополам, пользуясь разными источниками написал вот такой скрипт. Всё, вроде бы, нормально и отдельные листы выглядят как и было задумано. Но при объединении, дальше первого листа, весь текст начинает переезжать. Может кто-нибудь подсказать в чём может быть дело? Спасибо.

 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()
py.user.next
crewdk
С грехом пополам, пользуясь разными источниками написал вот такой скрипт. Всё, вроде бы, нормально и отдельные листы выглядят как и было задумано.
Теперь их по отдельности переводи в pdf, а потом эти листы в pdf соединяй в один pdf.

crewdk
Но при объединении, дальше первого листа, весь текст начинает переезжать. Может кто-нибудь подсказать в чём может быть дело?
Да там много в чём может быть дело. Другие шрифты, форматы документов, настройки программы для просмотра и тому подобное. Также сами модули в языках программирования бывают несовершенными и глючными. В любом случае ты даже вручную если будешь это объединять, то на каком-нибудь компе оно съедет куда-нибудь не туда. Так что лучше пользоваться тем, что не зависит от этих меняющихся характеристик. Поэтому надо использовать pdf, который везде выглядит одинаково после его создания. Для этого он и создавался, для этого его и придумали.
crewdk
Спасибо за ответ. К сожалению, в этих наградных грамотах есть картинка-подложка и при сохранении в pdf качество этой картинки очень сильно ухудшается. Рабочего варианта перевода без потери качества из word в pdf найти так и не смог. Может сможете навскидку подсказать в какую сторону копать?
py.user.next
crewdk
и при сохранении в pdf качество этой картинки очень сильно ухудшается
Звучит бредово. Как ты сохраняешь docx в pdf? Надеюсь, не через какое-нибудь облако Яндекс или что-то наподобие.

crewdk
Рабочего варианта перевода без потери качества из word в pdf найти так и не смог.
Так ты пиши, что ты нашёл. Может, ты этим просто пользоваться не умеешь.

Ты вечно пишешь что-то вроде
crewdk
дальше первого листа, весь текст начинает переезжать
Что это значит? Переезжает куда, в Америку с чемоданами? Переезжать оно может по-разному, штук десять разных переезжаний я тебе могу привести. Про какое из них ты говоришь?
crewdk
и при сохранении в pdf
При каком сохранении? Сохранять можно десятком разных способов.

Поэтому пиши конретно, у нас нет хрустальных шаров, в которых показывается, что у тебя за программы, что ты там делаешь и как ты и что куда сохраняешь.

Видно только твой код, который ты выложил, по котором понятно, что ты вообще программировать не умеешь. Мешанина просто какая-то.

Так что ты пока что никак не показал, что ты в состоянии программами просто пользоваться правильно. Так что положиться на то, что ты якобы всё правильно настроил, я тоже не могу. Для этого нет оснований просто.

Ты вот используешь docxcomposer; ты видал, сколько там багов?
https://github.com/4teamwork/docxcompose/issues
Сырой модуль какой-то. Документации даже нет.
crewdk
py.user.next
Что это значит? Переезжает куда, в Америку с чемоданами? Переезжать оно может по-разному, штук десять разных переезжаний я тебе могу привести. Про какое из них ты говоришь?

Для примера, вот так выглядит конец первого листа и конец 8го листа

Конец первого листа

Конец 8го листа

py.user.next
Видно только твой код, который ты выложил, по котором понятно, что ты вообще программировать не умеешь. Мешанина просто какая-то.

Да, это всего 2й мой код, написанный на питоне. И, как я уже писал, надёрганный из разных источников.


Конвертировать в pdf например вот так пробовал:

 import os
import win32com.client
from docx2pdf import convert
word_file_path = 'word.docx'
convert(word_file_path)
pdf_file_path = os.path.splitext(word_file_path)[0] + '.pdf'
word = win32com.client.Dispatch('Word.Application')
doc = word.Documents.Open(word_file_path)
doc.SaveAs(pdf_file_path, FileFormat=17)
doc.Close()
word.Quit()

А получалось вот так:
Качество подложки после конвертирования в pdf

Качество подложки до
py.user.next
crewdk
Для примера, вот так выглядит конец первого листа и конец 8го листа
Покажи исправный лист. Как он выглядит?

crewdk
А получалось вот так:
Видно, что он сжимает изображение.

Вот пример есть, где можно выставить качество изображения в 100% (чтобы сжатия не было)
https://blog.aspose.com/words/convert-word-to-pdf-in-python/#Word-to-PDF-with-a-Particular-PDF-Standard
  
...
 
saveOptions.jpeg_quality = 100
 
...

Попробуй эти пакеты
https://pypi.org/project/aspose-words/
https://pypi.org/project/aspose-pdf/

По крайней мере эти пакеты выглядят профессионально. Видно, что не какой-то лох этим занимается, который даже документацию написать не в состоянии, а там команда есть, которая кучу пакетов разрабатывает сразу.
xam1816
Приложи исходные данные, и руками сделай как должно получиться на выходе, выложи сюда.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB