We have addressed converting Parameter and FamilyParameter to Shared Parameter previously. Now let’s see how to convert Project Parameter to Shared Parameter with VB.NET.
Before creating the specific code for the Project Parameter Converter, we need to put some Coders together first that we introduced and demonstrated before. They will save us a lot of precious time and avoid duplicate efforts.
Revit Parameter Organizer can organize various Revit parameters such as Shared Parameters, Family Parameters, Project Parameters and Built-in Parameter in many good ways.
Here they are:
#Region "From ProjectParameter Infoer"
Public Class RawProjectParameterInfo
Public Shared Property FileName() As String
Get
Return m_FileName
End Get
Set(ByVal value As String)
m_FileName = value
End Set
End Property
Private Shared m_FileName As String
Public Property Name() As String
Get
Return m_Name
End Get
Set(ByVal value As String)
m_Name = value
End Set
End Property
Private m_Name As String
Public Property Group() As BuiltInParameterGroup
Get
Return m_Group
End Get
Set(ByVal value As BuiltInParameterGroup)
m_Group = value
End Set
End Property
Private m_Group As BuiltInParameterGroup
Public Property Type() As ParameterType
Get
Return m_Type
End Get
Set(ByVal value As ParameterType)
m_Type = value
End Set
End Property
Private m_Type As ParameterType
Public Property [ReadOnly]() As Boolean
Get
Return m_ReadOnly
End Get
Set(ByVal value As Boolean)
m_ReadOnly = value
End Set
End Property
Private m_ReadOnly As Boolean
Public Property BoundToInstance() As Boolean
Get
Return m_BoundToInstance
End Get
Set(ByVal value As Boolean)
m_BoundToInstance = value
End Set
End Property
Private m_BoundToInstance As Boolean
Public Property BoundCategories() As String()
Get
Return m_BoundCategories
End Get
Set(ByVal value As String())
m_BoundCategories = value
End Set
End Property
Private m_BoundCategories As String()
Public Property FromShared() As Boolean
Get
Return m_FromShared
End Get
Set(ByVal value As Boolean)
m_FromShared = value
End Set
End Property
Private m_FromShared As Boolean
Public Property GUID() As String
Get
Return m_GUID
End Get
Set(ByVal value As String)
m_GUID = value
End Set
End Property
Private m_GUID As String
Public Property Owner() As String
Get
Return m_Owner
End Get
Set(ByVal value As String)
m_Owner = value
End Set
End Property
Private m_Owner As String
Public Property Visible() As Boolean
Get
Return m_Visible
End Get
Set(ByVal value As Boolean)
m_Visible = value
End Set
End Property
Private m_Visible As Boolean
End Class
Public Shared Function RawGetProjectParametersInfo(ByVal doc As Document) As List(Of RawProjectParameterInfo)
RawProjectParameterInfo.FileName = doc.Title
Dim paramList As New List(Of RawProjectParameterInfo)()
Dim map As BindingMap = doc.ParameterBindings
Dim it As DefinitionBindingMapIterator = map.ForwardIterator()
it.Reset()
While it.MoveNext()
Dim eleBinding As ElementBinding = TryCast(it.Current, ElementBinding)
Dim insBinding As InstanceBinding = TryCast(eleBinding, InstanceBinding)
Dim def As Definition = it.Key
If def IsNot Nothing Then
Dim extDef As ExternalDefinition = TryCast(def, ExternalDefinition)
Dim sharedVar As Boolean = extDef IsNot Nothing
Dim param As New RawProjectParameterInfo() With { _
.Name = def.Name, _
.Group = def.ParameterGroup, _
.Type = def.ParameterType, _
.ReadOnly = def.IsReadOnly, _
.BoundToInstance = insBinding IsNot Nothing, _
.BoundCategories = RawConvertSetToList(Of Autodesk.Revit.DB.Category)(eleBinding.Categories).Select(Function(c) c.Name).ToArray(), _
.FromShared = sharedVar, _
.GUID = If(sharedVar, extDef.GUID.ToString(), String.Empty), _
.Owner = If(sharedVar, extDef.OwnerGroup.Name, String.Empty), _
.Visible = If(sharedVar, extDef.Visible, True) _
}
paramList.Add(param)
End If
End While
Return paramList
End Function
Public Shared Function RawParametersInfoToCSVString(Of T)(ByVal infoList As List(Of T), ByRef title As String) As String
Dim sb As New StringBuilder()
Dim propInfoArrary As PropertyInfo() = GetType(T).GetProperties()
For Each pi As PropertyInfo In propInfoArrary
title += pi.Name + ","
Next
title = title.Remove(title.Length - 1)
For Each info As T In infoList
For Each pi As PropertyInfo In propInfoArrary
Dim obj As Object = info.GetType().InvokeMember(pi.Name, BindingFlags.GetProperty, Nothing, info, Nothing)
Dim list As IList = TryCast(obj, IList)
If list IsNot Nothing Then
Dim str As String = String.Empty
For Each e As Object In list
str += e.ToString() & ";"
Next
str = str.Remove(str.Length - 1)
sb.Append(str & ",")
Else
sb.Append((If(obj Is Nothing, String.Empty, obj.ToString())) & ",")
End If
Next
sb.Remove(sb.Length - 1, 1).Append(Environment.NewLine)
Next
Return sb.ToString()
End Function
#End Region
#Region "From SharedParameter Creator"
Public Shared Function RawConvertSetToList(Of T)(ByVal setVar As IEnumerable) As List(Of T)
Dim list As List(Of T) = (From p In setVar Select p)
Return list
End Function
Public Shared Function RawCreateSharedParameter(ByVal app As RvtApplication, ByVal name As String, ByVal group As String, ByVal type As ParameterType, ByVal visible As Boolean) As Definition
Dim defFile As DefinitionFile = app.OpenSharedParameterFile()
If defFile Is Nothing Then
Throw New Exception("No SharedParameter File!")
End If
Dim dg As DefinitionGroup = RawConvertSetToList(Of DefinitionGroup)(defFile.Groups).FirstOrDefault(Function(g) g.Name = group)
If dg Is Nothing Then
dg = defFile.Groups.Create(group)
End If
Dim def As Definition = RawConvertSetToList(Of Definition)(dg.Definitions).FirstOrDefault(Function(d) d.Name = name)
If def IsNot Nothing Then
Return def
End If
'dg.Definitions.Erase(def); //ReadOnly Exception!!
def = dg.Definitions.Create(name, type, visible)
Return def
End Function
#End Region
With all the above code handy, it becomes a pretty easy task to create some code to convert a particular Project Parameter or all Project Parameter instances of a Revit Project Document to shared parameters:
Public Shared Sub ConvertProjectParameterInfoToSharedParameter(ByVal doc As Document, ByVal info As RawProjectParameterInfo, ByVal visibilityOverride As Boolean)
If info.Type = ParameterType.Invalid Then
info.Type = ParameterType.Text
End If
RawCreateSharedParameter(doc.Application, info.Name, "For_" & Convert.ToString(doc.Title), info.Type, visibilityOverride)
End Sub
Public Shared Sub ConvertProjectParameterToSharedParameter(ByVal doc As Document, ByVal name As String, ByVal visibilityOverride As Boolean)
Dim pList As List(Of RawProjectParameterInfo) = RawGetProjectParametersInfo(doc)
Dim pListOfInterest As List(Of RawProjectParameterInfo) = pList.FindAll(Function(p) p.Name = name)
For Each info As RawProjectParameterInfo In pListOfInterest
ConvertProjectParameterInfoToSharedParameter(doc, info, visibilityOverride)
Next
End Sub
Public Shared Sub ConvertAllProjectParametersToSharedParameters(ByVal doc As Document, ByVal visibilityOverride As Boolean)
Dim pList As List(Of RawProjectParameterInfo) = RawGetProjectParametersInfo(doc)
For Each info As RawProjectParameterInfo In pList
ConvertProjectParameterInfoToSharedParameter(doc, info, visibilityOverride)
Next
End Sub
A few points may be worth of mentioning here:
• The ParameterType of some valid Project Parameter instances may be Invalid! We assign the most popular Text ParameterType to the Project Parameter in this case to resolve the creation problem of the affected shared parameters.
• The name of the DefinitionGroup of all the shared parameters will be defaulted as For_<Project Document Name>.
• Since the visibility information of the original shared parameter definitions if any is not easy to find back, we give a chance in these methods to override the visibility for the shared parameters.
The following test code can exercise the methods:
ConvertProjectParameterToSharedParameter(CachedDoc, "URL", True)
ConvertAllProjectParametersToSharedParameters(CachedDoc, True)
In terms of details of the various coders referenced in this post please refer to previous posts for ideas and code examples either in VB.NET or C#.
Project Parameter Converter of RevitAddinWizard can create all these in a second.
I am in a situation where I desperately need to convert a project parameter to a shared parameter but I am not able to use the code you provided. I have a Revit project where I am importing elements from another source (IFC). The beams and columns come into Revit fine, but the size of the members is in a project parameter. I need to tag the beams and column with the size but cannot make a tag. Do you know of a simple way to do this, even manually? I only need to do it once. I would really appreciate any help.
Please email me at [email protected]
Larry Summerfield
Thanks
Posted by: Larry Summerfield | 03/21/2012 at 12:04 AM
It does not seem a project parameter to shared parameter convertion matter. The issue may have something to do with the IFC source or the Revit import.
If anything wrong with the code as posted here, please feel free to point it out. I'd like to look into it in case a reproducible case could be isolated and provided.
Posted by: Spiderinnet | 03/21/2012 at 12:46 AM
I am having trouble getting the script to work. I have coppied and pasted the script into visual basic 2010.. I am a NOOB and need some help. Can someone help?
Posted by: Preston Monroe | 08/20/2013 at 06:44 AM
This is the error i get:
Error 1 Statement is not valid in a namespace. C:\test\convert test 2\convert test 2\Class1.vb 106 1 convert test 2
for line:
Public Shared Function RawGetProjectParametersInfo(ByVal doc As Document) As List(Of RawProjectParameterInfo)
Posted by: Preston Monroe | 08/20/2013 at 08:29 AM
Preston, it seems some namespaces were missing in your code. As pointed out by another post, some commonly used namespaces had better be put at the head of any source files for Revit API coding:
http://spiderinnet.typepad.com/blog/2011/01/some-commonly-used-revit-net-api-namespaces.html
Posted by: Spiderinnet | 08/20/2013 at 02:58 PM
I am using Revit Addin Wizard so all of them are already at the head of the source. I am still confused on the process. I have started the revit addin wizard and which produced the ExtCmd.vb and the ExtApp.vb. I then coppied part of the script from the top down until i reached the comment: " With all the above code handy..." and pasted it in at the bottom after the pre made script generated by the wizard after 'End Namespace in the ExtCmd.vb window. I then coppied the rest of the script, following comment ending: "Revit Project Document to shared parameters:"
Doing it this way generates 7 errors all with not valid in a namespace.
I also tried pasting the code in the gererated script right below ''TODO: add your code below. which produced 22 errors. Am i too a noob to be explained? is it a loss cause?
Posted by: Preston Monroe | 08/20/2013 at 05:58 PM
Preston, I tried the VB.NET code on my side and verified it compiled just fine.
It seems you copied and pasted the code snippet to somewhere outside of a Class. If the code were enclosed in a class as follows, the compiler should have been happy.
Public Class MyTest
'The code snippet copied and pasted from here
End Class
Posted by: Spiderinnet | 08/20/2013 at 10:28 PM