使用 openpyxl 可以更精确地放置图像吗?(像素坐标而不是单元坐标?)

Dec*_*lan 2 python openpyxl

我试图在工作中复制和自动化一个很好用的实践:我试图在 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')
Run Code Online (Sandbox Code Playgroud)

在上述情况下'B2'。我还没有找到任何方法让它采用(或从)像素坐标转换。但是,如果我能做到这一点,那么我想我可以将单元格中的图像和文本格式化为清晰/可接受(如果不是很漂亮)的级别。

最终所需输出的模拟示例

无论openpyxl.drawing.image也不openpyxl.worksheet.worksheet有绝对式锚的方法,我可以看到。openpyxl.drawing.spreadsheet_drawing确实如此,但我不确定是否或如何使用它。

有没有办法做到这一点?或者我是否有另一种方式来实现这个目标?

Dec*_*lan 10

(编辑:这是使用 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')
Run Code Online (Sandbox Code Playgroud)

但这仍然很麻烦,因为我需要知道我想要放置的每个图像的绝对坐标......理想情况下,我仍然希望它锚定到一个单元格,但随后能够在一个单元格内更精细地移动它。那时我注意到 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')
Run Code Online (Sandbox Code Playgroud)

其中产生:

在此处输入图片说明

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

  • @Declan:我非常感谢你。对于那些只想在工作表右上角对齐图像的人:[链接](https://gist.github.com/clementlefevre/030ccbd8a936c812a9d510134cf6c6bf) (2认同)
  • 这一定是糟糕设计的缩影。为什么他们向用户隐藏所有这些功能?他们为什么不将其封装成有用的东西呢?为什么看起来**他们确实早些时候这样做了然后被砍掉了?**(查看[此处](https://openpyxl.readthedocs.io/en/2.1/usage.html#inserting-an-image))。那么,如果“xlsxwriter”中存在这个基本功能,为什么还要费心使用“openpyxl”呢? (2认同)