简体   繁体   English

JMP 9自动化错误-解决方法?

[英]JMP 9 automation bug — workarounds?

I'm using JMP 9.0.3 64-bit under Windows 7 and automating it from Python ( EDIT : I've confirmed that the bug can equally be reproduced with VBScript automation, and still exists in JMP 11.0.0). 我正在Windows 7下使用64位JMP 9.0.3并从Python对其进行自动化( 编辑 :我已经确认该错误可以通过VBScript自动化同样地重现,并且仍然存在于JMP 11.0.0中)。 My automation code is based on the JMP 9 Automation Guide . 我的自动化代码基于《 JMP 9自动化指南》 All the JMP9 PDFs seem now to have disappeared from the website . 现在似乎所有JMP9 PDF都已从网站上消失了

This bug is becoming quite a show-stopper for me. 对于我来说,此错误已成为相当大的麻烦。 I quite frequently need to manipulate tables in automation code and then exchange the table names with JSL code, and this bug makes it impossible to do so reliably. 我经常需要用自动化代码操作表,然后用JSL代码交换表名,而该错误使可靠地做到这一点是不可能的。 Has anyone else encountered it? 还有其他人遇到吗? Any known fixes or workarounds? 任何已知的修复程序或解决方法?

(I haven't seen many JMP/JSL questions on StackOverflow, but I'm posting here on the off-chance that there are some JMP-using lurkers. Originally posted on SAS's JMP forum: https://community.jmp.com/message/213132#213132 ) (我在StackOverflow上没有看到很多JMP / JSL问题,但是我在这里偶然发布了一些使用JMP的潜伏者。最初发布在SAS的JMP论坛上: https : //community.jmp.com / message / 213132#213132

The problem 问题

the Document automation object has properties Name , FullName , and Path which are supposed to reflect the table name or file name of the associated JMP table. Document自动化对象具有NameFullNamePath属性,这些属性应该反映相关JMP表的表名或文件名。 However, in many cases these properties turn out to be blank, despite the table having a non-blank name which can be accessed from JSL code, and despite the fact that the table automation object can in fact be retrieved using this name. 但是,在许多情况下,尽管表具有可以从JSL代码访问的非空白名称, 并且尽管事实上可以使用该名称来检索表自动化对象,但是这些属性仍然是空白的。

Demo code 演示代码

Here's some Python code that demonstrates the bug. 这是一些演示该错误的Python代码。 It creates a table using JSL, saves the name of this table, and looks up the table's automation object by name. 它使用JSL创建一个表,保存该表的名称,并按名称查找该表的自动化对象。 It then checks whether table.Document.Name matches the known name of the table--which was just used to look it up!--and reports the cases where this doesn't hold. 然后,它检查table.Document.Name是否匹配表的已知名称(该表只是用来查找它的!),并报告不成立的情况。 It does this 100 times and typically the name starts coming back blank after the first 2-4 iterations: 它执行了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)

Typical output: 典型输出:

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

I've come up with a workaround, but it's an excruciatingly awkward one. 我想出了一种解决方法,但这是一个非常尴尬的方法。 In order to get the name of an automation table, I now do this: 为了获得自动化表的名称,我现在执行以下操作:

  1. Get names of all JMP tables in a list by running JSL code. 通过运行JSL代码获取列表中所有JMP表的名称。
  2. Use app.GetJSLValue to get this list into the automating application. 使用app.GetJSLValue将此列表添加到自动化应用程序中。
  3. Loop through the list of names one-by-one, looking up automation table objects by name using app.GetTableHandleFromName 遍历名称列表,使用app.GetTableHandleFromName按名称查找自动化表对象
  4. I then use an ugly kludge to compare the OLE object identity of each table to the OLE object identity of my target table. 然后,我 使用一个丑陋的代码 将每个表的OLE对象标识与目标表的OLE对象标识进行比较。 If they match, I return the name which I used to look it up. 如果它们匹配,我将返回用于查找的名称。

Code for my horrible ugly workaround: 我可怕的变通方法代码:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM