简体   繁体   中英

python-docx does not add picture

I'm trying to insert a picture into a Word document using python-docx but running into errors.

The code is simply:

document.add_picture("test.jpg", width = Cm(2.0))

From looking at the python-docx documentation I can see that the following XML should be generated:

<pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
  <pic:nvPicPr>
    <pic:cNvPr id="1" name="python-powered.png"/>
    <pic:cNvPicPr/>
  </pic:nvPicPr>
  <pic:blipFill>
    <a:blip r:embed="rId7"/>
    <a:stretch>
      <a:fillRect/>
    </a:stretch>
  </pic:blipFill>
  <pic:spPr>
    <a:xfrm>
      <a:off x="0" y="0"/>
      <a:ext cx="859536" cy="343814"/>
    </a:xfrm>
    <a:prstGeom prst="rect"/>
  </pic:spPr>
</pic:pic>

This does in fact get generated in my document.xml file. (When unzipping the docx file). However looking into the OOXML format I can see that the image should also be saved under the media folder and the relationship should be mapped in word/_rels/document.xml:

<Relationship Id="rId20"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
Target="media/image20.png"/>

None of this is happens however, and when I open the Word document I'm met with a "The picture can't be displayed" placeholder.

Can anyone help me understand what is going on?

It looks like the image is not embedded the way it should be and I need to insert it in the media folder and add the mapping for it, however as a well documented feature this should be working as expected.

UPDATE:

Testing it out with an empty docx file that image does get added as expected which leads me to believe it might have something to do with the python-docx-template library. ( https://github.com/elapouya/python-docx-template )

It uses python-docx and jinja to allow templating capabilities but runs and works the same way python-docx should . I added the image to a subdoc which then gets inserted into a full document at a given place.

A sample code can be seen below (from https://github.com/elapouya/python-docx-template/blob/master/tests/subdoc.py ):

from docxtpl import DocxTemplate
from docx.shared import Inches

tpl=DocxTemplate('test_files/subdoc_tpl.docx')

sd = tpl.new_subdoc()
sd.add_paragraph('A picture :')
sd.add_picture('test_files/python_logo.png', width=Inches(1.25))

context = {
    'mysubdoc' : sd,
}

tpl.render(context)
tpl.save('test_files/subdoc.docx')

I'll keep this up in case anyone else manages to make the same mistake as I did :) I managed to debug it in the end.

The problem was in how I used the python-docx-template library. I opened up a DocxTemplate like so:

    report_output = DocxTemplate(template_path)
    DoThings(value,template_path)
    report_output.render(dictionary)
    report_output.save(output_path)

But I accidentally opened it up twice. Instead of passing the template to a function, when working with it, I passed a path to it and opened it again when creating subdocs and building them.

def DoThings(data,template_path):
    doc = DocxTemplate(template_path)
    temp_finding = doc.new_subdoc()
    #DO THINGS

Finally after I had the subdocs built, I rendered the first template which seemed to work fine for paragraphs and such but I'm guessing the images were added to the "second" opened template and not to the first one that I was actually rendering. After passing the template to the function it started working as expected!

I came acrossed with this problem and it was solved after the parameter width=(1.0) in method add_picture removed.

在此处输入图片说明

when parameter width=(1.0) was added, I could not see the pic in test.docx

so, it MIGHT BE resulted from an unappropriate size was set to the picture,

to add pictures, headings, paragraphs to existing document:

doc = Document(full_path) # open an existing document with existing styles
for row in tableData:   # list from the json api ... 
    print ('row {}'.format(row))
    level = row['level']
    levelStyle = 'Heading ' + str(level)
    title = row['title']
    heading = doc.add_heading( title , level)
    heading.style = doc.styles[levelStyle]
    p = doc.add_paragraph(row['description'])
    if row['img_http_path']:
        ip = doc.add_paragraph()
        r = ip.add_run()
        r.add_text(row['img_name'])
        r.add_text("\n")
        r.add_picture(row['img_http_path'], width = Cm(15.0))

doc.save(full_path)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM