# Conditionally Extracting Rows from Table

**URL:** <https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993>\
**Category:** Ignition\
**Tags:** scripting, perspective\
**Created:** [November 2, 2022, 1:48pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993 "2022-11-02T13:48:20Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![CMuecke](https://avatars.discourse-cdn.com/v4/letter/c/df705f/32.png) [@CMuecke](https://forum.inductiveautomation.com/u/CMuecke)\
**Post date:** [November 2, 2022, 1:48pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/1 "2022-11-02T13:48:20Z")

</div>

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/0/2/02e13f08b6c3ba3886179463715d5fb778f18991.png)

```auto
def transform(self, value, quality, timestamp):
	RouteData = []
	# This maps out the list.
	for row in value:
			RouteData.append({
		"DeviceID": row["DEVICE_ID"],
		"DeviceName": row["DEVICE_NAME"],
		"DestinationSelected": row["CHECKBOX"]
	})  
	return RouteData

```

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/0/e/0e6181b7d4222485b01aa7f85fc4d791f809ddb6.png)

I am able to everything from the Table and place it in a Custom Property. What I want to do is be able to only append the ones that have DestinationSelected checked.

I am guessing I would need an if then statement but need some help.

---

<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:** [November 2, 2022, 2:44pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/2 "2022-11-02T14:44:50Z")

</div>

```python
def transform(self, value, quality, timestamp):
	# This maps out the list.
	return [{'DeviceID':row['DEVICE_ID'],'DeviceName':row['DEVICE_NAME'],'DestinationSelected':row['CHECKBOX']} for row in value if row['CHECKBOX']]

```

---

<div class="post-metadata">

