Using `wb.save` results in UnboundLocalError: local variable rel referenced before assignment

2024/7/8 6:45:40

I am trying to learn how to place an image in an Excel worksheet but I am having a problem with wb.save. My program ends with the following error:

"C:\Users\Don\PycharmProjects\Test 2\venv\Scripts\python.exe" "C:/Users/Don/PycharmProjects/Test 2/Test 2.py"
Traceback (most recent call last):File "C:/Users/Don/PycharmProjects/Test 2/Test 2.py", line 20, in <module>wb.save('POKENO Cards new.xlsx')File "C:\Users\Don\PycharmProjects\Test 2\venv\lib\site-packages\openpyxl\workbook\workbook.py", line 392, in savesave_workbook(self, filename)File "C:\Users\Don\PycharmProjects\Test 2\venv\lib\site-packages\openpyxl\writer\excel.py", line 293, in save_workbookwriter.save()File "C:\Users\Don\PycharmProjects\Test 2\venv\lib\site-packages\openpyxl\writer\excel.py", line 275, in saveself.write_data()File "C:\Users\Don\PycharmProjects\Test 2\venv\lib\site-packages\openpyxl\writer\excel.py", line 75, in write_dataself._write_worksheets()File "C:\Users\Don\PycharmProjects\Test 2\venv\lib\site-packages\openpyxl\writer\excel.py", line 218, in _write_worksheetsself._write_drawing(ws._drawing)File "C:\Users\Don\PycharmProjects\Test 2\venv\lib\site-packages\openpyxl\writer\excel.py", line 141, in _write_drawingself._archive.writestr(drawing.path[1:], tostring(drawing._write()))File "C:\Users\Don\PycharmProjects\Test 2\venv\lib\site-packages\openpyxl\drawing\spreadsheet_drawing.py", line 295, in _writeself._rels.append(rel)
UnboundLocalError: local variable 'rel' referenced before assignmentProcess finished with exit code 1

This is my code. It works until the last statement.

import openpyxl as xl
from PIL import Image
#im = Image.open(r"Playing Cards/2C.jpg")
im = Image.open(r"C:/Users/Don/Pictures/resized Nyle.jpg")
wb = xl.load_workbook(filename="C:/Users/Don/PycharmProjects/Test 2/POKENO   Cards.xlsx")
ws1 = wb.worksheets[0]
im.show()
img = im.resize((78, 100))
img.show()
wb2 = xl.load_workbook(filename="C:/Users/Don/PycharmProjects/Test 2/POKENO Cards new.xlsx")
ws2 = wb2.active
ws2.add_image(im, 'A4')
wb2.save(filename="C:/Users/Don/PycharmProjects/Test 2/POKENO Cards new.xlsx")
Answer

The error is a bit cryptic, but the Traceback is quite clear enough to trace the cause of the problem: that openpyxl's add_image method expects a openpyxl.drawing.image.Image object, and not a PIL Image.

If you check the lines in openpyxl / drawing / spreadsheet_drawing.py that raised the error, there's a check there for the image type:

for idx, obj in enumerate(self.charts + self.images, 1):anchor = _check_anchor(obj)if isinstance(obj, ChartBase):rel = Relationship(type="chart", Target=obj.path)...elif isinstance(obj, Image):rel = Relationship(type="image", Target=obj.path)...anchors.append(anchor)self._rels.append(rel)

The problem is that your code

im = Image.open(r"C:/Users/Don/Pictures/resized Nyle.jpg")
...
ws2.add_image(im, 'A4')

passed in a 'PIL.PngImagePlugin.PngImageFile' type. It is not a ChartBase type or openpyxl's own Image type. So rel will never be initialized leading to the error that rel was used before being assigned something, leading to "local variable 'rel' referenced before assignment...".

If you check openpyxl / drawing / image, you might notice that openpyxl's Image is just a wrapper for PIL's Image. It needs a PIL.Image.Image object and internally calls PILImage.open(img) on the passed image object if it isn't one.

