From 312b2aecf078f729da3f27957e59fc3af2b19bcd Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sun, 20 Aug 2023 14:41:34 +1000 Subject: [PATCH] Fix #3607. IfcCSV now supports omitting the GlobalId column. This is great for presentation schedules, but the tradeoff is that you can't use it for imports. --- .../blenderbim/bim/module/csv/operator.py | 13 +++++- .../blenderbim/bim/module/csv/prop.py | 3 ++ .../blenderbim/bim/module/csv/ui.py | 8 +++- src/ifccsv/ifccsv.py | 40 +++++++++++++++---- 4 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/csv/operator.py b/src/blenderbim/blenderbim/bim/module/csv/operator.py index 9e82522be4..baff11e62b 100644 --- a/src/blenderbim/blenderbim/bim/module/csv/operator.py +++ b/src/blenderbim/blenderbim/bim/module/csv/operator.py @@ -155,7 +155,10 @@ class ExportIfcCsv(bpy.types.Operator): output=self.filepath, format=props.format, delimiter=sep, + include_global_id=props.include_global_id, null=props.null_value, + bool_true=props.true_value, + bool_false=props.false_value, ) return {"FINISHED"} @@ -183,7 +186,15 @@ class ImportIfcCsv(bpy.types.Operator): ifc_csv = ifccsv.IfcCsv() sep = props.csv_custom_delimiter if props.csv_delimiter == "CUSTOM" else props.csv_delimiter attributes = [a.name for a in props.csv_attributes] - ifc_csv.Import(ifc_file, self.filepath, attributes=attributes, delimiter=sep, null=props.null_value) + ifc_csv.Import( + ifc_file, + self.filepath, + attributes=attributes, + delimiter=sep, + null=props.null_value, + bool_true=props.true_value, + bool_false=props.false_value, + ) if not props.should_load_from_memory: ifc_file.write(props.csv_ifc_file) purge_module_data() diff --git a/src/blenderbim/blenderbim/bim/module/csv/prop.py b/src/blenderbim/blenderbim/bim/module/csv/prop.py index aca72d6dd9..f718283be3 100644 --- a/src/blenderbim/blenderbim/bim/module/csv/prop.py +++ b/src/blenderbim/blenderbim/bim/module/csv/prop.py @@ -54,7 +54,10 @@ class CsvProperties(PropertyGroup): ], ) csv_attributes: CollectionProperty(name="CSV Attributes", type=CsvAttribute) + include_global_id: BoolProperty(default=True, name="Include GlobalId") null_value: StringProperty(default="N/A", name="Null Value") + true_value: StringProperty(default="YES", name="True Value") + false_value: StringProperty(default="NO", name="False Value") csv_delimiter: EnumProperty( items=[ (";", ";", ""), diff --git a/src/blenderbim/blenderbim/bim/module/csv/ui.py b/src/blenderbim/blenderbim/bim/module/csv/ui.py index 3a32559c4d..b927af30ad 100644 --- a/src/blenderbim/blenderbim/bim/module/csv/ui.py +++ b/src/blenderbim/blenderbim/bim/module/csv/ui.py @@ -67,8 +67,14 @@ class BIM_PT_ifccsv(Panel): row = layout.row(align=True) row.prop(props, "csv_custom_delimiter") - row = layout.row(align=True) + row = layout.row() + row.prop(props, "include_global_id") + row = layout.row() row.prop(props, "null_value") + row = layout.row() + row.prop(props, "true_value") + row = layout.row() + row.prop(props, "false_value") blenderbim.bim.helper.draw_filter(self.layout, props, SearchData, "csv") diff --git a/src/ifccsv/ifccsv.py b/src/ifccsv/ifccsv.py index a5c6e17599..8e20cb860c 100755 --- a/src/ifccsv/ifccsv.py +++ b/src/ifccsv/ifccsv.py @@ -54,17 +54,31 @@ class IfcCsv: self.results = [] self.dataframe = None - def export(self, ifc_file, elements, attributes, headers=None, output=None, format=None, delimiter=",", null=None): + def export( + self, + ifc_file, + elements, + attributes, + headers=None, + output=None, + format=None, + include_global_id=True, + delimiter=",", + null="-", + bool_true="YES", + bool_false="NO", + ): self.ifc_file = ifc_file self.results = [] if not headers: headers = [None] * len(attributes) for element in elements: result = [] - if hasattr(element, "GlobalId"): - result.append(element.GlobalId) - else: - result.append(None) + if include_global_id: + if hasattr(element, "GlobalId"): + result.append(element.GlobalId) + else: + result.append(None) for index, attribute in enumerate(attributes or []): if "*" in attribute: @@ -75,10 +89,14 @@ class IfcCsv: value = ifcopenshell.util.selector.get_element_value(element, attribute) if value is None: value = null + elif value is True: + value = bool_true + elif value is False: + value = bool_false result.append(value) self.results.append(result) - self.headers = ["GlobalId"] + self.headers = ["GlobalId"] if include_global_id else [] for i, attribute in enumerate(attributes or []): if headers[i]: self.headers.append(headers[i]) @@ -190,7 +208,7 @@ class IfcCsv: results.update([p.Name for p in element.Quantities]) return ["{}.{}".format(pset_qto_name, n) for n in results] - def Import(self, ifc_file, table, attributes=None, delimiter=",", null="-"): + def Import(self, ifc_file, table, attributes=None, delimiter=",", null="-", bool_true="YES", bool_false="NO"): # Currently only supports CSV. with open(table, newline="", encoding="utf-8") as f: reader = csv.reader(f, delimiter=delimiter) @@ -215,6 +233,10 @@ class IfcCsv: continue # Skip GlobalId if value == null: value = None + elif value == bool_true: + value = True + elif value == bool_false: + value = False key = attributes[i] or headers[i] ifcopenshell.util.selector.set_element_value(ifc_file, element, key, value) @@ -262,5 +284,7 @@ if __name__ == "__main__": elif getattr(args, "import"): ifc_csv = IfcCsv() ifc_file = ifcopenshell.open(args.ifc) - ifc_csv.Import(ifc_file, args.spreadsheet, attributes=args.attributes or [], delimiter=args.delimiter, null=args.null) + ifc_csv.Import( + ifc_file, args.spreadsheet, attributes=args.attributes or [], delimiter=args.delimiter, null=args.null + ) ifc_file.write(args.ifc)