# Creating and defining a dataset in Vision

**URL:** <https://forum.inductiveautomation.com/t/creating-and-defining-a-dataset-in-vision/92448>\
**Category:** Ignition\
**Tags:** vision, ignition81\
**Created:** [June 27, 2024, 9:57am UTC](https://forum.inductiveautomation.com/t/creating-and-defining-a-dataset-in-vision/92448 "2024-06-27T09:57:55Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Omer\_Oren](https://avatars.discourse-cdn.com/v4/letter/o/5f8ce5/32.png) [@Omer\_Oren](https://forum.inductiveautomation.com/u/Omer_Oren)\
**Post date:** [June 27, 2024, 9:57am UTC](https://forum.inductiveautomation.com/t/creating-and-defining-a-dataset-in-vision/92448/1 "2024-06-27T09:57:55Z")

</div>

Hello,  
I am having total n00b trouble creating a dataset:

I have few integer tags originating from a PLC through OPC which I need to display in a table (retention is done on the PLC side) and enable editing for some of the cells. To do this I need to create a dataset which will include those tags (or rather their values) in the correct order, which is where I'm having trouble.  
I watched the IU video on arrays and datasets which I learned nothing from, I also found [this](https://www.docs.inductiveautomation.com/docs/7.9/scripting/python-scripting/variables-datatypes-and-objects/datasets) but I don't know where to put this code (modified to my needs) to get it to work, and clearly I couldn't find a step by step tutorial explaining this.  
I know I should have been able to google my way through this but for some reason I'm unable to.

Any help would be greatly appreciated.

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [June 27, 2024, 11:23am UTC](https://forum.inductiveautomation.com/t/creating-and-defining-a-dataset-in-vision/92448/2 "2024-06-27T11:23:40Z")

</div>

Is it going to be live values, or is it going to be time stamped historical values?

---

<div class="post-metadata">

**Author:** ![Omer\_Oren](https://avatars.discourse-cdn.com/v4/letter/o/5f8ce5/32.png) [@Omer\_Oren](https://forum.inductiveautomation.com/u/Omer_Oren)\
**Post date:** [June 27, 2024, 12:04pm UTC](https://forum.inductiveautomation.com/t/creating-and-defining-a-dataset-in-vision/92448/3 "2024-06-27T12:04:09Z")

</div>

Live values.

In the meantime I managed to define the table with tags manually, but that generated another question: When I set the row to be editable, I am able to type values into a cell but on focus loss the tag isn't updated and the value displayed returns to the live tag value (the tags are editable in the designer's tag manager, so this isn't a problem with the tags themselves) how do I make the editable value update the tag?

Thanks

---

<div class="post-metadata">

**Author:** ![bschroeder](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bschroeder/32/13260_2.png) [@bschroeder](https://forum.inductiveautomation.com/u/bschroeder)\
**Post date:** [June 27, 2024, 12:14pm UTC](https://forum.inductiveautomation.com/t/creating-and-defining-a-dataset-in-vision/92448/4 "2024-06-27T12:14:20Z")

</div>

How do you have your tags setup in your gateway?

For something like this, for lack of a better way at the moment, I'd setup a folder for the table, and then a sub folder, with a number, for each row and then in each folder have a tag that is named via the column. Then you will have a folder for each row and a tag for each column.

Using scripting, or @pturmel Toolkit function, generate the dataset.

Now... updating that data is going to be tricky since you are hitting tags and not a table in a database or a dataset specifically.

I assume you are using the power table to show the data. You are going to want to use the onCellEdited function in the power table: [Vision - Power Table Scripting Functions | Ignition User Manual](https://docs.inductiveautomation.com/docs/8.1/appendix/components/vision-components/tables/power-table/power-table-scripting-functions#oncelledited)

If you use the tag folder structure above, you can get the rowIndex and colName and then create the final tag to update.

Alternatively, rather than using a table, a template repeater might be a cleaner and easier way to do this.

---

<div class="post-metadata">

**Author:** ![Omer\_Oren](https://avatars.discourse-cdn.com/v4/letter/o/5f8ce5/32.png) [@Omer\_Oren](https://forum.inductiveautomation.com/u/Omer_Oren)\
**Post date:** [July 1, 2024, 7:01am UTC](https://forum.inductiveautomation.com/t/creating-and-defining-a-dataset-in-vision/92448/5 "2024-07-01T07:01:39Z")

</div>

I set the tags in the structure you described, now I'm trying to create the dataset.

Copying the code from the first example [here](https://www.docs.inductiveautomation.com/docs/7.9/scripting/python-scripting/variables-datatypes-and-objects/datasets) into the scripting console seems to work in the sense that I get no error messages back, however I do have 2 problems:  
One is I can't find where that new dataset was created, searching the tag browser gives no results. Manually creating a dataset tag with the same name and then running the script doesn't populate the dataset tag with the content of the script.  
Two is I can enter the data as it appears in the example i.e. numbers and strings, but I can't figure out the syntax for it to include data from tags, every attempt at entering a tag path results in a syntax error.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [July 1, 2024, 12:12pm UTC](https://forum.inductiveautomation.com/t/creating-and-defining-a-dataset-in-vision/92448/6 "2024-07-01T12:12:44Z")

</div>

> [@Omer\_Oren](#):
>
> Copying the code

Those examples are snippets, not complete solutions. You need to tailor your own code to retrieve your own raw data, and deliver the result where you wish.

If you are using `runScript` to bind a dataset property, the delivery part is to simply `return` the dataset from your function.

However, you will struggle getting both live values **and** editability into a Vision table--the live dataset will keep replacing your edits.

Consider using a template repeater, where the repeater dataset supplies descriptions and tag paths to a row-like template. (Or omit the description if you will obtain it from the tag.)

The row-like template would have multiple indirect tag bindings to not only obtain the live value, but also obtain formatting, units, and descriptive information to make the "row" useful. The numeric editing field placed in this template would be set to ignore updates while focused, and use a property change script to write back to the tag (when the new value doesn't match the current live value).

---

<div class="post-metadata">

**Author:** ![Omer\_Oren](https://avatars.discourse-cdn.com/v4/letter/o/5f8ce5/32.png) [@Omer\_Oren](https://forum.inductiveautomation.com/u/Omer_Oren)\
**Post date:** [July 1, 2024, 1:06pm UTC](https://forum.inductiveautomation.com/t/creating-and-defining-a-dataset-in-vision/92448/7 "2024-07-01T13:06:45Z")

</div>

Of course there must be modifications to suit my needs, I didn't mention it as it seemed trivial.

The editability shouldn't just remain in the table, the new values were supposed to actually update the tag.

I've actually got some of this to work by running the code in the table's propertyChange event based on [this](https://forum.inductiveautomation.com/t/create-dataset-and-assign-to-table-data/22948/7) thread. However, since I couldn't get tag data to appear in there I don't know if this would have created live values or a single data pull.  
I tried to read tag values this based on [this thread](https://forum.inductiveautomation.com/t/wanting-to-add-data-to-dataset/27437/5) here, modified to a single tag for the test, but my project refuses to read the path and I can't understand what it is that I'm doing wrong.

The reason I'm trying to get a table to work is that I initially tried just placing numeric text fields side by side to get the "table look", but when I open the project on a different size screen it looks bad with out of alignment cells etc. and I'm not sure how a row of those fields set as a template (and stacked vertically via the template repeater) will look.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [July 1, 2024, 1:12pm UTC](https://forum.inductiveautomation.com/t/creating-and-defining-a-dataset-in-vision/92448/8 "2024-07-01T13:12:45Z")

</div>

> [@Omer\_Oren](#):
>
> I didn't mention it as it seemed trivial.

> [@Omer\_Oren](#):
>
> read tag values this based on

Nowhere in this topic have you posted **your actual code** , so the rest of us have to guess at the possible common mistakes you might be making. Post your code (as code, using the "preformatted text" button in the forum comment editor). Adjusting examples to suit a particular case is not trivial.

> [@Omer\_Oren](#):
>
> I'm not sure how a row of those fields set as a template (and stacked vertically via the template repeater) will look

Oy! _ **Try It.** _

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [July 1, 2024, 1:15pm UTC](https://forum.inductiveautomation.com/t/creating-and-defining-a-dataset-in-vision/92448/9 "2024-07-01T13:15:20Z")

</div>

> [@Omer\_Oren](#):
>
> I can't understand what it is that I'm doing wrong.

Ironically, neither can we as long as you don't show us your code.

Here are the basic steps to achieve what you are trying to do.

```python
#read the tags to get the values.
tagPaths = ["tagPath1", "tagPath2", "tagPath3"]
tagValues = [tag.value for tag in system.tag.readBlocking(tagPaths)]

#Assemble those values into a dataset
#As the values are already in a list, all we need is a header
tagValueDataset = system.dataset.toDataSet(['tagValueHeaer'], tagValues)

```

Then you just set the tables data property to your dataset.

To go the other way, you would use writeBlocking in a similar way.

---

<div class="post-metadata">

**Author:** ![Omer\_Oren](https://avatars.discourse-cdn.com/v4/letter/o/5f8ce5/32.png) [@Omer\_Oren](https://forum.inductiveautomation.com/u/Omer_Oren)\
**Post date:** [July 1, 2024, 1:26pm UTC](https://forum.inductiveautomation.com/t/creating-and-defining-a-dataset-in-vision/92448/10 "2024-07-01T13:26:30Z")

</div>

So, when I run this under propertyChange of the table works just fine:

```python
if event.propertyName == 'componentRunning':
	headers = ["Stage", "Temperature", "Humidity"]
	data = []
	data.append([1, 20, 'Test'])
	data.append([70, 15, 'Worm'])
	TT = system.dataset.toDataSet(headers, data)
	event.source.data = TT

```

I've made several attempts at reading tag data and didn't keep all of those that didn't work, but this is where I'm stopped at the moment:

```python
if event.propertyName == 'componentRunning':
	headers = ["Stage", "Temperature", "Humidity"]
	data = []
	data.append([1, 20, 'Test'])
	data.append([70, 15, 'Worm'])
	value = system.tag.readBlocking([default]Room_Temp_SP)
	data.append([99, value, 'Book'])
	TT = system.dataset.toDataSet(headers, data)
	event.source.data = TT

```

I tried the list way described in the thread I linked (editing the path and reducing the lists to just 1 item) but as it didn't work for me I was trying to get a more basic version to run and build from there.

> [@pturmel](#):
>
> Oy! _ **Try It.** _

Will do! but that doesn't mean I'm giving up on learning to use tables.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [July 1, 2024, 1:31pm UTC](https://forum.inductiveautomation.com/t/creating-and-defining-a-dataset-in-vision/92448/11 "2024-07-01T13:31:54Z")

</div>

> [@Omer\_Oren](#):
>
> giving up on learning to use tables.

But for live tag data, you **should** give it up. At least, if reading tags via script. Scripts don't cause leased tags to be leased, like bindings do, and `readBlocking` has much greater overhead than a binding.

Using a template that takes a tagpath and does an indirect binding will make a tag reference, not a simple read, and works properly with the rest of Ignition's tag machinery. Templates add slight overhead on the client UI side, where `readBlocking` burdens both gateway and client.

The only tool I'd recommend to let you avoid the template would be to use my Integration Toolkit's [tags()](https://www.automation-pros.com/toolkit/doc/utility.html#tags) expression function.

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [July 1, 2024, 1:44pm UTC](https://forum.inductiveautomation.com/t/creating-and-defining-a-dataset-in-vision/92448/12 "2024-07-01T13:44:00Z")

</div>

In the spirit of teaching, I will explain what is wrong with the script you've posted, but seriously, use a repeater as Phil has advised.

> [@Omer\_Oren](#):
>
> `value = system.tag.readBlocking([default]Room_Temp_SP)`

This is wrong, readBlocking expects either a single string tag path or a list of strings. What you have provided is an _undefined identifier_, at least as far as the interpreter is concerned, because you didn't surround it with single or double quotes to identify it as a string. I would recommend always using a list, even if you are only reading a single path, this way the function signature in your scripts always looks the same.

```python
value = system.tag.readBlocking(['[default]Room_Temp_SP'])

```

`system.tag.readBlocking()` returns a _List_ of _QualifiedValue_ objects. So you can not use them as is in a dataset the way that you are trying. In this case, we need to get the value attribute of the first QualifiedValue item in the list.

```python
value = system.tag.readBlocking('[defalut]Room_Temp_SP')[0].value

```

So, if your code looked like this, it should work to populate your table:

```python
if event.propertyName == 'componentRunning':
    headers = ['Stage', 'Temperature', 'Humidity']
    data = [[1,20,'Test'],[70,15,'Worm']]
    value = system.tag.readBlocking(['[default]Room_Temp_SP'])[0].value
    data.append([99,value,'Book'])
    event.source.data = system.dataset.toDataSet(headers,data)

```

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [July 1, 2024, 2:22pm UTC](https://forum.inductiveautomation.com/t/creating-and-defining-a-dataset-in-vision/92448/13 "2024-07-01T14:22:18Z")

</div>

> [@bschroeder](#):
>
> Alternatively, rather than using a table, a template repeater might be a cleaner and easier way to do this.

I think @Omer_Oren may have skipped over this solution too quickly.

You can easily make an editable pseudo-table by making a single row in a template with indirection and then use a template repeater to make the table. I've done this many times - it's a great solution with very little complexity.
