Let’s say you have 100 view templates in a project, and you make a new one. You want to transfer only that new template to another project (not the other 100 View Templates). If you use Transfer Project Standards (on View Templates and Filters), you will get the lot. How can we transfer just one of them?
This is a great opportunity to show Revit 2014’s new ability to copy elements from one document to another.
public void CopyTemplate()
{
Document doc = this.ActiveUIDocument.Document;
// get the id of the view template assigned to the active view
ElementId templateId = doc.ActiveView.ViewTemplateId;
if (templateId == ElementId.InvalidElementId)
{
TaskDialog.Show("Error", "Active view must have a view template assigned.");
return;
}
// find the other open document in this session of Revit
Application app = this.Application;
Document otherDoc = app.Documents.Cast<Document>().Where(d => d.Title != doc.Title).FirstOrDefault();
if (otherDoc == null)
{
TaskDialog.Show("Error", "There must be a 2nd document open.");
return;
}
// add the template id to a collection
// must have 'using System.Collections.ObjectModel;' to use 'new Collection'
ICollection<ElementId> copyIds = new Collection<ElementId>();
copyIds.Add(templateId);
// create a default CopyPasteOptions
CopyPasteOptions cpOpts = new CopyPasteOptions();
// create a new transaction in the other document
using (Transaction t = new Transaction(otherDoc, "Copy View Template"))
{
t.Start();
// perform the copy into the other document using this new 2014 feature
ElementTransformUtils.CopyElements(doc, copyIds, otherDoc, Transform.Identity, cpOpts);
t.Commit();
}
}
[…] from Boost your BIM steps up to the plate and creates a macro for […]
Sorry to bug you with this but… what langauge is that Macro in? C#, Ruby, Python or VB.net? (I’m new to macros as of today.)
Hi Duncan,
Everything here is in C#
Harry
How would you implement this to copy sheets? I tried:
ICollection copyIds = new Collection();
FilteredElementCollector sheets = new FilteredElementCollector(doc).OfClass(typeof(ViewSheet));
foreach (Element elem in sheets)
{
ElementId sheetId = elem.Id;
copyIds.Add(sheetId);
}
With the rest of your code and it gave me an error. The DuplicateViews sample seems quite complex. I am thinking that you have to also get the ids of all the elements in each sheet as well? Thanks.
I hope this helps – https://boostyourbim.wordpress.com/2013/09/01/copy-a-sheet-from-one-project-to-another/
[…] response to my post “Transferring just one View Template from Project to Project“, Mike […]
How do you change this macro into an addin? I did read up on the conversion on https://boostyourbim.wordpress.com/2012/12/24/converting-a-macro-into-an-add-in/ But I’m new to programming.
Hi,
Where are you stuck? This topic (and many others) is covered in my Revit API course at https://www.udemy.com/revitapi/?couponCode=%2425off-4158ef98
Harry
Hi Harry,
Very new at the Revit API and I found this solution while Google since this exact situation popped up in the course of my day.
I tried pasting your code into a new module created in the SharpDevelop environment, but when I try to compile, I receive 2 errors.
The first refers to the ‘Application app = this.Application;’ line, where I get a CS0118 error and the description, “‘Autodesk.Revit.UI.Macros.ApplicationEntryPoint.Application’ is a ‘property’ but is used like a ‘type’ (CS0118).
The second error refers to the ‘ICollection copdIds = new Collection();’ line, where I received a ‘The type or namespace name ‘Collection’ could not be found (are you missing a using directive or an assembly reference?) (CS0246).
Needless to say, I hopped from a situation involving the need to copy one view template to another has transformed into the discovery of the Revit API and the robustness of its application… but it has me intrigued and I’m interested in seeing how I can implement this thinking into my workflow. How would I be able to integrate this into my code properly? I’ve been pasting your code in the Revit Macros generated code portion, after creating a module and adding through the ‘Macro’ button.
Cheers!
Thanks,
Andrew
Hi Andrew
Looks like you need to add some Using statements at the top of your file. Here are some posts that should help.
Harry
Hey, interesting code which I tried to use, doesn’t work so I’m probably doing something wrong here. Since I’m missing a step-by-step tutorial, here are my steps.
1. Create module (free to choose name)
2. revit will launch Sharpdevelop and some preset coding by Revit.
3. go back to Revit
4. in the macro manager (still open), click button create > macro.
5. name: from your example: CopyTemplate
6. in Sharpdevelop the new macro is added > insert your function here.
7. save and use.
So the whole code looks like:
/*
* Created by SharpDevelop.
* User: jm
* Date: 28-4-2014
* Time: 9:26
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.Linq;
namespace Transfer_Single_View
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.DB.Macros.AddInId(“83A58DCD-F4D0-4718-A36A-D06FFACDDCE0”)]
public partial class ThisApplication
{
private void Module_Startup(object sender, EventArgs e)
{
}
private void Module_Shutdown(object sender, EventArgs e)
{
}
#region Revit Macros generated code
private void InternalStartup()
{
this.Startup += new System.EventHandler(Module_Startup);
this.Shutdown += new System.EventHandler(Module_Shutdown);
}
#endregion
public void CopyTemplate()
{
Document doc = this.ActiveUIDocument.Document;
// get the id of the view template assigned to the active view
ElementId templateId = doc.ActiveView.ViewTemplateId;
if (templateId == ElementId.InvalidElementId)
{
TaskDialog.Show(“Error”, “Active view must have a view template assigned.”);
return;
}
// find the other open document in this session of Revit
Application app = this.Application;
Document otherDoc = app.Documents.Cast().Where(d => d.Title != doc.Title).FirstOrDefault();
if (otherDoc == null)
{
TaskDialog.Show(“Error”, “There must be a 2nd document open.”);
return;
}
// add the template id to a collection
// must have ‘using System.Collections.ObjectModel;’ to use ‘new Collection’
ICollection copyIds = new Collection();
copyIds.Add(templateId);
// create a default CopyPasteOptions
CopyPasteOptions cpOpts = new CopyPasteOptions();
// create a new transaction in the other document
using (Transaction t = new Transaction(otherDoc, “Copy View Template”))
{
t.Start();
// perform the copy into the other document using this new 2014 feature
ElementTransformUtils.CopyElements(doc, copyIds, otherDoc, Transform.Identity, cpOpts);
t.Commit();
}
}
}
}
While my 3D view has a template activly in use: the view template isn’t tranferred to another project.
Any thoughts?
Hi,
You might look at this post & step through the execution of the macro line-by-line to make sure that it is getting to the CopyElements line and that doc, copyIds, & otherDoc have the data you expect. Also, CopyElements returns a ICollection for the ids of the newly created copied elements. The current code is not storing that collection. You could check that to see what it contains.
Harry
I have watched the video of creating macro from source code. I’ve done this with the copy template. I was getting 2 errors on build. 1 I took care of by adding Autodesk.Revit.ApplicationServices;
The other I cannot seem to find an answer and has to do with this line
ICollection copyIds = new ICollection();
I am receiving this error
Edit, I added an I in the above new Icollection(); that should of not been there. Without that in this is the error I get
The type or namespace name ‘Collection’ could not be found (are you missing a using directive or an assembly reference?) (CS0246) – C:\ProgramData\Autodesk\Revit\Macros\2014\Revit\AppHookup\Myfirst\Source\Myfirst\ThisApplication.cs:66,42
My bad….Staring me right in my face.
using System.Collections.ObjectModel;
hello Harry,
I am new with using API and macros. I have copied and made compilation with no errors in the shapDevelop, however, when running the macro from the project with the template, says the Revit fails to execute the macro.
Why would this be?
Thank you.
What is the exact message that Revit gives when it fails to execute the macro?
Hi,
I’m getting this error;
http://screencast.com/t/QTY3lEZchrc
How can I resolve this?
Where(d => d.Title != doc.Title).FirstOrDefault();
assumes that there are only two documents open – the active document (containing the view template to copy) and the document that will receive the view template. If either of these files contains Revit links, then this assumption is incorrect and the document that is found may be an RVT link.
To handle this situation, try this:
Where(d => d.Title != doc.Title && !d.IsLinked).FirstOrDefault();
Thanks! I’m not getting the error anymore. But now no View Template is being copied when running the macro. Any other suggesdtions ; )
Have you stepped through the code to check the values of templateId & otherDoc?
I still have to familiarize myself wit the API. I’m used to programming in visual lisp.
Please consider my Revit API video course (https://www.udemy.com/revitapi/?couponCode=199). It is a great way to learn the basics of C# and the Revit API.
I will…
will this work with Revit 2016? I am running the Macros – CopyTemplate, and it is not transferring the view template to the new revit file. Also, will this work if I want to transfer a view template to a project that already has other view templates?
Hi,
It should work in 2016. Have you stepped through the code to make sure that the ElementTransformUtils.CopyElements line is executed? Is a value being assigned to templateId?
Harry
Hi Harry,
i tried to run the macro in 2016 and 2017 and getting those two errors
on line 52 Application app = this.Application; i am getting;
‘Autodesk.Revit.UI.UIApplication.Application’ is a ‘property’ but is used like a ‘type’ (CS0118) – C:\ProgramData\Autodesk\Revit\Macros\2017\Revit\AppHookup\qw\Source\qw\ThisApplication.cs:52,5
on line 62 ICollection copyIds = new Collection();
The type or namespace name ‘Collection’ could not be found (are you missing a using directive or an assembly reference?) (CS0246) – C:\ProgramData\Autodesk\Revit\Macros\2017\Revit\AppHookup\qw\Source\qw\ThisApplication.cs:62,42
You might need to add
using Autodesk.Revit.ApplicationServices;