Revit 2022: ParameterType.Text to ForgeTypeId

peter_sylvester
Participant
Participant

Revit 2022: ParameterType.Text to ForgeTypeId

peter_sylvester
Participant
Participant

Could somebody please help me out with this conversion from Deprecated ParameterType to ForgeTypeId for Revit 2022 Api?

 

The 'old' code has a line like:

if (parameter.Definition.ParameterType == ParameterType.Text)  ....

 

What would be the 2022 equivalent for it?

 

It seems that the left side may be:

if (parameter.Definition.GetDataType() == ????)  ....

but for some reason I cannot find what do I have to use on right side of the operation 😞 There must be something I am overlooking.

Thanks in advance.

Reply
Accepted solutions (2)
17,074 Views
26 Replies
Replies (26)

architect.bim
Collaborator
Collaborator

Hi! To perform this check you need to create instance of ForgeTypeId class. Use one of the SpecTypeId's properties to get value to compare with. In your case (for text parameter) you need Number property:

 

 

>>> element.Parameter[BuiltInParameter.ALL_MODEL_MARK].Definition.GetSpecTypeId() == SpecTypeId.Number
True

 

 

 Also take a look at this conversation.


Maxim Stepannikov | Architect, BIM Manager, Instructor

peter_sylvester
Participant
Participant

Oh dear! This is super confusing. I've just checked and Parameter Definition that store TEXT have a SpecTypeId.Number!!   😮  

0 Likes

peter_sylvester
Participant
Participant

Oh dear! This is super confusing. I've just checked and Parameter Definition that store TEXT have a SpecTypeId = SpecTypeId.Number  😮  

 

Now how do you distinguish between actual Numbers and Text ??

 

It looks like the problem is this:

The Autodesk.Revit.DB.InternalDefinition class has:

- ParameterType  - this can be: Invalid | Text | Integer | Number

- UnitType -  seemingly for Text type parameters this is "UT_Number"

 

Now with ParameterType becoming obsolete, we have to use Parameter.GetSpecTypeId() that SEEMINGLY coresponds to the "UnitType" member above and for Text parameters like "Comment" it has a value of SpecTypeId.Number!

 

The question is: How can I know if a Parameter is Text or not in Revit 2022 - without using Definition.ParameterType ?

 

Same would apply to YesNo type parameters... SpecTypeId cannot be used to determine if a ParameterDefinition is for a YesNo type parameter...  

And even more: The ONLY place where I can see if a parameter is a YesNo parameter is in the Parameter.Definition.ParameterType !! If ParameterType is obsolete... how to determine if a parameter is YesNo or something else?

architect.bim
Collaborator
Collaborator
Accepted solution

It is a well-known fact that unit type of text is number. Actually I don't know why 😁. But you definetly should use Number property. Each Parameter object also has StorageType property. In case of Yes/No parameter its value is Integer. In case of Text parameter - string. I hope this solves your problem.


Maxim Stepannikov | Architect, BIM Manager, Instructor
0 Likes

peter_sylvester
Participant
Participant

Well, sorry for my ignorance but seemingly there is still one 'minor' issue left for me to be answered. 😞

 

var option = new ExternalDefinitionCreationOptions("ExampleParamForge", SpecTypeId.XXX???);
var definition = definitionGroup.Definitions.Create(option);

 

 

Using SpecTypeId.Number  creates a Parameter that has the "Type of Parameter" set to Number (obviously!, right?)

How do I create a simple TEXT Parameter definition using the Revit 2022 API?

There must be something here that I am missing 😞

 

Thanks for your attention.

0 Likes

david_becroft
Autodesk
Autodesk
Accepted solution

Good morning,

 

To create a text parameter, please use SpecTypeId.String.Text.

 

For context, the ForgeTypeId properties directly in the SpecTypeId class identify the measurable data types, like SpecTypeId.Length or SpecTypeId.Mass. The non-measurable data types are organized into nested classes within SpecTypeId, like SpecTypeId.String.Text, SpecTypeId.Boolean.YesNo, SpecTypeId.Int.Integer, or SpecTypeId.Reference.Material.

 

