Saving workbook stream with stream images raise an error
I'm using openpyxl 3.1.2
and Pillow 9.5.0
, and when I insert an image using Image.open()
, then insert the image in the cell and then save it using a stream, it raised the following error:
File "LocalCache\local-packages\Python311\site-packages\openpyxl\workbook\workbook.py", line 386, in save
save_workbook(self, filename)
File "LocalCache\local-packages\Python311\site-packages\openpyxl\writer\excel.py", line 294, in save_workbook
writer.save()
File "LocalCache\local-packages\Python311\site-packages\openpyxl\writer\excel.py", line 275, in save
self.write_data()
File "LocalCache\local-packages\Python311\site-packages\openpyxl\writer\excel.py", line 79, in write_data
self._write_images()
File "LocalCache\local-packages\Python311\site-packages\openpyxl\writer\excel.py", line 116, in _write_images
self._archive.writestr(img.path[1:], img._data())
AttributeError: '_io.BytesIO' object has no attribute 'path'
But only happens when I try to insert an stream image. This is the code I used:
Excel = openpyxl.load_workbook(BytesIO(plantillaExcel64xlsx))
cellBookMarkNames = Excel.defined_names
for name, bookmarkValue in bookmarks.items():
if name not in cellBookMarkNames.keys():
continue
bookmarkCell = cellBookMarkNames.pop(name)
sheet = bookmarkCell.attr_text.split("!")[0] # Hoja
location = bookmarkCell.attr_text.split("!")[1].replace("$","")
excelSheet = Excel[sheet]
cell = excelSheet[location]
replaceBookmark(cell, bookmarkValue, excelSheet)
excelMemory = BytesIO()
Excel.save(excelMemory)
excelMemory.seek(0)
excelBase64 = base64.b64encode(excelMemory.read()).decode('utf-8')
Excel.close()
def replaceBookmark(cell, value, worksheet):
if value in [None, ""]:
cell.value = cell.value
elif isbase64(value):
picture = insertImage(value)
worksheet.add_image(picture, cell.coordinate)
elif cell.value is None or cell.value.strip() == "":
cell.value = value
elif isinstance(cell.value, str):
cell.value = f"{cell.value} {value}"
def isbase64(string):
if "=" == string[-1:] or string in ['/+', '+/'] or '+' in string:
return True
return False
def insertImage(string):
picture = BytesIO()
imageBytes = base64.b64decode(string)
image = Image.open(BytesIO(imageBytes))
image.save(picture, format = image.format)
picture.seek(0)
return picture
Edited by CharlieC