I am trying to add a header row to a dataset using system.dataset.addRow. The dataset comes from a table component displaying strings and floats depending on the column. The newRow I am trying to add is a list of tag names and are strings. I don't know how to fix the error I am getting involving being unable to coerce a tag name to a number. Thank you
import csv
self.props.style['borderStyle'] = 'inset'
self.props.style['borderWidth'] = '2px'
data = self.parent.parent.getChild("Table").props.data
cols = data.getColumnNames()
idx = []
for c in cols:
if c != 'None':
idx.append(cols.index(c))
# data = system.dataset.filterColumns(data,idx)
tags = list(self.view.custom.complianceConfig.tagPaths)
tagNames = list(self.view.custom.complianceConfig.tagNames)
for i in range(len(tagNames)):
if tagNames[i] == None or tagNames[i] == '':
continue
else:
tags[i] = tags[i] + '.Name'
pops = []
for t in tags:
if '.Name' not in t:
pops.append(tags.index(t))
for x in reversed(pops):
tags.pop(x)
realNames = system.tag.readBlocking(tags)
newRow = []
for name in realNames:
newRow.append(name.value)
newRow.insert(0,'')
data = system.dataset.filterColumns(data,idx)
data = system.dataset.addRow(data, 0, newRow)
export = system.dataset.toCSV(data)
system.file.writeFile('tempfiles/exportTemp.csv',export)
with open('tempfiles/exportTemp.csv','ab') as f:
writer = csv.DictWriter(f,fieldnames=newRow)
writer.writeheader()
f.close()
# csvData.insert(1,newRow)
date = str(system.date.format(system.date.now(), "yyyy-MM-dd"))
filename = self.parent.parent.parent.parent.getChild("FlexContainer").getChild("Dropdown").props.value + " Compliance " + date
system.perspective.download(filename + ".csv", system.file.readFileAsBytes('tempfiles/exportTemp.csv'))
What do you mean, add a header row with addRow
? Datasets have headers already, and that's not how you configure them
I'll look through the code.
Also in my code there is a csv.writer for the header but it appends the tag names to the end of the csv file instead of the beginning. I was attempting to add the header using system.dataset.addRow before converting to csv but if changing my writeheader() is easier I would appreciate some input.
import csv
uses the jython csv writer and in that case it does not know about Ignition datasets. I would suggest using one of the built-in solutions for exporting Ignition datasets to csv like system.dataset.exportCSV
system.dataset.exportCSV - Ignition User Manual 8.1 - Ignition Documentation
This one has the option to write the headers built in and knows about the Ignition datasets so it will just grab your column names for you. No extra row at the top required.
I see what you are saying now. Thank you I will look at the writeheader I have in the code that is adding the header to the very end of the dataset.
Ok I'm sorry but this code makes very little sense at first glance and I don't have time to study it.
If you can tell me what your input is and what the output should be, I'll give refactoring it a shot.
edit: If I may, the whole point of using a context manager on open
is that you don't need to manually call close.
with open('tempfiles/exportTemp.csv','ab') as f:
writer = csv.DictWriter(f,fieldnames=newRow)
writer.writeheader()
f.close()
I think ultimately he just wants to make a CSV file by the looks of it. He's converting a dataset into a CSV string and then using the jython library csv
to write it.
He may never be able to do it this way though. He's trying to add a row of "headers" so that the csv
library will write that first, except that he has a column with non-string types, so thats what the error is being caused from.
I would suggest just using system.dataset.exportCSV - no additional row writing required.
I am going to do that. I understand the error I am getting now. I will let you guys now how that works out. Thank you
Sorry about the code I inherited it from someone else and I am still very green to scripting in this environment. I will remove the close() and you don't need to refactor anything.
I would suggest all of this be replaced with
system.dataset.exportCSV('tempfiles/exportTemp.csv',1,data)
- this will write your dataset with the column name headers to your file path.
As a general rule, you should check if there is a first party way (ie through Ignitions system.*
functions) to do something as those functions know how to deal with Ignition objects.
Can't help it, I have to do it.
But not right now because it 9pm over here and I have to eat.
I'll come back with a few hints and tips that should help you clean this up.
I mean, so does system.dataset.toCSV()
and it does it by default.
The big problem with exportCSV()
is that it is only available in Vison Client scope.
Here is a more concise and clear way to write your script, that I believe will produce exactly the same output.
self.props.style['borderStyle'] = 'inset'
self.props.style['borderWidth'] = '2px'
data = self.parent.parent.getChild("Table").props.data
idx = [i for i,c in enumerate(data.getColumnNames()) if c != 'None']
tagNames = [tag + '.Name' for tag,Path in zip(list(self.view.custom.complianceConfig.tagPaths),list(self.view.custom.complianceConfig.tagNames)) if !path]
realNames = system.tag.readBlocking(tags)
newRow = [''] + [name.value for name in system.tag.readBlocking(tags)]
data = system.dataset.filterColumns(data,idx)
data = system.dataset.addRow(data, 0, newRow)
export = system.dataset.toCSV(data)
date = system.date.format(system.date.now(), "yyyy-MM-dd")
filename ="{} Compliance {}.csv".format(self.parent.parent.parent.parent.getChild("FlexContainer").getChild("Dropdown").props.value,date)
system.perspective.download(filename, export)
You don't need to write the file out to disk and read it back in as bytes; system.perspective.download
can directly handle input strings and will download them as UTF-8 text.
Oh, yeah, I meant to fix that too, I'll edit.
You guys are awesome! Thank you so much