Добавление нового свойства детали

Автор ТрындецЪ, 02.11.17, 16:08:59

« назад - далее »

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

ТрындецЪ

Как на Python добавить новое свойство для текущей детали?
Не пойму, какой второй аргумент ( VT_EMPY) нужно передать методу AddProperty, чтобы свойство создалось.

iProperty = propMng.AddProperty(doc, ???)

ЦитироватьLPDISPATCH AddProperty( VARIANT libname, VARIANT val );
Синтаксис COM:
HRESULT AddProperty( VARIANT Libname, VARIANT Val, IProperty ** ColVal );

Входные параметры:
Libname ( VARIANT)
- полный путь к библиотеке на диске VT_BSTR, либо указатель на документ VT_DISPATCH. Теку­щий документ - VT_EMPTY,
val( VARIANT)
- новое свойство VT_EMPY, создать по прототипу другого свойства - VT_DISPATCH.

Возвращаемое значение:
- Указатель на интерфейс свойства IProperty.


Slaviation


ТрындецЪ

Цитата: Slaviation от 03.11.17, 07:04:01
С None не работает?
Не работает.

Только если подсунуть свойство-прототип, тогда создаётся.

# -*- coding: utf-8 -*-

import pythoncom
from win32com.client import Dispatch, gencache

def getKompasApi():
    module =  gencache.EnsureModule("{69AC2981-37C0-4379-84FD-5DD2F3C0A520}", 0, 1, 0)
    api = module.IKompasAPIObject(Dispatch("Kompas.Application.7")._oleobj_.QueryInterface(module.IKompasAPIObject.CLSID, pythoncom.IID_IDispatch))
    const = gencache.EnsureModule("{2CAF168C-7961-4B90-9DA2-701419BEEFE3}", 0, 1, 0)
    return module, api, const.constants

module, api, const =  getKompasApi()
app = api.Application
doc = app.ActiveDocument
doc3D = module.IKompasDocument3D(doc._oleobj_.QueryInterface(module.IKompasDocument3D.CLSID, pythoncom.IID_IDispatch))
part = doc3D.TopPart

# Интерфейс Менеджера свойств
propMng = module.IPropertyMng(app._oleobj_.QueryInterface(module.IPropertyMng.CLSID, pythoncom.IID_IDispatch))
# Интерфейс получения/редактирования значения свойств
propKeeper = module.IPropertyKeeper(part._oleobj_.QueryInterface(module.IPropertyKeeper.CLSID, pythoncom.IID_IDispatch))

# Свойство-прототип "Материал"
iProperty_0 = propMng.GetProperty(doc, 3)

# Добавить новое свойство
iProperty = propMng.AddProperty(doc, iProperty_0)

iProperty.ReadOnly = True
iProperty.Name = u"Новое свойство"
iProperty.Update()

propKeeper.SetPropertyValue( iProperty, u"Значение", True )
res, value, fromSource = propKeeper.GetPropertyValue(iProperty, "", True, True)
part.Update()
print iProperty.Name, value
+ Благодарностей: 1

ТрындецЪ

15.11.17, 14:26:14 #3 Последнее редактирование: 15.11.17, 19:19:21 от ТрындецЪ
Неужели никто из форумчан не добавлял свойства моделям?!
Если действовать, предложенным выше мною методом, то создаваемое свойство подменяет свойство-прототип. И получается, что свойство не создалось, а произошло обращение к уже имеющемуся.
Подозреваю, что это из-за невозможности редактирования уникального номера свойства iProperty.Id. Видимо, по этому номеру КОМПАС определяет, что это за свойство и в каких местах документа на него ссылаться.

Upd: Почитав справку, понял для себя следующее:
В модель можно добавить только свойство, которое заранее было создано в какой-нибудь библиотеке свойств. И уже после этого можно вызывать это свойство по ID и менять.

Slaviation

ЦитироватьВ модель можно добавить только свойство, которое заранее было создано в какой-нибудь библиотеке свойств.

Следующий фрагмент кода на C++ работает, новое свойство создается.

IPropertyPtr newDocProp(NULL);

VARIANTARG libName;
VariantInit(&libName);
libName.vt = VT_EMPTY;

VARIANT newProp;
VariantInit(&newProp);
newProp.vt = VT_EMPTY;

newDocProp = IPropertyPtr(propMng->AddProperty(libName, newProp)); //Создай новое свойство
newDocProp->Name = _bstr_t("my name")
newDocProp->Update();
+ Благодарностей: 1

ТрындецЪ

Цитата: Slaviation от 16.11.17, 09:40:47
Следующий фрагмент кода на C++ работает, новое свойство создается.
Мне сложно в Python это перевести.
Можете логику описать?
Тут libName это ссылка на реальную библиотеку или на пустую структуру? newProp тоже ссылка на пустую структуру?
Я пробовал свойству присваивать pythoncom.VT_EMPY, но значение становятся равно "0". Попробую ещё это для библиотеки.

