Spotfire: Creating filtering relationships by passing filters between tables I am using the code below to pass filter selections from table A to table B in Spotfire. I am doing this to create a filtering relationship between the tables, but skipping the creation of a traditional Spotfire table relationship, as this is not advisable in this setting.

The code is associated with a document property which itself is driven by a simple data function, following the instructions found here. 

After it is triggered, the code finds a specific filter in table A. It reads the content and creates a list. It checks the length of the list, and if greater than zero, it takes the filter object and passes it to the matching filter in table B. If nothing is selected (len = 0), then the matching filter in table B is reset. The process is repeated for multiple filters.

As far as I can tell it works on my machine. But even as a complete beginner, I can tell it is poorly written. I would appreciate suggestions and feedback on how I can make it better.

from Spotfire.Dxp.Application.Filters import *
from Spotfire.Dxp.Application.Visuals import VisualContent
from System import Guid     

#Get the active page and filterPanel
page = Application.Document.ActivePageReference
filterPanel = page.FilterPanel

##########################reasons#############################################
#get information for the first filter
theFilter = filterPanel.TableGroups[0].GetFilter("Reason")
lbFilter = theFilter.FilterReference.As[ListBoxFilter]()
#get information for the second filter
theFilter2 = filterPanel.TableGroups[1].GetFilter("Reason")
lb2Filter = theFilter2.FilterReference.As[ListBoxFilter]()

#check if any selections are made in the first filter
n = []
for value in lbFilter.SelectedValues:
    n.append(value)
if len(n)&gt;0:
    lb2Filter.IncludeAllValues = False
    lb2Filter.SetSelection(lbFilter.SelectedValues)
#if no selections are made, reset the second filter
else:
    lb2Filter.Reset()

#########################Type#####################################################
theFilterPT = filterPanel.TableGroups[0].GetFilter("Type")
lbFilterPT = theFilterPT.FilterReference.As[ListBoxFilter]()

theFilter2PT = filterPanel.TableGroups[1].GetFilter("Type")
lb2FilterPT = theFilter2PT.FilterReference.As[ListBoxFilter]()

n = []
for value in lbFilterPT.SelectedValues:
    n.append(value)
if len(n)&gt;0:
    lb2FilterPT.IncludeAllValues = False
    lb2FilterPT.SetSelection(lbFilterPT.SelectedValues)
else:
    lb2FilterPT.Reset()
from ... import * is discouraged by a large amount of people.

Currently it's easy to see what comes from Filters, as you only have one. But if you have two or more than it just becomes impossible to understand.
Your code doesn't look Pythonic, unfortunately this is because Spotfire has violated PEP 8 making anything that uses it look, to my eyes, ugly.

Whilst I'm not a fan of the style you are using, I would like to congratulate you on sticking to one style. Well done.
If the comments help you then keep them. However if you wrote them to help us then I would recommend that you remove them.
You have lots of un-needed variables; page, theFilter, theFilterPT.
Functions are the bread and butter of programming. And your code is in some dire need of functions.


In your code we see that you have the following definitions:


  #get information for the first filter
theFilter = filterPanel.TableGroups[0].GetFilter("Reason")
lbFilter = theFilter.FilterReference.As[ListBoxFilter]()
#get information for the second filter
theFilter2 = filterPanel.TableGroups[1].GetFilter("Reason")
lb2Filter = theFilter2.FilterReference.As[ListBoxFilter]()

  
  theFilterPT = filterPanel.TableGroups[0].GetFilter("Type")
lbFilterPT = theFilterPT.FilterReference.As[ListBoxFilter]()

theFilter2PT = filterPanel.TableGroups[1].GetFilter("Type")
lb2FilterPT = theFilter2PT.FilterReference.As[ListBoxFilter]()



We can see clearly that only two things change between them; [0] and [1], and "Reason" and "Type".
I personally think filterPanel.TableGroups[0] shouldn't be in the function and we can just pass the filter in the function. This can result in:

def getGroup(tableGroup, filter):
    return (
        tableGroup
            .getFilter(filter)
            .FilterReference
            .As[Filters.ListBoxFilter]()
    )


After this we can see you've written something else twice too.


  n = []
for value in lbFilter.SelectedValues:
    n.append(value)
if len(n)&gt;0:
    lb2Filter.IncludeAllValues = False
    lb2Filter.SetSelection(lbFilter.SelectedValues)
#if no selections are made, reset the second filter
else:
    lb2Filter.Reset()



Firstly creating n can be simplified simply as list(lbFilter.SelectedValues).
You don't need to use len(n)&gt;0 as just if n: does that check, with a list, for you.
Finally I find it easier to have the smaller code block first, and so flipped the if.

def filterGroups(tableGroups, filter):
    group1 = getGroup(tableGroups[0], filter)
    group2 = getGroup(tableGroups[1], filter)

    if not list(group1.SelectedValues):
        group2.Reset()
    else:
        group2.IncludeAllValues = False
        group2.SetSelection(group1.SelectedValues)


Finally I would wrap everything in a main function and you'd get the following:

import System
from Spotfire.Dxp.Application import Filters, Visuals


def getGroup(tableGroup, filter):
    return (
        tableGroup
            .getFilter(filter)
            .FilterReference
            .As[Filters.ListBoxFilter]()
    )


def filterGroups(tableGroups, filter):
    group1 = getGroup(tableGroups[0], filter)
    group2 = getGroup(tableGroups[1], filter)

    if not list(group1.SelectedValues):
        group2.Reset()
    else:
        group2.IncludeAllValues = False
        group2.SetSelection(group1.SelectedValues)


def main():
    tableGroups = (
        Filters
            .Application
            .Document
            .ActivePageReference
            .FilterPanel
            .TableGroups
    )
    filterGroups(tableGroups, "Reason")
    filterGroups(tableGroups, "Type")


if __name__ == '__main__':
    main()