Python win32com 和二维数组

3

当使用Python和win32com自动化Adobe软件表单时,会遇到传递二维坐标数组的问题。如果查看Adobe提供给Visual Basic(VB)的代码,它很简单。在Illustrator中绘制一条线的简化示例如下:

Set appObj = CreateObject("Illustrator.Application")
Set docObj = appObj.Documents.Add

Set pathItem = docObj.PathItems.Add
    pathItem.SetEntirePath Array(Array(0.0, 0.0), Array(20.0, 20.0))

现在一个天真的想法是,VB代码可以通过以下方式转换为Python代码:
from win32com.client import Dispatch

appObj = Dispatch("Illustrator.Application")  
docObj = appObj.Documents.Add()

pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( [ [0.0,0.0], [20.0,20.0] ] )

显然,这并不容易,Python会发出错误提示:“仅支持维度为1的数组”。现在我知道,数组和二维数组之间有区别。那么问题是如何强制Python生成正确类型的数组?
我试图创建自己的VARIANT类型,但失败了。我也看过ctypes。有人遇到过同样的问题吗?能否提供一些帮助?
PS:
我知道可以通过使用以下方法规避该问题:
pathItem = docObj.PathItems.Add()
for point in (  [0.0,0.0], [20.0,20.0] ):
    pp = pathItem.PathPoints.Add() 
    pp.Anchor = point

但是有类似的情况,实际上这并不起作用。无论如何,重点是向学生撰写移植指南,因此尽可能接近原始意图会更好。

2个回答

9

这里有一个替代方案,它实际上使用了win32com模块。事实上,IllustratorPhotoshop的数组类型都是单一的变体类型数组,其中变体类型也是一个数组。还有其他应用程序,如solidworks,也使用相同的策略。您可以使用以下代码强制win32com生成变体类型:

from win32com.client import VARIANT
from pythoncom import VT_VARIANT

def variant(data):
    return VARIANT(VT_VARIANT, data)

如果不需要在代码中到处输入变量类型,那么使用Python数组并将每个子元素变为variant会更加方便:

import collections

def vararr(*data):
    if (  len(data) == 1 and 
          isinstance(data, collections.Iterable) ):
        data = data[0]
    return map(variant, data)

所以,最终我的完整代码如下:

from win32com.client import Dispatch, VARIANT
from pythoncom import VT_VARIANT
import collections


appObj = Dispatch("Illustrator.Application")  
docObj = appObj.Documents.Add()

def variant(data):
    return VARIANT(VT_VARIANT, data)

def vararr(*data):
    if (  len(data) == 1 and 
          isinstance(data, collections.Iterable) ):
        data = data[0]
    return map(variant, data)

pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( vararr( [0.0,0.0], [20.0,20.0] )  )

#or you can have a iterable of iterables
pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( vararr( [[30.0,10.0], [60.0,60.0]] )  )

是的,这可以通过comtypes实现,但这回答了我的真正问题,即如何在win32com中实现此操作。此外,使用win32com的原因有很多,例如能够生成常量。经过长时间的探索,我终于找到了一个真正困扰我的问题的答案。希望这能帮助到某些人。


2
当我尝试使用win32com确定选择区域时,我遇到了相同的问题。我发现使用comtypes而不是win32com来访问Photoshop可以完全解决多维数组问题。

我认为一维数组问题是win32com的限制,但我可能错误。

您可以在http://sourceforge.net/projects/comtypes/上获取comtypes。

Tech Artists Org上有一篇关于此问题的文章值得一读。

以下是从技术艺术家论坛帖子中链接的示例,使用comtypes传递数组。路径点的实现应该类似。

import comtypes.client
ps_app = comtypes.client.CreateObject('Photoshop.Application') 
# makes a new 128x128 image
ps_app.Documents.Add(128, 128, 72)

# select 10x10 pixels in the upper left corner
sel_area = ((0, 0), (10, 0), (10, 10), (0, 10), (0, 0))
ps_app.ActiveDocument.Selection.Select(sel_area)

没错,那个方法可行,只是我更喜欢使用win32com,因为这是默认安装在这些电脑上的。唉,我想又要和IT部门谈判一个月了。 - joojaa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接