python-docx-template icon indicating copy to clipboard operation
python-docx-template copied to clipboard

Can I add image from user input data? (file path)

Open falconws opened this issue 2 years ago • 3 comments

Describe your problem

I want to add the image to a generated docx file. I was read (https://docxtpl.readthedocs.io/en/latest/#inline-image) and look inline_image_tpl.docx and inline_image.py. But these are not enough for my needs.

More details about your problem

Write the necessary data in a text file (in yaml format for ease of use later from my program). Load this file with the open function (yaml.safe_load() since it is in yaml format). Create a Python dict object based on the read data, pass it to tpl.render(), and tpl.save(). In this process, like the Markdown image tag (https://www.markdownguide.org/basic-syntax/#images-1), I want to specify the path to an image file and output the docx file with the pasted image file.

data: |-
  This is sample data
  hoge fuga piyo
  !!! Insert image like ![](images/filename.jpg)
  ↑ This image is ... (above image explanation)
import yaml
from docxtpl import DocxTemplate

with open('./data.yaml', 'r') as f:
    context = yaml.safe_load(f)

tpl = DocxTemplate('path/to/template/file.docx')
tpl.render(context)
tpl.save('path/to/output.docx')
1. title
2. explain

{{ data }}

↑ I want to add the multiple-image to {{ data }}.

falconws avatar Apr 22 '22 06:04 falconws

You would need to add some logic between yaml.safe_load(f) and render(context).

Any image that is brought into the document needs to be processed first before it can be rendered. So InlineImage kinda needs to be called. But there is hope for you!

By because python is dynamically typed, we can add a function that searches for a key with the a keyword,

doc = DocxTemplate("templates/docx/template.docx")
foobar_dict = { foo_text:"BAR", foo_img: "PATH/TO/FILE"}

for key in foobar_dict:
 if "img" in key:
  img = InlineImage(doc,image_descriptor=foobar_dict[key])
  foobar_dict[key] = img

doc.render(foobar_dict)
doc.save("newdoc.docx") 

Then in the document, you just use {{ foo_img }}

ILightThings avatar Apr 22 '22 12:04 ILightThings

@ILightThings Thank you response.

Then in the document, you just use {{ foo_img }}

But this is not dynamic or flexible. Sometimes an image is pasted, sometimes no image is pasted, sometimes one image is pasted, sometimes more than one image is pasted.

I hope to put one {{ variable }} (in the document) but its contents may or may not have images. Can I it?

falconws avatar Apr 22 '22 12:04 falconws

Dict Object

{
	"Object": {
		"images": [
			"path_to_image_1",
			"path_to_image_2",
			"path_to_image_3"
		]
	}
}

python

doctemplate = DocxTemplate(path_to_docx)

for x in len(object["images"]):
 object["images"][x] = InlineImage(doctemplate , object["images"][x]) # This will replace the path with the inlineimage object

doc.render(data)
doc.save(path_to_new_doc)

Doc Template

{% for x in Object.images %}
{{ x }}
{% endfor %}

Will print all images stored in the list of imagepaths of the object. WIll not error out if is empty.

ILightThings avatar May 20 '22 15:05 ILightThings