Schema - Invalid

I’m setting up some schemas in Revit… All of them have very similar code but for some reason I keep having issues with this one- in particular the second to last line that is trying to get the dictionary? Any idea why?

import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitServices')
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.ExtensibleStorage import *
from Autodesk.Revit.UI.Selection import ObjectType
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
import System
import sys
#import net library
from System import Array
from System.Collections.Generic import List, IList, Dictionary, IDictionary

#Get the GUID
schemaId = System.Guid(IN[0]) #Guid
schemaName = IN[1] #String
#unwrap 
myChosenDBobject = UnwrapElement(IN[2][0]) #Project base point

doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
schema = ExtensibleStorage.Schema.Lookup(schemaId)

def add_schema_instance(schema, myChosenDBobject, 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)
	myChosenDBobject.SetEntity(schema_instance)
	return myChosenDBobject
	
# Begin transaction
TransactionManager.Instance.EnsureInTransaction(doc)

# Create the schema if it doesn't exist
if schema is None:
	builder = ExtensibleStorage.SchemaBuilder(schemaId)
	builder.SetReadAccessLevel(ExtensibleStorage.AccessLevel.Public)
	builder.SetWriteAccessLevel(ExtensibleStorage.AccessLevel.Public)
	builder.SetSchemaName(schemaName)
	builder.SetDocumentation("This is the series information for the issue sheet")
   
	# Create dictionary for series descriptions
	Dict = builder.AddMapField("Dict_Data", System.String, System.String)
	Dict.SetDocumentation("Dictionary for series descriptions")
    
	schema = builder.Finish()
	BuildInfo = "Schema created successfully."
	BuildOutput = True

	######## Add all current series descriptions 
	fields = {
		"10": "Site, Existing, Demolition",
		"18": "Other Substructure Elements",
		"20": "General Arrangements",
		"21": "External Walls",
		"22": "Internal Walls",
		"23": "Floors",
		"31": "Windows / Exterior Doors",
		"32": "Internal Doors",
		"35": "Ceilings",
		"40": "Finishes",
		"68": "Security & Fire"
	}
			
	# Create the data dictionary
	data_dict = {"00": "WholeBuilding (Glossaries,Specs etc)"}
	
	# Store initial data
	add_schema_instance(schema, myChosenDBobject, data_dict)		
	# Loop through the fields and add them
	for key, value in fields.items():
		data_dict[key] = value
		add_schema_instance(schema, myChosenDBobject, data_dict)		    

else:
	BuildInfo = "Schema already exists."
	BuildOutput = True

TransactionManager.Instance.TransactionTaskDone()
doc.Regenerate()

entity = myChosenDBobject.GetEntity(schema)


### I keep getting errors on this next line... Why? 
dictionary = entity.Get[IDictionary[System.String, System.String]]("Dict_Data")
	
	
OUT =  dictionary, BuildInfo

Edit:

So it already exists… But why is the try bit not working if it exists?

Not knowing much about how extensible storage data schemes work or how they should be structured:
Do your other dictionary names have parentheses in them?
image

Pretty sure it’s not them causing the issue… The script runs fine on most projects, but it’s one I’ve run into issues but I have no idea why.

Same Revit version as other projects?

Yep.

This seems inefficient - why not load the information in one go?

# Create the data dictionary
    data_dict = Dictionary[System.String, System.String](
        {
            "00": "WholeBuilding (Glossaries,Specs etc)",
            "10": "Site, Existing, Demolition",
            "18": "Other Substructure Elements",
            "20": "General Arrangements",
            "21": "External Walls",
            "22": "Internal Walls",
            "23": "Floors",
            "31": "Windows / Exterior Doors",
            "32": "Internal Doors",
            "35": "Ceilings",
            "40": "Finishes",
            "68": "Security & Fire",
        }
    )
# Store data
    add_schema_instance(schema, myChosenDBobject, data_dict)

I think I tried that at first… but it didn’t seem to like it. I may try it again tho.

Either way though… I still can’t see my dictionary for some reason. :frowning:
Have you any idea what’s happening?

I have found the map field is fussy (in C# and python) so I use a simple string field with JSON

What I’m doing is creating an issue sheet… But I want client names + series descriptions too…

For the main entries I’m using a string field and JSON but for the other two I’m using a dictionary as it seemed to make more sense…

The idea is if it’s 20 (series) I can just look up the entry in the dictionary.

I thought that’d be way more difficult with a string field?

Use json.dumps(dict) and json.loads(str)

my_json_data = json.dumps(my_dict)
#...
entity.Set[String]("SimpleFieldJson", my_json_data)
#...
retrieved_json_data = json.loads(
        element.GetEntity(schema).Get[String]("SimpleFieldJson")
        )

The other thing to remember is extensible storage is persistent, even after you delete it hangs around. Use Application.PurgeReleasedAPIObjects() after deletion (outside of transaction) and sometimes you just have to close and restart Revit.

2 Likes