Zooming a new view

If you are creating a new view and then want to use the UIView.Zoom method, you need to make the new view the active view and then refresh the view. If you don’t, the attempt to zoom will be futile.

public void createNewViewAndZoom()
{
    Document doc = this.ActiveUIDocument.Document;
    UIDocument uidoc = this.ActiveUIDocument;
    ViewFamilyType vft3d = new FilteredElementCollector(doc).OfClass(typeof(ViewFamilyType)).Cast<ViewFamilyType>().FirstOrDefault(q => q.ViewFamily == ViewFamily.ThreeDimensional);
    View view = null;
    using (Transaction t = new Transaction(doc, "make views"))
    {
        t.Start();
        view = View3D.CreateIsometric(doc, vft3d.Id);
        t.Commit();
    }
    zoom(uidoc, view);            
}

private void zoom(UIDocument uidoc, View view)
{
    // YOU NEED THESE TWO LINES OR THE ZOOM WILL NOT HAPPEN!
    uidoc.ActiveView = view;
    uidoc.RefreshActiveView();
    
    UIView uiview = uidoc.GetOpenUIViews().Cast<UIView>().FirstOrDefault(q => q.ViewId == view.Id);
    uiview.Zoom(5);
}

Free “View Parameter for Detail Items” app now available

A few months ago I posted the source code showing how a “View” field could be added to a Detail Item schedule, even though out-of-the-box Revit does not offer View as a schedule-able field. The compiled application can now be downloaded for free at the Autodesk App Store.

Record view creation date in a shared parameter

Luke asked if it was possible to use the API to track the history of Revit view creation to a shared parameter. This allows a View List to be sorted by creation date.

Source code available at https://www.udemy.com/revitapi/?couponCode=%2425off-4158ef98

#RTCEUR Wish 3 – Copy View Types & Templates btw Documents

Q: Would be possible to create a tool that would “Transfer View Types” from one project to another?

Background: View Types have a couple of key properties, an assigned View Template, and if new view instances created from the Type should be dependent on the View Template. But the Revit UI does not allow view types to be transferred between projects.

A: Good news! With the API it is possible to determine the View Types defined in a project, read their associated parameters, create new View Types in a second Project, and set these parameters to match the values in the source project.

public void CopyViewTypes()
{
    Application app = this.Application;

    // source document is the active document
    Document sourceDoc = this.ActiveUIDocument.Document;

    // target document is an open file named "target.rvt"
    Document targetDoc = app.Documents.Cast<Document>().Where(q => Path.GetFileName(q.PathName) == "target.rvt").FirstOrDefault();

    // element ids for all instances of the ViewFamilyType class
    ICollection<ElementId> viewFamilyTypeIds = new FilteredElementCollector(sourceDoc).OfClass(typeof(ViewFamilyType)).ToElementIds();

    // element ids of the view templates used in View Types
    ICollection<ElementId> templateIds = new List<ElementId>();

    // list of pairs of strings - first item in each pair will be the name of the View Type - second item will be the name of the View Template used by that View Type 
    IList<Tuple<string, string>>  ssList = new List<Tuple<string, string>>();

    foreach (ViewFamilyType vft in new FilteredElementCollector(sourceDoc).OfClass(typeof(ViewFamilyType)))
    {
        // element id of the view template used in this View Type
        ElementId defaultTemplateId = vft.get_Parameter(BuiltInParameter.DEFAULT_VIEW_TEMPLATE).AsElementId();

        // go to the next View Type if there is no View Template assigned to this view type
        if (defaultTemplateId == ElementId.InvalidElementId)
            continue;

        templateIds.Add(defaultTemplateId);

        ssList.Add(new Tuple<string, string>(vft.Name, sourceDoc.GetElement(defaultTemplateId).Name));
    }

    CopyPasteOptions options = new CopyPasteOptions();

    using (Transaction t = new Transaction(targetDoc, "Copy View Types"))
    {
        t.Start();
        // copy the view templates
        ElementTransformUtils.CopyElements(sourceDoc, templateIds, targetDoc, Transform.Identity, options);
        // copy the view types
        ElementTransformUtils.CopyElements(sourceDoc, viewFamilyTypeIds, targetDoc, Transform.Identity, options);

        foreach (Tuple<string, string> tup in ssList)
        {
            Element vft = new FilteredElementCollector(targetDoc).OfClass(typeof(ViewFamilyType)).Where(q => q.Name == tup.Item1).FirstOrDefault();

            View template = new FilteredElementCollector(targetDoc).OfClass(typeof(View)).Cast<View>().Where(q => q.IsTemplate && q.Name == tup.Item2).FirstOrDefault();

            // assign the view template to the view type
            vft.get_Parameter(BuiltInParameter.DEFAULT_VIEW_TEMPLATE).Set(template.Id);
        }

        t.Commit();
    }
}

