Set Family Type Parameters Values: Multiple Families & Multiple Parameters

Working with Type Parameters can be a bit challenging in Dynamo for beginners and on top of that working with multiple elements and their parameters. Today we are going to look at how to set the multiple type parameters for each of the various families in the project.

Type parameters are specific to a family type, and we need to obtain the family type to access its parameters. Setting parameters for multiple elements can be achieved in a similar manner.

Setting Multiple Parameter Values

Sort Alphanumerically With Python: Sort, Sorted, Natural Sort

Sorting is a fundamental operation in computer programming that involves arranging a collection of data in a specific order. In Python, sorting can be performed using various built-in functions such as sorted(), sort(), and others.

Alphanumeric or Natural Sorting

Alphanumeric or natural sorting is a type of sorting that orders strings containing numeric characters in a more natural way. For example, consider the following list of strings:

lst = ['item1', 'item10', 'item11', 'item2', 'item3']

If we sort this list using the regular sorting method, we get the following result:

sorted_lst = sorted(lst)
print(sorted_lst) # ['item1', 'item10', 'item11', 'item2', 'item3']

As you can see, the regular sorting method sorts the list in lexicographical order, which is not the natural order we might expect. Alphanumeric sorting, on the other hand, would sort the list in the following order:

['item1', 'item2', 'item3', 'item10', 'item11']

This is the natural order we might expect when sorting a list of strings containing numbers.

Alphanumeric or Natural Sorting in Dynamo

import re

def sorted_alpha_num(lst):
    def convert(text):
        return int(text) if text.isdigit() else text.lower()

    def alphanum_key(key):
        return [convert(c) for c in re.split('([0-9]+)', key)]

    return sorted(lst, key=alphanum_key)

OUT = sorted_alpha_num(IN[0])

The Python code above is sorting the list in an alphanumeric order using a custom sorting key function. The code uses the re module to split the input string into alphanumeric components and then sorts them according to the natural ordering.

The ‘re’ module is a built-in module in Python that provides support for regular expressions. It provides various functions and methods to work with regular expressions, such as searching, matching, splitting, and substitution. In this code, the ‘re.split()‘ method is used to split the key string into alphanumeric components based on the regular expression pattern ‘[0-9]+‘.

The code defines two nested functions: convert() and alphanum_key(). The convert() function takes a text string and returns an integer if the text contains only digits; otherwise, it returns the lower-case version of the text. The alphanum_key() function takes a key string and splits it into alphanumeric components using the regular expression pattern ‘[0-9]+’. The function then applies the convert() function to each component and returns a list of converted components as the sorting key.

The sorted_alpha_num() function takes a list as input and applies the alphanum_key() function to each element of the list. The function then returns a new list sorted based on the converted keys.

Automating Everyday Tasks With PowerShell: Bulk Folder Creation & Renaming

Windows PowerShell is a scripting language and task automation framework for system administration both on-premises and remotely. PS comes preinstalled in every new Windows-based system now.

PS code is generally very short and effective due to the availability of a huge library of cmdlets pertaining to any module.

PowerShell comes preinstalled with Windows

Some people may find this blue screen similar to Command Prompt, but it is much more powerful than traditional CMD. To put it differently, PowerShell can be seen as an enhanced version of Command Prompt with added features and capabilities.
Here are some examples of PowerShell workflows that can automate everyday tasks on Windows.

  • Managing files and folders: you can use PowerShell to create, copy, move, and delete files and folders in bulk.
  • System configuration: It can be used to automate the configuration of system settings such as network settings, Windows updates, and user accounts.
  • Managing processes: It can help you automate the monitoring and management of processes running on your system, such as starting, stopping, and restarting services.
  • Software deployment: It can be used to automate the deployment of software to multiple computers, making it easier to roll out new software or updates.
  • Task scheduling: It can be used to create and manage scheduled tasks, allowing you to automate routine tasks such as backups, system maintenance, or running reports.

How to Use PowerShell?

There are many flavors of PowerShell, you may even run it on other IDEs (e.g. VS, VS Code) but for simplicity, Windows PowerShell ISE (Integrated Scripting Environment) works as an editor, debugger and provides ready IntelliSense.

