How to schedule un-schedulable Revit parameters using PropertyWizard

Revit’s schedules are very powerful, but there are some parameters that you cannot schedule. For example, you cannot schedule the ‘Top is Attached’ or ‘Base is Attached’ parameters on walls:

Revit screenshot showing Un-Schedulable built-in parameters

You can overcome this problem by using PropertyWizard to copy the un-schedulable parameter value into another parameter of your choice:

PropertyWizard Formula window showing a formula for the category 'Walls', Target Property is 'DWD-BaseIsAttached' and the Formula text is "[Base is Attached]

PropertyWizard will update your parameter whenever the un-schedulable parameter changes, and you can include your parameter in a schedule:

Revit screenshot showing Schedulable project parameters

How to work with Revit’s Yes/No parameters in PropertyWizard formulas

PropertyWizard treats Revit’s Yes/No parameters as True/False boolean values. So it is easy to use Yes/No parameter values in formulas, and it’s easy to set Yes/No parameters from formulas.

Using Yes/No parameter values

You can use a Yes/No parameter value anywhere that is expecting a True/False data value. So you can use them:

  • As the <condition> in an if() function
  • In the logical functions and() and or()
  • In the logical operator expressions And, Or and Not

For example, to use an if() function to tell if a wall top is attached, you would do something like this:

if([Top is Attached], "Top is attached", "Top isn't attached")

Similarly, to indicate the walls that have both top and base attached, you could use an and() and an if() like this:

if(and([Top is Attached], [Base is Attached]), "Base and Top are both attached", "Base and Top are not both attached")
PropertyWizard Formula window showing a formula for the category 'Walls', Target Property is 'DWD-BaseTopText' and the Formula text is "if(and([Top is Attached], [Base is Attached]), "Base and Top are both attached", "Base and Top are not both attached")"

Setting Yes/No parameters

You can set a Yes/No parameter using any expression that results in a True/False value.

  • The literals true and false
  • The identifier of a True/False parameter
  • The identifier of a boolean API Property
  • The logical functions and() and or()
  • The logical operator expressions And, Or and Not

So if you have a Yes/No project parameter, you can set it by simply using:

and([Top is Attached], [Base is Attached]) 
PropertyWizard Formula window showing a formula for the category 'Walls', Target Property is 'DWD-BaseAndTopAttached' and the Formula text is "and([Top is Attached], [Base is Attached])"

Expressions in PropertyWizard for Revit

Expressions are the building blocks of PropertyWizard formulas. They are like phrases in a language.

It’s useful to understand the different kinds of expressions in PropertyWizard, so you can put them together in different ways to write better formulas.

There are four main kinds of expression in PropertyWizard:

  1. Literal expressions
  2. Identifier expressions
  3. Operator expressions
  4. Function expressions

Literal Expressions

Also called ‘literals’, these are where you type a value directly in the formula, such as typing

"Hello Wall" 

or

2.5

or

5 sq m

The value of the literal expression is the value you type.

Identifier Expressions

These are the names of properties, such as

Level

or

Level.Name

The value of the identifier expression is the value of the property.

Operator Expressions

These are the expressions that use the standard maths and logical operators like the plus sign:

<number expr> + <number expr>

You can see how this expression contains two <number expr> sub-expressions. It’s a type of Composite Expression, in contrast to the Simple expressions (literal and identifier expressions)

The sub-expressions have to return the right data type – in this case Number data. But they can be any kind of expression – literals, identifiers, operator expressions or functions – that produce that data type in the end. This is how you can build up arbitrarily complex formulas to do exactly what you need.

Function Expressions

Function expressions are all of the form:

<function name>(<zero or more argument expressions separated by commas>)

They provide more complex functionality than operator expressions. Each function defines how many ‘arguments’ it takes, and what their data types should be. And as with operator expressions, each of the arguments can be any kind of expression as long as it produces the right data type.

All function expressions are Composite except pi(), which has no arguments.

How to use expressions

Every formula has to be an expression. If that’s a Simple expression, then that’s all there is. If it’s a Composite expression, then it will contain sub-expressions that may in turn be either Simple or Composite. There’s no practical limit to how complex your expression nesting can get.

Data Types in PropertyWizard for Revit

When you make a new Revit parameter you choose the Type of Parameter, and that determines the type of data that the parameter can hold:

Revit Parameter Properties dialog showing the 'Type of Parameter' drop-down menu

PropertyWizard uses these same data types:

  • Number
  • Integer
  • Length
  • Area
  • Volume
  • Text
  • True/False (equivalent to Yes/No)
  • Angle (measured in radians)
  • Currency

The only oddity is XYZ, which is a Revit API type. It is only valid as input to the internalToShared() and sharedToInternal() functions.

Formulas have data types

It follows that each formula produces a result of a particular data type. It’s important that the formula result is compatible with the Target Property:

Parameter TypeCompatible Types
NumberNumber or Integer
IntegerNumber or Integer (see Note 1)
LengthLength
AreaArea
VolumeVolume
TextAny (see Note 2)
Yes/NoTrue/False
AngleAngle (see Note 3)
CurrencyCurrency (see Note 3)

Note 1: When setting Integer parameters, Number values are rounded down. For more control, you will usually want to carry out the rounding within your formula.

Note 2: PropertyWizard will convert virtually all values to text when setting Text parameters. Dimension values (Length, Area, and Volume) will be converted using the current Revit project’s Units settings.

Note 3: Angle and Currency parameters can currently be set with any numeric value. Please do not rely on this: I will tighten it up in a future version of PropertyWizard.

Implementation Types

Behind the scenes, the PropertyWizard data types are stored in .Net data types. You may see these data types in error messages. The details may vary in future versions.

PropertyWizard Data TypeImplementation Data Type
NumberDouble
IntegerInt32
LengthUnitsNet.Length
AreaUnitsNet.Area
VolumeUnitsNet.Volume
TextString
True/FalseBool
AngleDouble
CurrencyDouble (see Note 4)
XYZAutodesk.Revit.DB.XYZ

Note 4: Best practice would suggest storing Currency values in a Decimal form. Revit’s implementation uses Doubles to store currency values, so PropertyWizard follows suit. This may change in the future.

How to filter Revit elements using an if() function

A PropertyWizard formula usually affects all the elements in the category you’ve selected. But what if you only want to affect a subset of the elements?

You can do this with an if() function in this form:

if(<filter criteria>, <your formula>, <target parameter>)

The <filter criteria> is where you choose which elements to affect, and the <target parameter> is the name of the formula’s target parameter. The <your formula> is where you put the formula that you want to apply to the selected elements.

For example, to affect only elements on Level 1, your filter criteria would be something like this:

if(Level.Name == "Level 1", <your formula>, <target parameter>) 
PropertyWizard Formula window showing a formula for the category 'Doors', Target Property is 'DWD-Test' and the Formula text is 'if(Level.Name == "Level 1", "This door is on Level1", [DWD-Test])'

How does this work?

This technique works because, when PropertyWizard evaluates the if() function for each element, it starts by evaluating the <filter criteria>. If that returns ‘true’, meaning that the element passes the filter, the if() function returns the value of <your formula>.

On the other hand, if the element doesn’t pass the filter, the if() function will return the value of the <target parameter>, and since that is equal to the actual <target parameter>, the formula has no effect.

This leaves the other elements uncontrolled

You will have noticed that, normally, if you change the value of a parameter that’s controlled by a formula, PropertyWizard immediately changes it back.

However, if you use this technique, the elements that don’t pass the filter aren’t controlled by the formula. So you are free to edit the value of the target parameter on these uncontrolled elements.

How to use the if() function in PropertyWizard for Revit

PropertyWizard’s if() function works in the same way as the native Revit one, which is described in the online Help here:

http://help.autodesk.com/view/RVT/2022/ENU/?guid=GUID-A0FA7A2C-9C1D-40F3-A808-73CD0A4A3F20

The syntax is:

if(<condition>, <result-if-true>, <result-if-false>)

When PropertyWizard evaluates an if() function, it starts with the <condition>. For example in this formula:

if(Level.Name == "Level 0", "It's Level 0!", "It's some other Level!")

It will start by evaluating this expression:

Level.Name == "Level 0"

In PropertyWizard, the double-equals-sign ‘==’ means ‘is equal to’. So the value of the expression will be ‘true’ if the element’s Level’s Name is equal to “Level 0” and ‘false’ otherwise.