#RTCEUR Wish 2 – Highlight and Isolate Warning Elements

@marcellosgamb suggested an API that runs thru every error in a model turns element w/error red then as u fix each error turn normal

There is no API access to the Revit “Review Warnings” data, so this implementation requires the user to export the warning data. The program then imports this HTML, parses it to find the element IDs, and then isolates and colors the elements in two 3D views.

public void ShowWarningElements()
{
    Document doc = this.ActiveUIDocument.Document;

    string filename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "warnings.html");

    IList<ElementId> ids = new List<ElementId>();

    using (StreamReader sr = new StreamReader(filename))
    {
        string line = "";
        while ((line = sr.ReadLine()) != null)
        {
            string[] row = System.Text.RegularExpressions.Regex.Split(line,"id ");
            if (row.Length != 3)
            {
                continue;
            }
            string id1 = row[1].Split(' ')[0];
            string id2 = row[2].Split(' ')[0];

            ids.Add(new ElementId(int.Parse(id1)));
            ids.Add(new ElementId(int.Parse(id2)));
        }
    }    

    View isolateView = new FilteredElementCollector(doc).OfClass(typeof(View)).Cast<View>().Where(q => q.Name == "IsolateWarningElements").FirstOrDefault();
    View overrideView = new FilteredElementCollector(doc).OfClass(typeof(View)).Cast<View>().Where(q => q.Name == "OverrideWarningElements").FirstOrDefault();

    OverrideGraphicSettings ogs = new OverrideGraphicSettings();
    Color red = new Color(255, 0, 0);
    ogs.SetProjectionLineColor(red);
    ogs.SetProjectionLineWeight(8);

    Element solidFill = new FilteredElementCollector(doc).OfClass(typeof(FillPatternElement)).Where(q => q.Name.Contains("Solid")).First();

    ogs.SetProjectionFillPatternId(solidFill.Id);
    ogs.SetProjectionFillColor(new Color(0, 255,0));

    using (Transaction t = new Transaction(doc, "Isolate/Override Warnings"))
    {
        t.Start();
        isolateView.IsolateElementsTemporary(ids);

        foreach (ElementId id in ids)
        {
            overrideView.SetElementOverrides(id, ogs);
        }
        t.Commit();
    }
}

What sheets are my views on?

A reader asked: How do u find out what sheet a view is on via API?

Below is some code and the screenshot shows the Project Browser and output from the API macro.

ViewSheetReport

public void viewSheetReport()
{
    Document doc = this.ActiveUIDocument.Document;
    string data = "";
    foreach (View v in new FilteredElementCollector(doc).OfClass(typeof(View)))
    {
        string thisSheet = "";
        foreach (ViewSheet vs in new FilteredElementCollector(doc)
            .OfClass(typeof(ViewSheet))
            .Cast<ViewSheet>())
        {
            foreach (View view in vs.Views)
            {
                if (view.Id == v.Id)
                {
                    thisSheet += vs.Name + " - " + vs.SheetNumber + ", ";
                    break;
                }
            }
        }
        if (thisSheet != "")
        {
            data += v.ViewType + " - " + v.Name + ": " + thisSheet.TrimEnd(' ',',') + Environment.NewLine + Environment.NewLine;
        }
    }
    TaskDialog.Show("Sheet Report", data);
}

Copy a sheet from one project to another

In response to my post “Transferring just one View Template from Project to Project“, Mike asks:

How would you implement this to copy sheets?

To start, it is not possible to copy viewports with the API. This is not too much of a surprise, as the Revit UI does not allow duplicating sheets and does not allow copying viewports. Also, it is not possible to copy a sheet that has viewports on it.

However, it is possible to use the API to copy the sheet, titleblock, and view-specific elements on the sheet if we use this procedure:

  1. Temporarily delete the viewports from the sheet (this is done in a transaction that be rolled back at the end so that the viewports are not actually deleted)
  2. Copy the sheet to the new project
  3. Copy the view-specific elements (excluding the viewports) from the source sheet view to the destination sheet view

The sneaky part of this is realizing that that while a single document can have only one transaction open at any given time, we can have one transaction in each document open at the same time.

public void CopySheet()
{
    Document doc = this.ActiveUIDocument.Document;

    ViewSheet activeViewSheet = doc.ActiveView as ViewSheet;
    if (activeViewSheet == null)
    {
        TaskDialog.Show("Error", "Active view must be a sheet.");
        return;
    }

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

    // put the sheet in the source document into the copyIds collection
       ICollection<ElementId> copyIds = new Collection<ElementId>();
    copyIds.Add(activeViewSheet.Id);    

    // put view-specific elements on the sheet in the copyIdsViewSpecific collection
    ICollection<ElementId> copyIdsViewSpecific = new Collection<ElementId>();
    foreach (Element e in new FilteredElementCollector(doc).OwnedByView(doc.ActiveView.Id))
    {
        // do not put viewports into this collection because they cannot be copied
        if (!(e is Viewport))
            copyIdsViewSpecific.Add(e.Id);    
    }

    // Create a transaction in the source document to delete the viewports.
    // This transaction will be rolled-back so it won't cause any permanent change in the document
    // but it will enable copying of the sheet while it is in a state with no viewports
    using (Transaction t = new Transaction(doc,"Delete Viewports"))
    {
        t.Start();

        IList<Viewport> viewports = new FilteredElementCollector(doc).OfClass(typeof(Viewport)).Cast<Viewport>()
            .Where(q => q.SheetId == activeViewSheet.Id).ToList();

        foreach (Viewport vp in viewports)
        {
            doc.Delete(vp.Id);
        }

        using (Transaction tOther = new Transaction(otherDoc, "Copy View Template"))
        {
            tOther.Start();
            // copy the sheet using the CopyElements overload that accepts source and destination documents
            // get the newly created sheet in the target document - it will be the first (and only) element returned by ElementTransformUtils.CopyElements
            ViewSheet newSheet = otherDoc.GetElement(ElementTransformUtils.CopyElements(doc, copyIds, otherDoc, Transform.Identity, new CopyPasteOptions()).First()) as ViewSheet;

            // copy the view-specific elements using the CopyElements overload that accepts source and destination views
            ElementTransformUtils.CopyElements(activeViewSheet, copyIdsViewSpecific, newSheet, Transform.Identity, new CopyPasteOptions());

            tOther.Commit();
        }

        // rollback the transaction to "undo" the deletion of the viewports
        t.RollBack();
    }
}

Set graphic overrides for an element in a view

2014 includes a new View.SetElementOverrides that can be used to set view-specific graphic overrides for a specific element.

public void ElementOverride()
{
    Document doc = this.ActiveUIDocument.Document;
    UIDocument uidoc = this.ActiveUIDocument;
    ElementId id = uidoc.Selection.PickObject(ObjectType.Element,"Select an element").ElementId;
    OverrideGraphicSettings ogs = new OverrideGraphicSettings();
    ogs.SetProjectionLineColor(new Color(0,255,0));
    using (Transaction t = new Transaction(doc,"Set Element Override"))
    {
        t.Start();
        doc.ActiveView.SetElementOverrides(id, ogs);
        t.Commit();
    }
}

