Scroll scrollbar to position via script

UPDATED: 2020-06-25

I’ve since created a script library for this (not exactly) function that will scroll to an item in the scrollable component’s dataset:

# call this on a button or other
scrollableObj = event.source.parent.getComponent('Table')
shared.components.scrollable.scrollToPos(scrollableObj, 'Col 1', 29, 1)
# copy into library: shared.components.scrollable
def scrollToPos(scrollableObj, DataSetFieldName, NewDataSetPosValue, position=0, recursionLevel=0):
	'''
	Description:
	Scrolls the table component to the item above the new position.
	
	Arguments:
	scrollableObj			- the scrollable component (table, power table, template repeater - untested with any others)
	DataSetFieldName		- the field name in the templateParams dataset to find the new position value in
	NewDataSetPosValue		- the field value of the field name to find in the dataset to move to
	Position				- the position to scroll to:
								0 - position item at the top minus 1
								1 - position item in the centre
                                2 - position item at the top
	
	Revision:
	No.		Date		Author			Comment
	1.0		2018-11		Nick Minchin	Original
	1.1		2019-12		Nick Minchin	Simplified function. Can set value of scrollbar directly without having to use the viewport.
	1.2		2019-12-15	Nick Minchin	Simplified further method to get the scrollbar object. Added ability to change scroll to position type.
	1.3		2020-06-25	Nick Minchin	Fixed issue with rowHeight for Power Tables. Made item height and items count round up
	'''
	import math
	objType = str(type(scrollableObj))
	
	ds = None
	#get the component's items dataset so that we can work out the current index of the maximum
	if any([t in objType for t in ['PMITable', 'VisionAdvancedTable']]):
		ds = scrollableObj.data
	if any([t in objType for t in ['TemplateRepeater']]):
		ds = scrollableObj.templateParams
	
	if ds == None:
		import sys
		system.gui.messageBox("The object type you passed in is not accounted for. '%s'" % objType, 'Error')
		sys.exit()
	ds = system.dataset.toPyDataSet(ds)
	
	if len(ds) > 0:
		#find the index of the new item from the dataset
		index = 0
		for i in range(len(ds)):
			if ds[i][DataSetFieldName] == NewDataSetPosValue:
				index = i
		
		scrollBar = scrollableObj.verticalScrollBar
		scrollBarHeight = scrollBar.height
		itemHeight = scrollableObj.getTable().getRowHeight(0)
		itemsInView = (1.0*scrollBarHeight) / itemHeight
		
		#Calculate the position of the current step using the item height and the new item's index
		if position == 0:
			newPos = int(itemHeight*(index - 1))
		elif position == 1: #WORKING
			newPos = int(itemHeight*(index + 1 - (itemsInView/2.0)))
			#newPos = int(math.ceil(itemHeight*(index  - (itemsInView/2.0))))
		elif position == 2:
			newPos = int(itemHeight*(index - 0))
		else:
			newPos = int(itemHeight*(index - 0))
		
		scrollBar.setValue(newPos)
		scrollableObj.selectedRow = index
		recursionLevel += 1
		# for some reason the first time this is run, the scroll is off by a few pixels.. so call it again
		if recursionLevel == 1:
			scrollToPos(scrollableObj, DataSetFieldName, NewDataSetPosValue, position, recursionLevel)
3 Likes