2014-09-26 3 views
0

Я использую JMP 9.0.3 64-бит под Windows 7 и автоматизирую его из Python (EDIT: Я подтвердил, что ошибка может быть воспроизведена с автоматизацией VBScript и все еще существует в JMP 11.0.0) , Мой код автоматизации основан на JMP 9 Automation Guide. Все JMP9 PDFs seem now to have disappeared from the website.Ошибка автоматизации JMP 9 - обходные пути?

Эта ошибка становится для меня прекрасной пробкой. Мне довольно часто приходится манипулировать таблицами в коде автоматизации, а затем обмениваться именами таблиц с JSL-кодом, и эта ошибка делает невозможным сделать это надежно. Кто-нибудь еще столкнулся с этим? Любые известные исправления или обходные пути?

(я не видел много вопросов JMP/JSL на StackOverflow, но я отправляю здесь на авось, что есть некоторые JMP-с использованием таится Первоначально опубликован на JMP форуме SAS в:. https://community.jmp.com/message/213132#213132)

проблема

Document объект автоматизации имеет свойства Name, FullName и Path, которые должны отражать имя таблицы или имя файла из соответствующей таблицы 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 

ответ

0

Я придумал обходной путь, но это мучительно неудобный. Чтобы получить название таблицы автоматизации, я теперь делаю это:

  1. Получите имена всех JMP-таблиц в списке, запустив JSL-код.
  2. Используйте app.GetJSLValue, чтобы получить этот список в автоматизирующем приложении.
  3. Loop по списку имен один за другим, глядя табличные объекты автоматизации по имени, используя app.GetTableHandleFromName
  4. Я тогда use an ugly kludge to compare the OLE object identity of each table к объекту идентичности 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