Transferring just one View Template from Project to Project

Luke asks:

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();
    }
}

28 thoughts on “Transferring just one View Template from Project to Project

  1. 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.)

  2. 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.

  3. 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

  4. 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

  5. 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

    Cannot create an instance of the abstract class or interface 'System.Collections.Generic.ICollection<Autodesk.Revit.DB.ElementId>' (CS0144) - C:\ProgramData\Autodesk\Revit\Macros\2014\Revit\AppHookup\Myfirst\Source\Myfirst\ThisApplication.cs:66,38
  6. 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

  7. 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.

  8. 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

Leave a reply to Sofie Kopolla Cancel reply