mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-19 22:50:21 +00:00
You can now specify custom attribute mappings to COBie spreadsheets
This commit is contained in:
@@ -167,6 +167,7 @@ if bpy is not None:
|
|||||||
operator.ExecuteBIMTester,
|
operator.ExecuteBIMTester,
|
||||||
operator.BIMTesterPurge,
|
operator.BIMTesterPurge,
|
||||||
operator.SelectCobieIfcFile,
|
operator.SelectCobieIfcFile,
|
||||||
|
operator.SelectCobieJsonFile,
|
||||||
operator.ExecuteIfcCobie,
|
operator.ExecuteIfcCobie,
|
||||||
operator.SelectIfcPatchInput,
|
operator.SelectIfcPatchInput,
|
||||||
operator.SelectIfcPatchOutput,
|
operator.SelectIfcPatchOutput,
|
||||||
|
|||||||
@@ -1319,6 +1319,20 @@ class SelectCobieIfcFile(bpy.types.Operator):
|
|||||||
return {'RUNNING_MODAL'}
|
return {'RUNNING_MODAL'}
|
||||||
|
|
||||||
|
|
||||||
|
class SelectCobieJsonFile(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.select_cobie_json_file"
|
||||||
|
bl_label = "Select COBie JSON File"
|
||||||
|
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
bpy.context.scene.BIMProperties.cobie_json_file = self.filepath
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
context.window_manager.fileselect_add(self)
|
||||||
|
return {'RUNNING_MODAL'}
|
||||||
|
|
||||||
|
|
||||||
class ExecuteIfcCobie(bpy.types.Operator):
|
class ExecuteIfcCobie(bpy.types.Operator):
|
||||||
bl_idname = 'bim.execute_ifc_cobie'
|
bl_idname = 'bim.execute_ifc_cobie'
|
||||||
bl_label = 'Execute IFCCOBie'
|
bl_label = 'Execute IFCCOBie'
|
||||||
@@ -1335,11 +1349,17 @@ class ExecuteIfcCobie(bpy.types.Operator):
|
|||||||
logger = logging.getLogger('IFCtoCOBie')
|
logger = logging.getLogger('IFCtoCOBie')
|
||||||
logger.addHandler(fh)
|
logger.addHandler(fh)
|
||||||
selector = ifcopenshell.util.selector.Selector()
|
selector = ifcopenshell.util.selector.Selector()
|
||||||
|
if bpy.context.scene.BIMProperties.cobie_json_file:
|
||||||
|
with open(bpy.context.scene.BIMProperties.cobie_json_file, 'r') as f:
|
||||||
|
custom_data = json.load(f)
|
||||||
|
else:
|
||||||
|
custom_data = {}
|
||||||
parser = IfcCobieParser(logger, selector)
|
parser = IfcCobieParser(logger, selector)
|
||||||
parser.parse(
|
parser.parse(
|
||||||
bpy.context.scene.BIMProperties.cobie_ifc_file,
|
bpy.context.scene.BIMProperties.cobie_ifc_file,
|
||||||
bpy.context.scene.BIMProperties.cobie_types,
|
bpy.context.scene.BIMProperties.cobie_types,
|
||||||
bpy.context.scene.BIMProperties.cobie_components)
|
bpy.context.scene.BIMProperties.cobie_components,
|
||||||
|
custom_data)
|
||||||
if self.file_format == 'xlsx':
|
if self.file_format == 'xlsx':
|
||||||
from cobie import CobieXlsWriter
|
from cobie import CobieXlsWriter
|
||||||
writer = CobieXlsWriter(parser, output)
|
writer = CobieXlsWriter(parser, output)
|
||||||
|
|||||||
@@ -1127,6 +1127,7 @@ class BIMProperties(PropertyGroup):
|
|||||||
cobie_ifc_file: StringProperty(default='', name="COBie IFC File")
|
cobie_ifc_file: StringProperty(default='', name="COBie IFC File")
|
||||||
cobie_types: StringProperty(default='.COBieType', name="COBie Types")
|
cobie_types: StringProperty(default='.COBieType', name="COBie Types")
|
||||||
cobie_components: StringProperty(default='.COBie', name="COBie Components")
|
cobie_components: StringProperty(default='.COBie', name="COBie Components")
|
||||||
|
cobie_json_file: StringProperty(default='', name="COBie JSON File")
|
||||||
diff_json_file: StringProperty(default='', name="Diff JSON File")
|
diff_json_file: StringProperty(default='', name="Diff JSON File")
|
||||||
diff_old_file: StringProperty(default='', name="Diff Old IFC File")
|
diff_old_file: StringProperty(default='', name="Diff Old IFC File")
|
||||||
diff_new_file: StringProperty(default='', name="Diff New IFC File")
|
diff_new_file: StringProperty(default='', name="Diff New IFC File")
|
||||||
|
|||||||
@@ -1591,6 +1591,10 @@ class BIM_PT_cobie(Panel):
|
|||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.prop(props, "cobie_components")
|
row.prop(props, "cobie_components")
|
||||||
|
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(props, "cobie_json_file")
|
||||||
|
row.operator("bim.select_cobie_json_file", icon="FILE_FOLDER", text="")
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
op = row.operator('bim.execute_ifc_cobie', text='CSV')
|
op = row.operator('bim.execute_ifc_cobie', text='CSV')
|
||||||
op.file_format = 'csv'
|
op.file_format = 'csv'
|
||||||
|
|||||||
+104
-44
@@ -14,24 +14,12 @@ class IfcCobieParser():
|
|||||||
self.selector = selector
|
self.selector = selector
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
self.file = None
|
self.file = None
|
||||||
self.contacts = {}
|
self.sheets = ['contacts', 'facilities', 'floors', 'spaces', 'zones',
|
||||||
self.facilities = {}
|
'types', 'components', 'systems', 'assemblies', 'connections',
|
||||||
self.floors = {}
|
'spares', 'resources', 'jobs', 'impacts', 'documents', 'attributes',
|
||||||
self.spaces = {}
|
'coordinates', 'issues']
|
||||||
self.zones = {}
|
for sheet in self.sheets:
|
||||||
self.types = {}
|
setattr(self, sheet, {})
|
||||||
self.components = {}
|
|
||||||
self.systems = {}
|
|
||||||
self.assemblies = {}
|
|
||||||
self.connections = {}
|
|
||||||
self.spares = {}
|
|
||||||
self.resources = {}
|
|
||||||
self.jobs = {}
|
|
||||||
self.impacts = {}
|
|
||||||
self.documents = {}
|
|
||||||
self.attributes = {}
|
|
||||||
self.coordinates = {}
|
|
||||||
self.issues = {}
|
|
||||||
self.picklists = {
|
self.picklists = {
|
||||||
'Category-Role': [],
|
'Category-Role': [],
|
||||||
'Category-Facility': [],
|
'Category-Facility': [],
|
||||||
@@ -49,11 +37,11 @@ class IfcCobieParser():
|
|||||||
}
|
}
|
||||||
self.default_date = (datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds = -2177452801)).isoformat()
|
self.default_date = (datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds = -2177452801)).isoformat()
|
||||||
|
|
||||||
def parse(self, filename, type_query=None, component_query=None):
|
def parse(self, filename, type_query='.COBieType', component_query='.COBie', custom_data={}):
|
||||||
if type_query is None:
|
self.custom_data = custom_data
|
||||||
type_query = '.COBieType'
|
for sheet in self.sheets:
|
||||||
if component_query is None:
|
if sheet not in self.custom_data:
|
||||||
component_query = '.COBie'
|
self.custom_data[sheet] = {}
|
||||||
self.file = ifcopenshell.open(filename)
|
self.file = ifcopenshell.open(filename)
|
||||||
self.type_assets = self.selector.parse(self.file, type_query)
|
self.type_assets = self.selector.parse(self.file, type_query)
|
||||||
self.component_assets = self.selector.parse(self.file, component_query)
|
self.component_assets = self.selector.parse(self.file, component_query)
|
||||||
@@ -103,6 +91,8 @@ class IfcCobieParser():
|
|||||||
'PostalCode': self.get_attribute_from_address(postal_address, 'PostalCode'),
|
'PostalCode': self.get_attribute_from_address(postal_address, 'PostalCode'),
|
||||||
'Country': self.get_attribute_from_address(postal_address, 'Country')
|
'Country': self.get_attribute_from_address(postal_address, 'Country')
|
||||||
}
|
}
|
||||||
|
for field, key in self.custom_data['contacts'].items():
|
||||||
|
self.contacts[email][field] = self.get_element_value(history, key)
|
||||||
|
|
||||||
def get_facilities(self):
|
def get_facilities(self):
|
||||||
buildings = self.file.by_type('IfcBuilding')
|
buildings = self.file.by_type('IfcBuilding')
|
||||||
@@ -132,6 +122,8 @@ class IfcCobieParser():
|
|||||||
'SiteDescription': self.get_object_attribute(self.get_parent_spatial_element(building, 'IfcSite'), 'Description', default='n/a'),
|
'SiteDescription': self.get_object_attribute(self.get_parent_spatial_element(building, 'IfcSite'), 'Description', default='n/a'),
|
||||||
'Phase': self.get_object_attribute(self.get_parent_spatial_element(building, 'IfcProject'), 'Phase', default='n/a')
|
'Phase': self.get_object_attribute(self.get_parent_spatial_element(building, 'IfcProject'), 'Phase', default='n/a')
|
||||||
}
|
}
|
||||||
|
for field, key in self.custom_data['facilities'].items():
|
||||||
|
self.facilities[building_name][field] = self.get_element_value(building, key)
|
||||||
|
|
||||||
def get_floors(self):
|
def get_floors(self):
|
||||||
storeys = self.file.by_type('IfcBuildingStorey')
|
storeys = self.file.by_type('IfcBuildingStorey')
|
||||||
@@ -148,6 +140,8 @@ class IfcCobieParser():
|
|||||||
'Elevation': self.get_object_attribute(storey, 'Elevation', default='n/a'),
|
'Elevation': self.get_object_attribute(storey, 'Elevation', default='n/a'),
|
||||||
'Height': self.get_height_from_storey(storey)
|
'Height': self.get_height_from_storey(storey)
|
||||||
}
|
}
|
||||||
|
for field, key in self.custom_data['floors'].items():
|
||||||
|
self.floors[storey_name][field] = self.get_element_value(storey, key)
|
||||||
|
|
||||||
def get_spaces(self):
|
def get_spaces(self):
|
||||||
spaces = self.file.by_type('IfcSpace')
|
spaces = self.file.by_type('IfcSpace')
|
||||||
@@ -167,6 +161,8 @@ class IfcCobieParser():
|
|||||||
'GrossArea': self.get_gross_area_from_space(space),
|
'GrossArea': self.get_gross_area_from_space(space),
|
||||||
'NetArea': self.get_net_area_from_space(space),
|
'NetArea': self.get_net_area_from_space(space),
|
||||||
}
|
}
|
||||||
|
for field, key in self.custom_data['spaces'].items():
|
||||||
|
self.spaces[space_name][field] = self.get_element_value(space, key)
|
||||||
|
|
||||||
def get_zones(self):
|
def get_zones(self):
|
||||||
zones = self.file.by_type('IfcZone')
|
zones = self.file.by_type('IfcZone')
|
||||||
@@ -182,6 +178,8 @@ class IfcCobieParser():
|
|||||||
'ExtIdentifier': zone.GlobalId,
|
'ExtIdentifier': zone.GlobalId,
|
||||||
'Description': self.get_object_attribute(zone, 'Description', default='n/a'),
|
'Description': self.get_object_attribute(zone, 'Description', default='n/a'),
|
||||||
}
|
}
|
||||||
|
for field, key in self.custom_data['zones'].items():
|
||||||
|
self.zones[zone_name][field] = self.get_element_value(zone, key)
|
||||||
|
|
||||||
def get_types(self):
|
def get_types(self):
|
||||||
types = self.file.by_type('IfcTypeObject')
|
types = self.file.by_type('IfcTypeObject')
|
||||||
@@ -235,6 +233,8 @@ class IfcCobieParser():
|
|||||||
'CodePerformance': self.get_pset_value_from_object(type, 'COBie_Specification', 'CodePerformance', 'n/a'),
|
'CodePerformance': self.get_pset_value_from_object(type, 'COBie_Specification', 'CodePerformance', 'n/a'),
|
||||||
'SustainabilityPerformance': self.get_pset_value_from_object(type, 'COBie_Specification', 'SustainabilityPerformance', 'n/a'),
|
'SustainabilityPerformance': self.get_pset_value_from_object(type, 'COBie_Specification', 'SustainabilityPerformance', 'n/a'),
|
||||||
}
|
}
|
||||||
|
for field, key in self.custom_data['types'].items():
|
||||||
|
self.types[type_name][field] = self.get_element_value(type, key)
|
||||||
|
|
||||||
def get_components(self):
|
def get_components(self):
|
||||||
components = self.file.by_type('IfcElement')
|
components = self.file.by_type('IfcElement')
|
||||||
@@ -259,6 +259,8 @@ class IfcCobieParser():
|
|||||||
'BarCode': self.get_pset_value_from_object(component, 'Pset_ManufacturerOccurence', 'BarCode', 'n/a'),
|
'BarCode': self.get_pset_value_from_object(component, 'Pset_ManufacturerOccurence', 'BarCode', 'n/a'),
|
||||||
'AssetIdentifier': self.get_pset_value_from_object(component, 'COBie_Component', 'AssetIdentifier', 'n/a'),
|
'AssetIdentifier': self.get_pset_value_from_object(component, 'COBie_Component', 'AssetIdentifier', 'n/a'),
|
||||||
}
|
}
|
||||||
|
for field, key in self.custom_data['components'].items():
|
||||||
|
self.components[component_name][field] = self.get_element_value(component, key)
|
||||||
|
|
||||||
def get_systems(self):
|
def get_systems(self):
|
||||||
systems = self.file.by_type('IfcSystem')
|
systems = self.file.by_type('IfcSystem')
|
||||||
@@ -274,6 +276,8 @@ class IfcCobieParser():
|
|||||||
'ExtIdentifier': system.GlobalId,
|
'ExtIdentifier': system.GlobalId,
|
||||||
'Description': self.get_object_attribute(system, 'Description', default='n/a'),
|
'Description': self.get_object_attribute(system, 'Description', default='n/a'),
|
||||||
}
|
}
|
||||||
|
for field, key in self.custom_data['systems'].items():
|
||||||
|
self.systems[system_name][field] = self.get_element_value(system, key)
|
||||||
|
|
||||||
def get_assemblies(self):
|
def get_assemblies(self):
|
||||||
assemblies = self.file.by_type('IfcRelAggregates')
|
assemblies = self.file.by_type('IfcRelAggregates')
|
||||||
@@ -293,6 +297,8 @@ class IfcCobieParser():
|
|||||||
'ExtIdentifier': assembly.GlobalId,
|
'ExtIdentifier': assembly.GlobalId,
|
||||||
'Description': self.get_object_attribute(assembly, 'Description', default='n/a'),
|
'Description': self.get_object_attribute(assembly, 'Description', default='n/a'),
|
||||||
}
|
}
|
||||||
|
for field, key in self.custom_data['assemblies'].items():
|
||||||
|
self.assemblies[assembly_name][field] = self.get_element_value(assembly, key)
|
||||||
|
|
||||||
def get_connections(self):
|
def get_connections(self):
|
||||||
connections = self.file.by_type('IfcRelConnects')
|
connections = self.file.by_type('IfcRelConnects')
|
||||||
@@ -314,6 +320,8 @@ class IfcCobieParser():
|
|||||||
'ExtIdentifier': connection.GlobalId,
|
'ExtIdentifier': connection.GlobalId,
|
||||||
'Description': self.get_object_attribute(connection, 'Description', default='n/a'),
|
'Description': self.get_object_attribute(connection, 'Description', default='n/a'),
|
||||||
}
|
}
|
||||||
|
for field, key in self.custom_data['connections'].items():
|
||||||
|
self.connections[connection_name][field] = self.get_element_value(connection, key)
|
||||||
|
|
||||||
def get_spares(self):
|
def get_spares(self):
|
||||||
spares = self.file.by_type('IfcConstructionProductResource')
|
spares = self.file.by_type('IfcConstructionProductResource')
|
||||||
@@ -332,6 +340,8 @@ class IfcCobieParser():
|
|||||||
'SetNumber': self.get_contact_pset_value_from_object(spare, 'COBie_Spare', 'SetNumber'),
|
'SetNumber': self.get_contact_pset_value_from_object(spare, 'COBie_Spare', 'SetNumber'),
|
||||||
'PartNumber': self.get_contact_pset_value_from_object(spare, 'COBie_Spare', 'PartNumber'),
|
'PartNumber': self.get_contact_pset_value_from_object(spare, 'COBie_Spare', 'PartNumber'),
|
||||||
}
|
}
|
||||||
|
for field, key in self.custom_data['spares'].items():
|
||||||
|
self.spares[spare_name][field] = self.get_element_value(spare, key)
|
||||||
|
|
||||||
def get_resources(self):
|
def get_resources(self):
|
||||||
resources = self.file.by_type('IfcConstructionProductResource')
|
resources = self.file.by_type('IfcConstructionProductResource')
|
||||||
@@ -346,6 +356,8 @@ class IfcCobieParser():
|
|||||||
'ExtIdentifier': resource.GlobalId,
|
'ExtIdentifier': resource.GlobalId,
|
||||||
'Description': self.get_object_attribute(resource, 'Description', default='n/a'),
|
'Description': self.get_object_attribute(resource, 'Description', default='n/a'),
|
||||||
}
|
}
|
||||||
|
for field, key in self.custom_data['resources'].items():
|
||||||
|
self.resources[resource_name][field] = self.get_element_value(resource, key)
|
||||||
|
|
||||||
def get_jobs(self):
|
def get_jobs(self):
|
||||||
jobs = self.file.by_type('IfcTask')
|
jobs = self.file.by_type('IfcTask')
|
||||||
@@ -372,6 +384,8 @@ class IfcCobieParser():
|
|||||||
'Priors': self.get_priors_from_job(job),
|
'Priors': self.get_priors_from_job(job),
|
||||||
'ResourceNames': self.get_resource_names_from_job(job),
|
'ResourceNames': self.get_resource_names_from_job(job),
|
||||||
}
|
}
|
||||||
|
for field, key in self.custom_data['jobs'].items():
|
||||||
|
self.jobs[job_name][field] = self.get_element_value(job, key)
|
||||||
|
|
||||||
# Impacts is not explicitly defined as a mapping in the responsibliity
|
# Impacts is not explicitly defined as a mapping in the responsibliity
|
||||||
# matrix. This is my best guess. This data should not be relied upon until
|
# matrix. This is my best guess. This data should not be relied upon until
|
||||||
@@ -401,6 +415,8 @@ class IfcCobieParser():
|
|||||||
'ExtIdentifier': impact.GlobalId,
|
'ExtIdentifier': impact.GlobalId,
|
||||||
'Description': self.get_object_attribute(impact, 'Description', default='n/a'),
|
'Description': self.get_object_attribute(impact, 'Description', default='n/a'),
|
||||||
}
|
}
|
||||||
|
for field, key in self.custom_data['impacts'].items():
|
||||||
|
self.impacts[impact_name][field] = self.get_element_value(impact, key)
|
||||||
|
|
||||||
def get_documents(self):
|
def get_documents(self):
|
||||||
documents = self.file.by_type('IfcDocumentInformation')
|
documents = self.file.by_type('IfcDocumentInformation')
|
||||||
@@ -422,6 +438,8 @@ class IfcCobieParser():
|
|||||||
'Description': self.get_object_attribute(document, 'Description', default=document_name),
|
'Description': self.get_object_attribute(document, 'Description', default=document_name),
|
||||||
'Reference': document_name,
|
'Reference': document_name,
|
||||||
}
|
}
|
||||||
|
for field, key in self.custom_data['documents'].items():
|
||||||
|
self.documents[document_name][field] = self.get_element_value(document, key)
|
||||||
|
|
||||||
# Attributes is not explicitly defined as a mapping in the responsibliity
|
# Attributes is not explicitly defined as a mapping in the responsibliity
|
||||||
# matrix. This is my best guess. This data should not be relied upon until
|
# matrix. This is my best guess. This data should not be relied upon until
|
||||||
@@ -903,7 +921,7 @@ class IfcCobieParser():
|
|||||||
def get_phone_from_person_or_organisation(self, person_or_org):
|
def get_phone_from_person_or_organisation(self, person_or_org):
|
||||||
for address in (person_or_org.Addresses or []):
|
for address in (person_or_org.Addresses or []):
|
||||||
if address.is_a('IfcTelecomAddress'):
|
if address.is_a('IfcTelecomAddress'):
|
||||||
return address.TelephoneNumbers[0]
|
return address.TelephoneNumbers[0]
|
||||||
self.logger.warning('A phone was not found for {}'.format(person_or_org))
|
self.logger.warning('A phone was not found for {}'.format(person_or_org))
|
||||||
|
|
||||||
def get_email_from_person_or_organisation(self, person_or_org):
|
def get_email_from_person_or_organisation(self, person_or_org):
|
||||||
@@ -912,6 +930,12 @@ class IfcCobieParser():
|
|||||||
return address.ElectronicMailAddresses[0]
|
return address.ElectronicMailAddresses[0]
|
||||||
self.logger.warning('An email address was not found for {}'.format(person_or_org))
|
self.logger.warning('An email address was not found for {}'.format(person_or_org))
|
||||||
|
|
||||||
|
def get_element_value(self, element, key):
|
||||||
|
value = self.selector.get_element_value(element, key)
|
||||||
|
if hasattr(value, 'wrappedValue'):
|
||||||
|
return value.wrappedValue
|
||||||
|
return value
|
||||||
|
|
||||||
class CobieWriter():
|
class CobieWriter():
|
||||||
def __init__(self, parser, filename=None):
|
def __init__(self, parser, filename=None):
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
@@ -938,7 +962,7 @@ class CobieWriter():
|
|||||||
'Phone', 'ExtSystem', 'ExtObject', 'ExtIdentifier',
|
'Phone', 'ExtSystem', 'ExtObject', 'ExtIdentifier',
|
||||||
'Department', 'OrganizationCode', 'GivenName', 'FamilyName',
|
'Department', 'OrganizationCode', 'GivenName', 'FamilyName',
|
||||||
'Street', 'PostalBox', 'Town', 'StateRegion', 'PostalCode',
|
'Street', 'PostalBox', 'Town', 'StateRegion', 'PostalCode',
|
||||||
'Country'], 'ririrreeeoooooooooo')
|
'Country'], 'ririrreeeoooooooooo', self.parser.custom_data['contacts'])
|
||||||
self.write_data('Facility', self.parser.facilities, 'Name',
|
self.write_data('Facility', self.parser.facilities, 'Name',
|
||||||
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'ProjectName',
|
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'ProjectName',
|
||||||
'SiteName', 'LinearUnits', 'AreaUnits', 'VolumeUnits', 'CostUnit',
|
'SiteName', 'LinearUnits', 'AreaUnits', 'VolumeUnits', 'CostUnit',
|
||||||
@@ -946,17 +970,21 @@ class CobieWriter():
|
|||||||
'ExternalProjectIdentifier', 'ExternalSiteObject',
|
'ExternalProjectIdentifier', 'ExternalSiteObject',
|
||||||
'ExternalSiteIdentifier', 'ExternalFacilityObject',
|
'ExternalSiteIdentifier', 'ExternalFacilityObject',
|
||||||
'ExternalFacilityIdentifier', 'Description', 'ProjectDescription',
|
'ExternalFacilityIdentifier', 'Description', 'ProjectDescription',
|
||||||
'SiteDescription', 'Phase'], 'ririrriiiireeeeeeeoooo')
|
'SiteDescription', 'Phase'], 'ririrriiiireeeeeeeoooo',
|
||||||
|
self.parser.custom_data['facilities'])
|
||||||
self.write_data('Floor', self.parser.floors, 'Name',
|
self.write_data('Floor', self.parser.floors, 'Name',
|
||||||
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'ExtSystem',
|
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'ExtSystem',
|
||||||
'ExtObject', 'ExtIdentifier', 'Description', 'Elevation', 'Height'], 'ririeeeooo')
|
'ExtObject', 'ExtIdentifier', 'Description', 'Elevation', 'Height'],
|
||||||
|
'ririeeeooo', self.parser.custom_data['floors'])
|
||||||
self.write_data('Space', self.parser.spaces, 'Name',
|
self.write_data('Space', self.parser.spaces, 'Name',
|
||||||
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'FloorName',
|
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'FloorName',
|
||||||
'Description', 'ExtSystem', 'ExtObject', 'ExtIdentifier', 'RoomTag',
|
'Description', 'ExtSystem', 'ExtObject', 'ExtIdentifier', 'RoomTag',
|
||||||
'UsableHeight', 'GrossArea', 'NetArea'], 'ririireeeoooo')
|
'UsableHeight', 'GrossArea', 'NetArea'], 'ririireeeoooo',
|
||||||
|
self.parser.custom_data['spaces'])
|
||||||
self.write_data('Zone', self.parser.zones, 'Name',
|
self.write_data('Zone', self.parser.zones, 'Name',
|
||||||
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'SpaceNames',
|
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'SpaceNames',
|
||||||
'ExtSystem', 'ExtObject', 'ExtIdentifier', 'Description',], 'ririieeeo')
|
'ExtSystem', 'ExtObject', 'ExtIdentifier', 'Description',],
|
||||||
|
'ririieeeo', self.parser.custom_data['zones'])
|
||||||
self.write_data('Type', self.parser.types, 'Name',
|
self.write_data('Type', self.parser.types, 'Name',
|
||||||
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'Description',
|
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'Description',
|
||||||
'AssetType', 'Manufacturer', 'ModelNumber',
|
'AssetType', 'Manufacturer', 'ModelNumber',
|
||||||
@@ -967,45 +995,56 @@ class CobieWriter():
|
|||||||
'NominalWidth', 'NominalHeight', 'ModelReference', 'Shape', 'Size',
|
'NominalWidth', 'NominalHeight', 'ModelReference', 'Shape', 'Size',
|
||||||
'Color', 'Finish', 'Grade', 'Material', 'Constituents', 'Features',
|
'Color', 'Finish', 'Grade', 'Material', 'Constituents', 'Features',
|
||||||
'AccessibilityPerformance', 'CodePerformance',
|
'AccessibilityPerformance', 'CodePerformance',
|
||||||
'SustainabilityPerformance',], 'riririoooooooeeeooooooooooooooooooo')
|
'SustainabilityPerformance',],
|
||||||
|
'riririoooooooeeeooooooooooooooooooo',
|
||||||
|
self.parser.custom_data['types'])
|
||||||
self.write_data('Component', self.parser.components, 'Name',
|
self.write_data('Component', self.parser.components, 'Name',
|
||||||
['Name', 'CreatedBy', 'CreatedOn', 'TypeName', 'Space',
|
['Name', 'CreatedBy', 'CreatedOn', 'TypeName', 'Space',
|
||||||
'Description', 'ExtSystem', 'ExtObject', 'ExtIdentifier',
|
'Description', 'ExtSystem', 'ExtObject', 'ExtIdentifier',
|
||||||
'SerialNumber', 'InstallationDate', 'WarrantyStartDate',
|
'SerialNumber', 'InstallationDate', 'WarrantyStartDate',
|
||||||
'TagNumber', 'BarCode', 'AssetIdentifier',], 'ririireeeoooooo')
|
'TagNumber', 'BarCode', 'AssetIdentifier',], 'ririireeeoooooo',
|
||||||
|
self.parser.custom_data['components'])
|
||||||
self.write_data('System', self.parser.systems, 'Name',
|
self.write_data('System', self.parser.systems, 'Name',
|
||||||
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'ComponentNames',
|
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'ComponentNames',
|
||||||
'ExtSystem', 'ExtObject', 'ExtIdentifier', 'Description',], 'ririieeeo')
|
'ExtSystem', 'ExtObject', 'ExtIdentifier', 'Description',],
|
||||||
|
'ririieeeo', self.parser.custom_data['systems'])
|
||||||
self.write_data('Assembly', self.parser.assemblies, 'Name',
|
self.write_data('Assembly', self.parser.assemblies, 'Name',
|
||||||
['Name', 'CreatedBy', 'CreatedOn', 'SheetName', 'ParentName',
|
['Name', 'CreatedBy', 'CreatedOn', 'SheetName', 'ParentName',
|
||||||
'ChildNames', 'AssemblyType', 'ExtSystem', 'ExtObject',
|
'ChildNames', 'AssemblyType', 'ExtSystem', 'ExtObject',
|
||||||
'ExtIdentifier', 'Description',], 'rirrrrreeeo')
|
'ExtIdentifier', 'Description',], 'rirrrrreeeo',
|
||||||
|
self.parser.custom_data['assemblies'])
|
||||||
self.write_data('Connection', self.parser.connections, 'Name',
|
self.write_data('Connection', self.parser.connections, 'Name',
|
||||||
['Name', 'CreatedBy', 'CreatedOn', 'ConnectionType', 'SheetName',
|
['Name', 'CreatedBy', 'CreatedOn', 'ConnectionType', 'SheetName',
|
||||||
'RowName1', 'RowName2', 'RealizingElement', 'PortName1',
|
'RowName1', 'RowName2', 'RealizingElement', 'PortName1',
|
||||||
'PortName2', 'ExtSystem', 'ExtObject', 'ExtIdentifier',
|
'PortName2', 'ExtSystem', 'ExtObject', 'ExtIdentifier',
|
||||||
'Description',], 'ririiiiiiieeeo')
|
'Description',], 'ririiiiiiieeeo',
|
||||||
|
self.parser.custom_data['connections'])
|
||||||
self.write_data('Spare', self.parser.spares, 'Name',
|
self.write_data('Spare', self.parser.spares, 'Name',
|
||||||
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'TypeName',
|
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'TypeName',
|
||||||
'Suppliers', 'ExtSystem', 'ExtObject', 'ExtIdentifier',
|
'Suppliers', 'ExtSystem', 'ExtObject', 'ExtIdentifier',
|
||||||
'Description', 'SetNumber', 'PartNumber',], 'ririiieeeooo')
|
'Description', 'SetNumber', 'PartNumber',], 'ririiieeeooo',
|
||||||
|
self.parser.custom_data['spares'])
|
||||||
self.write_data('Resource', self.parser.resources, 'Name',
|
self.write_data('Resource', self.parser.resources, 'Name',
|
||||||
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'ExtSystem',
|
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'ExtSystem',
|
||||||
'ExtObject', 'ExtIdentifier', 'Description',], 'ririeeeo')
|
'ExtObject', 'ExtIdentifier', 'Description',], 'ririeeeo',
|
||||||
|
self.parser.custom_data['resources'])
|
||||||
self.write_data('Job', self.parser.jobs, 'Name',
|
self.write_data('Job', self.parser.jobs, 'Name',
|
||||||
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'Status', 'TypeName',
|
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'Status', 'TypeName',
|
||||||
'Description', 'Duration', 'DurationUnit', 'Start', 'TaskStartUnit',
|
'Description', 'Duration', 'DurationUnit', 'Start', 'TaskStartUnit',
|
||||||
'Frequency', 'FrequencyUnit', 'ExtSystem', 'ExtObject',
|
'Frequency', 'FrequencyUnit', 'ExtSystem', 'ExtObject',
|
||||||
'ExtIdentifier', 'TaskNumber', 'Priors', 'ResourceNames',], 'ririiirriririeeeoii')
|
'ExtIdentifier', 'TaskNumber', 'Priors', 'ResourceNames',],
|
||||||
|
'ririiirriririeeeoii', self.parser.custom_data['jobs'])
|
||||||
self.write_data('Impact', self.parser.impacts, 'Name',
|
self.write_data('Impact', self.parser.impacts, 'Name',
|
||||||
['Name', 'CreatedBy', 'CreatedOn', 'ImpactType', 'ImpactStage',
|
['Name', 'CreatedBy', 'CreatedOn', 'ImpactType', 'ImpactStage',
|
||||||
'SheetName', 'RowName', 'Value', 'Unit', 'LeadInTime', 'Duration',
|
'SheetName', 'RowName', 'Value', 'Unit', 'LeadInTime', 'Duration',
|
||||||
'LeadOutTime', 'ExtSystem', 'ExtObject', 'ExtIdentifier',
|
'LeadOutTime', 'ExtSystem', 'ExtObject', 'ExtIdentifier',
|
||||||
'Description',], 'ririiiirioooeeeo')
|
'Description',], 'ririiiirioooeeeo',
|
||||||
|
self.parser.custom_data['impacts'])
|
||||||
self.write_data('Document', self.parser.documents, 'Name',
|
self.write_data('Document', self.parser.documents, 'Name',
|
||||||
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'ApprovalBy',
|
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'ApprovalBy',
|
||||||
'Stage', 'SheetName', 'RowName', 'Directory', 'File', 'ExtSystem',
|
'Stage', 'SheetName', 'RowName', 'Directory', 'File', 'ExtSystem',
|
||||||
'ExtObject', 'ExtIdentifier', 'Description', 'Reference',], 'ririiiiirreeeoo')
|
'ExtObject', 'ExtIdentifier', 'Description', 'Reference',],
|
||||||
|
'ririiiiirreeeoo', self.parser.custom_data['documents'])
|
||||||
self.write_data('Attribute', self.parser.attributes, 'Name',
|
self.write_data('Attribute', self.parser.attributes, 'Name',
|
||||||
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'SheetName',
|
['Name', 'CreatedBy', 'CreatedOn', 'Category', 'SheetName',
|
||||||
'RowName', 'Value', 'Unit', 'ExtSystem', 'ExtObject',
|
'RowName', 'Value', 'Unit', 'ExtSystem', 'ExtObject',
|
||||||
@@ -1021,9 +1060,9 @@ class CobieWriter():
|
|||||||
'Description', 'Owner', 'Mitigation', 'ExtSystem', 'ExtObject',
|
'Description', 'Owner', 'Mitigation', 'ExtSystem', 'ExtObject',
|
||||||
'ExtIdentifier',], 'ririooooooooooeee')
|
'ExtIdentifier',], 'ririooooooooooeee')
|
||||||
|
|
||||||
def write_data(self, sheet, data, primary_key, fieldnames, colours):
|
def write_data(self, sheet, data, primary_key, fieldnames, colours, custom_data={}):
|
||||||
self.sheet_data[sheet] = {
|
self.sheet_data[sheet] = {
|
||||||
'headers': fieldnames,
|
'headers': fieldnames + list(custom_data.keys()),
|
||||||
'colours': colours,
|
'colours': colours,
|
||||||
'rows': []
|
'rows': []
|
||||||
}
|
}
|
||||||
@@ -1032,6 +1071,8 @@ class CobieWriter():
|
|||||||
values = []
|
values = []
|
||||||
for fieldname in fieldnames:
|
for fieldname in fieldnames:
|
||||||
values.append(row[fieldname])
|
values.append(row[fieldname])
|
||||||
|
for fieldname in custom_data.keys():
|
||||||
|
values.append(row[fieldname])
|
||||||
self.sheet_data[sheet]['rows'].append(values)
|
self.sheet_data[sheet]['rows'].append(values)
|
||||||
|
|
||||||
|
|
||||||
@@ -1074,7 +1115,11 @@ class CobieXlsWriter(CobieWriter):
|
|||||||
for row in self.sheet_data[name]['rows']:
|
for row in self.sheet_data[name]['rows']:
|
||||||
c = 0
|
c = 0
|
||||||
for col in row:
|
for col in row:
|
||||||
cell = worksheet.write(r, c, col, self.cell_formats[self.sheet_data[name]['colours'][c]])
|
if c >= len(self.sheet_data[name]['colours']):
|
||||||
|
cell_format = 'p'
|
||||||
|
else:
|
||||||
|
cell_format = self.sheet_data[name]['colours'][c]
|
||||||
|
cell = worksheet.write(r, c, col, self.cell_formats[cell_format])
|
||||||
c += 1
|
c += 1
|
||||||
r += 1
|
r += 1
|
||||||
|
|
||||||
@@ -1112,7 +1157,11 @@ class CobieOdsWriter(CobieWriter):
|
|||||||
tr = TableRow()
|
tr = TableRow()
|
||||||
c = 0
|
c = 0
|
||||||
for col in row:
|
for col in row:
|
||||||
tc = TableCell(valuetype='string', stylename=self.sheet_data[name]['colours'][c])
|
if c >= len(self.sheet_data[name]['colours']):
|
||||||
|
cell_format = 'p'
|
||||||
|
else:
|
||||||
|
cell_format = self.sheet_data[name]['colours'][c]
|
||||||
|
tc = TableCell(valuetype='string', stylename=cell_format)
|
||||||
tc.addElement(P(text=col))
|
tc.addElement(P(text=col))
|
||||||
tr.addElement(tc)
|
tr.addElement(tc)
|
||||||
c += 1
|
c += 1
|
||||||
@@ -1149,6 +1198,12 @@ if __name__ == '__main__':
|
|||||||
type=str,
|
type=str,
|
||||||
help='A custom selector for types. Defaults to COBieType',
|
help='A custom selector for types. Defaults to COBieType',
|
||||||
default='.COBieType')
|
default='.COBieType')
|
||||||
|
parser.add_argument(
|
||||||
|
'-d',
|
||||||
|
'--data',
|
||||||
|
type=str,
|
||||||
|
help='JSON file containing custom data to be appended to the COBie spreadsheet template',
|
||||||
|
default='')
|
||||||
args = vars(parser.parse_args())
|
args = vars(parser.parse_args())
|
||||||
|
|
||||||
print('Processing IFC file ...')
|
print('Processing IFC file ...')
|
||||||
@@ -1161,7 +1216,12 @@ if __name__ == '__main__':
|
|||||||
logger.info('Starting conversion')
|
logger.info('Starting conversion')
|
||||||
selector = ifcopenshell.util.selector.Selector()
|
selector = ifcopenshell.util.selector.Selector()
|
||||||
parser = IfcCobieParser(logger, selector)
|
parser = IfcCobieParser(logger, selector)
|
||||||
parser.parse(args['input'], args['types'], args['components'])
|
if args['data']:
|
||||||
|
with open(bpy.context.scene.BIMProperties.cobie_json_file, 'r') as f:
|
||||||
|
custom_data = json.load(f)
|
||||||
|
else:
|
||||||
|
custom_data = {}
|
||||||
|
parser.parse(args['input'], args['types'], args['components'], custom_data)
|
||||||
|
|
||||||
print('Generating reports ...')
|
print('Generating reports ...')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user