PropertyWizard uses the value of the <condition> to decide which value to return from the if() as a whole. If the <condition> evaluates to ‘true’, it returns the <result-if-true>, and if the <condition> is ‘false’ it returns the <result-if-false>.

PropertyWizard Formula window showing an if() function

Nested if() functions

You can nest if() functions to code more complex logic. For example, you can check whether the level name is “Level 0”, “Level 1” or some other Level like this:

if(Level.Name == "Level 0", "It's Level 0!", if(Level.Name == "Level 1", "It's Level 1!", "It's some other Level!")) 

Here, the outer if() has the same <condition> as before, and the same <result-if-true>. But the <result-if-false> is a nested if() function:

if(Level.Name == "Level 1", "It's Level 1!", "It's some other Level!") 

So when the outer if()’s <condition> returns ‘false’, PropertyWizard goes on to evaluate this inner if() and decide whether the level name is “Level 1” or not.

You can put a nested if into the <result-if-true> as well., and you can have multiple layers of nesting. With complex nesting, it can get tricky to put all the commas and parentheses in the right place: I tend to start small and evaluate each piece individually, and then gradually assemble the formula. It is easier to find errors if you make small changes and test as you go along.

How to fix Revit’s Filters with PropertyWizard

Revit’s ‘Filters’ feature is great for highlighting elements based on their parameters, but you are restricted in which parameters you can use.

For Walls, for example, you cannot use any of these ‘Constraints’ parameters in a filter:

Revit's Instance Properties panel for a wall

PropertyWizard lets you overcome this restriction – because you can set up a formula to copy the values of these ‘forbidden’ parameters into another parameter of your choice, and then you can set up a filter using that new, unrestricted parameter. PropertyWizard keeps the new parameter value updated, so your filter will ‘just work’.

For example, you can set up a diagnostic view to colour walls by their Base Constraint Level like this:

First, set up a new project or shared parameter to hold the name of the level:

Revit Parameter Properties dialog showing the DWD-BaseConstraintName parameter. It is a Text parameter and applies to the Walls category.

Next, set up a formula to copy the Name of the Base Constraint level:

[Base Constraint].Name
PropertyWizard Formula window showing a formula for the category 'Walls', Target Property is 'DWD-BaseConstraintName' and the Formula text is [Base Constraint].Name

And finally, set up filters to highlight the walls based on your new parameter:

Revit Filters dialog showing a filter on Walls, where DWD-BaseConstraintName = Level 0

Here, I have highlighted the walls at Level 0 in green, and the ones at Level 1 in blue:

3D Revit view showing example walls coloured by their Base Constraint Level
Revit Wall Schedule showing example walls.

How to find text with PropertyWizard

You can use the instr() function to find text in a PropertyWizard function. It finds the position of one piece of text inside another, and returns the character position of the first character of the found text, or -1 if the text isn’t found.

So, say we want to find all the rooms where the room’s Name contains “Bedroom”, such as “Main Bedroom”, ” Bedroom 2″, etc. The formula for that would be:

instr(Name, "Bedroom")

To turn that into a true/false value, you could use:

instr(Name, "Bedroom") != -1

This checks whether the instr result is not equal to (!=) minus 1. It will return true if the Name contains “Bedroom” and false otherwise – you can put this true/false result directly into a Yes/No parameter.

Alternatively, if you wanted to get a text value as the result:

if(instr(Name, "Bedroom") != -1 , "Bedroom", "Not A Bedroom")

Here are the three formulas in PropertyWizard. I’ve made three new project parameters as target properties:

PropertyWizard Formulas window showing three formulas using instr to find the text "Bedroom"
The three instr formulas

And here is the result in a Room schedule:

Revit Room Schedule showing the results of using the three instr formulas to find the text "Bedroom"
Room schedule showing the results of the instr formulas

Notice how instr is case-sensitive – the formula has not found room number 4, because its name is “bedroom” not “Bedroom”. I will cover case-changing formulas in a future post, when the next version of PropertyWizard is live.

You can download the formulas XML here to import into your own project – you will need to change the target properties to suit your project:

How to generate Level Codes in Revit with PropertyWizard

It’s useful if your Revit Levels have a Level Code as well as a Level Name. That way, you can use the Level Code in your formulas for door numbers, room numbers, etc:

