Skip to content

Commit 7155b8d

Browse files
committed
now can add image in ods and xlsx
1 parent 3109780 commit 7155b8d

File tree

9 files changed

+91
-9
lines changed

9 files changed

+91
-9
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -947,7 +947,7 @@ The principle is exactly the same as for LibreOffice Calc exept for the creation
947947
|-------------------------|----------|----------|----------|------|-----------|-----|-----|-------|
948948
| text variables support |||||||||
949949
| dynamic tables support |||||||||
950-
| image variables support || | ||||||
950+
| image variables support || | ||||||
951951

952952
### Export
953953
For Writer

lotemplate/CalcTemplate.py

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313

1414

1515
from . import errors
16-
16+
from sorcery import dict_of
1717
from lotemplate.Statement.CalcTableStatement import CalcTableStatement
1818
from .Template import Template
1919
from lotemplate.Statement.CalcSearchStatement import CalcTextStatement
20+
from lotemplate.Statement.CalcImageStatement import CalcImageStatement
2021
from jsondiff import diff
21-
2222
class CalcTemplate(Template):
2323
formats = {
2424
"ods": "calc8",
@@ -68,14 +68,29 @@ def scan(self, **kwargs) -> dict[str: dict[str, Union[str, list[str]]]]:
6868
"""
6969

7070
#should_close = kwargs.get("should_close", False)
71-
texts = {}
71+
texts = {}
72+
images = {}
7273
#(Pdb) self.doc.getSheets().getElementNames()
7374
for sheet in self.doc.getSheets():
7475
texts = texts | CalcTextStatement.scan(sheet)
76+
images = images | CalcImageStatement.scan_image(sheet)
7577
tables=CalcTableStatement.scan(self.doc)
76-
#texts = CalcTextStatement.scan_Document_text(self.doc)
77-
#pdb.set_trace()
78-
return texts | tables
78+
variables_list = list(texts.keys()) + list(tables.keys()) + list(images.keys())
79+
duplicates = [variable for variable in variables_list if variables_list.count(variable) > 1]
80+
81+
if duplicates:
82+
first_type = "text" if duplicates[0] in texts.keys() else "image"
83+
second_type = "table" if duplicates[0] in tables.keys() else "image"
84+
self.close()
85+
raise errors.TemplateError(
86+
'duplicated_variable',
87+
f"The variable {duplicates[0]!r} is mentioned two times, but "
88+
f"for two different types: {first_type!r}, and {second_type!r}",
89+
dict_of(first_type, second_type, variable=duplicates[0])
90+
)
91+
92+
93+
return texts | tables | images
7994

8095

8196
def search_error(self, json_vars: dict[str, dict[str, Union[str, list[str]]]]) -> None:
@@ -132,6 +147,9 @@ def fill(self, variables: dict[str, dict[str, Union[str, list[str]]]]) -> None:
132147
if details['type'] == 'text':
133148
for sheet in self.doc.getSheets():
134149
CalcTextStatement.fill(sheet, "$" + var, details['value'])
150+
elif details['type'] == 'image':
151+
for sheet in self.doc.getSheets():
152+
CalcImageStatement.image_fill(sheet,self.cnx.graphic_provider,"$" + var, details['value'])
135153
elif details['type'] == "object" and CalcTableStatement.isTableVar(var) :
136154
objects[var]=details
137155
for var, details in objects.items():
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from com.sun.star.beans import PropertyValue
2+
from com.sun.star.lang import XComponent
3+
import regex
4+
from urllib import request
5+
from PIL import Image
6+
from lotemplate.utils import get_file_url, is_network_based
7+
from com.sun.star.awt import Size
8+
class CalcImageStatement:
9+
image_regex = regex.compile(r'\$\w+')
10+
11+
def scan_image(doc: XComponent) -> dict[str, dict[str, str]]:
12+
"""
13+
scan for images in the given doc
14+
15+
:param doc: the document to scan
16+
:return: the scanned variables
17+
"""
18+
imgs = {}
19+
for img in doc.getDrawPage():
20+
if CalcImageStatement.image_regex.fullmatch(img.LinkDisplayName):
21+
imgs[CalcImageStatement.image_regex.match(img.LinkDisplayName).group(0)[1:]] = {'type': 'image', 'value': ''}
22+
elif CalcImageStatement.image_regex.fullmatch(img.Description):
23+
imgs[CalcImageStatement.image_regex.match(img.Description).group(0)[1:]] = {'type': 'image', 'value': ''}
24+
return imgs
25+
26+
def image_fill(doc: XComponent,graphic_provider ,variable: str, path: str, should_resize=True) -> None:
27+
"""
28+
Fills all the image-related content
29+
30+
:param should_resize: specify if the image should be resized to keep his original size ratio
31+
:param doc: the document to fill
32+
:param variable: the variable to search
33+
:param path: the path of the image to replace with
34+
:return: None
35+
"""
36+
if not path:
37+
return
38+
39+
for graphic_object in doc.getDrawPage():
40+
if graphic_object.LinkDisplayName != variable and graphic_object.Description != variable :
41+
continue
42+
43+
new_image = graphic_provider.queryGraphic((PropertyValue('URL', 0, get_file_url(path), 0),))
44+
45+
if should_resize:
46+
with Image.open(request.urlopen(path) if is_network_based(path) else path) as image:
47+
ratio = image.width / image.height
48+
new_size = Size()
49+
new_size.Height = graphic_object.Size.Height
50+
new_size.Width = graphic_object.Size.Height * ratio
51+
graphic_object.setSize(new_size)
52+
53+
graphic_object.Graphic = new_image
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"toto": {"type": "text", "value": "HELO"}, "image": {"type": "image", "value": "lotemplate/unittest/files/jsons/Yami_Yugi.png"}}
32.1 KB
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"toto": {"type": "text", "value": "HELO"}, "image1": {"type": "image", "value": "lotemplate/unittest/files/jsons/Yami_Yugi.png"}}
32.5 KB
Binary file not shown.

lotemplate/unittest/test_calc.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import lotemplate as ot
77
from lotemplate.unittest.test_function import compare_files_html
8+
from lotemplate.unittest.test_function import compare_image
89

910
cnx = ot.start_multi_office()
1011

@@ -27,5 +28,13 @@ def test_var(self):
2728
def test_table(self):
2829
self.assertTrue(compare_files_html('calc_table',cnx))
2930

31+
class Test_Calc_Images(unittest.TestCase):
32+
33+
def test_image_xlsx(self):
34+
self.assertTrue(compare_image('image_xlsx',cnx))
35+
36+
def test_image_ods(self):
37+
self.assertTrue(compare_image('image_ods',cnx))
38+
3039

3140

lotemplate/unittest/test_function.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from pypdf import PdfReader
1111
import glob
1212

13-
1413
def file_to_dict(file_path: str) -> dict:
1514
with open(file_path) as f:
1615
return json.loads(f.read())
@@ -24,10 +23,11 @@ def compare_image(name: str, cnx) :
2423
base_path = 'lotemplate/unittest/files/content'
2524
def get_filename(ext: str):
2625
return base_path + '/' + name + '.' + ext
27-
2826
temp = None
2927
if os.path.isfile(get_filename('ods')):
3028
temp = ot.TemplateFromExt(get_filename('ods'), ot.randomConnexion(cnx), True)
29+
if os.path.isfile(get_filename('xlsx')):
30+
temp = ot.TemplateFromExt(get_filename('xlsx'), ot.randomConnexion(cnx), True)
3131
if os.path.isfile(get_filename('odt')):
3232
temp = ot.TemplateFromExt(get_filename('odt'), ot.randomConnexion(cnx), True)
3333
if os.path.isfile(get_filename('docx')):

0 commit comments

Comments
 (0)