Click twice to create a cropped dependent view

Here is how  to prompt the user to click twice and use those points to create a new dependent view cropped to the rectangle formed by those points.

public void MakeViewAndSheetWith2Clicks()
{
    Document doc = this.ActiveUIDocument.Document;
    UIDocument uidoc = new UIDocument(doc);

    // prompt user to pick two points
    XYZ lowLeftPickPoint = uidoc.Selection.PickPoint("Pick lower left corner");
    XYZ upRightPickPoint = uidoc.Selection.PickPoint("Pick upper right corner");

    // create a new BoundingBoxXYZ & set its Min and Max to the XYZ points selected by the user
    BoundingBoxXYZ bboxFromPicks = new BoundingBoxXYZ();
    bboxFromPicks.Min = lowLeftPickPoint;
    bboxFromPicks.Max = upRightPickPoint;

    // Find a titleblock in the project, or use InvalidElementId to create a sheet with no titleblock
    ElementId titleblockId = ElementId.InvalidElementId;
    FamilySymbol titleBlockSymbol = doc.TitleBlocks.Cast<FamilySymbol>().FirstOrDefault();
    if (titleBlockSymbol != null)
        titleblockId = titleBlockSymbol.Id;

    ViewSheet sheet = null;
    using (Transaction t = new Transaction(doc,"crop"))
    {
        t.Start();

        // duplicate the active view
        ElementId newViewId = doc.ActiveView.Duplicate(ViewDuplicateOption.AsDependent);
        View newView = doc.GetElement(newViewId) as View;

        // set the crop box of the new view to the bounding box created from the two picked points
        newView.CropBox = bboxFromPicks;

        // Create the new sheet
        sheet = ViewSheet.Create(doc, titleblockId);

        newView.Name = sheet.Name + "-" + sheet.SheetNumber;
        newView.Scale = 10;

        // Create the viewport to put the new view on the new sheet at (0,0,0)
        Viewport.Create(doc, sheet.Id, newViewId, XYZ.Zero);
        t.Commit();
    }
    // make the new sheet the active view
    uidoc.ActiveView = sheet;
}

“View” Field added to a Detail Item Schedule

Revit 2014 can schedule detail items, but some people still aren’t satisfied because out-of-the-box Revit doesn’t schedule the detail item’s view. Here’s an API solution for that.

// typically this would be done during OnStartup		
public void registerUpdater()
{
    MyUpdater updater = new MyUpdater(this.Application.ActiveAddInId);
    UpdaterRegistry.RegisterUpdater(updater);

    LogicalOrFilter orFilter =  new LogicalOrFilter
                               (new ElementClassFilter(typeof(View)),
                                 new ElementClassFilter(typeof(FamilyInstance)));

    UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), orFilter, Element.GetChangeTypeAny());
    UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), orFilter, Element.GetChangeTypeElementAddition());
}

public class MyUpdater : IUpdater
{
    static AddInId m_appId;
    static UpdaterId m_updaterId;
    public MyUpdater(AddInId id)
    {
        m_appId = id;
        m_updaterId = new UpdaterId(m_appId, new Guid("F2FBF6B2-4C06-42d4-97C1-D1B4EB593EFF"));
    }
    public void Execute(UpdaterData data)
    {
        Document doc = data.GetDocument();
        foreach (Element e in new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_DetailComponents))
        {
            Element v = doc.GetElement(e.OwnerViewId);
            e.get_Parameter("View").Set(v.Name);                        
        }
    }
    public string GetAdditionalInformation() { return "Detail View Parameter"; }
    public ChangePriority GetChangePriority() { return ChangePriority.FloorsRoofsStructuralWalls; }
    public UpdaterId GetUpdaterId() { return m_updaterId; }
    public string GetUpdaterName() { return "Detail View Parameter"; }
}

