Getting Element Type Parameters in multiple Documents

Hi,
A quite unique workflow is required where I need to extract element information from multiple different documents.

This is the current method mass opening document is using Orchid:

Instance information works perfectly. However, when I try and extract any type of information it returns nulls/errors:

From some googling, the extraction of parameter information uses the current document as a field. As the instance parameter information is stored within the element, not the family/type, they work. This is not the case for the type information as its needs to know what Document to look at the type.

I can see two ways of solving this:

  1. Tell the script to work with one document at a time
  2. When extracting type data, tell what document to extract from. There is an Orchid node that does this for Family data but not per document.

Currently, I’ve failed to get both working. Any ideas/tips would be greatly appreciated.

Many thanks
Joe

Hi Joe,

How about posting on the Orchid github for an enhancement?

A 3rd option would be to use Python to extract the information, but that will probably be a bit of work. I think there might be some Clockwork nodes which would give you example code.

Hope that helps,

Mark

2 Likes

This would be the way I’d go, as you can open, extract, and close each file subsequently. This means you don’t have N files open concurrently sucking RAM from the system.

2 Likes

Hey Mark and @jacob.small

Thanks both for the suggestion. How complicated would that python script be? I’ve only really used python for data management, I’m wondering if it would be within my ability.
Joe

1 Like

Hi Joe,

If you’re happy in Python I don’t think it wouldn’t be too bad.

The problem with parameters is they can take varying types… String, Double, Yes/No, Parameter etc. etc. so you need a cascade of statements to test each parameter and return the value if successful…

I tend to start these things by grabbing some code from a node which is similar and tweak it in your active document, then when it works, adjust it to iterate through the list of documents you’re feeding it.

I’d quickly strip out some RVT files for testing, otherwise the task time taken will mainly be you opening and shutting Revit files :slight_smile:

Hope that helps,

Mark

2 Likes

To @Mark.Ackerley’s point, the complexity of this task will vary depending on scope and consistency of the ask. The parameter storage type is just one of a few complications, each of which will reveal itself in time as your workflow scales up.

For now look to learn how to open a .rvt file (model path utilities class will help here), and close the .rvt file. I haven’t tested this, but something like it may be a good place to start:

import clr
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import * #this should be reduced to just what you need
app = DocumentManager.Instance.CurrentUIApplication.Applicaton #gets the current application 
##### note that I am not declaring the 'doc' variable as  you usually might in the boilerplate code, this means you can loop over the files and get the content as needed #####

listofPaths = IN[0]
paramName = IN[1]
paramVals = []

for path in listofPaths: #iterates over the list of files in the listofPaths variable - make sure you have a list there or this will have some issues
   mp = ModelPathUtils.ConvertUserVisiblePathToModelPath (path) #converts the path from what we undertsasnd to what Revit understands
   doc = app.OpenDocumentFile(mp) #opens the document
   wallCat = BuiltInCategory.OST_Walls #needed something to help collect stuff, looked like you were doing wall things, so I figured I'd use the wall category in the FEC
   fec = FilteredElementCollector(doc).Ofcategory(wallCat).WhereElementIsElementType().ToElements() #gets all the wall category types as elements so we can get info from them
   for e in fec: #for every item in the list of #for every wall type found 
      paramVals.append(e.GetParameters(paramName).AsString()) #appends the value as a string to the paramVals list
   doc.Close(False) #closes the document

OUT = paramVals #returns the paramVals list to the Dynamo environment

Haven’t tested this, just typed it up so sorry in advance for any typos.

2 Likes

Sorry for the late response @jacob.small, I was off on holiday.

Thanks you for the above, I really appreciate it. I’ve never had to work with this kind of code so was quite a learning experience.

I couldnt get the code working straight away, most notable I found disabling the ModelPathUtils and adding the .Application to line 17 and not 8 worked for some reason. Not sure if I fixed something or just broke it in a way that didnt produce errors in the below set-up:

Unfortunately I couldnt get the code to Run with the below error occuring:
image

I see that error as .AsString can’t operate as its been given a List not a Parameter. Which to me doesnt make sense as its a method or reading a single parameter.

Even so, I attempted to Loop through paramVals as it seemed to be a list:

for path in listofPaths: #iterates over the list of files in the listofPaths variable - make sure you have a list there or this will have some issues
   #mp = ModelPathUtils.ConvertUserVisiblePathToModelPath(path) #Not sure if needed, doesnt seem to work when enabled
   #test.append(mp)
   doc = app.Application.OpenDocumentFile(path) #opens the document
   ceilingCat = BuiltInCategory.OST_Ceilings #Test Category
   fec = FilteredElementCollector(doc).OfCategory(ceilingCat).WhereElementIsElementType().ToElements()#gets all the ceiling category types as elements so we can get info from them
   for e in fec: #for every item in the list of #for every wall type found 
   	paramVals.append(e.GetParameters(paramName))
   for parameterList in paramVals:
   	for Parameter in parameterList:
   		test.append(Parameter.AsString())

      #paramVals.append(e.GetParameters(paramName)) #appends the value as a string to the paramVals list
   doc.Close(False) #closes the document

This just bought me this error instead:
image

I’ve tried different methods of calling and reading parameters Values such as .GetOrderedParameters with not luck, but the the errors are consistant.

I’m not too sure if this my bad coding or something funny is going on with what I’m trying to do. I’m going to try and stick with it but if anyone has any ideas please let me know.

Thanks again for the starter code Jacob!

Joe

Can’t see what one 29 is, but try restarting the CPU. Because the file is open after the previous error you may be getting a hang up on the open.

1 Like

Thanks for replying, I gave it a restart and no luck.

I end up getting it working with the below code. I think the problem was the way I was looping through the list. Thanks again for the help

import clr
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
app = DocumentManager.Instance.CurrentUIApplication


listofPaths = IN[0]
paramVals = []

for path in listofPaths: #Interates over paths
	doc = app.Application.OpenDocumentFile(path) #Opens Document
	ceilingCat = BuiltInCategory.OST_Ceilings #Cat to Open
	fec = FilteredElementCollector(doc).OfCategory(ceilingCat).WhereElementIsElementType().ToElements() #Select All Elements
	for e in fec: #Interates over elements
		for p in e.GetOrderedParameters(): #Iterates over parameters
			paramVals.append(p.AsString()) #Appends as string 
	doc.Close(False) #Closes Document

OUT =  paramVals