# Dynamic Row/Column table creation?

**URL:** <https://forum.inductiveautomation.com/t/dynamic-row-column-table-creation/82902>\
**Category:** Ignition\
**Created:** [December 8, 2023, 2:02pm UTC](https://forum.inductiveautomation.com/t/dynamic-row-column-table-creation/82902 "2023-12-08T14:02:08Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Wasif\_Shaukat](https://avatars.discourse-cdn.com/v4/letter/w/d07c76/32.png) [@Wasif\_Shaukat](https://forum.inductiveautomation.com/u/Wasif_Shaukat)\
**Post date:** [December 8, 2023, 2:02pm UTC](https://forum.inductiveautomation.com/t/dynamic-row-column-table-creation/82902/1 "2023-12-08T14:02:08Z")

</div>

Hello I see you are the most engaging person here  
I wan to create tags in table using the row names and columns names for instance.  
For instance, if I have columns as C1 , C2, C3 and rows as R1, R2 R3,

Then I want to create a dynamic tag such that with one click all the table entries are tagged for instance R1C1 tag should look something like this

MotorA/R1.Name/process parameters/C1.Name. I want to make my tags dynamic to use my column values and update the tag for next column automatically by writing tag as MotorA/R1.Name/process paramters/C2.name

---

<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:** [December 8, 2023, 2:22pm UTC](https://forum.inductiveautomation.com/t/dynamic-row-column-table-creation/82902/2 "2023-12-08T14:22:25Z")

</div>

You need to start a new topic for this rather than necroposting.

---

<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:** [December 8, 2023, 3:57pm UTC](https://forum.inductiveautomation.com/t/dynamic-row-column-table-creation/82902/3 "2023-12-08T15:57:59Z")

</div>

> [@bschroeder](#):
>
> new topic

Done.

---

<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:** [December 8, 2023, 3:59pm UTC](https://forum.inductiveautomation.com/t/dynamic-row-column-table-creation/82902/4 "2023-12-08T15:59:11Z")

</div>

Please describe your desired behavior in more detail. Also, is this Perspective or Vision? Please tag the topic accordingly.

Examples of how you want it to look would help.

---

<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:** [December 8, 2023, 4:11pm UTC](https://forum.inductiveautomation.com/t/dynamic-row-column-table-creation/82902/5 "2023-12-08T16:11:04Z")

</div>

Thanks. I'm not cool enough to do that yet. 😛

---

<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:** [December 8, 2023, 10:51pm UTC](https://forum.inductiveautomation.com/t/dynamic-row-column-table-creation/82902/6 "2023-12-08T22:51:27Z")

</div>

My money is on a script that populates the table. Use 2 lists, one with the header names, one with the row "names". Use nested for loops to build one list of all the tags to be read for the entire table, then one call to `system.tag.readBlocking()` and create a dataset from the results.

Something like (using the path you provided)

```auto
columns = ['C1', 'C2', 'C3']
rows = ['R1','R2','R3']

tagPaths = []

for row in rows:
	for column in columns:
		tagPaths.append('MotorA/'+str(row)+'.Name/process parameters/'+str(column)+'.Name')
		
		
#tagQValues = system.tag.readBlocking(tagPaths)[tag]
#tagValues = [tagQValues[tag].Value for tag in tagQvalues]
tagValues = [qval.value for qval in system.tag.readBlocking(tagPaths)]

numColumns = len(columns)
numTags = len(tagValues)

data = [tagValues[i:i + numColumns] for i in range(0, numTags), numColumns)]

dataset = system.dataset.toDataSet(columns,data)

```

\*\*not tested or checked for syntax at all. can't remember if Qvalues `value` prop is capitalized or not and I might have the syntax for unpacking them all at once off.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [December 9, 2023, 7:39am UTC](https://forum.inductiveautomation.com/t/dynamic-row-column-table-creation/82902/7 "2023-12-09T07:39:30Z")

</div>

> [@amarks](#):
>
> ```auto
> tagQValues = system.tag.readBlocking(tagPaths)[tag]
> 
> tagValues = [tagQValues[tag].Value for tag in tagQvalues]
> 
> ```

I don't understand this and I can't figure out how it would ever work.  
I suggest reworking it to something simpler:

```python
tagValues = [qval.value for qval in system.tag.readBlocking(tagPaths)]

```

edit: here's how I'd do it (can't run it so there might be some fixing to do):

```python
from itertools import product

columns = ['c1', 'c2', 'c3']
rows = ['r1', 'r2', 'r3']

paths = ["foo/{}/bar/{}".format(r, c) for r, c in product(columns, rows)]
values = [qval.value for qval in system.tag.readBlocking(paths)]
ds = system.dataset.toDataSet(
	columns,
	lib.utils.chunks(values, chunk_size=len(columns))
)

```

Now you obviously don't have the same `lib.utils.chunks` as I have, but I suggest `librarying` this kind of function. There's a number of different implementations on the internet.  
To remove that dependency, let's inline the one @amarks provided (with one change and one fix), because it works very well in this case:

```python
from itertools import product

columns = ['c1', 'c2', 'c3']
rows = ['r1', 'r2', 'r3']

paths = ["foo/{}/bar/{}".format(r, c) for r, c in product(columns, rows)]
values = [qval.value for qval in system.tag.readBlocking(paths)]
chunk_size = len(columns)
ds = system.dataset.toDataSet(
	columns,
	[values[i:i+chunk_size] for i in xrange(0, len(values), chunk_size)]
)

```

---

<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:** [December 11, 2023, 2:13pm UTC](https://forum.inductiveautomation.com/t/dynamic-row-column-table-creation/82902/8 "2023-12-11T14:13:24Z")

</div>

> [@pascal.fragnoud](#):
>
> > [@amarks](#):
> >
> > ```auto
> > tagQValues = system.tag.readBlocking(tagPaths)[tag]
> > 
> > tagValues = [tagQValues[tag].Value for tag in tagQvalues]
> > 
> > ```
> 
> I don't understand this and I can't figure out how it would ever work.  
> I suggest reworking it to something simpler:
> 
> ```python
> tagValues = [qval.value for qval in system.tag.readBlocking(tagPaths)]
> 
> ```

Ya, like I said I wasn't sure on the syntax on that. I've done it before, but it's not something I have committed to memory yet.

As for the rest of the code, I'd argue that my version is a bit easier to read.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [December 11, 2023, 2:53pm UTC](https://forum.inductiveautomation.com/t/dynamic-row-column-table-creation/82902/9 "2023-12-11T14:53:06Z")

</div>

Which part ?  
The only thing I really changed is the use of `xrange` instead of `range` and `product` instead of nested loops.  
If you're thinking of the call to `toDataSet`, it's only cosmetic, so it's up to personal preference.  
I agree that it's a bit "heavier" on the eye, but it also has the benefit of putting things exactly where they're used, which - to me - makes it easier to parse.

---

<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:** [December 11, 2023, 2:58pm UTC](https://forum.inductiveautomation.com/t/dynamic-row-column-table-creation/82902/10 "2023-12-11T14:58:49Z")

</div>

Path creation string is not as direct as using string concatenation as I did.  
Creation of the dataset is not as direct.

I've simplified mine using list comprehension, as you did to highlight those differences.

```auto
columns = ['C1', 'C2', 'C3']
rows = ['R1','R2','R3']

tagPaths = ['MotorA/' + str(row) + '.Name/process parameters/' + str(column) + '.Name' for row in rows for column in columns]
		
tagValues = [qval.value for qval in system.tag.readBlocking(tagPaths)]

numColumns = len(columns)
numTags = len(tagValues)

data = [tagValues[i:i + numColumns] for i in range(0, numTags), numColumns)]

dataset = system.dataset.toDataSet(columns,data)

```

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [December 11, 2023, 3:27pm UTC](https://forum.inductiveautomation.com/t/dynamic-row-column-table-creation/82902/11 "2023-12-11T15:27:47Z")

</div>

> [@amarks](#):
>
> Path creation string is not as direct as using string concatenation as I did.

I know it's a matter of personal preference but... are you saying you find this:

```python
['MotorA/' + str(row) + '.Name/process parameters/' + str(column) + '.Name' for row in rows for column in columns]

```

easier to read than this:

```python
["MotorA/{}.Name/process parameters/{}.Name".format(r, c) for r, c in product(columns, rows)]

```

?

Is it the formatting method, or the product ?  
I'm not sure what you mean by "direct".

---

<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:** [December 11, 2023, 3:39pm UTC](https://forum.inductiveautomation.com/t/dynamic-row-column-table-creation/82902/12 "2023-12-11T15:39:48Z")

</div>

Yes, of course it's just personal preference. For me, it's using `{}.format(r,c)` I'm not familiar with that method. String concatenation with the `+` operator just feels more natural.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [December 11, 2023, 3:48pm UTC](https://forum.inductiveautomation.com/t/dynamic-row-column-table-creation/82902/13 "2023-12-11T15:48:06Z")

</div>

I really don't like those `+` and `str()` in the middle of my strings, that's why I use format... even though concatenation is a bit more efficient in most cases.
