Material Filters
Material
(
$categories := ["Profiles","Supports","Detail Items"];
$familyIds := $[type = "Family"].id;
$[
type = "FamilySymbol"
and parent.id in $familyIds
and $not(values.category.name in $categories)
and $exists(values.solids.allFacesHaveMaterial)
and values.solids.allFacesHaveMaterial != null
].{
"id": id,
"type": type,
"name": name,
"allFacesHaveMaterial":
$not(false in ($type(values.solids.allFacesHaveMaterial) = "array"
? values.solids.allFacesHaveMaterial
: [values.solids.allFacesHaveMaterial]))
}
)
All Materials
(
/* 1) collect ids of all MaterialId parameters */
$matParamIds := $$[type = "Parameter" and values.spec = "MaterialId"].id;
/* 2) keys in an object that start with p_ */
$getPKeys := function($values){
$filter($keys($values), function($k){ $match($k, /^p_/) })
};
/* 3) only the p_* keys that are MaterialId parameters */
$getMaterialSPKeys := function($values){
$filter(
$getPKeys($values),
function($k){
$exists($lookup($values,$k)) and
$lookup($values,$k).ref = "Parameter" and
($count($matParamIds[$ = $lookup($values,$k).id]) > 0)
}
)
};
/* Returns a single name for a single id, or an array of names for an array of ids */
$nameById := function($id){
($type($id) = "array")
? $map($id, function($i){ ($$[id = $i])[0].name })
: ($$[id = $id])[0].name
};
/* 5) details for those keys (adds valueName by id-lookup) */
$getMaterialSPDetails := function($values){
$map(
$getMaterialSPKeys($values),
function($k){
{
"key": $k,
"paramId": $lookup($values,$k).id,
"value": $lookup($values,$k).value,
"valueAsString": $lookup($values,$k).valueAsString,
"valueName": $nameById($lookup($values,$k).value)
}
}
)
};
/* 6) helper: get a FamilySymbol's values by id */
$symbolValues := function($symbolId){
($$[type = "FamilySymbol" and id = $symbolId])[0].values
};
/* RESULT: only FamilyInstances with MaterialId SPs (self or parent) */
$[
type = "FamilyInstance" and
(
$count($getMaterialSPKeys(values)) > 0 or
$count($getMaterialSPKeys($symbolValues(parent.id))) > 0
)
].{
"id": id,
"name": name,
"parentId": parent.id,
"parentName": ($$[type = "FamilySymbol" and id = parent.id])[0].name,
"materialNames":$nameById(values.materialIds),
/* instance structural material + name */
"instance_structuralMaterialId": values.structuralMaterialId,
"instance_structuralMaterialName": $nameById(values.structuralMaterialId),
/* parent symbol structural material + name */
"symbol_structuralMaterialId": $symbolValues(parent.id).structuralMaterialId,
"symbol_structuralMaterialName": $nameById($symbolValues(parent.id).structuralMaterialId),
/* combined details (tag source) */
"materialSP_details": $append(
$map($getMaterialSPDetails(values), function($d){ $merge([$d, {"source":"instance"}]) }),
$map($getMaterialSPDetails($symbolValues(parent.id)), function($d){ $merge([$d, {"source":"symbol"}]) })
)
}
)
all Material parameters
(
/* 1) collect ids of all MaterialId parameters */
$matParamIds := $$[type = "Parameter" and values.spec = "MaterialId"].id;
/* 2) keys in an object that start with p_ */
$getPKeys := function($values){
$filter($keys($values), function($k){ $match($k, /^p_/) })
};
/* 3) only the p_* keys that are MaterialId parameters */
$getMaterialSPKeys := function($values){
$filter(
$getPKeys($values),
function($k){
$exists($lookup($values,$k)) and
$lookup($values,$k).ref = "Parameter" and
($count($matParamIds[$ = $lookup($values,$k).id]) > 0)
}
)
};
/* 4 Returns a single name for a single id, or an array of names for an array of ids */
$nameById := function($id){
($type($id) = "array")
? $map($id, function($i){ ($$[id = $i])[0].name })
: ($$[id = $id])[0].name
};
/* 4a Returns a single name for a single id, or an array of names for an array of ids */
$nameArrayById := function($ids){
$filter(
$map( ($type($ids) = "array") ? $ids : [$ids],
function($i){ ($$[id = $i])[0].name } ),
function($n){ $exists($n) }
)
};
/* 5) details for those keys (adds valueName by id-lookup) */
$getMaterialSPDetails := function($values){
$map(
$getMaterialSPKeys($values),
function($k){
{
"key": $k,
"paramId": $lookup($values,$k).id,
"value": $lookup($values,$k).value,
"valueAsString": $lookup($values,$k).valueAsString,
"valueName": $nameById($lookup($values,$k).value)
}
}
)
};
/* 6) helper: get a FamilySymbol's values by id */
$symbolValues := function($symbolId){
($$[type = "FamilySymbol" and id = $symbolId])[0].values
};
/* RESULT: only FamilyInstances with MaterialId SPs (self or parent) */
$[
type = "FamilyInstance" and
(
$count($getMaterialSPKeys(values)) > 0 or
$count($getMaterialSPKeys($symbolValues(parent.id))) > 0
)
].{
"id": id,
"name": name,
"parentId": parent.id,
"parentName": ($$[type = "FamilySymbol" and id = parent.id])[0].name,
"materialNames":$count($nameArrayById(values.materialIds))> 0 ? $nameArrayById(values.materialIds):"",
/* instance structural material + name */
"instance_structuralMaterialId": values.structuralMaterialId,
"instance_structuralMaterialName": $exists($nameById(values.structuralMaterialId))?$nameById(values.structuralMaterialId):"",
/* parent symbol structural material + name */
"symbol_structuralMaterialId": $symbolValues(parent.id).structuralMaterialId,
"symbol_structuralMaterialName": $exists($nameById($symbolValues(parent.id).structuralMaterialId))?$nameById($symbolValues(parent.id).structuralMaterialId):"",
/* combined details (tag source) */
"materialSP_details": $append(
$map($getMaterialSPDetails(values), function($d){ $merge([$d, {"source":"instance"}]) }),
$map($getMaterialSPDetails($symbolValues(parent.id)), function($d){ $merge([$d, {"source":"symbol"}]) })
)
}
)
example
```JSONata (
/* Drop null/empty, then dedupe */
$cleanDistinct := function($arr){
$distinct(
$filter($arr, function($n){
$exists($n) and $type($n) = "string" and $trim($n) != ""
/* Optional: also drop placeholders like "{$ElementID}" */
/* and not $match($n, /^\{\$.*\}$/) */
})
)
};
/ Collect ids of all MaterialId parameters / $matParamIds := $$[type = "Parameter" and values.spec = "MaterialId"].id;
/ p_ keys in an object */ $getPKeys := function($values){ $filter($keys($values), function($k){ $match($k, /^p_/) }) };
/ p_ keys that are MaterialId parameters */ $getMaterialSPKeys := function($values){ $filter( $getPKeys($values), function($k){ $exists($lookup($values,$k)) and $lookup($values,$k).ref = "Parameter" and ($count($matParamIds[$ = $lookup($values,$k).id]) > 0) } ) };
/ Always return array of names for id(s) (skip nulls) / $nameArrayById := function($ids){ $filter( $map( ($type($ids) = "array") ? $ids : ($exists($ids) ? [$ids] : []), function($i){ ($$[id = $i])[0].name } ), function($n){ $exists($n) } ) };
/ Details for MaterialId SP keys / $getMaterialSPDetails := function($values){ $map( $getMaterialSPKeys($values), function($k){ { "key": $k, "paramId": $lookup($values,$k).id, "value": $lookup($values,$k).value, "valueAsString": $lookup($values,$k).valueAsString, "valueName": $nameArrayById($lookup($values,$k).value)[0] } } ) };
/ NEW: names from SPs using valueAsString / $getMatNamesFromSPStrings := function($values){ $filter( $map($getMaterialSPKeys($values), function($k){ $lookup($values,$k).valueAsString }), function($s){ $exists($s) and $s != "" } ) };
/ Parent symbol helpers / $symbolValues := function($symbolId){ ($$[type = "FamilySymbol" and id = $symbolId])[0].values }; $ensureObj := function($x){ ($type($x) = "object") ? $x : {} };
/ Concat arrays, then dedupe / $concat := function($arrs){ $reduce($arrs, function($a,$b){ $append($a,$b) }, []) };
/* Collect all material names (instance + symbol) incl. SP.valueAsString */
$collectAllMaterialNames := function($instVals, $symVals){
$cleanDistinct(
$concat([
$nameArrayById($instVals.materialIds),
$nameArrayById($symVals.materialIds),
$nameArrayById($instVals.structuralMaterialId),
$nameArrayById($symVals.structuralMaterialId),
$nameArrayById($map($getMaterialSPKeys($instVals), function($k){ $lookup($instVals,$k).value })),
$nameArrayById($map($getMaterialSPKeys($symVals), function($k){ $lookup($symVals,$k).value })),
$getMatNamesFromSPStrings($instVals),
$getMatNamesFromSPStrings($symVals)
])
)
};
/ RESULT / $[ type = "FamilyInstance" and ( $count($getMaterialSPKeys(values)) > 0 or $count($getMaterialSPKeys($ensureObj($symbolValues(parent.id)))) > 0 ) ].{ "id": id, "name": name, "parentId": parent.id, "parentName": ($$[type = "FamilySymbol" and id = parent.id])[0].name,
/* Single, de-duplicated list incl. SP.valueAsString */
"allMaterialNames": $join($collectAllMaterialNames(values, $ensureObj($symbolValues(parent.id))),", "),
/* Keep details if you like */
"materialSP_details": $append(
$map($getMaterialSPDetails(values), function($d){ $merge([$d, {"source":"instance"}]) }),
$map($getMaterialSPDetails($ensureObj($symbolValues(parent.id))), function($d){ $merge([$d, {"source":"symbol"}]) })
)
} )```
```jsonata ( / Drop null/empty, then dedupe / $cleanDistinct := function($arr){ $distinct( $filter($arr, function($n){ $exists($n) and $type($n) = "string" and $trim($n) != "" / Optional: also drop placeholders like "{$ElementID}" / / and not $match($n, /^{\$.}$/) / }) ) }; / Collect ids of all MaterialId parameters */ $matParamIds := $$[type = "Parameter" and values.spec = "MaterialId"].id;
/ p_ keys in an object */ $getPKeys := function($values){ $filter($keys($values), function($k){ $match($k, /^p_/) }) };
/ p_ keys that are MaterialId parameters */ $getMaterialSPKeys := function($values){ $filter( $getPKeys($values), function($k){ $exists($lookup($values,$k)) and $lookup($values,$k).ref = "Parameter" and ($count($matParamIds[$ = $lookup($values,$k).id]) > 0) } ) };
/ Always return array of names for id(s) (skip nulls) / $nameArrayById := function($ids){ $filter( $map( ($type($ids) = "array") ? $ids : ($exists($ids) ? [$ids] : []), function($i){ ($$[id = $i])[0].name } ), function($n){ $exists($n) } ) };
/ Details for MaterialId SP keys / $getMaterialSPDetails := function($values){ $map( $getMaterialSPKeys($values), function($k){ { "key": $k, "paramId": $lookup($values,$k).id, "value": $lookup($values,$k).value, "valueAsString": $lookup($values,$k).valueAsString, "valueName": $nameArrayById($lookup($values,$k).value)[0] } } ) };
/ NEW: names from SPs using valueAsString / $getMatNamesFromSPStrings := function($values){ $filter( $map($getMaterialSPKeys($values), function($k){ $lookup($values,$k).valueAsString }), function($s){ $exists($s) and $s != "" } ) };
/ Parent symbol helpers / $symbolValues := function($symbolId){ ($$[type = "FamilySymbol" and id = $symbolId])[0].values }; $ensureObj := function($x){ ($type($x) = "object") ? $x : {} };
/ Concat arrays, then dedupe / $concat := function($arrs){ $reduce($arrs, function($a,$b){ $append($a,$b) }, []) };
/* Collect all material names (instance + symbol) incl. SP.valueAsString */
$collectAllMaterialNames := function($instVals, $symVals){
$cleanDistinct(
$concat([
$nameArrayById($instVals.materialIds),
$nameArrayById($symVals.materialIds),
$nameArrayById($instVals.structuralMaterialId),
$nameArrayById($symVals.structuralMaterialId),
$nameArrayById($map($getMaterialSPKeys($instVals), function($k){ $lookup($instVals,$k).value })),
$nameArrayById($map($getMaterialSPKeys($symVals), function($k){ $lookup($symVals,$k).value })),
$getMatNamesFromSPStrings($instVals),
$getMatNamesFromSPStrings($symVals)
])
)
};
/ RESULT / $[ type = "FamilyInstance" and ( $count($getMaterialSPKeys(values)) > 0 or $count($getMaterialSPKeys($ensureObj($symbolValues(parent.id)))) > 0 ) ].{ "id": id, "name": name, "parentId": parent.id, "parentName": ($$[type = "FamilySymbol" and id = parent.id])[0].name, "allMaterialNames": $count($collectAllMaterialNames(values, $ensureObj($symbolValues(parent.id)),", "))>0?$join($collectAllMaterialNames(values, $ensureObj($symbolValues(parent.id))),", "):"", "allMaterialNamesNum": $count($collectAllMaterialNames(values, $ensureObj($symbolValues(parent.id))),), } ) ````