Hi,
I am a bit late with the reply so I probably won't help the OP, but for everyone having a look here here's the explanation of the problem (yes, I got some help from AI ):
Overview
The AEC API uses an Element Adapter Pattern to handle the retrieval of existing elements from active documents. This pattern creates a clear separation between the unified interface for accessing elements and the specific object types used for creation.
Key Concepts
1. Two Different Contexts: Creation vs. Retrieval
Creation Context:
- You work directly with specific object types (WallElement , BarPlacement , etc.)
- You instantiate these objects and pass them to PythonPartsTransaction.execute() (in an interactor) or to CreateElementResult (in a script object)
- Simple and straightforward
Retrieval Context:
- You work with BaseElementAdapter objects
- All existing elements are initially (directly after the selection is completed by the user) represented as adapters
- Requires conversion to access type-specific properties
2. The BaseElementAdapter - Universal Interface
When you retrieve elements from a document, you get BaseElementAdapter instances that provide:
# Common properties available for ALL element types
element.GetDisplayName() # Name of the element
element.GetDrawingfileNumber() # Drawing file location
element.GetElementAdapterType() # Type information
element.GetElementUUID() # Unique identifier
element.Is3DElement() # Dimensionality check
element.GetCommonProperties() # Pen, color, stroke, etc.
element.GetAttributes() # Custom attributes
element.GetGeometry() # Basic geometry
3. The Conversion Challenge
To access type-specific properties (e.g., wall thickness, reinforcement diameter), you must convert the adapter:
# This is the critical conversion step
api_object = AllplanBaseEle.GetElement(element_adapter) if api_object: # Now you have the specific object type (Wall, Line, etc.) # Can access type-specific properties print(f"Converted to: {type(api_object).__name__}")
else: # Conversion failed - GetElement returned None print("Cannot convert this adapter to a specific API object")
❌ Wrong Assumption:
"If I created a WallElement object, then existing walls will also be WallElement objects when I retrieve them."
✅ Reality:
1. Creation: You work with WallElement objects directly
2. Retrieval: You get BaseElementAdapter objects first
3. Conversion: You must explicitly convert to get the WallElement object back
So why this pattern exists?
Benefits:
1. Unified Interface: All elements can be handled uniformly through BaseElementAdapter
2. Performance: Lazy loading - only convert when you need specific properties
3. Flexibility: Can handle any element type without knowing its specific type upfront
4. Safety: Graceful handling when conversion isn't possible
Trade-offs:
1. Complexity: Developers must understand the two-step process
2. Null Handling: Must check if conversion succeeds
3. Documentation: Requires clear explanation of the pattern
Practical Workflow
def handle_document_elements(): # Step 1: Get adapters from document (all elements as BaseElementAdapter) adapters = AllplanBaseEle.ElementsSelectService.SelectAllElements() for adapter in adapters: # Step 2: Access common properties directly print(f"Element: {adapter.GetDisplayName()}") print(f"Type: {adapter.GetElementAdapterType().GetTypeName()}") # Step 3: Convert to specific type for detailed access specific_object = AllplanBaseEle.GetElement(adapter) if specific_object: # Step 4: Now work with the specific object type if isinstance(specific_object, WallElement): print(f"Wall thickness: {specific_object.thickness}") elif isinstance(specific_object, ReinforcementBar): print(f"Bar diameter: {specific_object.diameter}") else: print("This element type cannot be converted to a specific API object") # not all elements can be retrieved!
Key Takeaways
1. Remember the Context Switch: Creation uses direct objects, retrieval uses adapters
2. Always Convert When Needed: Use GetElement() to access type-specific properties
3. Handle Conversion Failures: Not all adapters can be converted to specific objects
4. Leverage Common Properties: Use BaseElementAdapter for operations that don't need type-specific data
5. Think Lazy Loading: Only convert when you actually need the specific object properties
This pattern ensures consistency, performance, and flexibility while requiring developers to understand the adapter-to-object conversion step for accessing detailed, type-specific information.
Cheers,
Bart