Python Dataset Error

Since I am not a career programmer, but a controls guy, I am using some code I found in the forums here to manipulate an excel spreadsheet using the apache poi. At this point of the code I am getting an error:

Create header row in the sheet

	headerRow = sheet.createRow(0)
	for i, col in enumerate(pyDS.getColumnNames()):

pyDS is the python dataset. The error I am getting is:

AttributeError: 'com.inductiveautomation.ignition.common.script.bui' object has no attribute 'getColumnName'

Any help is appreciated.

Thanks!

RP

Are you sure pyDS is not None?

The error you show doesn't match the code you posted.
See how you're calling getColumnNames, but the error says getColumnName ?
Is that a typo, or is there some other place you're trying to call getColumnName, which, in fact, doesn't exist ?

Oops, sorry about that. It is in fact getColumnNames. I had tried it without the s on the end as I had seen somewhere else that had a method like that.

I am sure. To test this all I am doing is making a simple dataset:
headers = ["Letters", "Numbers"]
data=
data.append(['A',1])
data.append(['B',2])
data.append(['C',3])
dataOut = system.dataset.toDataSet(headers, data)

pythonDataset = system.dataset.toPyDataSet(dataOut)

EXCEL.WRITEXLSX.listToExcel(pythonDataset)

How old is your Ignition version?

In older Ignition, .getColumnNames() (aka .columnNames) is available only on proper Dataset instances, not on PyDataset instances.

2 Likes

Ignition Platform

8.1.36 (b2024010211)

Okay, let's take a step back.

Post:

  1. Exactly the error message you are getting, with the full details/stacktrace attached.
  2. Exactly the code you're running in the script console/on your button/whatever.
  3. Exactly the code you've got in the project library, apparently under the EXCEL package.

Post all of those here as preformatted text, so that indentation information (crucial to Python) is not lost.

Until you do that, we're all just taking stabs in the dark trying to help you.

@Rick_Pietruszka , I just tried your script. Here is what happened:

Calling .getColumnNames() within the enumerate() function returns either a 'com.inductiveautomation.ignition.common.script.bui' error if it is a PyDataSet or 'com.inductiveautomation.ignition.common.BasicDatas' error if it is a DataSet.

However, simply saving the column names to another variable, then using that in your enumerate function works like a champ

columnNames = pyDS.getColumnNames()
for i, col in enumerate(columnNames):

It sounded like a winning solution, but it gave the same error on the columnNames = pyDS.getColumnNames()

I got the code to work by simply not converting the dataset to a python dataset earlier in the script. I commented out the code for system.dataset.toPyDataSet(dsIn) and it is working great now. So ignition is not liking the methods for handling python datasets.

@Rick_Pietruszka , using the simple dataset example, the .getColumNames() function works on both a dataset and pyDataset. If it isn't working for you, perhaps there is something wrong with the pyDataset itself

headers = ["Name","Value"]
data = []
data.append(['A',1])
data.append(['B',2])
data.append(['C',3])

ds = system.dataset.toDataSet(headers, data)
pyDS = system.dataset.toPyDataSet(ds)

columnNames = ds.getColumnNames()
pyColumnNames = pyDS.getColumnNames()

print columnNames
print pyColumnNames

for i, col in enumerate(pyColumnNames): #works fine
	print col
	
#for i, col in enumerate(ds.getColumnnames()): #gives error
#	print col
#for i, col in enumerate(pyDS.getColumnnames()): #gives error
#	print col

I generally cast it to a list to prevent other issues that can arise from using the object directly:

columnNames = list(pyDS.getColumnNames())
1 Like

It never made sense to me that you can't use the list of headers you just extracted from a dataset to create another dataset without casting it first...

1 Like

It's because Ignition's toDataSet() function is strictly checking for python's list, where it should be looking any duck-typed list-like object. Java's java.util.List<> interface is wrapped by jython in a list-like implementation.

Arguably a poor API choice on IA's part, many years ago.

Oh, I won't argue it, I'd say it's unambiguously a poor choice. We're explicitly checking for PySequence, and have been since, as far as I can tell, we migrated VCS systems to Git in 2011.

Maybe I'll sneak in a fix for 8.3...

3 Likes