{"id":2018,"date":"2024-05-16T10:30:00","date_gmt":"2024-05-16T00:30:00","guid":{"rendered":"https:\/\/digitalbbq.au\/?p=2018"},"modified":"2024-05-08T07:35:44","modified_gmt":"2024-05-07T21:35:44","slug":"expanding-on-ifc-metadata-extraction-in-powerbi","status":"publish","type":"post","link":"https:\/\/digitalbbq.au\/index.php\/2024\/05\/16\/expanding-on-ifc-metadata-extraction-in-powerbi\/","title":{"rendered":"Expanding on IFC Metadata Extraction in PowerBI"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">In a previous post, &#8220;<a href=\"https:\/\/digitalbbq.au\/index.php\/2024\/05\/02\/extracting-ifc-metadata-directly-in-power-bi-using-power-query\/\" data-type=\"post\" data-id=\"2005\">Extracting IFC Metadata Directly in Power BI Using Power Query<\/a>,&#8221; we explored how to use Power Query in PowerBI to directly extract metadata from IFC files using a <a href=\"https:\/\/github.com\/shift-construction\/ifc4PowerBI\" data-type=\"link\" data-id=\"https:\/\/github.com\/shift-construction\/ifc4PowerBI\">Power Query shared by Shift Construction<\/a>. If you haven&#8217;t read that post, I recommend checking it out first for context. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A few people reached out as they found the instructions provided to import the IFC file by Shift were a little confusing, especially for the new and novice PowerBI users. So in this follow-up, we&#8217;ll look at some improvements and modifications to the original Power Query code to streamline the process even further<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Create Table Directly From IFC File<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We can resolve the confusion with importing the IFC with a slight modification to the code. His modification allows you to import your IFC data in one step on a model-by-model basis. The change is made in the first few lines like so:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">let<\/span>\n    Source = <span class=\"hljs-function\">(<span class=\"hljs-params\">filePath <span class=\"hljs-keyword\">as<\/span> text<\/span>) =&gt;<\/span> \n    <span class=\"hljs-keyword\">let<\/span>\n        <span class=\"hljs-comment\">\/\/ Initial Import using File.Contents to read file from a path<\/span>\n        BinaryContent = File.Contents(filePath),\n        Source = Table.FromColumns({Lines.FromBinary(BinaryContent, <span class=\"hljs-literal\">null<\/span>, <span class=\"hljs-literal\">null<\/span>, <span class=\"hljs-number\">1252<\/span>)}),\n        <span class=\"hljs-comment\">\/\/ The remaining steps follow on from here...<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This small change allows you to generate a table directly from the IFC file. Once this change is made, the steps to import the IFC are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Find your IFC in file explorer<\/li>\n\n\n\n<li>Right-click, and select &#8220;Copy as path&#8221; (Windows 11)<\/li>\n\n\n\n<li>Open PowerBI to the <em>Transform Data<\/em> window<\/li>\n\n\n\n<li>Find the IFC4PowerBI function<\/li>\n\n\n\n<li>Paste the path, removing the quotes<\/li>\n\n\n\n<li>Click <em>Invoke<\/em><\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"372\" src=\"https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/05\/image-1024x372.png\" alt=\"\" class=\"wp-image-2021\" srcset=\"https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/05\/image-1024x372.png 1024w, https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/05\/image-300x109.png 300w, https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/05\/image-768x279.png 768w, https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/05\/image-576x209.png 576w, https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/05\/image.png 1350w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">After following those steps, the function will generate a new table named <em>Invoked Function<\/em>. You can rename the new table and use the in your data visualisations. Not only that, but you can use the function as many times as you want to import IFC data for as many files as you like, the only limitation being your computer&#8217;s hardware.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Optimise Performance with Buffering<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If you have already played around with the original Power Query, you may notice your CPU fan starts spinning as the data is processing and the initial load can take some time. You may have also noticed that the status bar at the bottom right of PowerBI shows the amount of data read is significantly more than the size of your original IFC file.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is because in the original query, the dataset created by <em>ExtractBeforeCloseParenthesis<\/em> is used multiple times throughout the query. Each time this data is called upon, it is written to disk as new data, and practically the entire IFC file is contained within this dataset. The only thing missing a few lines that contain null values in the initial extraction. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can resolve this by modifying the original query to include <em>Table.Buffer(<\/em> on <em>ExtractBeforeCloseParenthesis<\/em>. The modified section of the query should look like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ Extract Data Before Close Parenthesis<\/span>\n      ExtractBeforeCloseParenthesis = Table.Buffer(Table.TransformColumns(\n        SplitByOpenParenthesis, \n        {{<span class=\"hljs-string\">\"Values\"<\/span>, each Text.BeforeDelimiter(_, <span class=\"hljs-string\">\")\"<\/span>, {<span class=\"hljs-number\">0<\/span>, RelativePosition.FromEnd}), type text}}\n      )), <\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This minor change means that <em>ExtractBeforeCloseParenthesis<\/em> will be loaded to memory once, and once loaded, <a href=\"https:\/\/learn.microsoft.com\/en-us\/powerquery-m\/table-buffer\" data-type=\"link\" data-id=\"https:\/\/learn.microsoft.com\/en-us\/powerquery-m\/table-buffer\">it is isolated from external changes during evaluation<\/a> and will be referenced throughout the remainder of the query. Using a 38mb IFC file as an example, this change reduces the data loaded when processing the query from ~150mb to 39mb.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can implement <em>Table.Buffer<\/em> elsewhere if you feel it&#8217;s warranted, but be mindful about how much data you&#8217;re buffering and that any data buffered will not take on changes. Some scenarios where <em>Table.Buffer<\/em> may be beneficial:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Multiple References<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>When your table or list will be referenced multiple times within your query (e.g., in a\u00a0<strong>List.Generate<\/strong>\u00a0function), using\u00a0<strong>Table.Buffer<\/strong>\u00a0can improve performance<a href=\"https:\/\/community.fabric.microsoft.com\/t5\/Power-Query\/When-to-use-Table-Buffer\/td-p\/2929784\" target=\"_blank\" rel=\"noreferrer noopener\"><sup>1<\/sup><\/a>.<\/li>\n\n\n\n<li>By buffering the table, you avoid recalculating it each time it\u2019s referenced, which can be especially helpful for large datasets.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Recursive Functions<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If you\u2019re working with recursive functions, consider using\u00a0<strong>Table.Buffer<\/strong>.<\/li>\n\n\n\n<li>Recursive functions often re-evaluate the same data repeatedly. Buffering the table prevents redundant recalculations and speeds up the process.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Before Merging<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Before merging tables, apply\u00a0<strong>Table.Buffer<\/strong>\u00a0to the target table.<\/li>\n\n\n\n<li>Merging involves comparing rows between tables. Buffering the target table ensures that it\u2019s loaded into memory, reducing the need for repeated scans.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Passing Tables to Functions<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>When passing tables to custom functions, consider buffering them.<\/li>\n\n\n\n<li>If your function processes the same table multiple times, buffering can enhance performance.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Buffering consumes memory, so use it wisely. If you\u2019re referencing a table only once, there\u2019s no advantage to buffering it.\u00a0Additionally, the impact of buffering depends on various factors, so always test your queries to find the optimal approach<a href=\"https:\/\/community.fabric.microsoft.com\/t5\/Power-Query\/Should-I-I-use-TABLE-BUFFER\/td-p\/2592084\" target=\"_blank\" rel=\"noreferrer noopener\"><sup>2<\/sup><\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Extracting Object Names<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When a colleague attempted to use the original query to run metadata checks, they found it had limited usefulness because they had certain metadata values that were tied to specific object name prefixes. The original query only extracts the property sets and none of the &#8220;element specific&#8221; data.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The way that I resolved this once the full table was generated, to take the resulting <em>Object ID<\/em> values and extract the individual line items from the IFC for that object, then finally splitting out the required object name and type information.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The information that appears as &#8220;element specific&#8221; in BIM Vision is found in the line related to the object itself, for example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">#8366= IFCCOLUMN('GUID Value',#41,'Object Name Value',$,'Object Type Name value',#8364,#8357,'Object Instance Identifier Value');<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">My approach to extracting this information was to go back to the <em>SplitByEquals<\/em> data, extract the matching lines, split the lines by the comma delimiter, then create new columns within the table to reflect the correct data.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;ll be the first to admit I&#8217;m no PowerBI whiz, so there may be a more efficient way to approach this, but for now, adding the following code to the query after <em>FinalSplit<\/em> seems to work well and without too much of a performance hit.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">        <span class=\"hljs-comment\">\/\/ Renaming columns to avoid conflicts<\/span>\n        RenamedSplitByEquals = Table.RenameColumns(\n            SplitByEquals,\n            {\n                {<span class=\"hljs-string\">\"Element ID\"<\/span>, <span class=\"hljs-string\">\"Element ID Renamed\"<\/span>}, \n                {<span class=\"hljs-string\">\"Values\"<\/span>, <span class=\"hljs-string\">\"Values Renamed\"<\/span>} <span class=\"hljs-comment\">\/\/ Example, rename as needed<\/span>\n            }\n        ),\n        <span class=\"hljs-comment\">\/\/ Add columns for \"Object Name\" and \"Object Type Name\", and remove quotes<\/span>\n        AddedObjectColumns = Table.AddColumn(\n            RenamedSplitByEquals,\n            <span class=\"hljs-string\">\"Object Name\"<\/span>,\n            each <span class=\"hljs-keyword\">let<\/span>\n                originalText = <span class=\"hljs-keyword\">try<\/span> Text.Split(&#91;Values Renamed], <span class=\"hljs-string\">\",\"<\/span>){<span class=\"hljs-number\">2<\/span>} otherwise <span class=\"hljs-literal\">null<\/span>,\n                cleanedText = Text.Replace(Text.Replace(originalText, <span class=\"hljs-string\">\"'\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>), <span class=\"hljs-string\">\"\"<\/span><span class=\"hljs-string\">\"\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>)\n            <span class=\"hljs-keyword\">in<\/span>\n                cleanedText,\n            type text\n        ),\n        AddedObjectTypeColumns = Table.AddColumn(\n            AddedObjectColumns,\n            <span class=\"hljs-string\">\"Object Type Name\"<\/span>,\n            each <span class=\"hljs-keyword\">let<\/span>\n                originalText = <span class=\"hljs-keyword\">try<\/span> Text.Split(&#91;Values Renamed], <span class=\"hljs-string\">\",\"<\/span>){<span class=\"hljs-number\">4<\/span>} otherwise <span class=\"hljs-literal\">null<\/span>,\n                cleanedText = Text.Replace(Text.Replace(originalText, <span class=\"hljs-string\">\"'\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>), <span class=\"hljs-string\">\"\"<\/span><span class=\"hljs-string\">\"\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>)\n            <span class=\"hljs-keyword\">in<\/span>\n                cleanedText,\n            type text\n        ),\n        <span class=\"hljs-comment\">\/\/ Performing the join<\/span>\n        JoinedData = Table.Join(\n            FinalSplit, \n            <span class=\"hljs-string\">\"Object ID\"<\/span>, \n            AddedObjectTypeColumns, \n            <span class=\"hljs-string\">\"Element ID Renamed\"<\/span>, \n            JoinKind.Inner\n        ),\n        <span class=\"hljs-comment\">\/\/ Remove the now unnecessary columns<\/span>\n        FinalCleanedTable = Table.RemoveColumns(\n            JoinedData,\n            {<span class=\"hljs-string\">\"Element ID Renamed\"<\/span>, <span class=\"hljs-string\">\"Values Renamed\"<\/span>}\n        )\n    <span class=\"hljs-keyword\">in<\/span>\n        FinalCleanedTable<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The reason why I generated these columns right at the end as I found it was significantly more efficient to have the full set of <em>Object ID<\/em> values and use a <em>JoinKind.Inner<\/em> to pull the data together. When I attempted to process the data mid-way through the query with a <em>Table.SelectRows<\/em> there was a significant performance hit. Although maybe all we needed was a buffer!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Once this last modification is made to the code, the dataset can be filtered by object name to gather more targeted insights and data validation.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"582\" src=\"https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/05\/image-1-1024x582.png\" alt=\"\" class=\"wp-image-2024\" srcset=\"https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/05\/image-1-1024x582.png 1024w, https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/05\/image-1-300x170.png 300w, https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/05\/image-1-768x436.png 768w, https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/05\/image-1-576x327.png 576w, https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/05\/image-1.png 1274w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">With these modifications to the original Power Query code &#8211; using TableFromColumns to generate the complete table in one step, and creating measures for key metrics &#8211; extracting and working with IFC metadata in PowerBI is now even more efficient and powerful.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As always, the full updated code is available on <a href=\"https:\/\/github.com\/ryanlenihan\/ifc4PowerBI\" data-type=\"link\" data-id=\"https:\/\/github.com\/ryanlenihan\/ifc4PowerBI\">Github<\/a> &#8211; feel free to use and adapt it for your own projects. If you have any other suggestions for working with IFC in PowerBI, I&#8217;d love to hear them.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In a previous post, &#8220;Extracting IFC Metadata Directly in Power BI Using Power Query,&#8221; we explored how to use Power Query in PowerBI to directly extract metadata from IFC files using a Power Query shared by Shift Construction. If you haven&#8217;t read that post, I recommend checking it out first for context. A few people reached out as they found&#8230;<\/p>\n","protected":false},"author":1,"featured_media":2028,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"Discover improved techniques for extracting and analyzing IFC metadata directly in PowerBI using Power Query. Optimize your workflow with our updated code.","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_seo_schema_type":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"Unlock the power of IFC metadata in #PowerBI with these #PowerQuery improvements! Check out the updated code and techniques in my latest blog post. #BIM #DataAnalytics #DigitalConstruction","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[1,78],"tags":[77,73],"class_list":["post-2018","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-digital","category-how-to-guides","tag-automation","tag-process"],"jetpack_publicize_connections":[],"jetpack-related-posts":[{"id":2005,"url":"https:\/\/digitalbbq.au\/index.php\/2024\/05\/02\/extracting-ifc-metadata-directly-in-power-bi-using-power-query\/","url_meta":{"origin":2018,"position":0},"title":"Extracting IFC Metadata Directly in Power BI Using Power Query","author":"Ryan Lenihan","date":"2 May 2024","format":false,"excerpt":"If you work with Industry Foundation Classes (IFC) files and want an easy way to access and analyze the metadata, there's a great article you should check out. \"How to extract data from IFC files\" by Matthew Osment on Medium demonstrates how to use Power Query in Power BI to\u2026","rel":"","context":"In &quot;Digital&quot;","block_context":{"text":"Digital","link":"https:\/\/digitalbbq.au\/index.php\/category\/digital\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2024\/04\/Shift_PowerBi_IFC.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2024\/04\/Shift_PowerBi_IFC.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2024\/04\/Shift_PowerBi_IFC.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2024\/04\/Shift_PowerBi_IFC.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2024\/04\/Shift_PowerBi_IFC.jpg?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2024\/04\/Shift_PowerBi_IFC.jpg?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":2403,"url":"https:\/\/digitalbbq.au\/index.php\/2025\/07\/17\/why-your-pipe-fittings-are-missing-materials-in-ifc-exports-and-how-to-fix-it\/","url_meta":{"origin":2018,"position":1},"title":"Your Pipe Fittings Are Grey in IFC? Here&#8217;s Why (And How to Fix It)","author":"Ryan Lenihan","date":"17 July 2025","format":false,"excerpt":"You\u2019ve exported your model to IFC. Pipes look great. Fittings? Grey. Again. What\u2019s going on? This one trips up a lot of teams, because pipe fittings in Revit don\u2019t actually carry system data, even though they look like they do. So when you rely on system-assigned materials for your IFC\u2026","rel":"","context":"In &quot;How to guides&quot;","block_context":{"text":"How to guides","link":"https:\/\/digitalbbq.au\/index.php\/category\/how-to-guides\/"},"img":{"alt_text":"Set of blue PVC pipe fittings isolated on dark background. Blue plastic water pipe. PVC accessories","src":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/set-of-blue-pvc-pipe-fittings-isolated-on-dark-background-blue-plastic-water-pipe-pvc-accessories.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/set-of-blue-pvc-pipe-fittings-isolated-on-dark-background-blue-plastic-water-pipe-pvc-accessories.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/set-of-blue-pvc-pipe-fittings-isolated-on-dark-background-blue-plastic-water-pipe-pvc-accessories.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/set-of-blue-pvc-pipe-fittings-isolated-on-dark-background-blue-plastic-water-pipe-pvc-accessories.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/set-of-blue-pvc-pipe-fittings-isolated-on-dark-background-blue-plastic-water-pipe-pvc-accessories.jpg?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/set-of-blue-pvc-pipe-fittings-isolated-on-dark-background-blue-plastic-water-pipe-pvc-accessories.jpg?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":2400,"url":"https:\/\/digitalbbq.au\/index.php\/2025\/09\/04\/optimising-ifc-files-in-python\/","url_meta":{"origin":2018,"position":2},"title":"Optimising IFC Files in Python","author":"Ryan Lenihan","date":"4 September 2025","format":false,"excerpt":"I came across a Python-based IFC optimiser built on top of IfcOpenShell. It was solid, removing unused spaces, orphaned entities, and redundant metadata, but I saw room to push it further. The original script handled: Removing empty attributes Cleaning up orphaned or unused relationships Removing tiny geometry Flattening the spatial\u2026","rel":"","context":"In &quot;Digital&quot;","block_context":{"text":"Digital","link":"https:\/\/digitalbbq.au\/index.php\/category\/digital\/"},"img":{"alt_text":"Big and small yellow rubber ducks on pink background","src":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/big-and-small-yellow-rubber-ducks-on-pink-background.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/big-and-small-yellow-rubber-ducks-on-pink-background.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/big-and-small-yellow-rubber-ducks-on-pink-background.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/big-and-small-yellow-rubber-ducks-on-pink-background.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/big-and-small-yellow-rubber-ducks-on-pink-background.jpg?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/big-and-small-yellow-rubber-ducks-on-pink-background.jpg?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":2413,"url":"https:\/\/digitalbbq.au\/index.php\/2025\/08\/07\/setting-ifc-material-overrides-for-cable-tray-and-conduit\/","url_meta":{"origin":2018,"position":3},"title":"Setting IFC Material Overrides for Cable Tray and Conduit","author":"Ryan Lenihan","date":"7 August 2025","format":false,"excerpt":"In a previous post, we looked at how to set IFC material overrides for pipe fittings. But when it comes to cable tray and conduit, things get a bit trickier. Unlike pipe and duct, cable tray and conduit don\u2019t belong to a system in Revit, so there's no MEP System\u2026","rel":"","context":"In &quot;Digital&quot;","block_context":{"text":"Digital","link":"https:\/\/digitalbbq.au\/index.php\/category\/digital\/"},"img":{"alt_text":"Low angle view of steel network cable trunking box.","src":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/low-angle-view-of-steel-network-cable-trunking-box-.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/low-angle-view-of-steel-network-cable-trunking-box-.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/low-angle-view-of-steel-network-cable-trunking-box-.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/low-angle-view-of-steel-network-cable-trunking-box-.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/low-angle-view-of-steel-network-cable-trunking-box-.jpg?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/07\/low-angle-view-of-steel-network-cable-trunking-box-.jpg?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":2672,"url":"https:\/\/digitalbbq.au\/index.php\/2026\/07\/09\/a-short-story-about-how-nested-families-work-when-exported-to-ifc\/","url_meta":{"origin":2018,"position":4},"title":"A Short Story About How Nested Families Work When Exported to Ifc.","author":"Ryan Lenihan","date":"9 July 2026","format":false,"excerpt":"I had a question come through that\u2019ll sound familiar if you\u2019ve ever pushed Revit \u2192 IFC on a live job: Nested families are carrying asset data in Revit, but that data disappears in the IFC. LOI attributes, classification, IDs.. gone. What's going on? This comes up more than it should,\u2026","rel":"","context":"In &quot;How to guides&quot;","block_context":{"text":"How to guides","link":"https:\/\/digitalbbq.au\/index.php\/category\/how-to-guides\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/house-model-on-floor-real-estate-and-housing-aspi-2026-03-25-09-14-22-utc.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/house-model-on-floor-real-estate-and-housing-aspi-2026-03-25-09-14-22-utc.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/house-model-on-floor-real-estate-and-housing-aspi-2026-03-25-09-14-22-utc.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/house-model-on-floor-real-estate-and-housing-aspi-2026-03-25-09-14-22-utc.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/house-model-on-floor-real-estate-and-housing-aspi-2026-03-25-09-14-22-utc.jpg?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/house-model-on-floor-real-estate-and-housing-aspi-2026-03-25-09-14-22-utc.jpg?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":2686,"url":"https:\/\/digitalbbq.au\/index.php\/2026\/07\/16\/data-on-the-host-data-in-the-ifc-not-so-fast\/","url_meta":{"origin":2018,"position":5},"title":"Data on the Host, Data in the IFC? Not So Fast.","author":"Ryan Lenihan","date":"16 July 2026","format":false,"excerpt":"A few days after the last post, I got handed a model that seemed like it should have worked perfectly. The nested families were already set up as Shared. The IFC export was running. The geometry was coming through. But the asset data? Completely missing. When this happens, it\u2019s easy\u2026","rel":"","context":"In &quot;How to guides&quot;","block_context":{"text":"How to guides","link":"https:\/\/digitalbbq.au\/index.php\/category\/how-to-guides\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/colorful-wooden-toy-blocks-on-wood-floor-2026-01-07-06-18-37-utc.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/colorful-wooden-toy-blocks-on-wood-floor-2026-01-07-06-18-37-utc.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/colorful-wooden-toy-blocks-on-wood-floor-2026-01-07-06-18-37-utc.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/colorful-wooden-toy-blocks-on-wood-floor-2026-01-07-06-18-37-utc.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/colorful-wooden-toy-blocks-on-wood-floor-2026-01-07-06-18-37-utc.jpg?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/colorful-wooden-toy-blocks-on-wood-floor-2026-01-07-06-18-37-utc.jpg?resize=1400%2C800&ssl=1 4x"},"classes":[]}],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/05\/currency-exchange-data-graph-and-charts-data.jpg","_links":{"self":[{"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/posts\/2018","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/comments?post=2018"}],"version-history":[{"count":8,"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/posts\/2018\/revisions"}],"predecessor-version":[{"id":2029,"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/posts\/2018\/revisions\/2029"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/media\/2028"}],"wp:attachment":[{"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/media?parent=2018"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/categories?post=2018"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/tags?post=2018"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}