Match Viewports to Sheets - Python List Troubles with Detail Numbers

Hello Dynamo Friends :slight_smile:

I have a python script that does the following tasks successfully:

  • Get a bunch of Viewports
  • Get Sheet from Viewports
  • Get all Viewports on sheet and their Detail Numbers (example 3,4,5)
  • Calculate Detail Numbers for new Viewports (consecutive: example 6,7,8)
  • Set these new Detail Numbers to some new Viewports.

Now I want to edit the code to make it also work for multiple sheets. My problem is i don´t really know how to start. Should i make a viewport list with sublists for every sheet? And then work with this leveled list? Zip sublists and sheets together? How can i even make my viewport sublists?

The code should make the following tasks possible:

  • Get a bunch of Viewports
  • Get the multiple Sheets the Viewports are placed on.
  • Get all Viewports on all Sheets an their Detail Numbers (example sheet1: 3,4,5, sheet2:18,19,20, sheet3:34,35,36)
  • Calculate Detail Numbers for new Viewports (consecutive: example sheet1: 6,7,8, sheets2:21,22,23, sheet3: 37,38,39)
  • Set these new Detail Numbers to the Viewports on multiple sheets.

(Keep in mind, this is only a part from a pretty long python code)

Would really appreciate any push in the right direction!

Kind Regards :slight_smile:

def CurrentViewports_DetailNumbers(viewports):	
	CurrentViewports_DetailNumbers = []
	for viewport in viewports:
		SheetId = viewport.SheetId
		Sheet = doc.GetElement(SheetId)
	CurrentViewportIDs = Sheet.GetAllViewports()
	CurrentViewports= [doc.GetElement(CurrentViewportID) for CurrentViewportID in CurrentViewportIDs]
	for CurrentViewport in CurrentViewports:
		CurrentViewports_DetailNumber = CurrentViewport.get_Parameter(BuiltInParameter.VIEWPORT_DETAIL_NUMBER).AsString()
		try:
			integer=int(CurrentViewports_DetailNumber)
			CurrentViewports_DetailNumbers.append(integer)
		except:
			pass
	return CurrentViewports_DetailNumbers
	
def NewViewports_DetailNumbers():
	NewViewports_DetailNumbers = []
	CurrentViewports_DetailNumbers = []
	for NewViewport in NewViewports:
		NewViewports_DetailNumber = NewViewport.get_Parameter(BuiltInParameter.VIEWPORT_DETAIL_NUMBER).AsString()
		try:
			integer=int(NewViewports_DetailNumber)
			NewViewports_DetailNumbers.append(integer)
		except:
			pass
		
def CreateDetailNumbers():
	Final_DetailNumbers = []
	MaximumDetailNumber = int(max(CurrentViewports_DetailNumbers))
	n = 100
	numbers = []
	for i in range(MaximumDetailNumber+1, n+1):
  		numbers.append(i)
  	for i in numbers:
		if str(i) not in CurrentViewports_DetailNumbers:
			Final_DetailNumbers.append(str(i))
	return Final_DetailNumbers
		
def SetDetailNumbers():
	Final_DetailNumbers = CreateDetailNumbers()
	for V, D in zip(NewViewports, Final_DetailNumbers):
		set = V.get_Parameter(BuiltInParameter.VIEWPORT_DETAIL_NUMBER).Set(D)

elements = CurrentSelection()
viewports = FilterViewports()

TransactionManager.Instance.EnsureInTransaction(doc)

if viewports:
	CurrentViewports_DetailNumbers = CurrentViewports_DetailNumbers(viewports)
	ViewFromViewports = ViewFromViewports()
	DuplicatedViews = DuplicateViews(ViewFromViewports)
	NewViewports = CreateViewport(DuplicatedViews, viewports)
	SetDetailNumbers = SetDetailNumbers()

TransactionManager.Instance.TransactionTaskDone()

OUT = SetDetailNumbers

Could make a dictionary and grouped it by sheet Ids.

viewport_dict = dict()

viewport_keys = [str(viewport.Id) for viewport in viewports]
viewport_values = [str(viewport.SheetId) for viewport in viewports]

for key, value in zip(viewport_keys,viewport_values):
	viewport_dict[key] = value
	
grouped_dict = {}
for i, v in viewport_dict.items():
    grouped_dict[v] = [i] if v not in grouped_dict.keys() else grouped_dict[v] + [i]

Create a class and use OOP. Dictionaries = primitive obsession and obscure intent.

2 Likes

Hello @Thomas_Mahon

I appreciate pointing out a better method and i really would like to try. I read up on python classes but it´s still pretty confusing, so i would need a little more help from you how exactly i can use a class for my usecase. Would the Class consist of the viewports and i would create class object instances for every sheet? I’m really iterrested what your idea is.

In the meantime I found another method. I´m now using a function and simply call this function with a loop for every sheet. Is this method better then using a dictionary? And is a class still the best way to go?

Kind Regards :slight_smile:

def SortedViewports(sheetID):
	outlist=[]	
	for viewport,viewportSheetId in zip(viewports,viewportSheetIds):
		if sheetID == viewportSheetId:
			outlist.append(viewport)
	return outlist
	
outlist2=[]	

for sheet in sheets:
	outlist2.append(SortedViewports(sheet))

OUT = outlist2

if you wanna use a class, something like this should work

class Sheet():
	
	InternalElement = None
	Viewports = None
	LastDetailNumber = 0
	
	def __init__(self, sheet):
		self.InternalElement = sheet
		self.Viewports = map(lambda vpId: sheet.Document.GetElement(vpId), self.InternalElement.GetAllViewports())
		allDetailNumber = map(lambda vp: vp.get_Parameter(BuiltInParameter.VIEWPORT_DETAIL_NUMBER).AsInt(), self.Viewports)
		self.LastDetailNumber = max(allDetailNumber)
	
	def SetNewViewportDetailNumber(self, newViewports):
		for newVP in newViewports:
			self.LastDetailNumber = self.LastDetailNumber + 1
			newVP.get_Parameter(BuiltInParameter.VIEWPORT_DETAIL_NUMBER).Set(self.LastDetailNumber)

and you simply create your sheet class from your original sheetviews, and use the SetNewViewportDetailNumber function go set new detail numbers

1 Like

Hello @stillgotme

Thanks for your reply, this will be a big help in understanding classes for me!

For now i got my code running by double looping over sheets like this:

def GroupedViewports():
	outlist=[]	
	for UniqueSheetId in UniqueSheetIds:
		outlist2=[]
		for NewViewport,NewViewportSheetId in zip(NewViewports,NewViewportSheetIds):
			if UniqueSheetId == NewViewportSheetId:
				outlist2.append(NewViewport)
		outlist.append(outlist2)
	return outlist

I´m now a list level deeper and have to use this double loop for pretty much all tasks I´m doing in functions, not pretty much fun.
I will study your class definition and i hope using classes will save me some time!