**Author:** ![CMuecke](https://avatars.discourse-cdn.com/v4/letter/c/df705f/32.png) [@CMuecke](https://forum.inductiveautomation.com/u/CMuecke)\
**Post date:** [November 2, 2022, 2:48pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/3 "2022-11-02T14:48:29Z")

</div>

Wow! Thank you for your help!

---

<div class="post-metadata">

**Author:** ![CMuecke](https://avatars.discourse-cdn.com/v4/letter/c/df705f/32.png) [@CMuecke](https://forum.inductiveautomation.com/u/CMuecke)\
**Post date:** [November 2, 2022, 3:33pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/4 "2022-11-02T15:33:38Z")

</div>

Part 2.

Let's say I want these entries to be added and removed based on the order they are selected.

I would just use the append and remove?

---

<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:** [November 2, 2022, 3:37pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/5 "2022-11-02T15:37:07Z")

</div>

Do you mean you want to add them to a prop when they are clicked?

Or are you trying to 'retain the order' in which they are selected?

In the original question, they would have maintained the order in which they were in the original prop.

---

<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:** [November 2, 2022, 4:05pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/7 "2022-11-02T16:05:10Z")

</div>

~~I'll suggest a slight change:~~

```auto
return [row for row in value if row['CHECKBOX']]

```

edit: nevermind, didn't notice the keys names were changed in the process.

---

<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:** [November 2, 2022, 4:12pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/8 "2022-11-02T16:12:30Z")

</div>

This will require you to keep track of when they're selected. Doing this in a transform won't be enough, as far as I can tell there's no way to tell which one was selected first.

You could build your custom prop using click events on the table, appending/removing items to it every time something is selected/unselected.

---

<div class="post-metadata">

**Author:** ![CMuecke](https://avatars.discourse-cdn.com/v4/letter/c/df705f/32.png) [@CMuecke](https://forum.inductiveautomation.com/u/CMuecke)\
**Post date:** [November 2, 2022, 4:27pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/9 "2022-11-02T16:27:17Z")

</div>

I am thinking I misunderstood the question. It is probably add them to prop when they are checked and remove them when they are unchecked.

---

<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:** [November 2, 2022, 5:15pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/10 "2022-11-02T17:15:53Z")

</div>

I would probably recommend that you use the `onEditCellCommit` event of the table and then use a script similar to this:

```python
	if event.column == 'CHECKBOX':
		routeData = self.view.custom.RouteData
		dataItem = self.props.data[row]
		if event.value:
			if not dataItem in routeData:
				routeData.append(dataItem)
		else:
			if dataItem in routeData:
				routeData.remove(dataItem)
		self.view.custom.RouteData == routeData

```

NOTE: I haven't tested this, so no guarantee, but I think it shows the basic principal. Also, I have not modified the keys here, which will facilitate the remove operation, and the checks to see if the item exists in the list or not. You can change them, but you will need to manually check each value of an item to see if the items are actually the same, or I suppose at least the DeviceID if that is all that matters as far as duplication goes.

Perhaps, @pascal.fragnoud or @bkarabinchak.psi have a magic python trick to make that is not quite so ugly, I couldn't think of one.

---

<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:** [November 3, 2022, 7:25am UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/11 "2022-11-03T07:25:03Z")

</div>

Frankly... this is clear and efficient.  
Maybe I'd group the conditions to avoid the extra level of nesting, but there's nothing ugly about this code.

---

<div class="post-metadata">

**Author:** ![CMuecke](https://avatars.discourse-cdn.com/v4/letter/c/df705f/32.png) [@CMuecke](https://forum.inductiveautomation.com/u/CMuecke)\
**Post date:** [November 3, 2022, 12:26pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/12 "2022-11-03T12:26:17Z")

</div>

I'll mess around with it. Thank you for the help everyone!

---

<div class="post-metadata">

**Author:** ![CMuecke](https://avatars.discourse-cdn.com/v4/letter/c/df705f/32.png) [@CMuecke](https://forum.inductiveautomation.com/u/CMuecke)\
**Post date:** [November 3, 2022, 1:18pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/13 "2022-11-03T13:18:03Z")

</div>

I can get it to add the route without an issue, but if I attempt to remove one, it gives me a

08:14:26.147 [AWT-EventQueue-0] ERROR com.inductiveautomation.ignition.client.util.gui.ErrorUtil - Error running action 'component.onEditCellCommit' on View/Recipe/Batching@D/root/LeftContainer/DestinationContainer/TableContainer/ScrollContainer/Table: Traceback (most recent call last):  
File "function:runAction", line 16, in runAction  
ValueError: : {u'CHECKBOX': True, u'DEVICE\_NAME': u'BIN 60', u'DEVICE\_ID': 60} is not in array

---

<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:** [November 3, 2022, 1:36pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/14 "2022-11-03T13:36:02Z")

</div>

The error means that it didn't find the item you're trying to remove in the List. Can you post your script?

You may need to write code that locates your item in the list prior to attempting to remove it.

---

<div class="post-metadata">

**Author:** ![CMuecke](https://avatars.discourse-cdn.com/v4/letter/c/df705f/32.png) [@CMuecke](https://forum.inductiveautomation.com/u/CMuecke)\
**Post date:** [November 3, 2022, 1:41pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/15 "2022-11-03T13:41:50Z")

</div>

Absolutely.

```auto
	Column = event.column
	Row = event.row
	Value = event.value
	self.props.data[self.props.selection.selectedRow].CHECKBOX = Value
	system.perspective.print(Column)
	system.perspective.print(Row)
	system.perspective.print(Value)
	if Column == 'CHECKBOX':
		RouteTable = self.custom.RouteData
		RouteData = self.props.data[Row]
		system.perspective.print(RouteData)
		if Value:
			if not RouteData in RouteTable:
				system.perspective.print("Route Removed.")
				RouteTable.remove(RouteData)
		else:
			if RouteData in RouteTable:
				system.perspective.print("Route Removed.")
				RouteTable.remove(RouteData)
		self.custom.RouteData == RouteTable

```

I took your snippet and got the Append to work fine, but even when I unchecked it it would not remove it.  
So I left some duplicate routes in the table and moved the remove so I could see any errors. What you say though makes a ton of sense. I am wondering if using two buttons with this would be easier than just the Checkbox in the Table.

---

<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:** [November 3, 2022, 1:50pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/16 "2022-11-03T13:50:37Z")

</div>

I'm wondering if this has something to do with the fact that you're storing the selected property too...  
I'll set up a test and try it myself, see if I can get you a working solution.

---

<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:** [November 3, 2022, 2:18pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/17 "2022-11-03T14:18:33Z")

</div>

I notice that in your script you are trying to remove the selection in both cases. One of them should be an append. You say you were able to get the append to work, but I don't see an append in this script.

Try this, it only looks at the Device ID for equality (similar to how a Primary Key in a database works).

```python
	if event.column == 'CHECKBOX':
		routeData = self.view.custom.RouteData
		rowData = self.props.data[row]
		if event.value and not any(rowData['DEVICE_ID'] == route['DEVICE_ID'] for route in routeData):
			routeData.append(rowData)
		else:
			routeData = [route for route in routeData if route['DEVICE_ID'] != rowData['DEVICE_ID']]
		self.view.custom.RouteData == routeData

```

And, @pascal.fragnoud the script looks much nicer without the unneeded nested conditions.

---

<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:** [November 3, 2022, 2:20pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/18 "2022-11-03T14:20:49Z")

</div>

So, I'm not quite sure why, but I couldn't get `remove` to work...  
So I used `pop` instead:

```python
def runAction(self, event):
	row = self.props.data[event.rowIndex]
	row.selected ^= True

	if not row.selected:
		self.custom.data.append({'label': row['label'],'value': row['value']})
	else:
		idx = next(i for i, d in enumerate(self.custom.data) if d.label == row.label)
		self.custom.data.pop(idx)

```

I put this on a `onRowClick` event, and toggle the `selected` column with `row.selected ^= True`.  
I do this partly because this way you can click any column, not just the `selected` one, but mostly because clicking checkboxes in tables is a pain in the ass: gotta click several times to get to interact with them. This fixes that.

edit:  
note that if for some reason the row isn't in the list when you deselect it in the table, you'll get a `StopIteration` error. This shouldn't happen, as long as you only add and remove items from the list by clicking on the table.  
If you want to prevent errors, wrap the `idx` assignation in a try/except block.

---

<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:** [November 3, 2022, 2:26pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/19 "2022-11-03T14:26:29Z")

</div>

Shouldn't that `event.rowIndex` be `event.row`?

It says, that `rowIndex` is the row index as it is represented in the current visible data. I take that to mean that it isn't always 1:1 to the index in `self.props.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:** [November 3, 2022, 2:29pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/20 "2022-11-03T14:29:21Z")

</div>

Maybe, I picked one randomly without asking myself what the difference is ;D

---

<div class="post-metadata">

**Author:** ![CMuecke](https://avatars.discourse-cdn.com/v4/letter/c/df705f/32.png) [@CMuecke](https://forum.inductiveautomation.com/u/CMuecke)\
**Post date:** [November 3, 2022, 3:16pm UTC](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993/21 "2022-11-03T15:16:09Z")

</div>

@lrose This did work. I will see if I can create something that will remove it if it sees it in the list.

```auto
   Column = event.column
   Row = event.row
   Value = event.value
   self.props.data[self.props.selection.selectedRow].CHECKBOX = Value
   system.perspective.print(Column)
   system.perspective.print(Row)
   system.perspective.print(Value)
   if Column == 'CHECKBOX':
   	routeData = self.custom.RouteData
   	rowData = self.props.data[Row]
   	if Value and not any(rowData['DEVICE_ID'] == route['DEVICE_ID'] for route in routeData):
   		routeData.append(rowData)
   else:
   	routeData = [route for route in routeData if route['DEVICE_ID'] != rowData['DEVICE_ID']]
   self.custom.RouteData == routeData

```

@pascal.fragnoud

I keep getting an error.

Error running action 'component.onRowClick' on View/Recipe/Batching@D/root/LeftContainer/DestinationContainer/TableContainer/ScrollContainer/Table: Traceback (most recent call last): File "function:runAction", line 3, in runAction AttributeError: 'com.inductiveautomation.perspective.gateway.script' object has no attribute 'selected'

```auto
	row = self.props.data[event.rowIndex]
	row.selected ^= True
					
	if not row.selected:
		self.custom.RouteData.append({'DeviceID': row['DEVICE_ID'],'DeviceName': row['DEVICE_NAME']})
	else:
		idx = next(i for i, d in enumerate(self.custom.RouteData) if d.DeviceID == row.DEVICE_ID)
		self.custom.RouteData.pop(idx)	

```

[Next page](https://forum.inductiveautomation.com/t/conditionally-extracting-rows-from-table/65993.md?page=2)