Delete ALL Views

I was asked today at RTC if it would be possible to delete all views in a Revit file in preparation for publishing the model to other firms.

It was a little more complicated than I thought and is contrary to all those kumbaya ideas about sharing and collaboration, but if this is something you need to do, the API can save you a bunch of clicking in the Project Browser.

The 3D geometry in the model still exists after the command completes and you can use the UI to create new 3D and plan views. 

View Category Overrides

Greetings from Revit Technology Conference NA in beautiful Vancouver! This is my first trip to RTC and it is great! Yesterday I gave a presentation titled “Raise the IQ of Your Revit model with the API” and then a fun and wide-ranging late-night API Q&A session with 20+ people.

Here’s a good question that I was asked this morning…

Q.  Is it possible to change the transparency of a category in a view in API? Basically the visibility/graphics dialog?

A. Yes, this is a new addition in the 2014 API. Below is a code sample and screenshot showing the result of this macro.

From the “2014 What’s New”:

Category override

Display of categories can be overridden. This can be done with the new class OverrideGraphicSettings and the new View methods:

  • SetCategoryOverrides
  • GetCategoryOverrides
  • IsOverrideValidForCategory
  • IsCategoryOverridable
public void setCatVis()
{
    UIDocument uidoc = this.ActiveUIDocument;
    Document doc = uidoc.Document;

    OverrideGraphicSettings ogs = new OverrideGraphicSettings();
    ogs.SetSurfaceTransparency(50);
    Category wallCat = doc.Settings.Categories.get_Item("Walls");

    using (Transaction t = new Transaction(doc,"Set Overrides"))
    {
        t.Start();
        doc.ActiveView.SetCategoryOverrides(wallCat.Id,ogs);
        t.Commit();
    }
}

Capture

How to toggle the visibility of Automatic Sketch Dimensions

I was asked if the API could be used to make it easier to toggle the visibility of Temporary Sketch Dimensions. This macro will toggle the state of this subcategory for one or all views in the project.

In future post I will examine how this can be made easier to access by adding the command to the ribbon so it can be invoked with a keyboard shortcut instead of having to access it through the Macros dialog.

public void ToggleAutoSketchDimensionVisibility()
{
    UIDocument uidoc = this.ActiveUIDocument;
    Document doc = uidoc.Document;

    // use the following line to set the visibility for only the active view
    // use the FilteredElementCollector and foreach loop to set it for all views
    // View view = doc.ActiveView;

    Category autoSketchDimCat = doc.Settings.Categories.get_Item(BuiltInCategory.OST_Dimensions).SubCategories.get_Item("Automatic Sketch Dimensions");

    using (Transaction t = new Transaction(doc,"Toggle 'Automatic Sketch Dimensions' Visibility"))
    {
        t.Start();
        foreach (View view in new FilteredElementCollector(doc).OfClass(typeof(View)).Cast<View>())
        {
            // set the visibility of this category to the opposite of its current value (if it is True, set it to False, etc)
            view.SetVisibility(autoSketchDimCat, !autoSketchDimCat.get_Visible(view));
        }
        t.Commit();
    }
}

GetCellText – Contents of Schedule Cells in 2014

In 2013 we could read the contents of a schedule through a bit of a workaround – export the schedule to a text file with ViewSchedule.Export and read the file back in with StreamReader.

Now in 2014 we can read the cell values directly with ViewSchedule.GetCellText as shown below with a macro that reads the schedule and shows the data in a TaskDialog.

GetCellText
publicvoid Schedule2014GetCellText()
{
    UIDocument uidoc = this.ActiveUIDocument;
    Document doc = uidoc.Document;
    ViewSchedule viewSchedule = doc.ActiveView as ViewSchedule;
    SectionType sectionType = SectionType.Body;

    string data = "";
    for (int i = 0; i < getRowColumnCount(viewSchedule, sectionType, true); i++)
    {
        for (int j = 0; j <  getRowColumnCount(viewSchedule, sectionType, false); j++)
        {
            data += viewSchedule.GetCellText(sectionType, i, j) + ",";
        }
        // remove the trailing "," after the last cell and add a newline for the end of this row
        data = data.TrimEnd(',') + "\n";
    }
    TaskDialog.Show(viewSchedule.Name, data);
}

