Python Dictonnary with Sheets List

So I am trying to use dictionaries to create entries of
[Schedule.Name,Sheet.Name]

Is there any way to use dictionaries to summarize schedules that way, or am I missing something?
I.e.
add “FooSchedule”,“Sheet1”
add “FooSchedule”,“Sheet2”
Add “BarSchedule”,“Sheet1”

So when I look up the key name “FooSchedule” it returns “Sheet1,Sheet2”.

I am this close to creating a def() that appends based on a key name- but I am hoping dictionaries will do it for me.

~TIA

Code to schedule schedules:

#!python3                   ##Code pre-directive untested!
##Apsis0215 R Allen 2022-09-28 CPy3
import clr
clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument        ##Current Document
import Revit
from Autodesk.Revit.DB import FilteredElementCollector,ScheduleSheetInstance,ViewSchedule
from Autodesk.Revit.DB import Transaction                   ##For outside and inner transactions
import Autodesk.Revit.DB as ARDB
import System.Collections.Generic                           ##For dictionary

SchSht=System.Collections.Generic.Dictionary[System.String,System.Object]()

def Views_Remove_ViewTemplates(Views):                      ##To remove view templates in list views
    viewlist = []   
    for view in Views:
    	if view.IsTemplate == False:                        ##If Is Template = false then
    		viewlist.append(view)                           ##Add to return list
    return viewlist                                         ##Return list of views (Not view templates)

PlacedSchedules = FilteredElementCollector(doc).OfClass(ScheduleSheetInstance).WhereElementIsNotElementType().ToElements()

PlacedSchedulesID=[VID.ScheduleId for VID in PlacedSchedules]


AllSchedules = FilteredElementCollector(doc).OfClass(ViewSchedule).WhereElementIsNotElementType().ToElements()

AllSchedulesID =[VID.Id for VID in AllSchedules]

##https://stackoverflow.com/questions/33577790/exclude-items-from-list-of-lists-python
SchedNotPlaced=[element for element in AllSchedulesID if element not in PlacedSchedulesID]
SchedNotPlaced=[doc.GetElement(VSHID)  for VSHID in SchedNotPlaced]

SchedNotPlaced = Views_Remove_ViewTemplates(SchedNotPlaced)
out=[]
for sch in PlacedSchedules:
    Sht=None
    Sht=doc.GetElement(sch.get_OwnerViewId())
    out.append([sch.Name,Sht]) ##<<<<<<<<This is where I have tried to append or add key+Value but I cannot get the syntax right.

OUT=out

Def is something like this:
I am sure this will be fraught with its own issues… : (

def AddByKey(objSch as ARDB.ViewSchedule,objSht as ARDB.ViewSheet, MyList[]):
    for each opair in MyList:                               ##For each item in the MyList with is a list of ([ViewSchedule,CiewSheet])
        if opair[0].Name = objSch.Name:                     ##If the name matches the item [0].Name [Viewschedule.name] then
            opair[1].Append(objSht)                         ##Add the sheet to that sublist.
            break
    return MyList

Hi,
you can use List as values

an example

2 Likes

Ah thanks~the Syntax isn’t “intuitive” (yet?:slight_smile: ), and that helped immensely!

Having an issue where the additional schedules E.g. “<Revision Schedule> ###” which have been lumped together under “<Revision schedule>” aren’t appending(). There should be 20+ sheet “<Revision schedule>” listed and only the 1st is showing. Maybe dictionaries don’t support lists as values?

2022-11-22(Revit) t121025 Dynamo

Tried:

##SNIP##
##Roll up all "Revision schedules" in section without numeric suffix
    else:                                                   ##Revision schedule
        if "<Revision Schedule>" not in SchDict:            ##Key not in dictionary
            SchDict["<Revision Schedule>"]=[sht]            ##Add new "<Revision Schedule>" key
        else:
            ol=SchDict["<Revision Schedule>"]
            ol.append(sht)
            SchDict["<Revision Schedule>"]=[ol]     ##Add under "<Revision Schedule>"
##SNIP##

but that didn’t work to reset the key’s value to a new [list].

Also tried a cast to an array:

SchDict=System.Collections.Generic.Dictionary[System.String,System.Collections.ArrayList]()

But that didn’t work either.

Here is the code - ‘mostly’ working : )