If you have a PowerShell script file (*.ps1) and want to run it, you can simply right-click on it and choose to run it with PowerShell. However, it’s advisable to review the script and modify the inputs if necessary before executing the file. To do this, you can open PowerShell ISE, load the PowerShell file, review and edit the code as needed, and then run it by clicking the “Run Script” button (shortcut: F5). This ensures that you have the opportunity to verify and adjust the script before executing it.


Let’s see some of the everyday workflows where PowerShell can be a great time-saver.

1. Rename Files

Here we are directly renaming files by adding a prefix to the file name and changing the file name text to the title case.

Renaming files
# Set the folder path and custom prefix
$folderPath = "C:\Users\{Username}\Documents\_Docs Temp\_Temp"
$prefix = "RAC_"

# Get all files in the folder
$files = Get-ChildItem $folderPath

# Loop through each file and rename it
foreach ($file in $files) {
    # Get the new file name with prefix and title case
    $newName = $prefix + ((Get-Culture).TextInfo.ToTitleCase($file.BaseName)) + $file.Extension
    
    # Rename the file
    Rename-Item $file.FullName -NewName $newName
}

This PowerShell script renames all files in a folder with a custom prefix and title case. It gets all the files in the folder, loops through each file to generate a new name with the prefix and title case base name, and renames the file with the new name.

2. Rename Multiple Files at Once using Excel / CSV

To rename large numbers of files located somewhere in the local drive at once using an external spreadsheet or CSV (Comma-separated Value) file seems to be the easiest workflow to anyone because of the quick and familiar way of editing text, finding and replacing text or using formulae in Excel.

Sample CSV file
Renaming Files Using the CSV file
# Set the folder path and import the CSV file
$folderPath = "C:\Users\{Username}\Documents\_Docs Temp\_Temp"
$csvPath = "C:\Users\{Username}\Documents\_Docs Temp\RenameFilesWithCSV.csv"
$fileNames = Import-Csv $csvPath

# Loop through each file name in the CSV file and rename the file
foreach ($fileName in $fileNames) {
    $existingName = $fileName.ExistingNames
    $newName = $fileName.NewNames
    $filePath = Join-Path $folderPath $existingName
    
    if (Test-Path $filePath) {
        Rename-Item $filePath -NewName $newName
        Write-Host "File '$existingName' renamed to '$newName'"
    }
    else {
        Write-Host "File '$existingName' not found in folder"
    }
}

This script renames files in a folder using a CSV file that contains “ExistingNames” and “NewNames” columns. The script imports the CSV file and loops through each row to extract the existing file name and new file name. It then checks if the file exists in the folder and renames it using the Rename-Item cmdlet if it does. Finally, it outputs a message indicating whether the file was renamed or not.

3. Create Multiple Folders

With PowerShell, you have the capability to create multiple folders simultaneously by importing a CSV or Excel file. These folders can have any number of subfolder levels as desired.

Bulk folder creation

This script creates multiple folders using a CSV file. It starts by setting the current location where the folders are to be created. Then, it imports a CSV file containing a list of folder names to be created.

Using a foreach loop, the script creates each folder in the CSV file by using the New-Item cmdlet with the type parameter set to the directory. The folder names are specified by the column header “FolderNames” in the CSV file.

# Location where your folders are to be created

Set-Location "C:\Users\{Username}\Documents\_Docs Temp\_Temp\Multiple Folder Creation\Folders Created"

# Import CSV file from location
 
$Folders = Import-Csv "C:\Users\{Username}\Documents\_Docs Temp\_Temp\Multiple Folder Creation\FoldersToBeCreated.csv"

# Create Folders from CSV ensure your have a heading of FolderNames in your CSV file
 
ForEach ($Folder in $Folders) { 
 
New-Item $Folder.FolderNames -type directory 
}  

To sum up, PowerShell is a powerful tool that can automate a wide range of tasks and processes in your daily work routine. Whether you need to manage files and folders, configure system settings, or deploy applications, PowerShell can help you save time and streamline your workflow.

Say Goodbye to Unwanted Materials in Revit: Deleting Elements with a Selection Dialogue

Revit is a powerful tool for building design and construction, but with great power comes great responsibility. Keeping your Revit projects tidy and efficient can be a daunting task, especially when it comes to purging unwanted elements. Revit does come with an out-of-the-box feature Purge Unwanted to purge items, but it doesn’t allow bulk deleting of custom-picked elements.