private int getRowColumnCount(ViewSchedule view, SectionType sectionType, bool countRows)
{
    int ctr = 1;
    // loop over the columns of the schedule
    while (true)
    {
        try // GetCellText will throw an ArgumentException is the cell does not exist
        {
            if (countRows)
                view.GetCellText(sectionType, ctr, 1);
            else
                view.GetCellText(sectionType, 1, ctr);
            ctr++;
        }
        catch (Autodesk.Revit.Exceptions.ArgumentException)
        {
            return ctr;
        }
    }
}

What you can do with View Filters in the 2014 API

Here’s are the new Filter items for the View class in 2014:

  • AddFilter – The filter will be added with default overrides, so there will be no change in the view’s display.
  • GetFilterOverrides – Returns all graphic overrides of a specific filter in the view
  • GetFilters – Returns the ids of the filters applied to the view
  • GetFilterVisibility – Returns true if the elements associated with a specific filter are visible in the view
  • IsFilterApplied – Returns true if a specific filter is applied to the view
  • RemoveFilter
  • SetFilterOverrides – Set the OverrideGraphicSettings for a filter in a view. Adds the filter to the view if it hadn’t been previously added.
  • SetFilterVisibility – Set the visibility of a specific filter (true / false) for a view. Adds the filter to the view if it hadn’t been previously added.
public void Filter2014Sample()
{
    UIDocument uidoc = this.ActiveUIDocument;
    Document doc = uidoc.Document;
    View view = doc.ActiveView;

    TaskDialog.Show("Boost Your BIM","# of filters applied to this view = " + view.GetFilters().Count);

    // create list of categories that will for the filter
    IList<ElementId> categories = new List<ElementId>();
    categories.Add(new ElementId(BuiltInCategory.OST_Walls));

    // create a list of rules for the filter
    IList<FilterRule> rules = new List<FilterRule>();
    // This filter will have a single rule that the wall type width must be less than 1/2 foot
    Parameter wallWidth = new FilteredElementCollector(doc).OfClass(typeof(WallType)).FirstElement().get_Parameter(BuiltInParameter.WALL_ATTR_WIDTH_PARAM);
    rules.Add(ParameterFilterRuleFactory.CreateLessRule(wallWidth.Id, 0.5, 0.001));

    ParameterFilterElement filter = null;
    using (Transaction t = new Transaction(doc, "Create and Apply Filter"))
    {
        t.Start();
        filter =  ParameterFilterElement.Create(doc, "Thin Wall Filter", categories, rules);
        view.AddFilter(filter.Id);
        t.Commit();
    }

    string filterNames = "";
    foreach (ElementId id in view.GetFilters())
    {
        filterNames += doc.GetElement(id).Name + "\n";
    }
    TaskDialog.Show("Boost Your BIM","Filters applied to this view: " + filterNames);

    // Create a new OverrideGraphicSettings object and specify cut line color and cut line weight
    OverrideGraphicSettings ogs = new OverrideGraphicSettings();
    ogs.SetCutLineColor(new Color(255,0,0));
    ogs.SetCutLineWeight(9);

    using (Transaction t = new Transaction(doc, "Set Override Appearance"))
    {
        t.Start();
        view.SetFilterOverrides(filter.Id,ogs);
        t.Commit();
    }
}

Extending the Renumber command for Viewports & Detail Number

Here is a response to the comment from Jeff at https://boostyourbim.wordpress.com/2013/01/17/quick-way-to-renumber-doors-grids-and-levels/ on how to extend that tool to work with the Viewport > Detail Number parameter.