#!python3                   ##Code pre-directive untested!
##Apsis0215 R Allen 2022-11-22-CPy3-R22
import clr
clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument        ##Current Document
import Revit
from Autodesk.Revit.DB import FilteredElementCollector,ScheduleSheetInstance,ViewSchedule
from Autodesk.Revit.DB import Transaction                   ##For outside and inner transactions
import Autodesk.Revit.DB as ARDB
import System.Collections.Generic                           ##For dictionary

SchDict=System.Collections.Generic.Dictionary[System.String,System.Object]()

def Views_Remove_ViewTemplates(Views):                      ##To remove view templates in list views
    viewlist = []   
    for view in Views:
    	if view.IsTemplate == False:                        ##If Is Template = false then
    		viewlist.append(view)                           ##Add to return list
    return viewlist                                         ##Return list of views (Not view templates)

PlacedSchedules = FilteredElementCollector(doc).OfClass(ScheduleSheetInstance).WhereElementIsNotElementType().ToElements()

PlacedSchedulesID=[VID.ScheduleId for VID in PlacedSchedules]


AllSchedules = FilteredElementCollector(doc).OfClass(ViewSchedule).WhereElementIsNotElementType().ToElements()
AllSchedulesID =[VID.Id for VID in AllSchedules]

##https://stackoverflow.com/questions/33577790/exclude-items-from-list-of-lists-python
SchedNotPlaced=[element for element in AllSchedulesID if element not in PlacedSchedulesID]  ##Get schedile IDs to comp
SchedNotPlaced=[doc.GetElement(VSHID)  for VSHID in SchedNotPlaced] ##Convert back to schedule

SchedNotPlaced = Views_Remove_ViewTemplates(SchedNotPlaced)

##https://forum.dynamobim.com/t/python-dictonnary-with-sheets-list/83380/2
for Sch in PlacedSchedules:
    sht=None
    sht=doc.GetElement(Sch.get_OwnerViewId())               
    ##Dictionaries don't like <CLASSES> or <Id>'s - have to use .Name : (
    if Sch.Name.find("<Revision Schedule>") == -1:                  ##if not a ,Revision schedule>" then 
        if Sch.Name not in SchDict:                         ##Key not in dictionary
            SchDict[Sch.Name]=[sht]                         ##Set 1st key with value
        else:
            SchDict[Sch.Name].append (sht)                  ##Append key to current value

##Roll up all "Revision schedules" in section without numeric suffix
    else:                                                   ##Revision schedule
        if "<Revision Schedule>" not in SchDict:            ##Key not in dictionary
            SchDict["<Revision Schedule>"]=[sht]            ##Add new "<Revision Schedule>" key
        else:
            SchDict["<Revision Schedule>"].append (sht)     ##Add under "<Revision Schedule>"

##Schedules not placed
for Sch in SchedNotPlaced:                                  ##Flipped form name/sheet to "Not placed"/Schedule
    if "Not Placed" not in SchDict:                             ##Key not in dictionary
        SchDict["Not Placed"] = [Sch]                       ##Set 1st key with value
    else:
        SchDict["Not Placed"].append(Sch)                  ##Append key to current value

OUT=SchDict ##sorted(SchDict,SchDict.Keys)

Keys must be unique and will overwrite their associated values if you just update them. It’s easier to group your values by key first and then create the key, value pairs just once.

I’ve done this pretty easily by creating a list of unique schedules and using that to filter and group all the sheets by their corresponding schedule instance. Then I just create the key, value pair after each unique schedule has been filtered.

3 Likes

Seems like I am going backwards there : )

settling on lists where the first element in the list is the schedule and the remaining elements are the sheets. The Types have been taken out as I once the Schedule Sheet to a View Schedule before returning the SchArr (Schedule array):

