mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-06 07:51:47 +00:00
See #6570. Formula column for ifc5d import from csv
Now it's possible to specify the Formula column in the csv in order to calculate cost item quantities
This commit is contained in:
committed by
Massimo Fabbro
parent
2c2d0f2434
commit
528964ca56
@@ -55,6 +55,9 @@ class CsvHeader(TypedDict):
|
||||
RateSchedule: NotRequired[str]
|
||||
RateID: NotRequired[str]
|
||||
|
||||
# Formula
|
||||
Formula: NotRequired[str]
|
||||
#QuantityClass: NotRequired[str]
|
||||
|
||||
# Currently we assume that if column is not part of the main header,
|
||||
# then it is a cost value category. So here we list any additional column
|
||||
@@ -91,6 +94,8 @@ class CostItem(TypedDict):
|
||||
Property: Union[str, None]
|
||||
Query: Union[str, None]
|
||||
|
||||
Formula: Union[str, None]
|
||||
#QuantityClass: Union[str, None]
|
||||
|
||||
class Csv2Ifc:
|
||||
# Inputs.
|
||||
@@ -108,6 +113,7 @@ class Csv2Ifc:
|
||||
categories: dict[str, int]
|
||||
has_categories: bool
|
||||
has_rates: bool
|
||||
has_formula: bool
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -163,9 +169,13 @@ class Csv2Ifc:
|
||||
if not self.headers:
|
||||
self.has_categories = True
|
||||
self.has_rates = False
|
||||
self.has_categories = False
|
||||
self.has_formula = False
|
||||
self.headers = {col: i for i, col in enumerate(row) if col}
|
||||
if "RateSchedule" in self.headers and "RateID" in self.headers:
|
||||
self.has_rates = True
|
||||
if "Formula" in self.headers:
|
||||
self.has_formula = True
|
||||
if "Value" in self.headers:
|
||||
self.has_categories = False
|
||||
else:
|
||||
@@ -233,6 +243,11 @@ class Csv2Ifc:
|
||||
else:
|
||||
cost_rate = None
|
||||
|
||||
if self.has_formula:
|
||||
cost_formula = row[(self.headers["Formula"])] if "Formula" in self.headers else None
|
||||
else:
|
||||
cost_formula = None
|
||||
|
||||
return {
|
||||
"Identification": str(identification) if identification else None,
|
||||
"Name": str(name) if name else None,
|
||||
@@ -244,6 +259,7 @@ class Csv2Ifc:
|
||||
"Query": query,
|
||||
"children": [],
|
||||
"CostRate": cost_rate,
|
||||
"Formula": cost_formula,
|
||||
}
|
||||
|
||||
def create_ifc(self) -> None:
|
||||
@@ -381,17 +397,31 @@ class Csv2Ifc:
|
||||
# and some query in "Query" column.
|
||||
# If query is provided it will override the defined value
|
||||
# due current behaviour in cost.assign_cost_item_quantity.
|
||||
if results:
|
||||
if results and not cost_item["Formula"]:
|
||||
ifcopenshell.api.cost.assign_cost_item_quantity(
|
||||
self.file,
|
||||
cost_item=cost_item["ifc"],
|
||||
products=results,
|
||||
prop_name=prop_name,
|
||||
)
|
||||
elif not quantity:
|
||||
elif not quantity and not cost_item["Formula"]:
|
||||
quantity = ifcopenshell.api.cost.add_cost_item_quantity(
|
||||
self.file, cost_item=cost_item["ifc"], ifc_class=quantity_class
|
||||
)
|
||||
if cost_item["Formula"]:
|
||||
results = ifcopenshell.util.selector.filter_elements(self.file, cost_item["Query"])
|
||||
results = [r for r in results]
|
||||
ifc_quantity_class = ifcopenshell.util.unit.get_symbol_quantity_class(cost_item["Unit"])
|
||||
try:
|
||||
quantity = ifcopenshell.api.cost.assign_cost_item_quantity(
|
||||
self.file,
|
||||
cost_item=cost_item["ifc"],
|
||||
products=results,
|
||||
formula=cost_item["Formula"],
|
||||
ifc_class=ifc_quantity_class,
|
||||
)
|
||||
except:
|
||||
quantity=0
|
||||
|
||||
self.create_cost_items(cost_item["children"], cost_item["ifc"])
|
||||
|
||||
|
||||
@@ -125,14 +125,14 @@ class Usecase:
|
||||
settings: dict[str, Any]
|
||||
|
||||
def execute(self):
|
||||
if self.settings["prop_name"]:
|
||||
if self.settings["prop_name"] or self.settings["formula"]:
|
||||
self.quantities = set(self.settings["cost_item"].CostQuantities or [])
|
||||
for product in self.settings["products"]:
|
||||
if product.is_a("IfcSpatialElement"):
|
||||
continue
|
||||
self.assign_cost_control(related_object=product, cost_item=self.settings["cost_item"])
|
||||
if self.settings["formula"]:
|
||||
# not so much elegant, but simple and useful because variables can't has the dot in the name
|
||||
# not so much elegant, but simple and useful because variables can't have the dot in the name
|
||||
# and Psets have the dot
|
||||
separator = "0"
|
||||
variables = self.extract_variables(self.settings["formula"])
|
||||
@@ -153,9 +153,8 @@ class Usecase:
|
||||
result = eval(formula_modified, {}, variables_modified)
|
||||
|
||||
new_quantity = None
|
||||
self.quantities = set(self.settings["cost_item"].CostQuantities or [])
|
||||
for quantity in self.quantities:
|
||||
if quantity.Formula == self.settings["formula"]:
|
||||
if quantity.Formula == self.settings["formula"] and len(self.settings["products"]) == 1: #Todo improve it
|
||||
new_quantity = quantity
|
||||
self.settings["ifc_class"] = quantity.is_a()
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user