To solve this problem, we can turn to Dynamo, a visual programming platform that allows us to automate tasks in Revit. By creating a Dynamo script or workflow, we can first get all the materials used in the project and then let the user pick the elements or materials that need to be deleted. The script filters out the selected materials and deletes them in bulk.

List.FilterBySelection from Springs package

Delete Unwanted Materials Dynamo Graph

By creating our own Dynamo workflows around this, we can delete other unplaced elements in bulk, such as views, floor plans, sections, legends, schedules, spaces, rooms, scope boxes, imported files, and more.

By using Dynamo to automate the process of purging unwanted elements in Revit, we can save time and improve the efficiency of our workflow. So why not give it a try and see how it can streamline your Revit projects?

Python 1: Get All Materials
This piece of code retrieves all the material elements and their names in the project.

# Import the necessary packages
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager

# Get the Revit document
doc = DocumentManager.Instance.CurrentDBDocument

# Get all the materials in the project
materials = FilteredElementCollector(doc).OfClass(Material)
mats = FilteredElementCollector(doc).OfClass(Material).ToElements()
# Create lists to store the material names and IDs
material_names = []
material_ids = []

# Loop through the materials and retrieve their names and IDs
for material in materials:
    material_names.append(str(material.Id) + " - " + material.Name)

# Define the outputs
OUT = mats, material_names

Python 2: Filter List

The Python 2: Filter List node is taken from the List.FilterBySelection custom node by spring nodes by Dimitar Venkov. This Python code defines a custom form with checkboxes that allow the user to select elements. The code adds references to the necessary libraries, defines a few functions, and then creates the form using the CheckBoxForm class. The form includes buttons to check or uncheck all the elements, and to save the selected elements. This code can be used in Dynamo scripts to enable user selection of elements for further processing.

#Copyright(c) 2016, Dimitar Venkov
# @5devene, dimitar.ven@gmail.com

import clr
clr.AddReference('System.Windows.Forms')
clr.AddReference('System.Drawing')
from System.Drawing import Point, Color, Font
from System.Windows.Forms import *

def tolist(obj1):
	if hasattr(obj1,"__iter__"): return obj1
	else: return [obj1]
	
def hasInd(l1, i):
	try: l1[i] ; return True
	except: return False

class CheckBoxForm(Form):
	def __init__(self, cm1):
		self.Text = "Filter By Selection"
		self.Width = 400
		self.BackColor = Color.FromArgb(40,40,40)
		self.output1 = []
		self.ControlBox = False
		self.TopMost = True
		self.FormBorderStyle = FormBorderStyle.FixedDialog
		self.StartPosition = FormStartPosition.CenterScreen
		
		self.label = Label()
		self.label.Text = cm1
		self.label.Location = Point(5, 5)
		self.label.ForeColor = Color.FromArgb(234,234,234)
		self.label.Font = Font("Calibri", 10)
		self.label.AutoSize = True
		self.Controls.Add(self.label)

		self.button1 = Button()
		self.button1.Text = 'Save Selection'
		self.button1.AutoSize = True
		self.button1.ForeColor = Color.FromArgb(234,234,234)
		self.button1.Font = Font("Calibri", 10)
		self.button1.Click += self.save
		self.Controls.Add(self.button1)

		self.button2 = Button()
		self.button2.Text = 'Uncheck All'
		self.button2.AutoSize = True
		self.button2.ForeColor = Color.FromArgb(234,234,234)
		self.button2.Font = Font("Calibri", 10)
		self.button2.Click += self.uncheckAll
		self.Controls.Add(self.button2)

		self.button3 = Button()
		self.button3.Text = 'Check All'
		self.button3.AutoSize = True
		self.button3.ForeColor = Color.FromArgb(234,234,234)
		self.button3.Font = Font("Calibri", 10)
		self.button3.Click += self.checkAll
		self.Controls.Add(self.button3)
		
		self.panel1 = Panel()
		self.panel1.Location = Point(5, 31)
		self.panel1.Width = 370
		self.panel1.BackColor = Color.FromArgb(53,53,53)
		self.panel1.ForeColor = Color.FromArgb(234,234,234)
		self.Controls.Add(self.panel1)
		
	def add_check(self, text1, y1, b1):
		self.check1 = CheckBox()
		self.check1.Text = text1
		self.check1.Location = Point(5, y1)
		self.check1.AutoSize = True
		self.check1.Font = Font("Calibri", 10)
		self.check1.Checked = b1
		self.panel1.Controls.Add(self.check1)
	
	def btn_adjust(self,y1):
		if y1 > 700:
			y1 = 700
			self.panel1.AutoScroll = True
			self.panel1.Focus()
		self.panel1.Height = y1
		self.button1.Location = Point(5,   y1 + 38)
		self.button2.Location = Point(170, y1 + 38)
		self.button3.Location = Point(275, y1 + 38)
		self.Height = y1 + 130
			
	def save(self, sender, event):
		ctrl1 = self.panel1.Controls
		count1 = ctrl1.Count
		loc = 0
		self.output1 = [c.Checked == 1 for c in ctrl1]
		#for i in xrange(count1):
		#	if ctrl1[i].Checked == 1:
		#		self.output1.append(l1[loc])
		#	else:
		#		self.output2.append(l1[loc])
		#	loc += 1
		self.Close()
	
	def uncheckAll(self, sender, event):
		ctrl1 = self.panel1.Controls
		count1 = ctrl1.Count
		for i in xrange(count1):
			ctrl1[i].Checked = False
	
	def checkAll(self, sender, event):
		ctrl1 = self.panel1.Controls
		count1 = ctrl1.Count
		for i in xrange(count1):
			ctrl1[i].Checked = True

