Changing Paragraph formatting in python-docx

自作多情 提交于 2020-06-28 05:57:28

问题


I am trying to change the formatting for multiple paragraphs using Python's python-docx module.

from docx import Document
from docx.shared import Pt
from docx.shared import Inches
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.enum.section import WD_ORIENTATION
from content import report_content, provinces, report_date, introduction, intro_content

alignment_dict = {'justify': WD_PARAGRAPH_ALIGNMENT.JUSTIFY,
                  'center': WD_PARAGRAPH_ALIGNMENT.CENTER,
                  'centre': WD_PARAGRAPH_ALIGNMENT.CENTER,
                  'right': WD_PARAGRAPH_ALIGNMENT.RIGHT,
                  'left': WD_PARAGRAPH_ALIGNMENT.LEFT}

orientation_dict = {'portrait': WD_ORIENTATION.PORTRAIT,
                    'landscape': WD_ORIENTATION.LANDSCAPE}

document = Document()


def change_orientation(orientation='portrait', set_left_margin=1.0, set_right_margin=1.0):
    section = document.sections[-1]
    new_width, new_height = section.page_height, section.page_width
    section.orientation = orientation_dict[orientation]
    section.page_width = new_width
    section.page_height = new_height
    section.left_margin = Inches(set_left_margin)
    section.right_margin = Inches(set_right_margin)


def add_logo(path, align):
    document.add_picture(path, width=Inches(4.5), height=Inches(1.5))
    last_paragraph = document.paragraphs[-1]
    last_paragraph.alignment = alignment_dict[align]


def add_content(content, space_after, font_name='Arial', font_size=11, line_spacing=0, space_before=0,
                align='justify', keep_together=True, keep_with_next=False, page_break_before=False,
                widow_control=False, set_bold=False, set_italic=False, set_underline=False, set_all_caps=False):
    paragraph = document.add_paragraph(content)
    style = document.styles['Normal']
    font = style.font
    font.name = font_name
    font.size = Pt(font_size)
    font.bold = set_bold
    font.italic = set_italic
    font.all_caps = set_all_caps
    font.underline = set_underline
    paragraph_format = paragraph.paragraph_format
    paragraph_format.alignment = alignment_dict.get(align.lower())
    paragraph_format.space_before = Pt(space_before)
    paragraph_format.space_after = Pt(space_after)
    paragraph_format.line_spacing = line_spacing
    paragraph_format.keep_together = keep_together
    paragraph_format.keep_with_next = keep_with_next
    paragraph_format.page_break_before = page_break_before
    paragraph_format.widow_control = widow_control


def create_numbered_list():
    pass


def add_subheading(subheading, level):
    document.add_heading(subheading, level)


change_orientation(orientation='landscape', set_left_margin=0.5, set_right_margin=0.5)
add_logo('logo.png', 'center')
add_content(report_content, align='Center', space_before=40, space_after=20, line_spacing=1, font_name='Arial',
            set_bold=True, set_all_caps=True)
add_content(provinces, align='Center', space_before=20, space_after=20, line_spacing=1, font_name='Arial',
            set_bold=True, set_all_caps=True)
add_content(report_date, align='Center', space_before=20, space_after=20, line_spacing=1, font_name='Arial',
            set_bold=True, set_all_caps=True)
document.add_page_break()

add_subheading(introduction, level=1)

add_content(intro_content, space_after=20, space_before=20)

document.save('demo.docx')

The problem is every time I add formatting to a new paragraph block via the add_content method the formatting for the older blocks gets changed as the formatting for the current block.

Why am I not being able to retain the formatting, why does it get reset to the formatting of the latest block?


回答1:


Try this code. use add_style to add new style. document.styles['Normal'] is a system style I test it ok

from docx.enum.style import WD_STYLE_TYPE
#.........................
def add_content(content, space_after, font_name='Arial', font_size=16, line_spacing=0, space_before=0,
                align='justify', keep_together=True, keep_with_next=False, page_break_before=False,
                widow_control=False, set_bold=False, set_italic=False, set_underline=False, set_all_caps=False,style_name=""):
    paragraph = document.add_paragraph(content)
    paragraph.style = document.styles.add_style(style_name, WD_STYLE_TYPE.PARAGRAPH)
    font = paragraph.style.font
    font.name = font_name
    font.size = Pt(font_size)
    font.bold = set_bold
    font.italic = set_italic
    font.all_caps = set_all_caps
    font.underline = set_underline
    paragraph_format = paragraph.paragraph_format
    paragraph_format.alignment = alignment_dict.get(align.lower())
    paragraph_format.space_before = Pt(space_before)
    paragraph_format.space_after = Pt(space_after)
    paragraph_format.line_spacing = line_spacing
    paragraph_format.keep_together = keep_together
    paragraph_format.keep_with_next = keep_with_next
    paragraph_format.page_break_before = page_break_before
    paragraph_format.widow_control = widow_control

add_content("1234", align='Center', space_before=40, space_after=20, line_spacing=1, font_name='Arial', font_size=16,
            set_bold=True, set_all_caps=True,style_name ="Normal1")
add_content("12345", align='Center', space_before=20, space_after=20, line_spacing=1, font_name='Arial',font_size=14,
            set_bold=True, set_all_caps=True,style_name ="Normal2")



回答2:


Your problem is here:

style = document.styles['Normal']
font = style.font

A style applies to all paragraphs that have that style. It's a document global thing. So any change you make the style.font affect all paragraphs with that style (which is all your paragraphs in this case).

Make sure you read this page in the documentation and the one that follows it:
http://python-docx.readthedocs.io/en/latest/user/styles-understanding.html

Character formatting (e.g. bold, size, typeface) happens at the run level (below paragraph, a paragraph is composed of runs). So if you want to apply character formatting directly, as opposed to by using a style, you need to do it to each run.

Adding content to a paragraph by calling document.add_paragraph(content) places all that content in a single run. So a quick fix might be:

font = paragraph.runs[0].font

Might be worth a try. But probably also a good idea to spend a little time with the concepts parts of the documentation to understand the Word object model a bit better. It's pretty complex for what seems on the surface to be a simple thing. This page is a good place to start:
http://python-docx.readthedocs.io/en/latest/user/text.html



来源:https://stackoverflow.com/questions/48150222/changing-paragraph-formatting-in-python-docx

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