Here are the summaries of some of the Revit API ADN cases handled by me and my colleagues Joe Ye and Saikat Bhattacharya in the past few days:
- Set the display colour of a line.
- Split walls and lines, or ducts and pipes.
- Change colour of a family instance.
- Export family symbols from a project and save in an external RFA file.
1. Set the display colour of a line
Question: How can I set the display colour of a line?
Answer: In Revit 2009, I do not see any way to access the color settings in the line styles which in turn affects the color of lines. The line style Color property is not exposed to enable us to change the color.
Revit 2010 offers a new possibility to modify the line colour via the new LineColor property on the Category class. Thus, for any given line, one can access its category and its line color property, which is read and write enabled.
2. Split walls and lines, or ducts and pipes
Question: I would like to split ducts and pipes in Revit MEP. Can I call the 'Split Walls and Lines' functionality somehow from the Revit 2009 API and apply it to Ducts and Pipes? If not, is this feature going to be available in the 2010 API? I have heard that duct and pipe creation will be included.
Answer: The Revit 2010 API does not provide any API method to cut or split any of the duct, pipe or wall elements. Methods to create ducts and pipes are indeed provided in 2010. Thus you could use the NewDuct, NewPipe and NewWall methods to create a new element, shorten the original one accordingly, and set the properties and parameters obtained from the original to the newly created one. This might provide a possibility to mimic the splitting effect.
3. Change colour of a family instance
This is a continuation of the previous post on this topic:
Question: Could you provide the code to illustrate the approach you described to change the colour of a family instance?
Answer: Since the colour of an instance is defined by the material assigned to the type or symbol referenced by the instance, this involves duplicating the family symbol it references, assigning a different material colour to the newly created type, and then assigning the new type to the object that you want to colour differently. Here is the code to illustrate this approach.
For simplicity, it works with only one family instance, say a column, in the Revit model. A material has been applied through the user interface, and then the following piece of code is executed to create a duplicate symbol and access the material from the symbol. In this case, for now, it directly changes the colour of the material instead of selecting another material with a different colour or duplicating the colour. Finally, it applies the duplicated symbol to the family instance:
ElementSet elemset = doc.Selection.Elements; foreach( Element e in elemset ) { FamilyInstance inst = e as FamilyInstance; // get the symbol and duplicate it: FamilySymbol dupSym = inst.Symbol.Duplicate( "D1" ) as FamilySymbol; // access the material: ElementId matId = dupSym.get_Parameter( "Material" ).AsElementId(); Material mat = doc.get_Element( ref matId ) as Autodesk.Revit.Elements.Material; // change the color of this material: mat.Color = new Color( 255, 0, 0 ); // assign the new symbol to the instance: inst.Symbol = dupSym; }
4. Export family symbols from a project and save as RFA files
Question: I would like to use the beta version of Revit 2010 and the new family API to save out all family symbols in an existing project to external RFA files. I am trying to use Document.EditFamily to open the family document, and then use the SaveAs method on that to export the family definition. Unfortunately, EditFamily throws an exception, System.InvalidOperationException, with the message 'Loaded Family Editing failed.'
Answer: Some families can be edited and saved to an external file, and others cannot. If the family can be edited in the Revit user interface, it should also be possible to open it through the API. Here is the result of logging the calls to EditFamily on all the families contained in a simple project named one_door.rvt containing one door symbol and an instance of it and very little else:
Error processing 'System Panel': Loaded Family Editing failed. Error processing 'Rectangular Mullion': Loaded Family Editing failed. Error processing 'Circular Mullion': Loaded Family Editing failed. Error processing 'L Corner Mullion': Loaded Family Editing failed. Error processing 'V Corner Mullion': Loaded Family Editing failed. Error processing 'Trapezoid Corner Mullion': Loaded Family Editing failed. Error processing 'Quad Corner Mullion': Loaded Family Editing failed. Success processing 'M_Single-Flush'
As you can see, a number of built-in system families are impossible to edit, and calling EditFamily on those throws an exception of type System.InvalidOperationException.
The door symbol is defined through a standard family and can be edited and saved. After running the command, the family file for the door symbol is stored on disk:
2009-04-06 13:37 192,512 M_Single-Flush.rfa 2009-02-24 10:41 294,912 one_door.rvt
Here is the code for the external command which iterates through all the families in the project and tries to save each to a separate RFA file on disk:
const string _path = "C:/tmp/extract/"; public IExternalCommand.Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements ) { Application app = commandData.Application; Document doc = app.ActiveDocument; Filter filter = app.Create.Filter.NewTypeFilter( typeof( Family ) ); List<Element> fams = new List<Element>(); doc.get_Elements( filter, fams ); foreach ( Family f in fams ) { string name = f.Name; try { Document famDoc = doc.EditFamily( f ); famDoc.SaveAs( _path + name + ".rfa" ); famDoc.Close( false ); Debug.Print( "Success processing '{0}'", name ); } catch( Exception ex ) { Debug.Print( "Error processing '{0}': {1}", name, ex.Message ); } } return IExternalCommand.Result.Failed; }
Have you tried to change a detail or model line style in 2010? I've been playing with it but can't get it to work.
essentially it breaks down to
Dim new_linestyle_elem As Autodesk.Revit.Element
' a sub
new_linestyle_elem = get_line_style_from_detail_line(element, "")
Dim target_param As Autodesk.Revit.Parameter
'another sub
target_param = get_param_from_elem(element, "line style")
'assign it
target_param.Set(new_linestyle_elem.Id)
'error!
I wonder if you have any ideas
...gregory
Posted by: gregory mertens | August 24, 2009 at 14:12
ah....you kind of answered it on one of your other posts.
:)....very cool....i needed to wrap my set in begin and endtransaction.
Posted by: gregory mertens | August 24, 2009 at 14:29
Dear Gregory,
Congratulations on sorting that out on your own!
Cheers, Jeremy.
Posted by: Jeremy Tammik | August 24, 2009 at 15:11
Hello Jeremy
I'm back in your blog. I saw your last answer to my question (http://thebuildingcoder.typepad.com/blog/2009/03/transform-instance-coordinates.html ) and I am very grateful with your help. Now I have another question about the material of a FamilySymbol, I tried with your code but you obtain the FamilySymbol from an element, and I'm trying to obtain the material of all FamilySymbols loaded in the document (at this moment I have all the FamilySymbols loaded in current document, but i cannot get the material from those FamilySymbols), Can you help me?
Thanks for you great help!
Salvador
Posted by: Salvador Elizarrarás | September 05, 2009 at 00:46
Dear Salvador,
Glad to hear back from you again, and I am happy that the previous answer helped.
Regarding your question on materials, have you looked yet at the following two posts?
http://thebuildingcoder.typepad.com/blog/2008/10/element-materials.html
http://thebuildingcoder.typepad.com/blog/2008/10/family-instance-materials.html
Please also have a look at the examples and explanations in section 17.3 Element Material in the Revit SDK developer guide 'Revit 2010 API Developer Guide.pdf'.
Cheers, Jeremy.
Posted by: Jeremy Tammik | September 05, 2009 at 08:59
Hey Jeremy, I have seen the two links that you sent me and I have checked the developer guide, but I need the default material from the .rfa files (by Type). In other words I need the material of all columns and beams symbols (Types) loaded in the document (not necessary placed as elements of the model). I saw that if I open a .rfa file I can modify the material value that will be loaded for all elements with that symbol and that family, I want to get that material for each symbol and family loaded in my document.
Thanks again for you help!
Salvador
Posted by: Salvador Elizarrarás | September 05, 2009 at 19:36
Dear Salvador,
Thank you for the clarification and the interesting topic. The approach is basically similar to that outlined in the developer guide. Go through all the types you are interested in. For each, you can open its family document and go through its geometrical elements. Each element either has a material assigned to it, or it inherits the default material for its assigned category.
Cheers, Jeremy.
Posted by: Jeremy Tammik | September 06, 2009 at 02:38
Hello Jeremy. I´m spanish student (¡Sorry for my English!) and new on Revit,I have a problem and I hope that you can help me.
I want to store a Revit family on a database but I don`t know how.
The idea is to create new families using Revit and with the API store this families on a database.¿Is it possible?
I have been trying to store a Revit family to a separate RFA file on disk using your code:
const string _path = "C:/tmp/extract/";
public IExternalCommand.Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements )
{
Application app = commandData.Application;
Document doc = app.ActiveDocument;
Filter filter = app.Create.Filter.NewTypeFilter(
typeof( Family ) );
List fams = new List();
doc.get_Elements( filter, fams );
foreach ( Family f in fams )
{
string name = f.Name;
try
{
Document famDoc = doc.EditFamily( f );
famDoc.SaveAs( _path + name + ".rfa" );
famDoc.Close( false );
Debug.Print( "Success processing '{0}'",
name );
}
catch( Exception ex )
{
Debug.Print( "Error processing '{0}': {1}",
name, ex.Message );
}
}
return IExternalCommand.Result.Failed;
}
But I have a AccesViolationException in the line "doc.get_Elements( filter, fams );".
¿What you think that it is the problem?
Thanks for help me.
Posted by: [email protected] | December 09, 2009 at 11:06
Hola Alex,
Que tal? I believe that you are having an issue with VB. You are passing in a List. I don't know what that will end up being in VB. In C#, the method get_Elements takes a generic List<Element. Maybe the name of the property is even not get_Elements in VB:
http://thebuildingcoder.typepad.com/blog/2009/09/document-elements.html
Cheers, Jeremy.
Posted by: Jeremy Tammik | December 10, 2009 at 03:06
Hello Jeremy, thank you for helping me.
As you know I'm trying to store a Revit family made with the Revit program in a database.
I made other function to skip the problem with "get_Elements" but it it doesn't work.
¿What I must do to get the family in the code? I will explain better(I know,you don´t understnad anything XD):
I have selected in the Revit program one family, then I executed my external command. While I´m debuging the program at this line:
public IExternalCommand.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) the variable "elements" is empty and then the program fails.
¿What I making wrong?¿What I have to do to send the family to the code?
thank you for your time.
Posted by: [email protected] | December 10, 2009 at 10:25
Dear Alexander,
The fact that 'elements' is empty is normal and expected. It is an output argument to the Execute method, not an input. Please see its use explained in the DevTV introduction to Revit programming, also known as Revit API introduction:
http://thebuildingcoder.typepad.com/blog/2009/12/updated-devtv-introduction-to-revit-programming.html
Have you listened to that yet?
Cheers, Jeremy.
Posted by: Jeremy Tammik | December 13, 2009 at 14:28
Hi Jeremy,
I want to save the one opened document in another new document by creating the new document. I have to do this work in "IExternalCommand.Result Execute(.....)" method of opened document.
I am using the below code to do the creation of new document and saving the current document in that:
private static void SaveOnClose(Autodesk.Revit.Application revitApp, Document document)
{
Autodesk.Revit.Application app = revitApp;
Document doc = document;
string name =doc.PathName+"\\"+ doc.ProjectInformation.Name+"101.rvt";
Document famDoc = new Document();
famDoc=doc;
famDoc.SaveAs(name);
famDoc.Close(false);
}
Please provide the useful help.
Regards,
Sam
Posted by: Sam | December 29, 2009 at 07:24
Dear Sam,
You cannot use the Document class default constructor. The default constructor is almost never used to create Revit API objects. You almost always use appropriate creation methods provided by the API instead. In this case the Application class provides the methods NewFamilyDocument to create a new family document, NewProjectDocument for a new project document, and NewProjectTemplateDocument for a new project template document.
Cheers, Jeremy.
Posted by: Jeremy Tammik | January 08, 2010 at 12:30
Jeremy,
I don't get the IsFamilyDocument property with the doc object.
This is what I am trying to do:
bool isFam = doc.IsFamilyDocument;
but when I type doc.IsFamilyDocument I get the following error. Any idea why?
Regards,
Nadim
Error 1 'Autodesk.Revit.Document' does not contain a definition for 'IsFamilyDocument' and no extension method 'IsFamilyDocument' accepting a first argument of type 'Autodesk.Revit.Document' could be found (are you missing a using directive or an assembly reference?) C:\API Manual\API Manual\Chapter10.cs 31 29 API Manual
Posted by: NAyche | January 11, 2010 at 12:06
Jeremy,
Never mind my previous post, apparently I had referenced the wrong RevitAPI.dll file.
Now I have IsFamilyDocument property.
Sorry about that.
Regards,
Nadim
Posted by: NAyche | January 11, 2010 at 12:11
Jeremy,
When trying to view the types in the steel section family
W-Wide Flange.rfa, the FamilyManager.Types will return only the types within the family.rfa file (in this case it is one type only).
All other types are actually referenced in a text file W-Wide Flange.txt in the same folder.
How do we retreive these types and list them?
Regards,
Nadim
Posted by: NAyche | January 11, 2010 at 12:21
Dear Nadim,
Glad you got it sorted out.
Cheers, Jeremy.
Posted by: Jeremy Tammik | January 11, 2010 at 16:12
Dear Nadim,
As far as I know, the only option you have for doing this is to check whether a text file with the same filename stem as the family exists and read and parse that yourself.
Cheers, Jeremy.
Posted by: Jeremy Tammik | January 11, 2010 at 16:15
Saving custom data generated by other Structural Software into Revit file (.rvt)
Hi,
I am using a Structural Modeling/Design application to model'design a simple building. And I am trying to save the content/data generated by the application into a revit file format (.rvt) using the Revit API.
Example : How to save the (Source)Structural Beam Data (generated by my Structural Modeling/Design application) into the (Target)Beam Data in Revit Structural Software. (.rvt)
As a result, Autodesk Revit Structure can be able to generate the same building i have modeled/designed.
Any idea of doing this?
Any help would be greatly appreciated.
Regards,
bsyap
Posted by: bsyap | June 09, 2010 at 03:47
Dear bsyap,
I see you posted the same comment again on
http://thebuildingcoder.typepad.com/blog/2010/06/devcamp-session-on-whats-new.html
So I will pick up the second version of your question.
Cheers, Jeremy.
Posted by: Jeremy Tammik | June 09, 2010 at 09:35
Jeremy,
how to change the dimension of duplicated family instance .
Regards,
sherif
Posted by: sherif | October 25, 2010 at 08:22
Dear Sherif,
That depends on what the family instance is, and what dimension you wish to change.
In some cases, you will have to change the family instance type using the FamilyInstance.Symbol property.
In others, it might be sufficient to change a parameter value or some other property.
Cheers, Jeremy.
Posted by: Jeremy Tammik | October 26, 2010 at 11:48
Hello Jeremy..
I want "activeView" of "ViewName" change..
====
Autodesk.Revit.DB.View view = document.ActiveView;
view.ViewName = "my section view";
======
but when running error!..
I wonder if you have any ideas
Posted by: JongWoo, Park | November 17, 2010 at 21:47
Dear JongWoo,
If I understand you correctly, you wish to change the name of the active view?
The following code works fine for me:
UIApplication app = commandData.Application;
Document doc = app.ActiveUIDocument.Document;
Transaction t = new Transaction( doc, "Change View Name" );
t.Start();
View docView = doc.ActiveView;
docView.Name = "Jeremy";
View view = commandData.View;
view.Name = "Tammik";
t.Commit();
return Result.Succeeded;
Cheers, Jeremy.
Posted by: Jeremy Tammik | November 19, 2010 at 02:33
Hello Jeremy, thank you for helping me.
But what I want...
/////
FilteredElementIterator itor = collector.OfClass(typeof(Autodesk.Revit.DB.ViewSheet)).GetElementIterator();
while (itor.MoveNext())
{
ListViewItem tmpItem = new ListViewItem(tmpViewSheet.Name);
listView1.Items.Add(tmpItem);
}
////////////
Dialogue box, select one from the list of view to the current view change
Thanks for you great help!
JongWoo, Park
Posted by: JongWoo, Park | November 22, 2010 at 19:52
Dear JongWoo, Park,
There is no possibility through the current Revit API to set the current view.
Cheers, Jeremy.
Posted by: Jeremy Tammik | November 23, 2010 at 09:12