l1 = tolist(IN[0])
if IN[1] == None: names = None
else: names = tolist(IN[1])

form = CheckBoxForm(IN[2])
y1 = 5
for i in xrange(len(l1)):
	try:
		if hasInd(names, i): val1 = names[i].ToString()
		else: val1 = l1[i].ToString()
		form.add_check(val1, y1, IN[3])
		y1 += 25
	except: pass
form.btn_adjust(y1)

Application.Run(form)
OUT = form.output1#, form.output2
Application.Exit()

Visualizing Collatz conjecture with Python

Collatz conjecture aka 3n+1 problem is notoriously famous for being the simplest to explain and yet unsolved problem in mathematics.

The problem goes like this: take any positive integer number; if it’s even – double the number, if it’s odd –triple it and add 1. Keep doing this to the new number you get until you finally reach 1. The conjecture is that after all these iterations, you always reach 1, no matter which positive integer you started from.

While no one has proved the conjecture, it has been verified for every number less than 268, which is more than 295 quintillion or 295 billion billion.

Here we are going to simulate this problem using Python. I’m using VS Code but you can prefer to use any IDE.

import matplotlib.pyplot as plt

num = int(input("Enter a positive integer: "))
seqList = [num]

while (num > 1):
    if num % 2 == 0:
        num = num/2
    else:
        num = 3 * num + 1
    seqList.append(num)   

print("Number of steps: ", len(seqList)-1)
print("Max step value: ", max(seqList))
print(seqList)

# Plotting graph
x = list(range(0,len(seqList)))

fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_ylim(0,max(seqList)+5)

# x and y axis
plt.plot(x, seqList)

# Annotating graph
for i,j in zip(x, seqList):
    ax.annotate(str(j), xy=(i+0.1,j+0.5))

plt.xlabel("Number of steps")
plt.ylabel("Value")
plt.grid()
plt.show()
Number 27 unexpectedly hops up and down 111 times reaching a maximum higher than the elevation of Mt. Everest in meters. Interestingly, 27 is the only positive integer that is 3 times the sum of its digits.
Plot for number 15

Export Data to an Existing Excel Template

Ever wondered how to export data from Revit or any source for that matter to an existing Excel file where you already have some formatting done? It can be a bit winding task to first export your data to an intermediary blank Excel sheet and then copy/paste or link the cells or range to your original Excel template file.

This workflow here does not require any custom node or high-level coding — just a couple of out-of-the-box nodes to get your job done in a few seconds.

A sample Excel workbook with some formatting and formula applied
This Dynamo graph could be used in any Dynamo for Revit version. List.Combine acts as a function.
Output Excel sheet with the data filled in respective places

