【问题标题】:More precise image placement possible with openpyxl? (Pixel coordinates instead of cell coordinates?)使用 openpyxl 可以更精确地放置图像吗? (像素坐标而不是单元坐标?)
【发布时间】:2021-03-20 01:21:25
【问题描述】:

我试图在工作中复制和自动化一个很好用的做法:我试图在 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”。我还没有找到任何方法来获取(或转换)像素坐标。但如果我能做到这一点,那么我认为我可以将单元格内的图像和文本格式化为清晰/可接受(如果不漂亮)的水平。

openpyxl.drawing.imageopenpyxl.worksheet.worksheet 都没有我可以看到的绝对锚定方法。 openpyxl.drawing.spreadsheet_drawing 可以,但我不确定是否或如何使用它。

有没有办法做到这一点?还是我忽略了实现此目标的另一种方法?

【问题讨论】:

  • 您可以创建自己的锚点:OneCell、TwoCell 和 Absolute,但我认为绝对锚点仅用于 ChartSheets。
  • @stovfl 这篇文章涉及图像大小和尺寸,效果很好(img.height = blah),但图像的位置仍然只能精确到一个单元格。
  • @CharlieClark 有任何关于如何制作自己的锚的信息吗?这是我真正苦苦挣扎的地方。
  • 您最好查看 OOXML 规范,openpyxl 将允许您通过图像传递锚点。

标签: python openpyxl


【解决方案1】:

(编辑:这是使用 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

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

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

但这仍然很麻烦,因为我需要知道我想要放置的每张图像的绝对坐标......理想情况下,我仍然希望它锚定到一个单元格,但随后能够更精细地移动它一个细胞。那时我注意到 OneCellAnchor 有一个偏移量参数。这很完美,然后我用默认 excel 单元格的测量厘米高度和宽度制作了 lambda 函数。

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')

产生:

完美!正是我正在寻找的精度:)

【讨论】:

  • 很高兴你能解决这个问题。注意。单位总是特定于操作系统的,所以在一个系统上工作的东西可能在另一个系统上不起作用。而且,ws.add_image(img, anchor) 也是我的做法。请考虑提交对 openpyxl 文档的改进。
  • @Declan :我感激不尽。对于那些只想在工作表右上角对齐图像的人:link
  • 这一定是糟糕设计的缩影。为什么他们对用户隐藏所有这些功能?他们为什么不把它封装成有用的东西呢?为什么看起来他们确实更早地这样做了然后被砍掉了?(看here)。那么,如果xlsxwriter 中存在这个基本功能,为什么还要打扰openpyxl
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 2021-05-31
  • 1970-01-01
  • 2013-09-26
  • 1970-01-01
  • 1970-01-01
  • 2017-10-24
相关资源
最近更新 更多