Getting view ID of view from callout

Hello,

I’m trying to get the view ID from a list of selected view callouts (elevations, sections, plan callouts, etc). The ultimate goal is to place these on a sheet using DB.Viewport.Create, but I need the viewID for this.

It seems that the only properties which I can get from the selection that don’t throw an error are inherrited from the ‘element’ class, not the view class. For instance the following code throws an error after selecting the callout tags.

for v in selected_views:
    print(v.ViewType)

I feel like I’m missing one layer of complexity, but I can’t find any mention of this on line or in documentation.

Thanks!

Aaron

Hi @aaronnordstrom,
How do you get selected_views?
Without knowing this information, I only can tell you that the c# way is to use the explicit cast and check if the result is not null

var view = (View)v;
if (view != null) {
  // work with view...
}

I’m not sure/don’t remember if and how ironpython handles this.

I’m getting selected_views by using revit.pick_elements(). This is a slight variation on the ‘move view’ script that comes with pyRevit already.

When I select the tags/callouts, I’m trying to find the viewID and/or properties of that view. Most of the examples I’m finding on line are geting this information from an already placed viewport, not from a callout.

#Run after sheet is selected
if dest_sheet:
    sel = revit.pick_elements()
    for el in sel:
        selected_views.append(el)

#Run for each view seelected        
for v in selected_views:
    print(v.ViewType)

not sure what you are trying to achieve.

  • Select a callout in a view
    or
  • Select a place viewport of a callout while in a sheet

use RevitLookup to understand how to get the data you need
for example, selecting a viewport in a sheet, the viewport refering to the callout placed in a viewplan


you could get all this data with something like

from pyrevit import revit, DB

doc = revit.doc

whatever = revit.pick_elements()
print(whatever)
print(whatever[0].Id)
print(whatever[0].ViewId)

Thank you. Sorry I’ve been late to reply, but I was away on vacation. So your example seems to be best suited for getting the ViewID of an already existing viewport on a sheet. Is it possible to get the viewID of an elevation callout which has not been placed on a sheet yet?

Almost every example I find of viewId assumes the view has already been placed. I can get the element ID of the callout, but that doesn’t help me with DB.Viewport.Create.

I am working with my IT dept to install RevitLookup, so I can’t use this an an option yet.

The builtin parameter SECTION_PARENT_VIEW_NAME will get you the element referenced by the callout. That should get you going.

Sorry…I feel like I’m really missing something here. When I get that parameter the following way:

for el in sel:
    print(el.get_Parameter(DB.BuiltInParameter.SECTION_PARENT_VIEW_NAME))

it returns the error:

AttributeError: ‘Reference’ object has no attribute ‘get_Parameter’

I’m trying to use chatgpt to help get to the bottom of this. From what I can tell with talking with you and experimenting with Chatgpt, it seems that the callout I’m trying to use (elevations, sections, etc), aren’t suited for what I’m trying to do. Once again, it feels like I’m missing a line of code somewhere.

I have installed RevitLookup, but that’s not giving me the viewID or the parent view ID of the callout.

In Revit lookup click on parameters

It seems that doing so gives me information on the parameter field itself, but not on the data stored within it. For instance, I would have thought that snooping on ‘view name’ would give the the info I needed, but it just gives me information on the parameter itself, not on the data.

Yep, there is a ‘new’ way to get values.
Not in front of my computer.
Try all the blue links in Revit lookup when selecting the callout

Nothing. I’m actually really confused. I took a deep dive and used chatgpt 4.0 to try and diagnose why my elevation callouts aren’t producing any view data. After many back and forths with it, it finally gave me the following information:

This consistently returned result implies that the element you’re selecting might not be the type of elevation callout that we’re targeting with the code. There are various ways elements might be represented or categorized in Revit, and it seems we’ve not quite nailed down the exact nature of the element you’re working with.

I don’t understand because the elevation callouts I’m selecting are just the standard callouts. There is nothing special about them. I know that chatgpt is known for buggy code, but the fact that it’s not coming up with anything close to a solution leaves me confused. I’m just not seeing how to get the view data from an elevation/section callout.

So when you use revitlookup on one of your elevation callouts, are you seeing something that would give you the viewID and allow python to ultimately place the view on a sheet? I’m not able to find any parameter that I can use to find the corresponding view. Both revitlookup and python appear to be seeing the callout as an element and not a view (which makes sense). How do I make that connection from the callout ‘element’ to the corresponding ‘view’?

It seems I need to find the ‘ownerviewid’ first, but this is what I get when selecting a callout.

image

@aaronnordstrom
my not so elegant solution is to test your callout selected name against the view list of names.

# -*- coding: utf-8 -*-
from pyrevit import revit, script, DB

doc = revit.doc
output = script.get_output()
output.close_others()

# get the selected callouts
callouts = revit.get_selection() # will give you the callout, not the cropped view itself
callouts_names = [c.Name for c in callouts]
# collect all views in the project
views = DB.FilteredElementCollector(doc).OfClass(DB.View).ToElements()
# filter the views to get only the callouts views
callout_views = []
for view in views:
    if view.Name in callouts_names:
        callout_views.append(view)

# get the first sheet in the project
sheet = DB.FilteredElementCollector(doc).OfClass(DB.ViewSheet).ToElements()[0] # get the first sheet in the project

count = 0
with revit.Transaction("Create Callouts from selection"):
    for callout_view in callout_views:
        try:
            vp = DB.Viewport.Create(doc, sheet.Id, callout_view.Id , DB.XYZ(count, 0, 0))
        except Exception as e:
            print(e)
        count += 1 # to offset the viewports
1 Like

That’s it. Your solution makes sense. I’m glad I’m not crazy that I was missing something in the callout properties.

Hi, some “code-freak” tips regarding @Jean-Marc solution:

  • sets are a better structure for “bunch of things” to search into: callout_names = {c.Name for c in callouts}
  • you can use list comprehension instead of building the callout_views one by one: callout_views = [v for v in views if v.Name in callout_names]
  • pyrevit offers the pyrevit.revit.db.query.get_sheet_sets function to get the list of ViewSheets

let me rephrase then :stuck_out_tongue:

# -*- coding: utf-8 -*-
from pyrevit import revit, script, DB

doc = revit.doc
output = script.get_output()
output.close_others()

# get the selected callouts
callouts = revit.get_selection() # will give you the callout, not the cropped view itself
callouts_names = {c.Name for c in callouts}
# collect all views in the project
views = DB.FilteredElementCollector(doc).OfClass(DB.View).ToElements()
# filter the views to get only the callouts views
callout_views = [v for v in views if v.Name in callout_names]

# get the first sheet in the project
sheet = DB.FilteredElementCollector(doc).OfClass(DB.ViewSheet).ToElements()[0] # get the first sheet in the project

count = 0
with revit.Transaction("Create Callouts from selection"):
    for callout_view in callout_views:
        try:
            vp = DB.Viewport.Create(doc, sheet.Id, callout_view.Id , DB.XYZ(count, 0, 0))
        except Exception as e:
            print(e)
        count += 1 # to offset the viewports

I will let @sanzoghenzo polish it. Leaving right now, so no time to apply point 3.