Quick update on this post. The above solution of transforming the easychart component with scripting turned out to be too clunky for practical use. The other problem with the approach was that the save button was saving all of the pens no matter which pens were selected. The OP wanted to post the actual solution here, so it can help anybody else who needs to do something like this.
What ended up working was the use of a couple of templates in repeaters with a homemade save button.
This is the end result:
The templates are simple. One is nothing more than a checkbox with the isSelected property bidirectionally bound to a custom property. The other is a label and a template repeater with a border around it:
groupTags.zip (6.8 KB)
The group template is used in a template repeater with a custom property called tagPens. Obviously, the dataset was much simpler than the original chart's because it only contains what's needed for this function:
Once the tagPens dataset has been loaded, the following script parses the data into the two internal template repeaters' datasets:
chart = event.source.parent.getComponent('Template Repeater') #Change this path relative to where the script runs from
chartData =chart.tagPens
def getColumnIndex(columnName):
for column in range(chart.tagPens.columnCount):
if chart.tagPens.getColumnName(column) == columnName:
return column
groupColumn = chart.tagPens.getColumnAsList(getColumnIndex('groupName'))
groups = set(groupColumn)
groupList = list(groups)
data = []
headers = ['groupName', 'colorBorder', 'colorText', 'tagPens']
for group in groupList:
groupHeaders = ['colorText', 'isSelected', 'penName', 'tagPath']
groupData = []
for row in range(chart.tagPens.rowCount):
if chart.tagPens.getValueAt(row, getColumnIndex('groupName')) == group:
groupData.append(['0,0,0', False, chart.tagPens.getValueAt(row, getColumnIndex('penName')), chart.tagPens.getValueAt(row, getColumnIndex('tagPath'))])
groupDataset = system.dataset.toDataSet(groupHeaders, groupData)
data.append([group, "0,0,0", "0,0,0", groupDataset])
chart.templateParams = system.dataset.toDataSet(headers, data)
Here is the save button script that loops through pens to see which ones are checked and then converts the corresponding tag query to a spreadsheet which is then saved on the user's desktop:
import getpass
import time
from com.inductiveautomation.factorypmi.application.components import TemplateRepeater
def renameHeaders(dataset, headers):
values = [[dataset.getValueAt(row,col) for col in range(dataset.columnCount)] for row in range(dataset.rowCount)]
return system.dataset.toDataSet(headers,values)
def getFilename():
current_time = time.localtime()
username = getpass.getuser()
filepath = 'C:/Users/' + username + '/Desktop/'
fileName = 'tagHistoryExport_' + time.strftime('%Y-%m-%d_%H-%M-%S', time.localtime())
return filepath + fileName
primaryRepeater = event.source.parent.getComponent('Template Repeater')
tagPaths = []
headers = ['Time Stamp']
startTime = event.source.parent.getComponent('Date Group').getComponent('stDate').date
endTime = event.source.parent.getComponent('Date Group').getComponent('endDate').date
for template in primaryRepeater.getLoadedTemplates():
for component in template.getComponents():
if isinstance(component, TemplateRepeater):
for subTemplate in component.getLoadedTemplates():
isSelected = False
tagPath = None
penName = None
for customProperty in subTemplate.dynamicProps:
if customProperty == 'isSelected':
isSelected = subTemplate.getPropertyValue(customProperty)
elif customProperty == 'tagPath':
tagPath = subTemplate.getPropertyValue(customProperty)
elif customProperty == 'penName':
penName = subTemplate.getPropertyValue(customProperty)
if isSelected and tagPath is not None and penName is not None:
tagPaths.append(tagPath)
headers.append(penName)
break
filename = getFilename()
tagHistory = system.tag.queryTagHistory(paths=tagPaths, startDate=startTime, endDate=endTime, returnSize=-1, aggregationMode="Maximum", returnFormat='Wide', noInterpolation=True)
dataset = renameHeaders(tagHistory, headers)
system.dataset.exportCSV(filename, True, dataset)
Edit: Included the function that was added to correct the header names that are returned by the tag history query, so the headers in the spreadsheet are the actual pen names instead of the full tag paths.