# Progress bar not being updated

**URL:** <https://forum.inductiveautomation.com/t/progress-bar-not-being-updated/89191>\
**Category:** Ignition\
**Tags:** ignition81, vision, scripting\
**Created:** [April 22, 2024, 9:11am UTC](https://forum.inductiveautomation.com/t/progress-bar-not-being-updated/89191 "2024-04-22T09:11:31Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![Om33](https://avatars.discourse-cdn.com/v4/letter/o/7ba0ec/32.png) [@Om33](https://forum.inductiveautomation.com/u/Om33)\
**Post date:** [April 22, 2024, 9:11am UTC](https://forum.inductiveautomation.com/t/progress-bar-not-being-updated/89191/1 "2024-04-22T09:11:31Z")

</div>

Hello,

I have a property change script that takes about 9 to 13 sec to execute. I want to display the execution progress with a progress bar. But my progress bar is being updated just twice: at the beginning with 0% and at the end of script with 100%. It doesn't update inbetween.

```python
if event.propertyName=="selected" and event.source.selected==True:
	def actualiseTable():
		...

		event.source.parent.getComponent('Progress Bar').visible=True
		total_rows = tagPaths.rowCount
		processed_rows = 0
		def actualiseProgress():
			progress_percent = int(processed_rows / total_rows * 100)
			event.source.parent.getComponent('Progress Bar').value=progress_percent
		for x in range(tagPaths.rowCount):
			processed_rows += 1
			system.util.invokeLater(actualiseProgress)

			...

	system.util.invokeAsynchronous(actualiseTable)
	
	

```

---

<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:** [April 22, 2024, 9:47am UTC](https://forum.inductiveautomation.com/t/progress-bar-not-being-updated/89191/2 "2024-04-22T09:47:58Z")

</div>

What is your `propertyChange` script doing? For this to work as intended, the whole script that the event calls should be ran in the same asynchronous thread, touching the EDT as needed with invoke later. It looks like you are running the propertyChange event script in the EDT, and then running the actualizer asynchronously. That means that every invokeLater will be scheduled for after the gui operation completes giving the illusion that the status bar is updating to 100% instantly.

> [@Om33](#):
>
> `tagPaths.rowCount`

Just out of curiosity, does this mean that you are running a separate read or writeblocking operation per tag instead of batching them in one call?

---

<div class="post-metadata">

**Author:** ![Om33](https://avatars.discourse-cdn.com/v4/letter/o/7ba0ec/32.png) [@Om33](https://forum.inductiveautomation.com/u/Om33)\
**Post date:** [April 22, 2024, 10:28am UTC](https://forum.inductiveautomation.com/t/progress-bar-not-being-updated/89191/3 "2024-04-22T10:28:11Z")

</div>

That is the whole script the event calls. What is an EDT?  
the script just calculates duration on of Tags (Alarm)

---

<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:** [April 22, 2024, 10:32am UTC](https://forum.inductiveautomation.com/t/progress-bar-not-being-updated/89191/4 "2024-04-22T10:32:47Z")

</div>

> [@Om33](#):
>
> What is an EDT

Event dispatch [gui] thread

> [@Om33](#):
>
> a property change script that takes about 9 to 13 sec to execute.

I'm not seeing this in your code snippet. All I see is the progress bar control. Am I overlooking it?

---

<div class="post-metadata">

**Author:** ![Om33](https://avatars.discourse-cdn.com/v4/letter/o/7ba0ec/32.png) [@Om33](https://forum.inductiveautomation.com/u/Om33)\
**Post date:** [April 22, 2024, 10:37am UTC](https://forum.inductiveautomation.com/t/progress-bar-not-being-updated/89191/5 "2024-04-22T10:37:25Z")

</div>

No you are not overlooking something. I just posted the part regarding the progress bar for a better overview and since I have already posted the rest of the code in another discussion.

> [@Component event script in inheritable project](https://forum.inductiveautomation.com/t/component-event-script-in-inheritable-project/89019/2):
>
> That shouldn't happen, there must be something else at play here. Can you describe the setup more accurately ? Show the script, how it's called, etc.

---

<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:** [April 22, 2024, 10:56am UTC](https://forum.inductiveautomation.com/t/progress-bar-not-being-updated/89191/6 "2024-04-22T10:56:13Z")

</div>

Go ahead and repost the whole thing as it's currently written so we can decipher why the progress bar part isn't working. You can highlight the whole thing and use the hide details option if you want to save space in your post.

---

<div class="post-metadata">

**Author:** ![Om33](https://avatars.discourse-cdn.com/v4/letter/o/7ba0ec/32.png) [@Om33](https://forum.inductiveautomation.com/u/Om33)\
**Post date:** [April 22, 2024, 11:03am UTC](https://forum.inductiveautomation.com/t/progress-bar-not-being-updated/89191/7 "2024-04-22T11:03:03Z")

</div>

```python
if event.propertyName=="selected" and event.source.selected==True:
	def actualiseTable():
		start=event.source.parent.getComponent('CalStart').date
		ende=event.source.parent.getComponent('CalEnd').date
		folderPath = event.source.parent.dataPath 
		folderArchiv = folderPath + "/AlarmData/alarmArchiv"    
		modifiedHistoryDataset = system.dataset.toDataSet(["ID","Description", "Start ", "End", "Duration"], [])
		tagPaths=system.tag.readBlocking(folderPath +"/AlarmData/alarmList")[0].value	
		startTimestamp=None
		event.source.parent.getComponent('Progress Bar').visible=True
		total_rows = tagPaths.rowCount
		processed_rows = 0
		def actualiseProgress():
			progress_percent = int(processed_rows / total_rows * 100)
			event.source.parent.getComponent('Progress Bar').value=progress_percent
		for x in range(tagPaths.rowCount):
			processed_rows += 1
			system.util.invokeLater(actualiseProgress)
			identification = tagPaths.getValueAt(x,0) 
			description =tagPaths.getValueAt(x,1)
			tagPath = tagPaths.getValueAt(x,2) 
			history = system.tag.queryTagHistory([tagPath],start,ende, aggregationMode="LastValue")
			for i in range(history.rowCount):
				if history.getValueAt(i,1) == 1: # Check if the tag value is 1
					startTimestamp = history.getValueAt(i,0)
					endTimestamp=history.getValueAt(i + 1, 0) if i<history.rowCount-1 else system.date.now()
					if startTimestamp is not None and endTimestamp is not None:
						formatted_duration = shared.Func_Dataset.calculate_duration(startTimestamp, endTimestamp)
			        	startFormatted = system.date.format(startTimestamp, "dd.MM.yyyy HH:mm:ss")
			        	endFormatted = system.date.format(endTimestamp, "dd.MM.yyyy HH:mm:ss")
			        	modifiedHistoryDataset = system.dataset.addRow(modifiedHistoryDataset, [identification, description, startFormatted, endFormatted, formatted_duration])
		modifiedHistoryDataset=system.dataset.sort(modifiedHistoryDataset, 2, False)	        
		system.tag.writeBlocking(folderArchiv, modifiedHistoryDataset)

	system.util.invokeAsynchronous(actualiseTable)

```

---

<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:** [April 22, 2024, 12:27pm UTC](https://forum.inductiveautomation.com/t/progress-bar-not-being-updated/89191/8 "2024-04-22T12:27:18Z")

</div>

This older topic still applies:

> [@Update progress bar from within a script](https://forum.inductiveautomation.com/t/update-progress-bar-from-within-a-script/21995):
>
> I have this script on a button to copy data to a PLC from a database. Since this script takes 10 - 20 seconds to run, i would like to have the progress bar show progress. Issue I have is the progress bar updates only when the script has completed. Is there anyway to get value outside of the script to update as the script is running?

---

<div class="post-metadata">

**Author:** ![Om33](https://avatars.discourse-cdn.com/v4/letter/o/7ba0ec/32.png) [@Om33](https://forum.inductiveautomation.com/u/Om33)\
**Post date:** [April 23, 2024, 4:44am UTC](https://forum.inductiveautomation.com/t/progress-bar-not-being-updated/89191/9 "2024-04-23T04:44:48Z")

</div>

I read this post already and I'm doing exactly what it says, isn't it?

---

<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:** [April 23, 2024, 6:02am UTC](https://forum.inductiveautomation.com/t/progress-bar-not-being-updated/89191/10 "2024-04-23T06:02:20Z")

</div>

I made this more explicit:

> [@Om33](#):
>
> `progress_percent = int(processed_rows / total_rows * 100)`

I see some gui stuff being touched from the asynchronous thread. Another thing is that most of this will run really fast, the slow stuff will be the read and write blocks, so the incrementations are best placed directly after those. Here is a quick and dirty _ **untested** _ refactor you can try:

> **Refactored Code Sample**
>
> ```python
> # Run only when the selected property changes to true
> if event.propertyName=="selected" and event.newValue:
> 	
> # Asynchronous function to assemble table data
> def actualiseTable():
> 		
> # Function for touching the gui thread when updating the progress bar
> def actualiseProgress():
> 			
> # Total = total tagpath iterations plus two (Initial write and final write)
> totalIterations = tagPaths.rowCount + 2
> 			
> progress_percent = int((processed_rows / total_rows) * 100)
> event.source.parent.getComponent('Progress Bar').value = progress_percent
> 		
> # Complete the folder path
> folderArchiv = folderPath + "/AlarmData/alarmArchiv"    
> 		
> # Initialize a modified history dataset with headers and an empty body list
> modifiedHistoryDataset = system.dataset.toDataSet(["ID","Description", "Start ", "End", "Duration"], [])
> 		
> # Read the tag value
> tagPaths=system.tag.readBlocking(folderPath +"/AlarmData/alarmList")[0].value	
> 		
> # Trigger progress bar update
> system.util.invokeLater(actualiseProgress)
> 		
> # Create an empty timestamp variable
> startTimestamp=None
> 		
> # Create variables for various row counts
> total_rows = tagPaths.rowCount # Alarm list
> processed_rows = 0 # independant variable for enumerating the iteration
> 		
> # Iterate through the alarm list
> for x in xrange(tagPaths.rowCount):
> processed_rows += 1 # increment enumeration
> 			
> # Get various variables variables from the tagpaths dataset
> identification = tagPaths.getValueAt(x,0) 
> description =tagPaths.getValueAt(x,1)
> tagPath = tagPaths.getValueAt(x,2) 
> 			
> # Query the tag history
> history = system.tag.queryTagHistory([tagPath],start,ende, aggregationMode="LastValue")
> 			
> # Trigger progress bar update
> system.util.invokeLater(actualiseProgress)
> 			
> # Iterate through the history and modify the history dataset as needed
> for i in range(history.rowCount):
> if history.getValueAt(i,1) == 1: # Check if the tag value is 1
> 					
> # Get the timestamps from each row of the history
> startTimestamp = history.getValueAt(i,0)
> endTimestamp=history.getValueAt(i + 1, 0) if i<history.rowCount-1 else system.date.now()
> 					
> # If both timestamps exist for an entry...
> if startTimestamp is not None and endTimestamp is not None:
> 						
> # Format the timestamps
> formatted_duration = shared.Func_Dataset.calculate_duration(startTimestamp, endTimestamp)
> startFormatted = system.date.format(startTimestamp, "dd.MM.yyyy HH:mm:ss")
> endFormatted = system.date.format(endTimestamp, "dd.MM.yyyy HH:mm:ss")
> 			        	
> # Add the row to the history dataset
> modifiedHistoryDataset = system.dataset.addRow(modifiedHistoryDataset, [identification, description, startFormatted, endFormatted, formatted_duration])
> 		
> # Sort the dataset and write it to a tag
> modifiedHistoryDataset=system.dataset.sort(modifiedHistoryDataset, 2, False)	        
> system.tag.writeBlocking(folderArchiv, modifiedHistoryDataset)
> 		
> # Trigger the final progress bar update
> system.util.invokeLater(actualiseProgress)
> 				
> # Make the progress bar visible
> event.source.parent.getComponent('Progress Bar').visible=True
> 		
> 	
> # Get start and end dates
> start = event.source.parent.getComponent('CalStart').date
> ende=event.source.parent.getComponent('CalEnd').date
> 	
> # Get the data path
> folderPath = event.source.parent.dataPath 
> 	
> # Call a long running funcion asynchronously
> system.util.invokeAsynchronous(actualiseTable)
> 
> ```

---

<div class="post-metadata">

**Author:** ![Om33](https://avatars.discourse-cdn.com/v4/letter/o/7ba0ec/32.png) [@Om33](https://forum.inductiveautomation.com/u/Om33)\
**Post date:** [April 23, 2024, 6:20am UTC](https://forum.inductiveautomation.com/t/progress-bar-not-being-updated/89191/11 "2024-04-23T06:20:00Z")

</div>

Just tried it, it still updates only at the beginning with 0% and at the end with 100%

Thank you anyway 🙂

---

<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:** [April 23, 2024, 6:23am UTC](https://forum.inductiveautomation.com/t/progress-bar-not-being-updated/89191/12 "2024-04-23T06:23:07Z")

</div>

It could be an integer division problem. Anything fractional in integer division evaluates to zero, so try rewriting the calculation like this:

```python
progress_percent = int(float(processed_rows / total_rows) * 100.0)

```

My hypothesis is that the fractional integer division is always evaluating to `0 * 100 = 0` until, finally at the end, the integer division evaluates to `1 * 100`

---

<div class="post-metadata">

**Author:** ![Om33](https://avatars.discourse-cdn.com/v4/letter/o/7ba0ec/32.png) [@Om33](https://forum.inductiveautomation.com/u/Om33)\
**Post date:** [April 23, 2024, 6:27am UTC](https://forum.inductiveautomation.com/t/progress-bar-not-being-updated/89191/13 "2024-04-23T06:27:50Z")

</div>

Yes this sounds plausible, but adding the "float" doesn't solve the problem

---

<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:** [April 23, 2024, 6:31am UTC](https://forum.inductiveautomation.com/t/progress-bar-not-being-updated/89191/14 "2024-04-23T06:31:30Z")

</div>

Uggh. The way I wrote it, inside the float conversion is still integer division. `float(0) * 100.0`

Try it like this:

```python
progress_percent = int(float(processed_rows) / float(total_rows) * 100.0)

```

You probably only need to convert the numerator, but... better to have it and not need it at this point.

---

<div class="post-metadata">

**Author:** ![Om33](https://avatars.discourse-cdn.com/v4/letter/o/7ba0ec/32.png) [@Om33](https://forum.inductiveautomation.com/u/Om33)\
**Post date:** [April 23, 2024, 6:34am UTC](https://forum.inductiveautomation.com/t/progress-bar-not-being-updated/89191/15 "2024-04-23T06:34:54Z")

</div>

It works, thank you so much ❤  
Have a great day
