IfcFM now uses Openpyxl and supports xlsx. Reorder columns to be more logical and group similar data types together (at least for me).

This commit is contained in:
Dion Moult
2023-09-08 13:16:17 +10:00
parent 763eaf83da
commit b7a481ec79
+64 -25
View File
@@ -29,7 +29,8 @@ import ifcopenshell.util.placement
import ifcopenshell.util.classification import ifcopenshell.util.classification
try: try:
from xlsxwriter import Workbook from openpyxl import Workbook
from openpyxl.styles import PatternFill
except: except:
pass # No XLSX support pass # No XLSX support
@@ -123,25 +124,25 @@ class Writer:
if preset == "BASIC": if preset == "BASIC":
self.config = { self.config = {
"Actors": {"colours": "ppssssssss", "sort": [{"name": "Name", "order": "ASC"}]}, "Actors": {"colours": "ppssssssss", "sort": [{"name": "Name", "order": "ASC"}]},
"Facilities": {"colours": "prppppsssseeee", "sort": [{"name": "Name", "order": "ASC"}]}, "Facilities": {"colours": "ppppreeeeessss", "sort": [{"name": "Name", "order": "ASC"}]},
"Storeys": { "Storeys": {
"colours": "prppeees", "colours": "ppreeees",
"sort": [{"name": "Elevation", "order": "ASC"}, {"name": "Name", "order": "ASC"}], "sort": [{"name": "Elevation", "order": "ASC"}, {"name": "Name", "order": "ASC"}],
}, },
"Spaces": { "Spaces": {
"colours": "prpprpeess", "colours": "ppprreeess",
"sort": [{"name": "LevelName", "order": "ASC"}, {"name": "Name", "order": "ASC"}], "sort": [{"name": "LevelName", "order": "ASC"}, {"name": "Name", "order": "ASC"}],
}, },
"Zones": {"colours": "prpree", "sort": [{"name": "Name", "order": "ASC"}]}, "Zones": {"colours": "prreee", "sort": [{"name": "Name", "order": "ASC"}]},
"Types": { "Types": {
"colours": "prpppeeee", "colours": "pppreeeee",
"sort": [{"name": "ModelObject", "order": "ASC"}, {"name": "Name", "order": "ASC"}], "sort": [{"name": "ModelObject", "order": "ASC"}, {"name": "Name", "order": "ASC"}],
}, },
"Elements": { "Elements": {
"colours": "prprrreee", "colours": "prrrreeee",
"sort": [{"name": "TypeName", "order": "ASC"}, {"name": "Name", "order": "ASC"}], "sort": [{"name": "TypeName", "order": "ASC"}, {"name": "Name", "order": "ASC"}],
}, },
"Systems": {"colours": "pprppee", "sort": [{"name": "Name", "order": "ASC"}]}, "Systems": {"colours": "pppreee", "sort": [{"name": "Name", "order": "ASC"}]},
} }
def write(self, null="N/A", empty="-", bool_true="YES", bool_false="NO"): def write(self, null="N/A", empty="-", bool_true="YES", bool_false="NO"):
@@ -234,6 +235,44 @@ class Writer:
doc.save(output, True) doc.save(output, True)
def write_xlsx(self, output):
workbook = Workbook()
cell_formats = {}
for key, value in self.colours.items():
fill = PatternFill(start_color=value, end_color=value, fill_type="solid")
cell_formats[key] = fill
for category, data in self.categories.items():
colours = self.config.get(category, {}).get("colours", [])
if category in workbook.sheetnames:
worksheet = workbook[category]
else:
worksheet = workbook.create_sheet(category)
r = 1 # Openpyxl uses 1-based indexing
c = 1
for header in data["headers"]:
cell = worksheet.cell(row=r, column=c, value=header)
cell.fill = cell_formats["h"]
c += 1
r += 1
for row in data["rows"]:
c = 1
for col in row:
if c > len(colours): # Adjusted the comparison
cell_format = "n"
else:
cell_format = colours[c - 1] # Adjusted the indexing
cell = worksheet.cell(row=r, column=c, value=col)
cell.fill = cell_formats[cell_format]
c += 1
r += 1
workbook.save(output)
def get_actors(ifc_file): def get_actors(ifc_file):
return ifc_file.by_type("IfcActor") return ifc_file.by_type("IfcActor")
@@ -295,19 +334,19 @@ def get_facility_data(ifc_file, element):
return { return {
"key": element.Name, "key": element.Name,
"Name": element.Name, "Name": element.Name,
"AuthorOrganizationName": get_owner_name(element),
"AuthorDate": get_owner_creation_date(ifc_file.by_type("IfcProject")[0]),
"Category": get_classification(element),
"ProjectName": ifc_file.by_type("IfcProject")[0].Name, "ProjectName": ifc_file.by_type("IfcProject")[0].Name,
"SiteName": getattr(get_facility_parent(element, "IfcSite"), "Name", None), "SiteName": getattr(get_facility_parent(element, "IfcSite"), "Name", None),
"LinearUnits": "millimeters", "Category": get_classification(element),
"AreaUnits": "square meters", "AuthorOrganizationName": get_owner_name(element),
"AreaMeasurement": "BIM Software", "AuthorDate": get_owner_creation_date(ifc_file.by_type("IfcProject")[0]),
"Phase": ifc_file.by_type("IfcProject")[0].Phase,
"ModelSoftware": get_owner_application(element), "ModelSoftware": get_owner_application(element),
"ModelProjectID": ifc_file.by_type("IfcProject")[0].GlobalId, "ModelProjectID": ifc_file.by_type("IfcProject")[0].GlobalId,
"ModelSiteID": getattr(get_facility_parent(element, "IfcSite"), "GlobalId", None), "ModelSiteID": getattr(get_facility_parent(element, "IfcSite"), "GlobalId", None),
"ModelBuildingID": element.GlobalId, "ModelBuildingID": element.GlobalId,
"LinearUnits": "millimeters",
"AreaUnits": "square meters",
"AreaMeasurement": "BIM Software",
"Phase": ifc_file.by_type("IfcProject")[0].Phase,
} }
@@ -315,9 +354,9 @@ def get_storey_data(ifc_file, element):
return { return {
"key": element.Name, "key": element.Name,
"Name": element.Name, "Name": element.Name,
"Category": "Level",
"AuthorOrganizationName": get_owner_name(element), "AuthorOrganizationName": get_owner_name(element),
"AuthorDate": get_owner_creation_date(element), "AuthorDate": get_owner_creation_date(element),
"Category": "Level",
"ModelSoftware": get_owner_application(element), "ModelSoftware": get_owner_application(element),
"ModelObject": element.is_a(), "ModelObject": element.is_a(),
"ModelID": element.GlobalId, "ModelID": element.GlobalId,
@@ -330,11 +369,11 @@ def get_space_data(ifc_file, element):
return { return {
"key": element.Name, "key": element.Name,
"Name": element.Name, "Name": element.Name,
"AuthorOrganizationName": get_owner_name(element), "Description": element.LongName,
"AuthorDate": get_owner_creation_date(element),
"Category": get_classification(element), "Category": get_classification(element),
"LevelName": getattr(get_facility_parent(element, "IfcBuildingStorey"), "Name", None), "LevelName": getattr(get_facility_parent(element, "IfcBuildingStorey"), "Name", None),
"Description": element.LongName, "AuthorOrganizationName": get_owner_name(element),
"AuthorDate": get_owner_creation_date(element),
"ModelSoftware": get_owner_application(element), "ModelSoftware": get_owner_application(element),
"ModelID": element.GlobalId, "ModelID": element.GlobalId,
"AreaGross": get_property(psets, "Qto_SpaceBaseQuantities", "GrossFloorArea", decimals=2), "AreaGross": get_property(psets, "Qto_SpaceBaseQuantities", "GrossFloorArea", decimals=2),
@@ -347,9 +386,9 @@ def get_zone_data(ifc_file, element):
return { return {
"key": (element.Name or "Unnamed") + (space.Name or "Unnamed"), "key": (element.Name or "Unnamed") + (space.Name or "Unnamed"),
"Name": zone.Name, "Name": zone.Name,
"SpaceName": space.Name,
"AuthorOrganizationName": get_owner_name(zone), "AuthorOrganizationName": get_owner_name(zone),
"AuthorDate": get_owner_creation_date(zone), "AuthorDate": get_owner_creation_date(zone),
"SpaceName": space.Name,
"ModelSoftware": get_owner_application(zone), "ModelSoftware": get_owner_application(zone),
"ModelID": zone.GlobalId, "ModelID": zone.GlobalId,
} }
@@ -359,10 +398,10 @@ def get_type_data(ifc_file, element):
return { return {
"key": element.Name, "key": element.Name,
"Name": element.Name, "Name": element.Name,
"Description": element.Description,
"Category": get_classification(element),
"AuthorOrganizationName": get_owner_name(element), "AuthorOrganizationName": get_owner_name(element),
"AuthorDate": get_owner_creation_date(element), "AuthorDate": get_owner_creation_date(element),
"Category": get_classification(element),
"Description": element.Description,
"ModelSoftware": get_owner_application(element), "ModelSoftware": get_owner_application(element),
"ModelObject": "{}[{}]".format(element.is_a(), ifcopenshell.util.element.get_predefined_type(element)), "ModelObject": "{}[{}]".format(element.is_a(), ifcopenshell.util.element.get_predefined_type(element)),
"ModelTag": element.Tag, "ModelTag": element.Tag,
@@ -378,11 +417,11 @@ def get_element_data(ifc_file, element):
return { return {
"key": element.Name, "key": element.Name,
"Name": element.Name, "Name": element.Name,
"AuthorOrganizationName": get_owner_name(element),
"AuthorDate": get_owner_creation_date(element),
"TypeName": ifcopenshell.util.element.get_type(element).Name, "TypeName": ifcopenshell.util.element.get_type(element).Name,
"SpaceName": space_name, "SpaceName": space_name,
"SystemName": system, "SystemName": system,
"AuthorOrganizationName": get_owner_name(element),
"AuthorDate": get_owner_creation_date(element),
"ModelSoftware": get_owner_application(element), "ModelSoftware": get_owner_application(element),
"ModelObject": "{}[{}]".format(element.is_a(), ifcopenshell.util.element.get_predefined_type(element)), "ModelObject": "{}[{}]".format(element.is_a(), ifcopenshell.util.element.get_predefined_type(element)),
"ModelID": element.GlobalId, "ModelID": element.GlobalId,
@@ -394,9 +433,9 @@ def get_system_data(ifc_file, element):
"key": element.Name, "key": element.Name,
"Name": element.Name, "Name": element.Name,
"Description": element.Description, "Description": element.Description,
"Category": get_classification(element),
"AuthorOrganizationName": get_owner_name(element), "AuthorOrganizationName": get_owner_name(element),
"AuthorDate": get_owner_creation_date(element), "AuthorDate": get_owner_creation_date(element),
"Category": get_classification(element),
"ModelSoftware": get_owner_application(element), "ModelSoftware": get_owner_application(element),
"ModelID": element.GlobalId, "ModelID": element.GlobalId,
} }