Search code examples
pythonpython-2.7docx

Decreasing the vertical space when using the paragraph function in the python docx module


I am adding single line text something like this string = "This is just some text." using the docx.paragraph function to a word document. It works fine, except I would like to make the vertical spacing between the texts less. Any ideas how I can do that.

Thanks.


Solution

  • I have created a test docx, the first two paragraphs are spaced with normal spacing, and the two next paragraph are spaced with more spacing:

    enter image description here

    The first two paragraphs have the following structure (document.xml, see the Tag Wiki)

    <w:p w:rsidR="009565D8" w:rsidRDefault="009336B0">
    <w:r>
    <w:t>Test</w:t>
    </w:r>
    </w:p>
    <w:p w:rsidR="009336B0" w:rsidRDefault="009336B0">
    <w:r>
    <w:t>
    Test
    </w:t>
    </w:r>
    </w:p>
    

    The paragraphs with spacing look like this:

    <w:p w:rsidR="009336B0" w:rsidRDefault="009336B0" w:rsidP="009336B0">
    <w:pPr>
    <w:spacing w:line="480" w:lineRule="auto"/>
    </w:pPr>
    <w:r>
    <w:t>Test2</w:t>
    </w:r>
    </w:p>
    <w:p w:rsidR="009336B0" w:rsidRDefault="009336B0" w:rsidP="009336B0">
    <w:pPr>
    <w:spacing w:line="480" w:lineRule="auto"/>
    </w:pPr>
    <w:r>
    <w:t>Test2</w:t>
    </w:r>
    <w:bookmarkStart w:id="0" w:name="_GoBack"/>
    <w:bookmarkEnd w:id="0"/>
    </w:p>
    

    As you can see, there is a <w:pPr> Tag that contains the properties of the tag, including the spacing.

    You should now be able to change the docx.py by changing the paragraph function.

    Here is the paragraph function:

    def paragraph(paratext, style='BodyText', breakbefore=False, jc='left'):
        """
        Return a new paragraph element containing *paratext*. The paragraph's
        default style is 'Body Text', but a new style may be set using the
        *style* parameter.
    
        @param string jc: Paragraph alignment, possible values:
                          left, center, right, both (justified), ...
                          see http://www.schemacentral.com/sc/ooxml/t-w_ST_Jc.html
                          for a full list
    
        If *paratext* is a list, add a run for each (text, char_format_str)
        2-tuple in the list. char_format_str is a string containing one or more
        of the characters 'b', 'i', or 'u', meaning bold, italic, and underline
        respectively. For example:
    
            paratext = [
                ('some bold text', 'b'),
                ('some normal text', ''),
                ('some italic underlined text', 'iu')
            ]
        """
        # Make our elements
        paragraph = makeelement('p')
    
        if not isinstance(paratext, list):
            paratext = [(paratext, '')]
        text_tuples = []
        for pt in paratext:
            text, char_styles_str = (pt if isinstance(pt, (list, tuple))
                                     else (pt, ''))
            text_elm = makeelement('t', tagtext=text)
            if len(text.strip()) < len(text):
                text_elm.set('{http://www.w3.org/XML/1998/namespace}space',
                             'preserve')
            text_tuples.append([text_elm, char_styles_str])
        pPr = makeelement('pPr')
        pStyle = makeelement('pStyle', attributes={'val': style})
        pJc = makeelement('jc', attributes={'val': jc})
        pPr.append(pStyle)
        pPr.append(pJc)
    
        ###   Added Content from edi9999:
            Here you should add a children to the pPr element
            spacing= makeelement('spacing',attributes={'line':480,'lineRule':'auto'})
            pPr.append(spacing)
        ###
    
        # Add the text to the run, and the run to the paragraph
        paragraph.append(pPr)
        for text_elm, char_styles_str in text_tuples:
            run = makeelement('r')
            rPr = makeelement('rPr')
            # Apply styles
            if 'b' in char_styles_str:
                b = makeelement('b')
                rPr.append(b)
            if 'i' in char_styles_str:
                i = makeelement('i')
                rPr.append(i)
            if 'u' in char_styles_str:
                u = makeelement('u', attributes={'val': 'single'})
                rPr.append(u)
            run.append(rPr)
            # Insert lastRenderedPageBreak for assistive technologies like
            # document narrators to know when a page break occurred.
            if breakbefore:
                lastRenderedPageBreak = makeelement('lastRenderedPageBreak')
                run.append(lastRenderedPageBreak)
            run.append(text_elm)
            paragraph.append(run)
        # Return the combined paragraph
        return paragraph