2012 2013
private Parameter getParameterForReference(Document doc, Reference r)
{
    Element e = doc.GetElement(r);
    Parameter p = null;
    if (e is Grid)
        p = e.get_Parameter("Name");
    else if (e is Autodesk.Revit.DB.Architecture.Room)
        p = e.get_Parameter("Number");
    else if (e is FamilyInstance)
        p = e.get_Parameter("Mark");
    else
    {
        p = e.get_Parameter("Detail Number");
        if (p == null)
        {
            TaskDialog.Show("Error", "Unsupported element");
            return null;
        }
    }
    return p;
}
private Parameter getParameterForReference(Document doc, Reference r)
{
    Element e = doc.GetElement(r);
    Parameter p = null;
    if (e is Grid)
        p = e.get_Parameter("Name");
    else if (e is Room)
        p = e.get_Parameter("Number");
    else if (e is FamilyInstance)
        p = e.get_Parameter("Mark");
    else if (e is Viewport) // Viewport class is new to Revit 2013 API
        p = e.get_Parameter("Detail Number");
    else
    {
        TaskDialog.Show("Error","Unsupported element");
        return null;
    }
    return p;
}    

The 2012 code can be used in 2013, but I like the 2013 version a bit better for being more explicit about which classes are being checked.

What views use which view templates? (2013 edition and better formatting)

View Templates got a big makeover in Revit 2013, so the previous post needs to be modified slightly to run in Revit 2013. I’ve also improved the format of the output so it looks like this:


---------------- Summary ---------------------------
Architectural Elevation: 4
Architectural Plan: 2
Architectural Reflected Ceiling Plan: 2
Site Plan: 1
Structural Framing Plan: 0
Structural Framing Elevation: 0
Architectural Section: 0
Site Section: 0
Structural Section: 0
Architectural Presentation 3D: 0
Architectural Presentation Elevation: 0
Export to Civil Engineering: 0

---------------- Details ---------------------------
'Architectural Elevation' is View Template for 4 views
Elevation East
Elevation North
Elevation West
Elevation South

'Architectural Plan' is View Template for 2 views
FloorPlan Level 1
FloorPlan Level 2

'Architectural Reflected Ceiling Plan' is View Template for 2 views
CeilingPlan Level 1
CeilingPlan Level 2

'Site Plan' is View Template for 1 views
FloorPlan Site

'Structural Framing Plan' is View Template for 0 views

'Structural Framing Elevation' is View Template for 0 views

'Architectural Section' is View Template for 0 views

'Site Section' is View Template for 0 views

'Structural Section' is View Template for 0 views

'Architectural Presentation 3D' is View Template for 0 views

'Architectural Presentation Elevation' is View Template for 0 views

'Export to Civil Engineering' is View Template for 0 views

The view parameter “Default View Template” has been renamed “View Template” and the API has a new property View.ViewTemplateId. 2013 also obsoleted Document.get_Element, replacing it with Document.GetElement.

public void TemplateUse()
{
    Document doc = this.ActiveUIDocument.Document;
    Dictionary<string, IList<string>> dict = new Dictionary<string, IList<string>>();
    foreach (View viewTemplate in (from v in new FilteredElementCollector(doc).OfClass(typeof(View)).Cast<View>() where v.IsTemplate select v))
    {
        IList<string> viewsUsed = new List<string>();
        foreach (View view in (from v in new FilteredElementCollector(doc).OfClass(typeof(View)).Cast<View>() where !(v.IsTemplate) select v))
        {
            ElementId id = view.ViewTemplateId;
            if (id != ElementId.InvalidElementId)
            {
                Element e = doc.GetElement(id);
                if (e.Name == viewTemplate.Name)
                    viewsUsed.Add(view.ViewType.ToString() + " " + view.Name);
            }
        }
        dict.Add(viewTemplate.Name, viewsUsed);
    }

    // sort the dictionary based on the number of views in each list
    var items = from pair in dict orderby pair.Value.Count descending select pair;

    string filename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "ViewTemplateUsage.txt");

    using (StreamWriter sr = new StreamWriter(filename, false))
    {
        sr.WriteLine("---------------- Summary ---------------------------");

        foreach (KeyValuePair<string, IList<string>> pair in items)
        {
            sr.WriteLine(pair.Key + ": " + pair.Value.Count);
        }
        sr.WriteLine();

        sr.WriteLine("---------------- Details ---------------------------");
        foreach (KeyValuePair<string, IList<string>> pair in items)
        {
            sr.WriteLine("'" + pair.Key + "' is View Template for " + pair.Value.Count + " views");
            foreach (string name in pair.Value)
            {
                sr.WriteLine(name);
            }
            sr.WriteLine();
        }
    }
    Process.Start(filename);
}    