Slaviation

libName и newProp заряжаются в AddProperty именно пустыми.
Предполагаю есть ошибка в API7 в части реализации для некоторых языков (в том числе и для Python).
+ Благодарностей: 1

333

import pythoncom
from win32com.client import Dispatch, gencache, VARIANT
...
emptyVal = VARIANT(pythoncom.VT_EMPTY, None)
property = property_mng.AddProperty(emptyVal , emptyVal)
+ Благодарностей: 3

ТрындецЪ

Цитата: 333 от 16.11.17, 12:11:33
import pythoncom
from win32com.client import Dispatch, gencache, VARIANT
...
emptyVal = VARIANT(pythoncom.VT_EMPTY, None)
property = property_mng.AddProperty(emptyVal , emptyVal)
Я нагугливал что-то подобное, но мой   win32com.client говорит, что у него нет функции VARIANT.
ЦитироватьImportError: cannot import name VARIANT

333


333

# A very simple VARIANT class.  Only to be used with poorly-implemented COM
# objects.  If an object accepts an arg which is a simple "VARIANT", but still
# is very pickly about the actual variant type (eg, isn't happy with a VT_I4,
# which it would get from a Python integer), you can use this to force a
# particular VT.
class VARIANT(object):
  def __init__(self, vt, value):
    self.varianttype = vt
    self._value = value

  # 'value' is a property so when set by pythoncom it gets any magic wrapping
  # which normally happens for result objects
  def _get_value(self):
    return self._value
  def _set_value(self, newval):
    self._value = _get_good_object_(newval)
  def _del_value(self):
    del self._value
  value = property(_get_value, _set_value, _del_value)

  def __repr__(self):
    return "win32com.client.VARIANT(%r, %r)" % (self.varianttype, self._value)

333

+ Благодарностей: 1

ТрындецЪ

Заработало!
Я обновил себе pywin32. Скачал вот это: pywin32-220.win32-py2.6.exe
После VARIANT появился и

emptyVal = VARIANT(pythoncom.VT_EMPTY, None)
property = property_mng.AddProperty(emptyVal , emptyVal)

создало новое свойство.

Всем спасибо! От меня  + в репу. (для Slaviation после истечения временного ограничения :) )

Upd: с pythoncom.Empty я пробовал, но не прокатило.

Slaviation

Проверил такой код, работает. Python 3.6.2
Спасибо 333 !!!!

import pythoncom
from win32com.client import Dispatch, gencache,  VARIANT
kompas_api7_module = gencache.EnsureModule("{69AC2981-37C0-4379-84FD-5DD2F3C0A520}", 0, 1, 0)
kompas_api_object = kompas_api7_module.IKompasAPIObject(Dispatch("Kompas.Application.7")._oleobj_.QueryInterface(kompas_api7_module.IKompasAPIObject.CLSID, pythoncom.IID_IDispatch))
application = kompas_api_object.Application
kompas_document = application.ActiveDocument
document_3d = kompas_api7_module.IKompasDocument3D(kompas_document)
top_part = document_3d.TopPart
property_keeper = kompas_api7_module.IPropertyKeeper(top_part)
property_mng = kompas_api7_module.IPropertyMng(application)
empty_val = VARIANT(pythoncom.VT_EMPTY, None)
new_property = property_mng.AddProperty(empty_val , empty_val)
new_property.Name = u"Новое свойство"
new_property.Update()
property_keeper.SetPropertyValue(new_property, u"Значение", True)
+ Благодарностей: 2

ТрындецЪ

Единственное, что плохо, так это то, что у свойств созданных в разных деталях будет разный Id. Не знаю, можно ли будет потом отчёты по таким свойствам создавать.

333

Для того чтобы свойство было с одинаковым id нужно использовать библиотеку типов

ТрындецЪ

Цитата: 333 от 16.11.17, 13:11:24
Для того чтобы свойство было с одинаковым id нужно использовать библиотеку типов
Имеется в  виду библиотека свойств, например, properties.lpt? Или я чего-то ещё не знаю?

333


333

Потом в property_mng.AddProperty передавать указатель на интерфейс типа свойства полученного из библиотеки типов свойств
Описание свойства будет скопировано в документ
+ Благодарностей: 3

ТрындецЪ

Цитата: 333 от 16.11.17, 13:24:21
Потом в property_mng.AddProperty передавать указатель на интерфейс типа свойства полученного из библиотеки типов свойств
Описание свойства будет скопировано в документ
Вот к такому решению я вчера и пришёл, но создание свойства "на лету" тоже может пригодиться.