And rather than badgering the creator with questions I thought id ask here. When running the script I get this error
PythonEvaluator.Evaluate operation failed.
Traceback (most recent call last):
File "<string>", line 44 in <module>
AtrributeError: 'NoneType' object has no attribute 'Name'
I have tested this on the project file which the creator uses and it works fine, but on my project file the error keeps occurring. Ill post the entire script at the bottom for your information.
The only trouble shooting ive done myself is check that every drawing has at least 1 revision. Which they do.
Any help will be greatly appreciated.
# Made by Gavin Crump
# Free for use
# BIM Guru, www.bimguru.com.au
# Boilerplate text
import clr
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
# Current doc/app/ui
doc = DocumentManager.Instance.CurrentDBDocument
# Define list/unwrap list functions
def uwlist(input):
result = input if isinstance(input, list) else [input]
return UnwrapElement(result)
# Preparing input from dynamo to revit
sheets = uwlist(IN[0])
# Get revision sequences and revisions
revSeqs = FilteredElementCollector(doc).OfClass(RevisionNumberingSequence).ToElements()
revIds = Revision.GetAllRevisionIds(doc)
revs = [doc.GetElement(i) for i in revIds]
# Get sequence name per revision
# Empty variable lists to store to
revSeqNames, revCharSeqs = [],[]
# Get sequence names and characters
for r in revs:
# Get sequence
rsId = r.RevisionNumberingSequenceId
rs = doc.GetElement(rsId)
# Append the name and start a sequence
revSeqNames.append(rs.Name)
charSequence = []
# Get sequence characters for numeric...
if rs.NumberType == RevisionNumberType.Numeric:
settings = rs.GetNumericRevisionSettings()
minDigits = settings.MinimumDigits
prefix = settings.Prefix
suffix = settings.Suffix
for n in range(settings.StartNumber,99,1):
char_str = str(n)
pad_str = char_str.rjust(minDigits,"0")
char_seq = prefix + pad_str + suffix
charSequence.append(char_seq)
# ... or Alphanumeric
else:
settings = rs.GetAlphanumericRevisionSettings()
prefix = settings.Prefix
suffix = settings.Suffix
for a in settings.GetSequence():
char_seq = prefix + a + suffix
charSequence.append(char_seq)
# Append the character sequence
revCharSeqs.append(charSequence)
# Get revision sequences per sheet
rowsOut = []
sep = "\t"
for s in sheets:
trackRevs = []
sheetRevs = s.GetAllRevisionIds()
rowOut = ""
rowOut += s.SheetNumber + sep + s.Name + sep
# For each revision in the document
for i in revIds:
# Check if the sheet has it
if i in sheetRevs:
# Get the sequence Id name and get its name
r = doc.GetElement(i)
rsId = r.RevisionNumberingSequenceId
rs = doc.GetElement(rsId)
rsn = rs.Name
# Find the index of the sequence name
i_sq = revSeqNames.index(rsn)
# Find out how many times the sequence occured so far
i_ch = trackRevs.count(rsn)
# Get the sequence character, then track the sequence
d = revCharSeqs[i_sq][i_ch] + sep
trackRevs.append(rsn)
else:
d = "" + sep
rowOut += d
# Add the value to the end
rowsOut.append(rowOut)
# Make the top header
header = "Number" + sep + "Name" + sep + sep.join([r.RevisionDate for r in revs]) + sep
rowsOut.insert(0,header)
# Preparing output to Dynamo
OUT = rowsOut
type or paste code here
The warning indicates that there is no name for a revision sequence that was not found. From what I can tell on line 41 it’s triggering an error so my guess is maybe one of your revisions has no sequence associated to it (None). Some firms use this to make a ‘title’ revision at the top of their table, in which case you should drop any of those revisions from the ones being collected first.
Maybe try catching it in try/except and using continue to get it to skip that iteration:
# Append the name and start a sequence
try:
revSeqNames.append(rs.Name)
except:
continue
Thanks for your help again. I can confirm that your solution works and I have tested it on a number of different models.
So that solution you provided, is that telling the code to check but if no just ignore it and keep going? If so is it a generic solution I could use elsewhere if I have the same problem?
The continue statement tells the code to stop this iteration and then go back to the next object in the iterable being looped through in the for statement you call it in. Other useful ones are pass (keep going) and break (stop the loop).
Deniz is also correct in that an if statement where the second branch doesn’t execute instead is probably more clean, although I sometimes find I prefer continue as it means you can avoid an extra visual level of indentation.
Well thanks to you both for the help/advice. I have started with the basics of Python as I want to understand the code myself to I can correct my own errors.
My next step in my project are to add a filter as an input so I can have the script only use certain plans.
To explain further,
How we set up sheets in a project is our Architectural plans always have an ‘A’ before the plan number, ‘S’ before structural etc although im going to assume thats very standard across the industry haha.
So if I just wanted to create a transmittal for just Architectural I was going to add an input to the script and player that a user can add a character (A, S etc) to create a transmittal of just those plans.
So far ive managed to create a bit of a separate part of the script for the filter but cant get it to plug back into the python script node as of yet.
Once I have this part worked out I plan to watch your video again to see where in the code it starts formatting the code for excel as I want to be able to use our company template which has titles and other parts so ill have to format the data to appear in other cells.
Ok managed to remove the error from the node. I think what the issue was is that I had the list of sheets and the filtered list of keys, but since the total amount of keys didnt match the total number of sheets, thats what the error was (I think)
I assume its a similar problem that occurred with the other node. The code is expecting a longer list of sheets, but as its a filtered list, and therefore less sheets, it returns the error?
Although after typing that, that doesnt really make sense to me, as the input into the code contains the filtered list of sheets and nothing from a node that contains all sheets, so you would think that it wouldnt be an issue because as far as the code knows, the filtered list is the only amount of sheets within the model?
Not sure if thats on the right track or not. Just a thought I had.
I have been working through it and managed to get a different error where there is a miss match with keys and sheets (too many keys not enough sheets) So I know what the problem is, So I have been attempting to insert the filter earlier into the script with no success.
Do you have any suggestions where I should insert the filter and what nodes to use? Screen shot is below to show where its up to now
I just adjusted the script and unfortunately its sent two lists of sheet numbers to the script rather than a list of numbers and a list of sheets.
First image is the result when the script is working without the filter im trying to create
Same error as before. You need to filter the sheets by the keys. Make sure to read errors carefully, that one is pretty clearly stating a string is not correct in python.
It may be worth revisiting python fundamentals also if not familiar with it, following full tutorials has less impact without this.
Thankyou! the errors are gone and its working…sort of. Haha there is always a But issnt there?
So the new issue is that the original script had the result in the correct sheet order (ordered by sheet number)
Here is what the original did. As you can see its in sheet number order but it has those sheets not in the A series (the ones I want to filter out) stil there
I have noticed that before the node below had two lists of sheet numbers, now with your change it has two lists of sheet names… So do you think this is what is causing the out of sheet number order issue?
I am in the middle of an online Python course so I am beginning to understand the code. It especially helps just knowing the nomenclature and what words mean.
At the moment I am at a point where I am trying to see what I have learned into real code