0

我在 Windows 7 下使用 JMP 9.0.3 64 位并从 Python 自动化它(编辑:我已经确认该错误同样可以通过 VBScript 自动化重现,并且仍然存在于 JMP 11.0.0 中)。我的自动化代码基于JMP 9 自动化指南。所有 JMP9 PDF 现在似乎都从网站上消失了

这个错误对我来说是一个相当大的障碍。我经常需要在自动化代码中操作表,然后用 JSL 代码交换表名,而这个错误使得无法可靠地做到这一点。有没有其他人遇到过?任何已知的修复或解决方法?

(我在 StackOverflow 上没有看到很多 JMP/JSL 问题,但我在这里发帖是因为有一些使用 JMP 的潜伏者。最初发布在 SAS 的 JMP 论坛上:https ://community.jmp.com /消息/213132#213132 )

问题

Document自动化对象具有属性NameFullNamePath,它们应该反映关联 JMP 表的表名或文件名。然而,在许多情况下,这些属性被证明是空白的,尽管表具有可以从 JSL 代码访问的非空名称,并且尽管事实上可以使用此名称检索表自动化对象。

演示代码

这是一些演示该错误的 Python 代码。它使用 JSL 创建一个表,保存该表的名称,并按名称查找该表的自动化对象。然后它检查是否table.Document.Name与表的已知名称匹配——它只是用来查找它!——并报告不成立的情况。它这样做了 100 次,通常名称在前 2-4 次迭代后开始变为空白:

from win32com.client import gencache
mod = gencache.GetModuleForProgID("JMP.Application")
app = mod.Application()

okay_table = [None]*100

for ii in range(len(okay_table)):
    # Create a table in JMP
    app.RunCommand("show(%d); ::dt=New Table(); ::retval=dt<<Get Name()" % ii)

    # Retrieve the name of that just-created table from the JSL variable
    retval = app.GetJSLValue("retval")

    # Retrieve the automation object for that table, by name
    table = app.GetTableHandleFromName(retval)

    # Now, table.Document.Name **SHOULD** match retval, but
    # it may be blank due to the bug.

    if not any((table.Document.Name, table.Document.Path, table.Document.FullName)):
        print "table %d: got blank table.Document.Name=%s, Path=%s, FullName=%s" % (ii,
            table.Document.Name, table.Document.Path, table.Document.FullName)
        app.RunCommand("close(DataTable(::retval), nosave)")
        okay_table[ii]=False
    else:
        print "table %d: looks okay; Name=%s, FullName=%s, Path=%s" % (ii,
            table.Document.Name, table.Document.FullName, table.Document.Path)
        app.RunCommand('close(DataTable("%s"), nosave)' % table.Document.Name)
        okay_table[ii]=True

print "Number of bad tables: %d" % okay_table.count(False)

典型输出:

table 0: looks okay; Name=Untitled 304, FullName=Untitled 304.jmp, Path=Untitled 304.jmp
table 1: looks okay; Name=Untitled 305, FullName=Untitled 305.jmp, Path=Untitled 305.jmp
table 2: got blank table.Document.Name=, Path=, FullName=
table 3: got blank table.Document.Name=, Path=, FullName=
table 4: got blank table.Document.Name=, Path=, FullName=
...
table 98: got blank table.Document.Name=, Path=, FullName=
table 99: got blank table.Document.Name=, Path=, FullName=
Number of bad tables: 98
4

1 回答 1

0

我想出了一个解决方法,但这是一个非常尴尬的解决方法。为了获得自动化表的名称,我现在这样做:

  1. 通过运行 JSL 代码获取列表中所有 JMP 表的名称。
  2. 用于app.GetJSLValue将此列表导入自动化应用程序。
  3. 逐个循环遍历名称列表,使用名称按名称查找自动化表对象app.GetTableHandleFromName
  4. 然后,我使用一个丑陋的组件将每个表的 OLE 对象标识与我的目标表的 OLE 对象标识进行比较。如果它们匹配,我会返回我用来查找它的名称。

我可怕的丑陋解决方法的代码:

def GetTableName(app, table):
    if table.Document.Name:
        return table.Document.Name
    else:
        # Get names of all JMP tables
        app.RunCommand("""
            NamesDefaultToHere(1);
            ::_retval={};
            for(ii=1, ii<=NTable(), ii++,
                InsertInto(::_retval, DataTable(ii)<<GetName())
            )""")
        tns = app.GetJSLValue("_retval")

        # See this thread for why == works here (http://thread.gmane.org/gmane.comp.python.windows/12977/focus=12978)
        for tn in tns:
            if table == self.app.GetTableHandleFromName(tn)
                return tn
        else:
            raise Exception
于 2014-09-29T16:31:49.853 回答