Attach attribute to existing element [Solved]


Hello all,

I have been trying to create attributes and wanted to attach them to some library elements. To do that, I created following method:

def loadLibaryElementFromEtcLibrary(path: str):
    path = os.path.join(AllplanSettings.AllplanPaths.GetEtcPath() + "Library\\", path)
    print(path)
    if not os.path.exists(path):
        print(f"The path '{path}' is not valid or does not exist.")
        return
    library_element_properties = \
    AllplanBasisElements.LibraryElementProperties(fullPathName=      path,
                                                  elementType=       getElementType(path),
                                                  placementMatrix=   AllplanGeo.Matrix3D())

This returns me a library element, which works just fine. Also, I am creating an attribute like this:

    def createAttribute(cls, doc: AllplanEleAdapter.DocumentAdapter,
                        attribute_name: str,
                        default_value: str,
                        dimension: str,
                        attr_type: AllplanBaseElements.AttributeService.AttributeType,
                        attr_control_type: AllplanBaseElements.AttributeService.AttributeControlType,
                        min_value: float = 0.0,
                        max_value: float = 0.0,
                        list_values=AllplanUtil.VecStringList()):
        """
        returns true, if the attribute is new, false if there is an attribute with the same name already
        additionally returns the id of the attribute
        """
        existing_id = AttributeHandler.getAttributeId(doc, attribute_name)
        if(existing_id != -1):
             LogHandler.log(Severity.INFORMATION, "Attribute already exists")
             return False, existing_id
        id = AllplanBaseElements.AttributeService.AddUserAttribute(
            doc,
            attr_type,
            attribute_name,
            default_value,
            min_value,
            max_value,
            dimension,
            attr_control_type,
            list_values
        )
        if(id == -1):
            LogHandler.log(Severity.ERROR, "The attribute could not be created!")
        else:
            LogHandler.log(Severity.INFORMATION, "Attribute creation was successful")
        return True, id

Now I have my attribute id and an element. I wanted to add the attribute to the library element using the AllplanBaseElements.ElementsAttributeService.ChangeAttribute(...) method, but it does not take a library element object as parameter, so of course this does not work. Then I tried setting an existing attribute, but this also does not work:

        libarary_element = LibraryElements.loadLibaryElementFromEtcLibrary(path)
        description_attr = BaseElements.AttributeString(507, "Neue Bezeichnung")
        attr_set = BaseElements.AttributeSet([description_attr])
        attributes = BaseElements.Attributes([attr_set])
        libarary_element.SetAttributes(attributes)
        attributes = libarary_element.GetAttributes()

... but nothing happens, the attribute is not set or anything. The attributes list from the library is also always empty at the beginning (after adding the attribute it does have the entry) and no error is thrown. The log file from allplan also does not show anything...

Help is very much appreciated!

Show solution Hide solution

LibraryElemets are "read-only" and have no attributes, because the are not really ModelElements. You can change anything after placing them to the model or make a ModelElement from it.

LibraryElemets are "read-only" and have no attributes, because the are not really ModelElements. You can change anything after placing them to the model or make a ModelElement from it.

Okay, thanks, that is good to know.
But if the library elements have no attributes and nobody can change them, why are there the methods available to read and write attributes?

..a very good question! I don't know. Ask Allplan...

Hi Melanie,

Library element is a representation of anything, that can be get from the Allplan's library: symbol, smart symbol, fixture, etc. It inherits from the abstract base class

AllplanElement
, that is why you can call the
SetAttribute
method. But the method does not do anything because, as Nemo says, these elements are read only. They are meant to be created in the DF using CreateElements. The inheritance is there to indicate just that. This is not perfect in this case, I admit. But there are no perfect software architectures.

In your case you must create the elements first and assign the attributes in the second step with ElementsAttributeService.

Best,
Bart