# Pass parameter to tag.writeAsync

**URL:** <https://forum.inductiveautomation.com/t/pass-parameter-to-tag-writeasync/43485>\
**Category:** Ignition\
**Tags:** ignition80\
**Created:** [February 16, 2021, 9:12pm UTC](https://forum.inductiveautomation.com/t/pass-parameter-to-tag-writeasync/43485 "2021-02-16T21:12:07Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![kelly.draehn](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kelly.draehn/32/21474_2.png) [@kelly.draehn](https://forum.inductiveautomation.com/u/kelly.draehn)\
**Post date:** [February 16, 2021, 9:12pm UTC](https://forum.inductiveautomation.com/t/pass-parameter-to-tag-writeasync/43485/1 "2021-02-16T21:12:07Z")

</div>

Hi All,

Do you know if there is a way to pass an additional parameter to the function called in writeAsync?

Basically I am iterating through a tag folder to store 1000 raw data samples using a for loop. I would like to pass along the index of my for loop as well in order to populate a column in my table called “Sample number”

I’m doing this in a gateway event script.

Is there a way to do this? Is there a better way to store a tag array than iterating through it one at a time?

Thanks!  
-Kelly

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [February 16, 2021, 9:59pm UTC](https://forum.inductiveautomation.com/t/pass-parameter-to-tag-writeasync/43485/2 "2021-02-16T21:59:00Z")

</div>

Are you asking about the `callback` function?

From the docs, regarding the callback function:

```auto
The function definition must provide a single argument, which will hold a List of quality codes when the callback function is invoked.

```

So no, I don’t believe there is a way.  
If you could provide a snippet of the relevant code, I could see about providing a good way to write to the table.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [February 16, 2021, 10:08pm UTC](https://forum.inductiveautomation.com/t/pass-parameter-to-tag-writeasync/43485/3 "2021-02-16T22:08:18Z")

</div>

You should be doing your reading and writing using single calls to the functions passing all (1000, in this case) tagpaths - then you just need to loop over them accordingly in your callback as well. Passing 1000 different callback functions to 1000 different writeAsync calls is orders of magnitude more of a performance hit than looping an in-memory list of 1000 items twice.

EDIT: But I’ll second Cody’s suggestion to post some code, otherwise we’re working blind.

---

<div class="post-metadata">

**Author:** ![kelly.draehn](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kelly.draehn/32/21474_2.png) [@kelly.draehn](https://forum.inductiveautomation.com/u/kelly.draehn)\
**Post date:** [February 17, 2021, 1:50pm UTC](https://forum.inductiveautomation.com/t/pass-parameter-to-tag-writeasync/43485/4 "2021-02-17T13:50:47Z")

</div>

Hi All,

Thank you for the suggestions! I actually ended up just doing a blocking call in the for loop since that seemed to work better. Still seems like a inelegant solution so if you have suggestions on a better way to do this I’m all ears!

```auto
for i in range (numberOfSamples):

		tagName = "[default]ForceData/ForceData_{}_".format(i)
		
		paths = [
			"[default]PartNumber",
			"[default]JobNumber",
			tagName]
		
		
		tagValues = system.tag.readBlocking(paths)
		
		
		args = [
				Equipment,
				currentDateTime,
				tagValues[0].value,
				tagValues[1].value,
				i,
				tagValues[2].value
				]
				
		query = """
				INSERT INTO [dbo].[DATA_RAW]
					 ([EQUIP_NUM]
				          ,[TIMESTAMP]
				          ,[PART_NUMBER]
				          ,[JOB_NUMBER]
				          ,[SAMPLE_NUMBER]
				          ,[SAMPLE_MEASUREMENT])
				VALUES
					(?,?,?,?,?,?)"""
		#logger.info("Query built")

		system.db.runPrepUpdate(query, args, "Monitoring")

```

---

<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:** [February 17, 2021, 2:01pm UTC](https://forum.inductiveautomation.com/t/pass-parameter-to-tag-writeasync/43485/5 "2021-02-17T14:01:16Z")

</div>

You _really_ don't want to call readBlocking() in a loop. See this topic for an example of combining many tag reads into a single call, then looping through the grouped results:

> [@Best Practices for Querying Tag History Data \[SOLVED\]](http://forum.inductiveautomation.com/t/best-practices-for-querying-tag-history-data-solved/43427/12):
>
> The code will run much faster if you don’t split these up. Read all of them at once. Consider using a project script module top level variable to hold the constructed list of tag paths, so that part won’t have to execute every time. (I strongly recommend placing all gateway event code in a project script module, leaving just a one-line function call in the event itself.) Something like this: # In a script, "bots", perhaps # Base path and channel names basepath = "[default]Alphabot/05 Bot …

I would also construct a SQL INSERT statement with a multi-row VALUES clause, permitting a single DB call as well.

---

<div class="post-metadata">

**Author:** ![kelly.draehn](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kelly.draehn/32/21474_2.png) [@kelly.draehn](https://forum.inductiveautomation.com/u/kelly.draehn)\
**Post date:** [February 17, 2021, 2:10pm UTC](https://forum.inductiveautomation.com/t/pass-parameter-to-tag-writeasync/43485/6 "2021-02-17T14:10:18Z")

</div>

@pturmel

Gotcha! So for the tag read this would be better:

```auto
paths = [
   		"[default]PartNumber",
   		"[default]JobNumber"]

for i in range (numberOfSamples):
   	tagName = "[default]ForceData/ForceData_{}_".format(i)
   	
   	paths.append(tagName)

```

And then read that all as once.

For the insert statement, you run it as a prep query? How would iterate through the list to add as value clauses? Would you construct it as a fully formed string and then do system.db.runQuery rather than as a prep?

-Kelly

---

<div class="post-metadata">

**Author:** ![kelly.draehn](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kelly.draehn/32/21474_2.png) [@kelly.draehn](https://forum.inductiveautomation.com/u/kelly.draehn)\
**Post date:** [February 17, 2021, 2:25pm UTC](https://forum.inductiveautomation.com/t/pass-parameter-to-tag-writeasync/43485/7 "2021-02-17T14:25:07Z")

</div>

Kinda thinking this might be the best way to go?

```auto
	query = """
			INSERT INTO [dbo].[DATA_RAW]
				 ([EQUIP_NUM]
			          ,[TIMESTAMP]
			          ,[PART_NUMBER]
			          ,[JOB_NUMBER]
			          ,[SAMPLE_NUMBER]
			          ,[SAMPLE_MEASUREMENT])
			VALUES"""
			
	for i in range (numberOfSamples):
		query += "({0},{1},{2},{3},{4},{5}),".format(equipment, currentDateTime, tagValues[0].value, tagValues[1].value, i, tagValues [2+i])

```

---

<div class="post-metadata">

**Author:** ![kelly.draehn](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kelly.draehn/32/21474_2.png) [@kelly.draehn](https://forum.inductiveautomation.com/u/kelly.draehn)\
**Post date:** [February 17, 2021, 2:48pm UTC](https://forum.inductiveautomation.com/t/pass-parameter-to-tag-writeasync/43485/8 "2021-02-17T14:48:26Z")

</div>

So I did the above and it all seems to look good but I get this error when trying to execute the updatequery:

Caused by: org.xml.sax.SAXParseException; lineNumber: 9; columnNumber: 53; An invalid XML character (Unicode: 0x0) was found in the CDATA section.

Tried doing the ascii encode then decode method to remove weird characters but that didn’t help.

Thoughts?

Thank you so much for your help!

---

<div class="post-metadata">

**Author:** ![kcollins](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kcollins/32/19646_2.png) [@kcollins](https://forum.inductiveautomation.com/u/kcollins)\
**Post date:** [February 17, 2021, 3:08pm UTC](https://forum.inductiveautomation.com/t/pass-parameter-to-tag-writeasync/43485/9 "2021-02-17T15:08:30Z")

</div>

While you’re getting the benefit of a single insert of multiple rows here, you’re losing the work (and safety) that is being done by the placeholder substitution you originally had (with the `prepUpdate()` call). You’ll have to do some extra formatting of those `()` _VALUES_ entries from your for-loop in order to get the syntax right; for example, making sure that the string fields are surrounded by single tick marks `'`, ensuring that the timestamp is in ODBC canonical form…

---

<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:** [February 17, 2021, 3:10pm UTC](https://forum.inductiveautomation.com/t/pass-parameter-to-tag-writeasync/43485/10 "2021-02-17T15:10:37Z")

</div>

Absolutely use a prep query. Simply add `, (?, ?, ?, ?, ?, ?)` to the end of your SQL for each additional row.

---

<div class="post-metadata">

**Author:** ![kcollins](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kcollins/32/19646_2.png) [@kcollins](https://forum.inductiveautomation.com/u/kcollins)\
**Post date:** [February 17, 2021, 3:12pm UTC](https://forum.inductiveautomation.com/t/pass-parameter-to-tag-writeasync/43485/11 "2021-02-17T15:12:01Z")

</div>

~~I’d be inclined to use a transaction, use individual prepUpdate() calls, and then commit the transaction. I think the bulk solution (with the single insert) might perform better, but the former would be “safer” and less at risk of formatting issues.~~

EDIT: well shucks, do what @pturmel said above… The `args` parameter is a _List_, so should be able to pass all the bulk row data in there…

---

<div class="post-metadata">

**Author:** ![kelly.draehn](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kelly.draehn/32/21474_2.png) [@kelly.draehn](https://forum.inductiveautomation.com/u/kelly.draehn)\
**Post date:** [February 17, 2021, 3:33pm UTC](https://forum.inductiveautomation.com/t/pass-parameter-to-tag-writeasync/43485/12 "2021-02-17T15:33:28Z")

</div>

@pturmel THANK U!!! This is working great now. And much more elegant!

---

<div class="post-metadata">

**Author:** ![JordanCClark](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jordancclark/32/83362_2.png) [@JordanCClark](https://forum.inductiveautomation.com/u/JordanCClark)\
**Post date:** [February 17, 2021, 4:04pm UTC](https://forum.inductiveautomation.com/t/pass-parameter-to-tag-writeasync/43485/13 "2021-02-17T16:04:49Z")

</div>

Sorry, I was pulled into a meeting as I was typing this, but if it helps, I do have a function to generate question marks for prep inserts.

```python
def prepInsertQmarks(numOfGroups, groupSize):
	''' 
	    Generate a string of grouped question marks for prepUpdate inserts
	    example: Generate three groups of four question marks:
	    prepInsertQmarks(3, 4) returns (?,?,?,?),(?,?,?,?),(?,?,?,?)
	'''
	group = '(' + ','.join(['?'] * groupSize) + ')'
	return ','.join([group] * numOfGroups)
	

query = """
INSERT INTO [dbo].[DATA_RAW]
	([EQUIP_NUM]
	,[TIMESTAMP]
	,[PART_NUMBER]
	,[JOB_NUMBER]
	,[SAMPLE_NUMBER]
	,[SAMPLE_MEASUREMENT])
VALUES %s""" % prepInsertQmarks(4,6)
		
print query

```

Output:

```nohighlight
INSERT INTO [dbo].[DATA_RAW]
	([EQUIP_NUM]
	,[TIMESTAMP]
	,[PART_NUMBER]
	,[JOB_NUMBER]
	,[SAMPLE_NUMBER]
	,[SAMPLE_MEASUREMENT])
VALUES (?,?,?,?,?,?),(?,?,?,?,?,?),(?,?,?,?,?,?),(?,?,?,?,?,?)

```

---

<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:** [February 17, 2021, 4:26pm UTC](https://forum.inductiveautomation.com/t/pass-parameter-to-tag-writeasync/43485/14 "2021-02-17T16:26:37Z")

</div>

I usually stick a newline and a tab into the `.join()` so if the SQL gets logged anywhere, it looks good. (:

---

<div class="post-metadata">

**Author:** ![kelly.draehn](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kelly.draehn/32/21474_2.png) [@kelly.draehn](https://forum.inductiveautomation.com/u/kelly.draehn)\
**Post date:** [February 17, 2021, 5:03pm UTC](https://forum.inductiveautomation.com/t/pass-parameter-to-tag-writeasync/43485/15 "2021-02-17T17:03:11Z")

</div>

I like the idea of creating a function for this, I could see this exact issue coming up anytime I’m logging raw data so it might be a good candidate for a shared script!

Hmmmm maybe that’s what I’ll work on this afternoon!