Level NameLevel Code
Level 000
Level 101
Level 202
etc.etc.
Level Names and Level Codes

You could type the level codes in, level by level. But if you have PropertyWizard, you can just generate them. This post walks through a couple of different ways of generating the level codes from the level names. And on the way, it explains two of the text functions in PropertyWizard: substr() and strlen().

Method 1: Simple substr()

The substr() function extracts a number of characters from a text value. It has three inputs:

substr(<text value>, <start character>, <number of characters>)

The <text value> is the text you want to extract characters from. In this case it will be the value of the Level’s Name parameter.

The <start character> is the character number to start at, with the first character in the text being number 0. In these level names, the digit is character number 6.

The <number of characters> is how many characters you want to extract. In this simple case, you would use 1 to extract just one digit.

So the substr will look like this:

substr(Name, 6, 1)

Finally, to generate the full level code, you prefix the extracted digit with a “0”:

"0" + substr(Name, 6, 1)
PropetyWizard Formula Window showing simple Level Code formula using substr

Method 2: substr() with strlen()

Method 1 will work for levels up to 9, but will fail with two-digit levels, 10 and up. How can you fix that?

Since the two-digit levels are longer than the one-digit ones, you can use an if() function and a strlen() function to choose between two different options.

The strlen() function simply returns the number of characters in the input text value:

strlen(<text value>)

The if() function chooses between two alternatives. It has three inputs:

if(<test>, <output if true>, <output if false>)

The <test> is an expression that evaluates to true or false. In this case, if the level name is 7 characters long you know that it is a one-digit level. Otherwise it will be a two-digit level:

if(strlen(Name) == 7, <one-digit level>, <two-digit level>)

If it is a one-digit level, you would use the function from Method 1, but if it is a two-digit level, you would just need something like:

substr(Name, 6, 2)

So the completed formula will be something like this:

if(strlen(Name) == 7, "0" + substr(Name, 6, 1), substr(Name, 6, 2))
PropetyWizard Formula Window showing simple Level Code formula using strlen and substr

Creating Revit Parameters to use with Groups and PropertyWizard

If you are creating parameters in projects that have Groups, and you are using PropertyWizard, you should be aware of this setting in the Parameter Properties dialog:

Revit Parameter Properties dialog, highlighting the group settings

What does the setting do? Well, it only has an effect if you’re using groups, and it’s only active for instance parameters. For example, imagine you add a new instance parameter to the Doors category. Each door in your project now has the new parameter, and since it’s an instance parameter you can set the value differently on every door.

But what happens if you create a Group, add a door to it, and then place several instances of the group? Can you still change all the parameter values independently?

That depends on this setting.

Group Settings from Revit Parameter Properties dialog

If you chose the first option ‘Values are aligned per group type’, then the doors will have the same parameter value in all the group instances – and you can only edit the value in Group Edit mode.

On the other hand, if you chose the second option, you can still freely edit the parameter values on each of the doors – you’re not restricted when they are part of a group.

How does this affect your PropertyWizard formulas?

This matters because PropertyWizard cannot enter Group Edit mode to edit parameter values. So if you choose the first option for your parameter, add some of the relevant elements to groups, and then try to drive the parameter with PropertyWizard, you will get a ‘editing while not in group edit mode’ error:

Revit Warning dialog showing a 'Changes to groups are only allowed in group edit mode' error

This error dialog cannot be bypassed or ignored – it only has a Cancel button. So it will stop and undo whatever you are doing. Which can be awkward.

So you have to use the second option ‘Values can vary by group instance’ for all parameters that you want to control with PropertyWizard.

A Few Awkward Types of Parameter

You will notice that the setting is sometimes greyed out, even for some Instance parameters. Why is this?

Well, for some reason Autodesk have chosen to lock the setting to the first option for these values of ‘Type of Parameter’:

Type of Parameter dropdown from the Parameter Properties dialog, highlighting the values that lock the group settings - which are: Integer, Angle, Length, Number, Slope, Yes/No, and Family Type

It is only locked for these few types of parameter in the ‘Common’ discipline, and not for any of the types in the ‘Structural’, ‘HVAC’, ‘Electrical’, etc. disciplines. It is unfortunate that the affected types include some of the most-used types of parameter in PropertyWizard.