how to know when a new paragraph in python-docx causes a new page

馋奶兔 提交于 2019-12-20 06:38:24

问题


I have to create word documents dynamically using python-docx. I do it by adding table rows dynamically and there is no way to know how many records fit on a page because it depends on the specific data.

I need to know when a new element added to the document (table row or paragraph) causes a new page, so I can record some data in the database accordingly with the information that each page contains.

This is the code for the word document generation with python-docx:

def get_invoice_word_report(self, request, invoices_controllers):
    import unicodedata
    from django.core.files import File
    from docx import Document
    from docx.shared import Inches, Pt
    from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_BREAK
    from docx.enum.table import WD_ALIGN_VERTICAL
    from docx.enum.table import WD_TABLE_ALIGNMENT

    document = Document()

    section = document.sections[-1]
    section.left_margin = Inches(0.5)
    section.right_margin = Inches(0.5)

    style = document.styles['Normal']
    font = style.font
    font.name ='Arial'
    font.size = Pt(8)

    i = 0
    for invoices_controller in invoices_controllers:
        context = invoices_controller.get_context()
        if i > 0:
            run.add_break(WD_BREAK.PAGE)
            if i == len(invoices_controllers) - 1:
                last = context['invoices']['invoice_number']
        else:
            first = context['invoices']['invoice_number']

        document.add_paragraph("Invoice".format(context['invoices']['invoice_number'])).alignment = WD_ALIGN_PARAGRAPH.RIGHT
        document.add_paragraph("Folio {}".format(context['invoices']['invoice_number'])).alignment = WD_ALIGN_PARAGRAPH.RIGHT
        document.add_paragraph(context['invoices']['agency']['company']['name'])
        document.add_paragraph(context['invoices']['agency']['company']['address'])
        date = context['invoices']['period_end_date'].split('-')
        document.add_paragraph("{}      {}      {}".format(date[2], date[1], date[0])).alignment = WD_ALIGN_PARAGRAPH.RIGHT
        document.add_paragraph(context['invoices']['line'])
        document.add_paragraph(context['invoices']['text'])

        table = document.add_table(rows=1, cols=4)
        hdr_cells = table.rows[0].cells

        hdr_cells[0].width = Inches(0.1)
        hdr_cells[1].width = Inches(10)
        hdr_cells[2].width = Inches(1)
        hdr_cells[3].width = Inches(1)

        for entry in context['invoices']['entries']:
            row_cells = table.add_row().cells
            row_cells[0].text = str(entry['amount'])
            row_cells[1].text = entry['line']
            row_cells[2].text = entry['unit_price_label']
            row_cells[2].paragraphs[0].alignment= WD_ALIGN_PARAGRAPH.RIGHT
            row_cells[3].text = entry['subtotal']
            row_cells[3].paragraphs[0].alignment= WD_ALIGN_PARAGRAPH.RIGHT

            if entry['text']:
                text_cells = table.add_row().cells
                text_cells[1].text = entry['text']

        row_cells = table.add_row().cells
        row_cells[0].text = ''
        row_cells[1].text = ''
        row_cells[2].text = ''
        row_cells[3].text = context['total']
        row_cells[3].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT

        row_cells = table.add_row().cells
        row_cells[0].text = ''
        row_cells[1].text = ''
        row_cells[2].text = ''
        row_cells[3].text = '$0.00'
        row_cells[3].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT

        row_cells = table.add_row().cells
        row_cells[0].text = ''
        row_cells[1].text = ''
        row_cells[2].text = ''
        row_cells[3].text = context['total']
        row_cells[3].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT

        run = document.add_paragraph("Son {}".format(context['total_text'])).add_run()
        i += 1

    current_directory = settings.MEDIA_DIR
    if len(invoices_controllers) > 1:
        file_name = "Invoices {}-{}.docx".format(first, last)
    else:
        file_name = "Invoice {}.docx".format(first)
    document.save(current_directory + file_name)

    return request.get_host()+ settings.MEDIA_URL + file_name

Thanks for your help.


回答1:


Detecting automatic (renderer-generated) page breaks in python-docx is not possible because those breaks are not reliably recorded in the XML.

You may be able to find some indication of the last rendered page break, depending on where your .docx files came from. Otherwise you probably need to use the Microsoft VBA interface to gain access to a live renderer which may be able to provide you this information. Note the page break location is subject to change based on the machine Word is running on, depending on factors like font metrics and printer drivers.

This has come up in other questions and answers. This one might be a good place to start: Page number python-docx

To see the rest, search on "[python-docx] page break" and you'll see there are quite a few. The square bracketed part limits results to those tagged with "python-docx".



来源:https://stackoverflow.com/questions/54371915/how-to-know-when-a-new-paragraph-in-python-docx-causes-a-new-page

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!