Python & ActiveX/COM Autocad

Автор Тема: Python & ActiveX/COM Autocad  (Прочитано 10995 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 8418
  • Карма: 1020
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Python & ActiveX/COM Autocad
« Ответ #15 : 22-11-2017, 17:50:12 »
Electric,
Приветствую на форуме!
1. Прочитай у меня в подписи как следует форматировать код на форуме и придерживайся этого правила.
2. Ты нашёл неудачную документацию. Удачная здесь: https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2015/ENU/AutoCAD-ActiveX/files/GUID-35CC52D6-03C1-48EE-90A3-97DFBBAC33C3-htm.html
В частности там сказано, что rowTypes - это одно из значений перечисления (числовые значения я подставил сам):

Код - C++ [Выбрать]
  1. enum AcRowType
  2.     {
  3.         acUnknownRow    = 0,
  4.         acDataRow       = 1,
  5.         acTitleRow      = 2,
  6.         acHeaderRow     = 4
  7.     }   AcRowType;
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Electric

  • ADN OPEN
  • Сообщений: 21
  • Карма: 0
Re: Python & ActiveX/COM Autocad
« Ответ #16 : 22-11-2017, 19:05:34 »
Electric,
Приветствую на форуме!

Спасибо за ссылку, помогло!
Но остается проблема, я не могу понять, как реализовать на Пайтоне эту команду  из документации VBA:

Код - Visual Basic [Выбрать]
  1. customObj.SetTextHeight AcRowType.acDataRow + AcRowType.acTitleRow, 1.3

К примеру. у меня все работает, когда передаю "1" или "2" по отдельности , назначая моему табличному стилю newTabStyle высоту 2,5:

Код - Python [Выбрать]
  1. newTabStyle.SetTextHeight("2", 2.5)

 но как передать эти два значения сразу? При попытке передать их в виде списка или кортежа выдает ошибку, когда я передаю "1"+"2" - функция игнорирует  один из них.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 8418
  • Карма: 1020
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Python & ActiveX/COM Autocad
« Ответ #17 : 22-11-2017, 19:18:34 »
К примеру. у меня все работает, когда передаю "1" или "2" по отдельности , назначая моему табличному стилю newTabStyle высоту 2,5:

Код - Python [Выбрать]

    newTabStyle.SetTextHeight("2", 2.5)


 но как передать эти два значения сразу? При попытке передать их в виде списка или кортежа выдает ошибку, когда я передаю "1"+"2" - функция игнорирует  один из них.
Зачем их передавать сразу?
Вот так тебя не устроит:
Код - Python [Выбрать]
  1. newTabStyle.SetTextHeight(1, 2.5)
  2. newTabStyle.SetTextHeight(2, 2.5)

???

Хотя так тоже должно работать:
Код - Python [Выбрать]
  1. newTabStyle.SetTextHeight(3, 2.5)

Не понял зачем ты пытаешься преобразовать число в строку. Этот метод принимает целые числа, а не строки.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Electric

  • ADN OPEN
  • Сообщений: 21
  • Карма: 0
Re: Python & ActiveX/COM Autocad
« Ответ #18 : 27-11-2017, 05:45:31 »
Вот так тебя не устроит:

Да, спасибо. В тот раз мне это помогло, разобрался с той проблемой.
« Последнее редактирование: 27-11-2017, 06:39:25 от Electric »

Оффлайн Electric

  • ADN OPEN
  • Сообщений: 21
  • Карма: 0
Re: Python & ActiveX/COM Autocad
« Ответ #19 : 27-11-2017, 18:03:00 »
Возник следующий вопрос.
Пользователю нужно выделить какой-то объект в Автокаде, при этом в командной строке  должен отображаться текст вроде "Выделите прямоугольник"

Этот код работает:

Код - Python [Выбрать]
  1. example, _ = aDoc.Utility.GetEntity()

Но этот выдает уже ошибку:

Код - Python [Выбрать]
  1. example, _ = aDoc.Utility.GetEntity('Укажите прямоугольник: ')

Цитировать
example, _ = aDoc.Utility.GetEntity('Укажите объект: ')
  File "<COMObject <unknown>>", line 3, in GetEntity
  File "C:\ProgramData\Anaconda3\lib\site-packages\win32com\client\dynamic.py", line 287, in _ApplyTypes_
    result = self._oleobj_.InvokeTypes(*(dispid, LCID, wFlags, retType, argTypes) + args)
TypeError: The Python instance can not be converted to a COM object

Кроме того, допустим, пользователю нужно выделить не один, а сразу несколько объектов в Автокаде, через какую команду это реализуется? Если смотрю  в справке по AcadUtility, то там из методов  в основном только выделение единичного объекта или получение чисел, строк, углов и т.п.

Оффлайн Khasan MamaevАвтор темы

  • ADN Club
  • Сообщений: 44
  • Карма: 7
    • Конструктивный диалог
  • Skype: wolfram222
Re: Python & ActiveX/COM Autocad
« Ответ #20 : 27-11-2017, 18:09:55 »
Можно получить предварительно выбранные объекты вот так sset = AcDoc.PickfirstSelectionSet

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 8418
  • Карма: 1020
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Python & ActiveX/COM Autocad
« Ответ #21 : 27-11-2017, 18:16:19 »
Кроме того, допустим, пользователю нужно выделить не один, а сразу несколько объектов в Автокаде, через какую команду это реализуется?
SelectionSet.SelectOnScreen: https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2016/ENU/AutoCAD-ActiveX/files/GUID-C4B442A3-D6A9-48FA-8C86-03D49A3B2ED7-htm.html
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 8418
  • Карма: 1020
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Python & ActiveX/COM Autocad
« Ответ #22 : 27-11-2017, 18:45:03 »
Но этот выдает уже ошибку:

Код - Python [Выбрать]

    example, _ = aDoc.Utility.GetEntity('Укажите прямоугольник: ')
Я не специалист по Python, но может быть так:
Код - Python [Выбрать]
  1. returnObj = aDoc.Utility.GetEntity("Укажите прямоугольник: ")
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Electric

  • ADN OPEN
  • Сообщений: 21
  • Карма: 0
Re: Python & ActiveX/COM Autocad
« Ответ #23 : 27-11-2017, 19:16:58 »
Но этот выдает уже ошибку:

Код - Python [Выбрать]

    example, _ = aDoc.Utility.GetEntity('Укажите прямоугольник: ')
Я не специалист по Python, но может быть так:
Код - Python [Выбрать]
  1. returnObj = aDoc.Utility.GetEntity("Укажите прямоугольник: ")

Ну я так понимаю, aDoc.Utility.GetEntity  возвращает и Объект и  координату точки сразу.  Вместе  они с точки зрения Python  являются кортежем tuple, я просто выбирал объект как первую часть кортежа. Без этого выражения у меня ошибка.

Цитировать
AttributeError: 'tuple' object has no attribute 'Layer'

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 8418
  • Карма: 1020
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Python & ActiveX/COM Autocad
« Ответ #24 : 27-11-2017, 19:24:16 »
Так. Я был не прав:
Код - Visual Basic [Выбрать]
  1. object.GetEntity Object, PickedPoint [, Prompt]
Т.е. первые два параметра - это объект и точка и только третий - это подсказка типа "Укажите прямоугольник: "
https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2015/ENU/AutoCAD-ActiveX/files/GUID-69164FAA-F3C7-47A4-962C-5F4B2D5BC583-htm.html
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн dlobyntsev

  • ADN Club
  • Сообщений: 8
  • Карма: 4
Re: Python & ActiveX/COM Autocad
« Ответ #25 : 30-11-2017, 10:46:46 »
Для того, чтобы метод GetEntity корректно работал с подсказкой при обращении к COM Autocad через pywin32, необходимо вызвать его следующим образом:
Код - Python [Выбрать]
  1. result = aDoc.Utility.GetEntity(None, None, "Укажите прямоугольник: ")
  2. picked_object = result[0]
  3. picked_point = result[1]
Выглядит неочевидно, видимо из-за особенностей реализации вызовов в pywin32, но работает. Причем если вместо None подставить переменные, в них ничего не запишется.
Метод возвращает кортеж из объекта и координаты точки. Координаты точки также представляют собой трёхэлементный кортеж: (picked_object, (X, Y, Z))

Оффлайн Electric

  • ADN OPEN
  • Сообщений: 21
  • Карма: 0
Re: Python & ActiveX/COM Autocad
« Ответ #26 : 30-11-2017, 19:25:36 »
Спасибо. Разобрался.

Еще вопрос.
В автокаде во многих стандартных командах в командной строке есть возможность выбора опций.
К примеру, когда запускаем стандартное черчение прямоугольника, возникают опции  "Фаска", "Уровень", "Сопряжение", "Толщина", "Ширина", которые можно щелкнуть или набрать их ключевую букву с клавиатуры.

Возможно ли через COM  сделать подобного рода опции для своих текстовых команд?

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 767
  • Карма: 120
Re: Python & ActiveX/COM Autocad
« Ответ #27 : 30-11-2017, 22:48:36 »
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн dlobyntsev

  • ADN Club
  • Сообщений: 8
  • Карма: 4
Re: Python & ActiveX/COM Autocad
« Ответ #28 : 01-12-2017, 11:47:44 »
Опции для команд через COM, конечно, доступны. При использовании методов Utility.GetInteger, Utility.GetReal, GetString и т.п. достаточно сформировать строку запроса особым образом. Для автокада наличие в запросе текста вида [Опция1/<оПция2>/опЦия3] означает, что в запросе имеются три опции, причем вторая - опция по-умолчанию. Но, как всегда, дьявол кроется в деталях. И имя его в данном случае - обработка ошибок. Например, ввод опции при использовании Utility.GetReal вызывает ошибку, т.к. автокад ожидает ввода числа, а нажатие опции - это ввод строки. Необходимо этот случай предусмотреть и обработать. Делается это следующим образом:
Код - Python [Выбрать]
  1. from pythoncom import com_error
  2. #Инициируем ввод
  3. doc.Utility.InitializeUserInput(128)
  4. #Запрашиваем ввод числа с плавающей точкой
  5. try:
  6.     inputresult = doc.Utility.GetReal("\nВведите число [Опция1/оПция2]"
  7. except com_error as error:
  8.     #Получаем код COM ошибки
  9.     errnumber = error.excepinfo[-1]
  10.     if errnumber == -2145320928: #Была введена строка вместо числа
  11.         #Запрашиваем введённую строку
  12.         inputresult = doc.Utility.GetInput()
  13.         #Проверяем, соответствует ли введенная строка выбору опций
  14.         if inputresult.upper() == "О" or  inputresult.upper() == "ОПЦИЯ1":
  15.             #Код, выполняемый при выборе "Опция1"
  16.             pass
  17.         elif inputresult.upper() == "П" or  inputresult.upper() == "ОПЦИЯ2":
  18.              #Код, выполняемый при выборе "Опция2"
  19.             pass
  20.         else:
  21.             #Код, выполняемый при вводе любых других символов, кроме относящихся к опциям
  22.             #при наличии опции по умолчанию необходимо сопоставить ей ввод пустой строки ""
  23.             pass
  24.     elif errnumber == -2147352567: #Была нажата кнопка Ecs, обработка приведена для примера
  25.         #Код, выполняемый при нажатии Esc
  26.         pass
  27.     else:
  28.         #Код, выполняемый при любых других ошибках
  29.         pass
Я для себя просто написал функции на основе GetString, и преобразую потом введённое в int, float и т.д. уже средствами pyton, при этом внутри функций предусмотрел автоматический конструктор строки запроса для ввода опций, опций по-умолчанию и т.п., чтобы каждый раз не прописывать, с чем сравнивать введенную строку, чтобы понять, была ли выбрана опция.

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 767
  • Карма: 120
Re: Python & ActiveX/COM Autocad
« Ответ #29 : 01-12-2017, 13:11:54 »
Опции для команд через COM, конечно, доступны. При использовании методов Utility.GetInteger, Utility.GetReal, GetString и т.п. достаточно сформировать строку запроса особым образом. Для автокада наличие в запросе текста вида [Опция1/<оПция2>/опЦия3] означает, что в запросе имеются три опции, причем вторая - опция по-умолчанию.
Кто сказал? В лиспе, по крайней мере, это не так. И, насколько я помню, в .NET тоже не так.
Вообще-то вот из официальной справки по VBA:
Код - Text [Выбрать]
  1. Sub Example_InitializeUserInput()
  2.     ' This example prompts for user input of a point. By using the
  3.     ' InitializeUserInput method to define a keyword list, the example can also
  4.     ' return keywords entered by the user.
  5.    
  6.     AppActivate ThisDrawing.Application.Caption
  7.    
  8.     On Error Resume Next
  9.    
  10.     ' Define the valid keywords
  11.     Dim keywordList As String
  12.     keywordList = "Line Circle"
  13.    
  14.     ' Call InitializeUserInput to set up the keywords
  15.     ThisDrawing.Utility.InitializeUserInput 128, keywordList
  16.    
  17.     ' Get the user input
  18.     Dim returnPnt As Variant
  19.     returnPnt = ThisDrawing.Utility.GetPoint(, vbLf & "Enter a point [Line/Circle]: ")
  20.     If Err Then
  21.          If StrComp(Err.Description, "User input is a keyword", 1) = 0 Then
  22.          ' One of the keywords was entered
  23.              Dim inputString As String
  24.              Err.Clear
  25.              inputString = ThisDrawing.Utility.GetInput
  26.              MsgBox "You entered the keyword: " & inputString
  27.          Else
  28.              MsgBox "Error selecting the point: " & Err.Description
  29.              Err.Clear
  30.          End If
  31.     Else
  32.         ' Display point coordinates
  33.         MsgBox "The WCS of the point is: " & returnPnt(0) & ", " & returnPnt(1) & ", " & returnPnt(2), , "GetInput Example"
  34.     End If
  35.    
  36. End Sub
Обрати внимание на InitializeUserInput и его обработку.
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!