#!python3                   ##Code pre-directive untested!
##Apsis0215 R Allen 2022-11-22-CPy3-R22
import clr
clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument        ##Current Document
import Revit
from Autodesk.Revit.DB import FilteredElementCollector,ScheduleSheetInstance,ViewSchedule
from Autodesk.Revit.DB import Transaction                   ##For outside and inner transactions
import Autodesk.Revit.DB as ARDB
import System.Collections.Generic                           ##For dictionary

#SchDict=System.Collections.Generic.Dictionary[System.String,System.Collections.IList]()
SchArr=[]
def Views_Remove_ViewTemplates(Views):                      ##To remove view templates in list views
    viewlist = []   
    for view in Views:
    	if view.IsTemplate == False:                        ##If Is Template = false then
    		viewlist.append(view)                           ##Add to return list
    return viewlist                                         ##Return list of views (Not view templates)

PlacedSchedules = FilteredElementCollector(doc).OfClass(ScheduleSheetInstance).WhereElementIsNotElementType().ToElements()
PlacedSchedulesID=[VID.ScheduleId for VID in PlacedSchedules]

AllSchedules = FilteredElementCollector(doc).OfClass(ViewSchedule).WhereElementIsNotElementType().ToElements()
AllSchedulesID =[VID.Id for VID in AllSchedules]

##https://stackoverflow.com/questions/33577790/exclude-items-from-list-of-lists-python
SchedNotPlaced=[element for element in AllSchedulesID if element not in PlacedSchedulesID]  ##Get schedile IDs to comp
SchedNotPlaced=[doc.GetElement(VSHID)  for VSHID in SchedNotPlaced] ##Convert back to schedule

SchedNotPlaced = Views_Remove_ViewTemplates(SchedNotPlaced)

##https://forum.dynamobim.com/t/python-dictonnary-with-sheets-list/83380/2
Sch=PlacedSchedules.pop()                                   ##Pop one off to prime
sht=doc.GetElement(Sch.get_OwnerViewId())                   ##Get sheet from ID
SchArr=[[Sch,sht]]                                          ##Schedule Array: the list of sublists primed with 1st element

rev=[]
for Sch in PlacedSchedules:                                 ##For each additional place schedule
    sht=None                                                ##Set sheet for placed schedule
    sht=doc.GetElement(Sch.get_OwnerViewId())               ##Get SHEET from owner view ID               
     
    #sos=doc.GetElement(Sch.ScheduleId)                      ##Get source schedule
    
    found=False                                             ##REset found

    if doc.GetElement(Sch.ScheduleId).Name.find("<Revision Schedule>") == -1:   ## Not a revision schedule

        for ssch in SchArr:                                     ##Existing list of schedules
            if ssch[0].Name == Sch.Name:                        ##If Schedule name = data pair element 0 name (schedule)#
                ssch.append(sht)                                ##Append to data pair[1] (Array of sheets)
                found=True                                      ##Found=true
                break ##to for Sch...                           ##Break to outer loop
        if not found:
            SchArr.append([Sch,sht])
    else:                                                   ##Is a revision schedule - stack those together
        rev.append([Sch,sht])                               ##Separate list ofr sequential revision schedules on sheets
        
##SchArr.extend(rev)                                        ##Extend Schedule array: with revision schedules
#################################################################
for Sch in SchArr:											##convert schedule on sheet to schedule viewSet all the schedules to the original schedule object not the schedule on sheet object
    Sch[0]=doc.GetElement(Sch[0].ScheduleId)

##SchArr.sort

OUT=SchArr

With this I can export those views to an excel or create generic annotation placeholder sheets with them to schedule.

Guess dictionaries aren’t the best choice for this.

Output looks like this:

  [
    [
      ScheduleView(Name = A11_RR-SUMMARY_IPC_ ),          ##Schedule View
      Sheet(Name = OVERALL OCCUPANCY AND EGRESS PLAN ),   ##Sheet ref 1
      Sheet(Name = OVERALL OCCUPANCY AND EGRESS PLAN )    ##Sheet Ref 2
    ],
    [
      ScheduleView(Name = • DATA - SHEETS • ),            ##Next Schedule View
      Sheet(Name = Start Up - Project Data )              ##Sheet ref (osched on only one sheet here#
    ]  
  ]