我试图与win32com.client进行更多的pythonic交互以供我自己使用,所以我可以做以下事情:
with Presentation(close=True) as P:
table = P[0].tables[0]
table.cells.Shape.TextFrame.TextRange.Text= 'hello'
我设法通过重载__getattr__
和__setattr__
来实现上述工作(非常满意)。
我希望将powerpoint表作为数组而不是线性对象进行交互,因此我创建了CellRange
对象
这是来自tables.py,它处理win32com.client表的数组视图。
from itertools import product
import numpy as np
from win32com.client import pywintypes
ALIGN_LABELS = 'bottom bottom_base middle top top_base mixed'.split()
ALIGN_LABELS_N = {k: i for i, k in enumerate(ALIGN_LABELS)}
class Win32Interface(object):
def __init__(self, win32_object):
super(Win32Interface, self).__setattr__('win32_object', win32_object)
def __setattr__(self, k, v):
setattr(self.win32_object, k, v)
def __getattr__(self, v):
return getattr(self.win32_object, v)
class Cell(Win32Interface):
def __repr__(self):
return self.Shape.TextFrame.TextRange.Text
@property
def text(self):
return self.Shape.TextFrame.TextRange.Text
@text.setter
def text(self, v):
setattr(self.Shape.TextFrame.TextRange, 'Text', v)
class CellRange(object):
def __init__(self, cell_array):
super(CellRange, self).__init__()
super(CellRange, self).__setattr__('cell_array', cell_array)
def _apply_map(self, f):
func = np.vectorize(f)
return func(self.cell_array)
def __getattr__(self, k):
try:
arr = self._apply_map(lambda x: getattr(x, k))
return CellRange(arr)
except (AttributeError, pywintypes.com_error):
return getattr(self.cell_array, k)
def __setattr__(self, k, v):
if hasattr(v, 'shape'):
assert self.shape == v.shape, 'mismatched shape'
for cell, value in zip(self.cell_array.ravel(), v.ravel()):
cell.__setattr__(k, value)
else:
self._apply_map(lambda x: setattr(x, k, v))
def __repr__(self):
return self.cell_array.__repr__()
暂时忽略Table对象,我想知道原因
cell_range = CellRange(cell_array)
cell_range.text = 'hello'
引发cannot be set
错误。上面调用__setattr__
然后调用_apply_map
来设置数组的每个元素,这会调用Cell.__setattr__
。为什么我可以print cell_range.text
而不是cell_range.text = 'hello'
?
答案 0 :(得分:0)
我发布后大约10分钟偶然发现了解决方案!
答案是使用Object
的{{1}}代替__setattr__
如此明显!
Win32Interface