Возможно ли более точное размещение изображений с помощью openpyxl? (Пиксельные координаты вместо координат ячейки?) - PullRequest
1 голос
/ 23 марта 2019

Я пытаюсь воспроизвести и автоматизировать хорошо используемую практику в работе: я пытаюсь поместить несколько изображений и текста в ячейку в openpyxl, однако я могу привязать изображения только к верхнему левому углу ячейки и иметь не нашел способ позиционировать более точно, чем это. Таким образом, они перекрываются друг с другом и текстом.

from openpyxl import Workbook
from openpyxl.drawing.image import Image

wb = Workbook()
ws = wb.active
img = Image('image.png')
ws.add_image(img, 'B2') # img.anchor is now 'B2'
wb.save('test.xlsx')

В вышеприведенном случае «B2». Я еще не нашел способа получить (или преобразовать) пиксельные координаты. Но если бы я мог сделать это, то я думаю, что тогда я мог бы отформатировать изображения и текст в ячейках до разборчивого / приемлемого (если не симпатичного) уровня.

Mock example of eventual desired output

Ни openpyxl.drawing.image , ни openpyxl.worksheet.worksheet не имеют метода абсолютной привязки, который я вижу. openpyxl.drawing.spreadsheet_drawing делает, но я не уверен, использовать его или как.

Есть ли способ сделать это? Или есть другой способ, которым я упускаю из виду достижение этой цели?

1 Ответ

2 голосов
/ 26 марта 2019

(Изменить: это было с Python 3.7 и openpyxl 2.6.1)

Итак, я открыл переименованный выходной файл Excel в zip-файл и обнаружил там «Drawing1.xml», где я мог видеть, что он использует OneCellAnchor. Поэтому, следуя совету Чарли, я углубился в код openpyxl и обнаружил, что есть класс AbsoluteAnchor, который я могу использовать. Чтобы установить позиции, мне нужно было импортировать координаты XDR, а затем из utils.units некоторые функции преобразования из пикселя / см в EMU (единицы измерения Excel?). Затем я просто установил привязку изображения к абсолюту и дал положение и «ext» (размеры).

from openpyxl import Workbook
from openpyxl.drawing.image import Image
from openpyxl.drawing.spreadsheet_drawing import AbsoluteAnchor
from openpyxl.drawing.xdr import XDRPoint2D, XDRPositiveSize2D
from openpyxl.utils.units import pixels_to_EMU, cm_to_EMU

wb = Workbook()
ws = wb.active
img = Image('image.png')

p2e = pixels_to_EMU

h, w = img.height, img.width

positie = XDRPoint2D(p2e(500), p2e(500))
size = XDRPositiveSize2D(p2e(h), p2e(w))

img.anchor = AbsoluteAnchor(pos=position, ext=size)
ws.add_image(img) 
wb.save('test.xlsx')

Но это все равно будет проблематично, так как мне нужно будет знать абсолютные координаты для КАЖДОГО изображения, которое я хочу разместить ... в идеале, я все еще хочу привязать его к ячейке, но затем иметь возможность более точно перемещать его внутри клетка. Именно тогда я заметил, что OneCellAnchor имеет аргумент смещения. Это было прекрасно, тогда я сделал лямбда-функции с измеренной сантиметровой высотой и шириной стандартных ячеек Excel.

from openpyxl.drawing.spreadsheet_drawing import OneCellAnchor, AnchorMarker

c2e = cm_to_EMU

# Calculated number of cells width or height from cm into EMUs
cellh = lambda x: c2e((x * 49.77)/99)
cellw = lambda x: c2e((x * (18.65-1.71))/10)

# Want to place image in row 5 (6 in excel), column 2 (C in excel)
# Also offset by half a column.
column = 2
coloffset = cellw(0.5)
row = 5
rowoffset = cellh(0.5)

marker = AnchorMarker(col=column, colOff=coloffset, row=row, rowOff=rowoffset)
img.anchor = OneCellAnchor(_from=marker, ext=size)
ws.add_image(img) 
wb.save('test.xlsx')

Который производит:

enter image description here

Отлично! Именно точность, которую я искал:)

...