Regarding text parameters that report their type as "Number", here's the history:

  • Prior to Revit 2021, a Definition had a UnitType and a ParameterType. The UnitType property was only meaningful for parameters with measurable ParameterType values, and a parameter with ParameterType.Text would report a meaningless UnitType.Number value.
  • Revit 2021 deprecated the UnitType property and replaced it with the GetSpecTypeId() method. But the behavior remained the same -- a parameter with ParameterType.Text would have GetSpecTypeId() == SpecTypeId.Number.
  • Revit 2022 deprecated the ParameterType property and the GetSpecTypeId() method, replacing them both with the GetDataType() method. A parameter with ParameterType.Text will report GetDataType() == SpecTypeId.String.Text. Side note: The GetDataType() method can also return a category identifier, indicating a Family Type parameter of that category.

architect.bim
Collaborator
Collaborator

Useful information. Thanks a lot!


Maxim Stepannikov | Architect, BIM Manager, Instructor

jeremy_tammik
Autodesk
Autodesk

Thank you for the great explanation. Shared here for posterity:

 

https://thebuildingcoder.typepad.com/blog/2021/04/pdf-export-forgetypeid-and-multi-target-add-in.htm...

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open

peter_sylvester
Participant
Participant

Thanx 2² the great previous answer.

 

As a last question: What would ParameterType.Invalid  be the equivalent of?

 

0 Likes

david_becroft
Autodesk
Autodesk

You're very welcome! 🙂

 

ParameterTypeId.Invalid is equivalent to an "empty" ForgeTypeId object. You can check if a ForgeTypeId is empty using its Empty() method and you can construct an empty one with the default constructor: new ForgeTypeId().

dev
Contributor
Contributor

@david_becroft 
Hi
Do you know what's the replacement SpecTypeId for ParameterType.FamilyType?

david_becroft
Autodesk
Autodesk

Good morning,

 

Strictly speaking, there isn't a SpecTypeId property that directly replaces ParameterType.FamilyType. This neighborhood of the API has changed a little bit.

 

Let's say you have a parameter's Definition object and you call its GetDataType() method....

  • For Family Type parameters, GetDataType() returns the identifier of the associated category. Use Category.IsBuiltInCategory(ForgeTypeId) to detect a category identifier.
  • For parameters associated with units of measurement, GetDataType() returns a measurable spec identifier. Use UnitUtils.IsMeasurableSpec(ForgeTypeId) to detect a measurable spec identifier.
  • For all other parameters, GetDataType() returns a spec identifier. Use Parameter.IsSpec(ForgeTypeId) to detect a spec identifier, including measurable specs.

(Use Parameter.IsValidDataType(ForgeTypeId) to detect any parameter data type identifier – i.e., any measurable or non-measurable spec or category.)

 

On the other hand, let's say you want to create a Family Type shared parameter. To create a Family Type shared parameter of a given category, you can construct an ExternalDefinitionCreationOptions with that category's ForgeTypeId identifier. So where do you get the category identifier as a ForgeTypeId? You would probably expect to find a CategoryTypeId class similar to SpecTypeId or UnitTypeId. Well, there isn't a CategoryTypeId class in Revit 2022, but you can use these two functions to exchange a BuiltInCategory enumeration value for the equivalent ForgeTypeId:

 

  • Category.GetBuiltInCategoryTypeId(BuiltInCategory)
  • Category.GetBuiltInCategory(ForgeTypeId)

 

dev
Contributor
Contributor

@david_becroft 
Thanks for the quick and elaborate answer. It is very helpful. To check if I understand correctly, for example for this method from family manager, which previously used BuiltInParameterGroup and ParameterType.

 

public FamilyParameter AddParameter(string parameterName, ForgeTypeId groupTypeId, ForgeTypeId specTypeId, bool isInstance);

 

For a (pre-revit 2022) parameter type of ParameterType.FamilyType, now I would have to know upfront the built in category (builtInCategory) of the family that will go there, and pass instead to specTypeId Category.GetBuiltInCategoryTypeId(builtInCategory)

david_becroft
Autodesk
Autodesk