What views use which view templates? (2012 edition)

Steve wrote at Revit OpEd:

When I travel back and forth between Revit versions, say between 12 and 13, I find myself missing things. For example I wanted to see (in 2012) how many views were assigned to view templates and which ones were really being used. In 2013 we can add that parameter to a View List, 2012 not so much. In 2013 we can select a view template and see how many views are assigned to it, in 2012…you get the idea. I wish life and project conditions didn’t make it hard to “just upgrade”. Just do it, as soon as you can!

Sometimes when you can’t upgrade your RVT to a newer version of Revit, you can use the Revit API to accomplish something similar (or even better!) than what you would do in the newer release of Revit. Here is a Revit 2012 macro that outputs a text file listing all view templates with the count and names of the views that use it as the default view template:

'Architectural Elevation' is Default View Template for 4 views

Elevation East, Elevation North, Elevation West, Elevation South,

'Architectural Plan' is Default View Template for 2 views

FloorPlan Level 1, FloorPlan Level 2,

'Architectural Reflected Ceiling Plan' is Default View Template for 2 views

CeilingPlan Level 1, CeilingPlan Level 2,

'Site Plan' is Default View Template for 1 views

FloorPlan Site,

'Structural Framing Plan' is Default View Template for 0 views

'Structural Framing Elevation' is Default View Template for 0 views

'Architectural Section' is Default View Template for 0 views

'Site Section' is Default View Template for 0 views

'Structural Section' is Default View Template for 0 views

'Architectural Presentation 3D' is Default View Template for 0 views

'Architectural Presentation Elevation' is Default View Template for 0 views

'Export to Civil Engineering' is Default View Template for 0 views
public void TemplateUse()
{
    Document doc = this.ActiveUIDocument.Document;
    Dictionary<string, IList<string>> dict = new Dictionary<string, IList<string>>();
    foreach (View viewTemplate in (from v in new FilteredElementCollector(doc).OfClass(typeof(View)).Cast<View>() where v.IsTemplate select v))
    {
        IList<string> viewsUsed = new List<string>();
        foreach (View view in (from v in new FilteredElementCollector(doc).OfClass(typeof(View)).Cast<View>() where !(v.IsTemplate) select v))
        {
            Parameter p = view.get_Parameter("Default View Template");
            if (p != null)
            {
                ElementId id = p.AsElementId();
                if (id != ElementId.InvalidElementId)
                {
                    Element e = doc.get_Element(p.AsElementId());
                    if (e.Name == viewTemplate.Name)
                        viewsUsed.Add(view.ViewType.ToString() + " " + view.Name);
                }
            }
        }
        dict.Add(viewTemplate.Name, viewsUsed);
    }

    // sort the dictionary based on the number of views in each list
    var items = from pair in dict orderby pair.Value.Count descending select pair;

    string filename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "ViewTemplateUsage.txt");

    using (StreamWriter sr = new StreamWriter(filename, false))
    {
        foreach (KeyValuePair<string, IList<string>> pair in items)
        {
            sr.WriteLine("'" + pair.Key + "' is Default View Template for " + pair.Value.Count + " views");
            string s = "";
            foreach (string name in pair.Value)
            {
                s += name + ", ";
            }
            sr.WriteLine(s);
            sr.WriteLine();
        }
    }
    Process.Start(filename);
}