So you might think that converting img to openpyxl's Image might work.

import openpyxl as xl
from openpyxl import Workbook
from openpyxl.drawing.image import Image as XLImage
from PIL import Image as PILImageim = PILImage.open("my_input_image.png")
pil_img = im.resize((78, 100))
xl_img = XLImage(pil_img)wb2 = Workbook()
ws2 = wb2.active
ws2.add_image(xl_img, 'A1')
wb2.save(filename="output.xlsx")

That would solve the original error, but then you'll get a new error, "'Image' object has no attribute 'fp'", because openpyxl's Image module expects that the image object has a fp attribute, which is only available if the Image was created from a file (i.e. open(filename)).

So, the solution I can come up with is to:

  1. Create the image object as PIL Image
  2. Do image pre-processing (ex. resize)
  3. Save the pre-processed image back to a file
  4. Create the image object as openpyxl's image
  5. Add that image to the workbook
from openpyxl import Workbook
from openpyxl.drawing.image import Image as XLImage
from PIL import Image as PILImageim = PILImage.open("my_input_image.png")pil_img = im.resize((78, 100))
pil_img.save("my_resized_image.png")xl_img = XLImage("my_resized_image.png")wb2 = Workbook()
ws2 = wb2.active
ws2.add_image(xl_img, 'A1')
wb2.save(filename="output.xlsx")

If you don't need to do any image processing before adding the image, just open the file directly using openpyxl's Image class:

from openpyxl import Workbook
from openpyxl.drawing.image import Image as XLImagexl_img = XLImage("my_input_image.png")wb2 = Workbook()
ws2 = wb2.active
ws2.add_image(xl_img, 'A1')
wb2.save(filename="output.xlsx")
https://en.xdnf.cn/q/119889.html

Related Q&A

Passing a Decimal(str(value)) to a dictionary for raw value

Im needing to pass values to a dictionary as class decimal.Decimal, and the following keeps happening:from decimal import *transaction_amount = 100.03 transaction_amount = Decimal(str(transaction_amoun…

Delete regex matching part of file

I have a file ,and i need to delete the regex matching part and write remaining lines to a file.Regex matching Code to delete file:import re with open("in1.txt") as f:lines = f.read()m = re.f…

How do I download files from the web using the requests module?

Im trying to download a webpage data to samplefile.txt on my hard drive using the following code:import requests res = requests.get(http://www.gutenberg.org/cache/epub/1112/pg1112.txt) res.raise_for_s…

how to get queryset from django orm create

i want to get queryset as a return value when i use the create in django ormnewUserTitle = User_Title.objects.none() newUserTitle = newUserQuestTitle | newUserReviewTitle newUserTitle = newUserQues…

Count and calculation in a 2D array in Python

I have 47 set of data to be analysised using Python with the following forma t and I stored the data in 2D array:2104,3,399900 1600,3,329900 2400,3,369000...I use len function to print the item stored …

How to create tree structure from hierarchical data in Python?

Hi I am a bit new to Python and am a bit confused how to proceed. I have a large dataset that contains both parent and child information. For example, if we have various items and their components, and…

%conda install -c conda-forge prophet takes forever to install

Trying to install fb prophet but it takes so long, it has been running for both vscode editor for almost an hour conda install -c conda-forge prophet

How to Send 2D array through php cURL

Im working with a a distributed system where a php app sends a post request to a python app. My code is pretty straight forward:$ch = curl_init(); curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CU…

Internally, is asyncio run_forever() basically a while True loop?

python asyncio run_forever or while True is similar but it is a "should I do this..." question. I am more trying to understand if the internals of python asyncio is basically a while True:...…

How do I switch from python 2.6 to 2.7 by default

How do I switch from python 2.6 to 2.7 by defaultls -l /usr/bin/python* lrwxrwxrwx 1 root root 9 Jan 27 12:36 /usr/bin/python -> python2.6 lrwxrwxrwx 1 root root 9 Jan 27 12:36 /usr/bin/python…