Good morning @dev,

 

Prior to Revit 2022, the FamilyManager class had:

(1) FamilyParameter AddParameter(string, BuiltInParameterGroup, ParameterType, bool)

 

Calling this function with ParameterType.FamilyType would give an ArgumentException saying "Cannot create family type parameter with this method." But you could add a Family Type parameter with this overload:

(2) FamilyParameter AddParameter(string, BuiltInParameterGroup, Category, bool)

 

In Revit 2022, the FamilyManager class deprecates overload (1) and now offers this overload as a replacement:

(3) FamilyParameter AddParameter(string, ForgeTypeId group, ForgeTypeId spec, bool)

 

Its behavior is basically unchanged. The "spec" argument to overload (3) only accepts spec identifiers, not category identifiers, so we will still use overload (2) above accepting Category to add a Family Type parameter. I hope that helps!

jeremy_tammik
Autodesk
Autodesk

Link to related thread:

 

https://forums.autodesk.com/t5/revit-api-forum/convert-parametertype-fixtureunit-to-forgetypeid/m-p/...

 

In it, Mark De Vries raises a question on how to handle ParameterType.FixtureUnit and shares a class to encapsulate the handling of the the new and old methods in one place.

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open

autodesk.ID.fisa
Contributor
Contributor

Hello

 

I'm starting to understand ParameterType in SpecTypeId and thanks for the explanations.

But I can't figure out how builtInParameterGroup: INVALID in GroupTypeId. The Invalid therme doesn't exist!

 

Sample :

.. FamilyManager->AddParameter("SAMPLE", BuiltInParameterGroup::INVALID, ParameterType::HVACThermalConductivity, false);

 

I would like to understand how I can pass this line of code into API Revit 2022?

 

Thank you in advance for your reply.

 

 

david_becroft
Autodesk
Autodesk

Good morning @autodesk.ID.fisa,

 

Great question! BuiltInParameterGroup.INVALID is equivalent to an empty ForgeTypeId.

 

Given a call like:

  • FamilyManager->AddParameter("SAMPLE", BuiltInParameterGroup::INVALID, ParameterType::HVACThermalConductivity, false);

In Revit 2022 we can instead write:

  • FamilyManager->AddParameter("SAMPLE", new ForgeTypeId(), SpecTypeId::ThermalConductivity, false);

autodesk.ID.fisa
Contributor
Contributor

Hello David,

 

You have to know, I would never have thought of that.

Thank you for your answer.

 

If we look at the other explanations, I would have been inclined to write this (as it is a group we define):

FamilyManager->AddParameter ("SAMPLE", gcnew GroupTypeId(), SpecTypeId::ThermalConductivity, false);

Too bad this does not work and GroupTypeId does not inherit ForgeTypeId.

 

Thank you again for your answer which corresponds exactly to what I was looking for.

stephen_harrison
Advocate
Advocate

Thank you for the prompt response and explanations.

If I have understood correctly the amendments to my code would look like the following:

Pre 2022: ParameterType spParmType = spFamilyListItem.DataType;
2022 Code: ForgeTypeId spParmType = spFamilyListItem.DataType;


Pre 2022: ExternalDefinitionCreationOptions option = new ExternalDefinitionCreationOptions(string, ParameterType);
2022 Code: ExternalDefinitionCreationOptions option = new ExternalDefinitionCreationOptions(string, ForgeTypeId)


Pre 2022: ParameterType spParamTypeNoFamily = definition.ParameterType;
2022 Code: ForgeTypeId spParamTypeNoFamily = Definition.GetDataType();


Pre 2022: DataType = familyParameter.Definition.ParameterType,
2022 Code: DataType = familyParameter.Definition. GetDataType();


Pre 2022: if (ParameterType.YesNo == fp.Definition.ParameterType)
2022 Code: if (SpecTypeId.Boolean.YesNo == fp.Definition.GetDataType())


Pre 2022:  if (def.ParameterType == ParameterType.FamilyType)
2022 Code:  if (!Category.IsBuiltInCategory(def.GetDataType()))

 

Again thanks for the assistance.