Back Referencing Views - Looking for existing script

@Dimitar_Venkov @jostein_olsen

Could either of you provide a copy of the script from the following old discussion?
http://dynamobim.com/forums/topic/element-parameter-showing-all-sheets-the-element-is-on/

The old script link is dead/broken and I would love to use the optimized version Dimitar created on a project I am currently working on.

Thanks in advance,
Robert Deardorff

Well, I have the picture! :slight_smile: Couldn’t find the script right now, unfortunately.

@Dimitar_Venkov @jostein_olsen

I can’t seem to get this to work. I am brand new to Dynamo and plan on going through all the tutorials but I have not yet so I apologize if I do not phrase my questions correctly.

  1. If I try to run it based on the picture you provided, I get a warning on the codeblock for the ElOnSht defenition (which reads Warning: Method ‘_Map()’ not found) and a warning on the final codeblock in the script which reads (Warning: Method ‘ElOnSht()’ not found). Does the definition codeblock have to be special in order to work?

  1. Per your original post, I downloaded the Elements in View(s) package which relied upon Turn Into List which, subsequently, has been rolled into clockwork as ReturnListOrSingleValue. I had to replace the TurnIntoList with ReturnListOrSingleValue in Elements In View(s) in order to get it not crash Dynamo when loaded. Unfortunately the two nodes are somewhat different. I will post a picture below, does it look right or do I need to modify it?

  1. Regarding the picture you provided above, is that the entire script to accomplish placing all sheets that a view appears on or is that just a custom node that exists in your original script? I figured the picture you posted was the entire script but just wanted to make sure.

Hopefully these questions make sense…and thanks again!

P.S. Just to make sure you understand what I am actually trying to get from this script. I would like each view to have the OnSheet parameter showing other sheets it is referenced on.

Hi,

You forgot an underscore.
It’s : (__Map(func,sv))

I actually caught that and fixed it but it still is not working properly. :frowning:

I could be completely wrong about this but it seems like the issues lies in the Elements in View(s) node. I have tried both scripts shown in @jostein_olsen s pictures and they both screw up right after the Elements in Views node is used.

So my next question would be if anyone knows another way to accomplish the goal that I am aiming for? (Finding all sheets that a given view is referenced on and apply it to a parameter)

Perhaps this workflow is what you are after?

@awilliams

I was looking at this earlier. This might work but the goal is not to find all referring views but to find only referring views that exist on sheets and then write those sheet numbers to a parameter for said view. If there is a way to modify this to work for that goal, I am all for trying it. I just am not skilled enough (yet) to do the modification myself.

@rdeardorff if you look at the image of the graph, it is only searching through views that are on sheets because it is searching in views output from the Rhythm node Sheet.GetViewportsAndViews

Edit: and yes the graph can be added to so that it gets the sheet numbers and writes them to the view’s parameter value :slight_smile:

@awilliams

Oh, ok. Then how might this fit into the workflow I am attempting (and failing) to achieve? Also, how would I modify it (do I have to?) to look at all views and not just drafting views (it appears to only be looking at drafting views but maybe I am wrong).

Edit: I am currently constructing the script from the post you linked BTW. Not being lazy, I promise! :slight_smile:

It accepts all view types, you just feed the node a view name. That script is only capable of finding referring views for one view at a time, but here is a modification so that it will handle a list of multiple views:

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager

doc = DocumentManager.Instance.CurrentDBDocument

views = UnwrapElement(IN[0])
names = IN[1]

if not isinstance(names, list):
	names = [names]
	
refviews = []

def getRefs(sheetviews, vName):
	refViews = []
	for view in sheetviews:
		viewColl = FilteredElementCollector(doc, view.Id).OfCategory(BuiltInCategory.OST_Viewers).ToElements()
		for viewer in viewColl:
			if viewer.Name == vName:
				refViews.append(view)
	return refViews

for name in names:
	refviews.append(getRefs(views,name))
	
OUT = refviews

