import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitServices')
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.DB import *
from Autodesk.Revit.UI.Selection import ObjectType
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
import System
schemaId = System.Guid(" ADD A GUID HERE ... ")
try:
doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
TransactionManager.Instance.EnsureInTransaction(doc)
wallRef = uidoc.Selection.PickObject(ObjectType.Element, "Select a wall")
wall = doc.GetElement(wallRef.ElementId)
schemaId = System.Guid(schemaId)
schema = ExtensibleStorage.Schema.Lookup(schemaId)
if schema is None:
builder = ExtensibleStorage.SchemaBuilder(schemaId)
builder.SetReadAccessLevel(ExtensibleStorage.AccessLevel.Public)
builder.SetWriteAccessLevel(ExtensibleStorage.AccessLevel.Public)
builder.SetSchemaName("VeryFirstAttemptAtThis")
builder.SetDocumentation("Data store for my very first attempt")
schema = builder.Finish()
BuildInfo = "Schema created successfully."
else:
BuildInfo = "Schema already exists."
except Exception as e:
BuildInfo = f"An error occurred: {str(e)}"
#Now the schema exists. So do things with it...
builder = ExtensibleStorage.SchemaBuilder(schemaId)
# Create field1
fieldBuilder1 = builder.AddSimpleField("WallLength", XYZ)
fieldBuilder1.SetSpec(SpecTypeId.Length) # https://www.revitapidocs.com/2023/87de2c69-a5e8-40e3-3d7a-9b18f1fda03a.htm
fieldBuilder1.SetDocumentation("this is the documentation here")
# Create field2
fieldBuilder2 = builder.AddSimpleField("WallNumber", str)
#fieldBuilder2.SetSpec(ForgeTypeId())
### Set value of field and attach to objects in Revit###
try:
entity = ExtensibleStorage.Entity(schema)
fieldName = "WallLength"
field = schema.GetField(fieldName)
if field is not None:
entity.Set[XYZ](field, XYZ(2, 0, 0), UnitTypeId.Millimeters)
wall.SetEntity(entity)
else:
output = "Field not found: " + fieldName
except Exception as e:
output = str(e) # error message
TransactionManager.Instance.TransactionTaskDone()
#TransactionManager.Instance.EnsureInTransaction(doc)
OUT = BuildInfo, "moose!" , output
So the schema built, the moose is output… however i’m getting an error on the field.
I am wondering why. Is it because the way I’ve tried to do it the fields would have to be created at the same time as the Schema?
If that’s the case, how do I add fields after the Schema is created?
import System
import sys
import clr
#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
#import specify namespace
from Autodesk.Revit.DB.ExtensibleStorage import Schema, SchemaBuilder, AccessLevel, Entity, Field
#import net library
from System import Array
from System.Collections.Generic import List, IList, Dictionary, IDictionary
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
def create_schema(schema_guid):
schema_builder = SchemaBuilder(schema_guid)
schema_builder.SetReadAccessLevel(AccessLevel.Public)
schema_builder.SetWriteAccessLevel(AccessLevel.Public)
schema_builder.SetSchemaName("DataSchema")
schema_builder.SetVendorId("XXXX")
schema_builder.SetDocumentation("Schema to store Data")
#
fieldBuilder_dict = schema_builder.AddMapField("Dict_Data", System.String, System.String)
fieldBuilder_dict.SetDocumentation("A Dictionary to store any value String data")
#
schema = schema_builder.Finish()
return schema
def add_schema_instance(schema, rvt_element, pydict = {}):
#
# get Field from DataStorage
fieldDict = schema.GetField("Dict_Data")
# set schema and store some datas
schema_instance = Entity(schema)
# store Datas Element in Dictionary
stringMap = Dictionary[System.String, System.String](pydict)
schema_instance.Set[IDictionary[System.String, System.String]](fieldDict.FieldName, stringMap)
rvt_element.SetEntity(schema_instance)
return rvt_element
def read_DataStorage(schema, rvt_element, searchValue = None):
"""
return DataStorage Value by Name of Field if failed search in Dictionnary 'Dict_Data'
Dict_Data -> Store and Read Datas in an IDictionnary
"""
ent = rvt_element.GetEntity(schema)
if ent.IsValid():
i_Dict = ent.Get[IDictionary[System.String, System.String]]("Dict_Data")
mydict = dict(zip(i_Dict.Keys, i_Dict.Values))
if isinstance(searchValue, (str, System.String)):
return mydict.get(searchValue)
return None
rvt_element = UnwrapElement(IN[0])
# create data to store with a dictionary {String : String, String : String}
data_dict = {"rvt_Id" : rvt_element.Id.ToString(), "rvt_uniqId" : rvt_element.UniqueId}
#
TransactionManager.Instance.EnsureInTransaction(doc)
#
schema = create_schema(System.Guid("18163872-127c-4615-9cc3-47f16726b6de"))
doc.Regenerate()
# store 1st data
add_schema_instance(schema, rvt_element, data_dict)
# add new Data and store again
data_dict["Dynamo"] = "BIM"
add_schema_instance(schema, rvt_element, data_dict)
TransactionManager.Instance.TransactionTaskDone()
OUT = []
for i in ["rvt_Id", "Dynamo", "missingKey"]:
OUT.append([i, read_DataStorage(schema, rvt_element, searchValue = i)])
If I attach the schema to a database element… but then someone deletes that element… are all my fields wiped clean?
Is there any way of retrieving that data?