This is how you can save precious time to export data to any existing Excel file without making any modifications to the formatting. You can re-run the Dynamo script after changing input data in order to make any further changes.

Power BI and BIM Data Integration

Power BI is one of the most popular business analytics service out there to leverage your data to create attractive dynamic presentations of stats to visualize the trends better than every before.

Building “Information” Models are not far away in terms of getting the insights of your built asset to make informed decisions and provide productive insights into them.

Power BI can be used to do a number of things to get a better view at your building model.

  • Create elaborate reports and dashboards
  • Interactable 2D and 3D models with Forge Integration
  • Can consume COBie data
  • APIs exposed for developers for embedding dashboards in other software products
  • Data Visualization back to Revit as Landing page or send over to web-page

In the gif below, we have got a floor plan of a sample Revit model to get the information of Rooms into Power BI.

Some Applications of BIM Data

  • Design Analysis – Options generation
  • Asset Analysis
  • Space Analysis
  • Model Health Check
  • Project Progress Tracking
  • Forge Integration
  • Software usage
  • PC Metrics
  • Software License Usage
  • Financial Performance
3D interactive Building Model (Courtesy: powerbiblogic)

COVID-19 Dashboard with Interactive graphs (Courtesy: DataClue)

Split Pipes/Ducts into Standard Lengths in Revit

Many times when you are creating MEP models in Revit using native rfa families, it would be required to split the piping or ducting into some standard lengths based on the project requirement. This could be quite a tedious manual process to measure and split the pipes/ducts especially when it comes to sloped piping the exact standard split length seems to be hard to achieve.

This Dynamo workflow helps you to split Pipe or Duct networks into optimal Manufacturer’s lengths in Revit. Just run the script in Dynamo or Dynamo Player and select the model in a Revit view. It will auto-detect all the piping/ducting and split them into user-specified lengths. You can anytime make adjustments to the selection method.

Split Pipes/Ducts into Standard Lengths

Supported Versions
Revit 2017, 2018, 2019, 2020, 2021
Dynamo 2.0.4 and above

Packages Required
GeniusLoci
Data-Shapes

Graph Instructions

  1. Simply run the script.
  2. The fitting (coupling/union) placed will be determined by the routing preference in Revit.
  3. The units for segment lengths should be entered as per the defined Project Units (UN) for Length in Revit. e.g.
    • If the unit of Length is mm in Revit, 1000 would mean 1000 mm.
    • If the unit of Length is feet and inches in Revit, 1000 would mean 1000 feet.
    • If the unit of Length is inches in Revit, 1000 would mean 1000 inches.

Thanks to Alban de Chasteigner for his amazing Genius Loci package for Dynamo.

WordPress compresses images, so the above picture might not be legible. Please see the screenshots in two parts below. Right click on the image and select ‘Open image in new tab’.

Script (Part 1/2)
Script (Part 2/2)

Text Case Changing in Revit

Dynamo can be used to perform basic text editing and formatting in bulk either in Autodesk Revit or any text information imported from other sources.

Image displaying changing the case of multiple text notes to Upper Case.

A simple dynamo workflow to change text case to lower case, upper case, title case, and separated by underscore.

How to use Dynamo Player?

Dynamo Player is a quick and easy way to run your Dynamo routines or scripts. It provides a visual user interface where you do not have to worry about all the nodes, wires, and the back-end stuff. It is just like any other music player to run the .dyn files. It proves to be most helpful when you have to run the same script over and over again in a Revit project.

To use the Dynamo Player:

  • Go to Manage > Dynamo Player
  • Browse the folder where all the Dynamo files (*.dyn) are kept.
  • Now all the scripts from the folder will be loaded to your current session.
  • This is a one-time set-up you can open Dynamo Player anytime to run any script directly without having to open Dynamo.

How do I enable my Dynamo scripts to run into Dynamo Player?

  • Open any Dynamo graph
  • Define all the inputs — right-click the node and select Is Input. Do not forget to rename the node.
  • Optional: Define all the outputs — right-click the node and select Is Output. Do not forget to rename the node.
  • Once you have set-up all the inputs and outputs in a Dynamo graph save the file. It is now ready to run on the Dynamo Player.