So you can do something like below and gather all views of the types you want into a list, then feed the Python script their names:

Give it a try and let me know how it goes :slight_smile:

@awilliams

First off, thank you so much for all of your time.

My first attempt threw me an error (Warning: Internal error, please report: Dereferencing a non-pointer). Any thoughts?

Edit: When I tried to type in view.Name it kept trying to suggest other things. Is there another package I need to download possibly?

Edit2: Nevermind. I just had to change each view type to something else and then back and the error went away.

@awilliams

Sorry for the spam. I realized why I was getting an error. I didnt have any sections in my project. Once I added one and placed it on a sheet it worked fine. In the event a project didnt have (lets say) an elevation, is there a way to have dynamo leave those out so that it doesnt break the script?

Otherwise, now that it seems to be working, how do I get the sheet numbers into a parameter for each view?

If you’d uploaded a screen capture of where your graph broke, I could give better direction as to how/where in the graph this can be done - you could use either a List.Clean node or a Flatten node to eliminate any Empty Lists (which I assume you would have gotten from the View.GetByType node? If you just moved the Flatten node that is after the codeblock with “view.Name” in it, I believe it would have worked

Use Element.GetParameterValueByName with the Python script output views as the element, and “Sheet Number” as the parameter. Then Element.SetParameterValueByName with the views you input the names of into the Python script as the elements, and the Sheet Numbers as the values

@awilliams

Here is my attempt at getting the script to input data into a parameter. In my case, the parameter is called OnSheet. I was a little confused by your last sentence so I think I missed the last step.

See below and adjust (note that I switched the placement of the Flatten node after “view.Name” ) I threw in some notes to help make sense of it

@awilliams

It worked! You are amazing!

Two more questions for you:

  1. Is it possible to sort the sheet numbers numerically and alphabetically prior to writing them into the parameter? i am sure it is but I am not sure where that step wants to sit in the order of things.

  2. Can I send you a Starbucks giftcard? lol

Edit: One other question for you when you have time. I played around with it and it seems to be working perfectly except for one thing. It recognizes views referenced by sections but not referenced by View References. I am not sure that it really matters but I am curious if there is a way for the parameter to show all references of the view including View References.

No problem :slight_smile: glad to help!

A List.Sort node with the list input @L2 (hit the small arrow next to list on the node) before String.Join should work

View References behave differently than sections/elevation markers which can be observed by the differences when selecting them in Revit; A section/elev marks/call out when selected shows the view that it belongs to, whereas a View Reference shows the family/type of the View Reference element, with a parameter value of “Target view” indicating the view that is being referenced. It’d take me a bit to modify the Python script to process all types of these elements in one run, but when I get to it I will share here !

1 Like

@rdeardorff I took a quick pass at it and this (messy) modified script seems to work:

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager

doc = DocumentManager.Instance.CurrentDBDocument

sheetViews = UnwrapElement(IN[0])
views = UnwrapElement(IN[1])

refviews = []

def getRefs(sheetviews, refdview):
	refViews = []
	for view in sheetviews:
		viewerColl = FilteredElementCollector(doc, view.Id).OfCategory(BuiltInCategory.OST_Viewers).ToElements()
		for viewer in viewerColl:
			if viewer.Name == refdview.Name:
				refViews.append(view)
		refColl = FilteredElementCollector(doc, view.Id).OfCategory(BuiltInCategory.OST_ReferenceViewer).ToElements()
		for refviewer in refColl:
			if refviewer.LookupParameter("Target view").AsElementId() == refdview.Id:
				refViews.append(view)
	return refViews

for view in views:
	refviews.append(getRefs(sheetViews,view))
	
OUT = refviews 

Note the changes that need to be made to the graph; the Python script now needs the view elements, and not their names, and there are some level changes on the nodes after the Python script:


edit: added flatten node after List.FilterByBoolMask

3 Likes

@awilliams

It works perfectly. Using this tool I was able to accomplish this.

Thank you so much for your help!

1 Like