BlenderBIM Script for Property Set
I'm trying to create a script for blenderBIM, that edits a custom property set. My coding experience is very limited as I'm an architect so please keep in mind I'm new to this!
I want the script to check for each Building Story and enter a custom value into a property set field "Geschosscode" in the Pset "Spezifisch".
The Pset is already existing with a placeholder "--", the script just needs to overwrite the values with the correct codes. The code should be corresponding to the Building Story, for example: The Building Story "Untergeschoss" should recieve the code entry "UG01", but the next Building Story "Erdgeschoss" should recieve "EG00".
The problem here is, that it works to run without error, but it only adds the code "OG04", which is the last entry, to the selected Building Story. It should add the right codes to all Storeys, no matter which one is currently selected.
This is the code I have so far, I think I have a logic issue, any help is highly appreciated:
import bpy
import blenderbim.bim.ifc
ifc = blenderbim.bim.ifc.IfcStore().get_file()
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
## define the globalIDs for each level
level_global_ids = {
"Untergeschoss": "2LiJvusYaHxODNN62wEaPg",
"Erdgeschoss": "2UCKF9sYaHxODNN62wEaPg",
"1_Obergeschoss": "2aK8mdsYaHxODNN62wEaPg",
"2_Obergeschoss": "2aK8r2sYaHxODNN62wEaPg",
"3_Obergeschoss": "2mvNausYaHxODNN62wEaPg",
"4_Obergeschoss": "3FOkb0tj0HxODNN62wEaPg"
}
## define the psetIDs for each level
level_pset_ids = {
"Untergeschoss": 171,
"Erdgeschoss": 297,
"1_Obergeschoss": 374,
"2_Obergeschoss": 439,
"3_Obergeschoss": 504,
"4_Obergeschoss": 616
}
## define the pset values to enter for each psetID
storey_codes_by_pset_id = {
171: "UG01",
297: "EG00",
374: "OG01",
439: "OG02",
504: "OG03",
616: "OG04"
}
## loop over each BuildingStorey object and set the corresponding value / i think the issue is here
for level, pset_id in level_pset_ids.items():
obj_name = f"IfcBuildingStorey/{level}"
global_id = level_global_ids[level]
bpy.ops.bim.enable_pset_editing(pset_id=pset_id, obj=obj_name, obj_type="Object")
## Create a new element, code didnt run without this (?)
element = bpy.context.scene.AddEditProperties.add()
element.pset_name = "Spezifisch"
element.property_name = "Geschosscode"
element.string_value = storey_codes_by_pset_id[pset_id]
element.primary_measure_type = 'IfcGloballyUniqueId'
element.template_type = 'IfcPropertySingleValue'
bpy.ops.bim.add_edit_custom_property()
bpy.ops.bim.disable_pset_editing(obj=obj_name, obj_type="Object")
bpy.context.scene.AddEditProperties.clear()
Comments
@LFR

Do you mean like this?
I hope you don't mind. I took the liberty to completely refactor your code.
I tried to remove all the hardcoded dictionaries from your script and created new two
OrderedDictionaries
from two separate lists. The script gets the IfcBuildingStorey instead of hardcoding the GlobalId in a dictionary.My code could probably do with some refactoring as well. But as you can see from the .gif it works. Hope this is what you meant?
I think with some tweaking of this script you could get what you want in detail?
Nice snippet @Coen ! I like these lower-level scripts. Might be a little more efficient to use
for storey in ifc_file.by_type('IfcBuildingStorey'):
instead of iterating over all products ?@LFR I didn't understand the use for the global ids in the OP. Was that for something else ?
Oh yes ofcourse, obvious. Silly mistake. ?, Here is the revised code:
I asked chatGPT to explain the code from the comment above:
This code is used to set specific properties on IfcBuildingStorey objects in an IFC file. An IFC file is a file format used in the architecture, engineering and construction industry to exchange information between different software applications.
The code first imports necessary modules and libraries such as ifcopenshell and blenderbim to work with IFC files in Python. It then opens the IFC file specified in
IfcStore.path
and retrieves all IfcBuildingStorey objects in the file.The code then creates three OrderedDict objects named
level_global_ids
,level_pset_ids
andstorey_codes_by_psetid
. These objects are used to keep track of various information as the code runs.The
level_global_ids dictionary
is used to map each IfcBuildingStorey object's name to its GlobalId. Thelevel_pset_ids dictionary
is used to map each IfcBuildingStorey object's name to a predefined Pset ID (a type of property set ID). Finally, thestorey_codes_by_psetid
dictionary is used to map each Pset ID to a storey code.The code then populates the
level_pset_ids
dictionary andstorey_codes_by_psetid
dictionary using the predefinedlevel_pset_list
andstorey_codes_list
.The code then loops over all IfcBuildingStorey objects and for each object, it loops over the
level_pset_ids
dictionary to find the matching Pset ID for the object. Once a match is found, the code uses the run function from theifcopenshell.api
module to create a new property set named "Spezifisch" on the object and sets the Pset ID and Geschosscode properties of the property set to the corresponding values.Finally, the modified IFC file is written back to disk.
Overall, the code is doing a few things:
Hello @Coen @Gorgious , thanks so much for your input!


I'm trying to change this entry to be specific:
This is inside of blender. Which program did you use @Coen ?
@Gorgious regarding your question, I used the globalIDs in an earlier version of the code, when I had trouble calling the Building Storeys, but you guys are right, best not to hardcode it.
Thanks for your snippet, its looking much better already, however I cant get it to work for me. My Property Set is not updating inside of blender, maybe I need some kind of refresh of the IfcOpenShell?
@LFR
Try having BIM Vision with the ifc openend, BIM Vision will prompt you for a reload of the file. Then try reloading it in your BlenderBIM add-on.
For what you trying to achieve,Bblender is ok. I also used that for this case. You could also toggle the system console to see the output.

If you want to get a more serious IDE (Integrated Development Environment). I recommend VS code and the VS Code Blender extension made my Jacques Lucke
It's not updating because the script is modifying the ifc file directly on disk, not the one that's in memory inside Blender. Change
ifc_file = ifcopenshell.open(IfcStore.path)
toifc_file = IfcStore.file
and delete the last lineifc_file.write(IfcStore.path)
because that will be taken care of by the BlenderBIM addon and you don't want to unknowingly overwrite stuff.Note that because the property sets are populated when you click on an object, your new pset won't appear unless you re-select the object.
Add
bpy.context.view_layer.objects.active = bpy.context.active_object
at the end to force the refresh.The other software is BIMVision if I'm not mistaken.
BTW I'm not sure it's necessary to use
OrderedDict
here, since Python 3.7 all regular dicts are guaranteed to be traversed in the order in which elements were added.@Gorgious
Wow, I did not know that.
I did not know that either. (❁´◡`❁)
@Gorgious @Coen
thanks again, that did the trick! Its working now
@LFR
Just curious what you came up with eventually, do you mind posting the code here? :-D
Yes sure, I only modified it slightly, added all of my building storeys and removed the ID entry from the Pset:
It even works if there is no Pset "Spezifisch" yet, it creates it :D
@LFR
Nice! Your lists are getting quite long, maybe it would be more practical to but it an external data source like CSV or Excel and read them from there with pyton? :-)