# Template Canvas: issue OK button

**URL:** <https://forum.inductiveautomation.com/t/template-canvas-issue-ok-button/32028>\
**Category:** General Discussion\
**Created:** [February 7, 2020, 12:12am UTC](https://forum.inductiveautomation.com/t/template-canvas-issue-ok-button/32028 "2020-02-07T00:12:56Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![csanyia](https://avatars.discourse-cdn.com/v4/letter/c/48db29/32.png) [@csanyia](https://forum.inductiveautomation.com/u/csanyia)\
**Post date:** [February 7, 2020, 12:12am UTC](https://forum.inductiveautomation.com/t/template-canvas-issue-ok-button/32028/1 "2020-02-07T00:12:56Z")

</div>

I’m loading a CSV into the template canvas dataset, templates.

Everything looks file, however, a lot of code I have to interact w/ the templates are disabled. If I go to the template canvas templates customizer and make no changes but click “OK”, everything works again as designed.

I imagine the template canvas needs to rewrite an index or something behind the scenes, is there any way to kick off that operation from a button or in my script loading the CSV?

---

<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 7, 2020, 2:16am UTC](https://forum.inductiveautomation.com/t/template-canvas-issue-ok-button/32028/2 "2020-02-07T02:16:52Z")

</div>

How are you loading the dataset? (show your code)

---

<div class="post-metadata">

**Author:** ![csanyia](https://avatars.discourse-cdn.com/v4/letter/c/48db29/32.png) [@csanyia](https://forum.inductiveautomation.com/u/csanyia)\
**Post date:** [February 7, 2020, 4:24pm UTC](https://forum.inductiveautomation.com/t/template-canvas-issue-ok-button/32028/3 "2020-02-07T16:24:42Z")

</div>

I was basically looking for a way to store the entire dataset into a MySQL database (BLOB) and load it back in to the template canvas. I couldn’t quite find the easiest way to pull the mysql BLOB directly in, so i used ‘temp file’ (i would love to not involve the local file system of the device, im still looking for options)

This is the code used to save the file to a blob:

```auto
component = event.source.parent.getComponent('Template Canvas')
csv = system.dataset.toCSV(component.templates
system.db.runPrepUpdate("UPDATE table SET column =? WHERE id = ?", [csv, 6])

```

Here is the code loading it

```auto
import os, tempfile, csv
id = 6
result = system.db.runPrepQuery("SELECT column FROM table WHERE ID = ?", [id])
if len(result): 
	blob = result[0][0]
temp = tempfile.NamedTemporaryFile()
temp.write(blob)
temp.seek(0)
csvData = csv.reader(open(temp.name))
header = csvData.next()
dataset = system.dataset.toDataSet(header ,list(csvData))
event.source.parent.pulledData = dataset
temp.close

```

---

<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 7, 2020, 5:32pm UTC](https://forum.inductiveautomation.com/t/template-canvas-issue-ok-button/32028/4 "2020-02-07T17:32:42Z")

</div>

I would suspect that your round-trip to CSV is not preserving some aspect of the encoded columns. Opening the customizer is “fixing” the discrepancy. Consider using java’s ObjectOutputStream to directly serialize the dataset, combined with a true binary blob column in your database.

---

<div class="post-metadata">

**Author:** ![csanyia](https://avatars.discourse-cdn.com/v4/letter/c/48db29/32.png) [@csanyia](https://forum.inductiveautomation.com/u/csanyia)\
**Post date:** [February 7, 2020, 5:37pm UTC](https://forum.inductiveautomation.com/t/template-canvas-issue-ok-button/32028/5 "2020-02-07T17:37:41Z")

</div>

I’m new to all this, i’ll start reading up on ObjectOutputStream.

What I was also thinking was since system.dataset.addRow / system.dataset.deleteRow is working flawlessly, something like this should work. I believe these rows essential recreate the entire database each time a row is added or deleted.

I’ve been trying to figure out how to system.dataset.addRow for each line in the CSV, but I’m running into countless issues, any advice on either front would be appreciated.

---

<div class="post-metadata">

**Author:** ![martinel3746](https://avatars.discourse-cdn.com/v4/letter/m/e0b2c6/32.png) [@martinel3746](https://forum.inductiveautomation.com/u/martinel3746)\
**Post date:** [February 7, 2020, 7:59pm UTC](https://forum.inductiveautomation.com/t/template-canvas-issue-ok-button/32028/6 "2020-02-07T19:59:21Z")

</div>

Does the data need to be a BLOB?  
If you create a table with the same column names and data-types as the template dataset with one additional column of “ID” then you could bind your template to a Named Query with “ID” as a parameter.  
It would be dynamic and fast with no coding. Maintaining discreet row, column data will be easier than managing a BLOB of CSV data.  
The table/SQL doesn’t even need all of the columns that template dataset uses. I have a template working this way from a SELECT Named Query and letting a lot of the columns take the IA default values. In my case, the only columns in my SELECT statement are:

- path
- text
- selectedText
- icon
- selectedIcon

---

<div class="post-metadata">

**Author:** ![csanyia](https://avatars.discourse-cdn.com/v4/letter/c/48db29/32.png) [@csanyia](https://forum.inductiveautomation.com/u/csanyia)\
**Post date:** [February 7, 2020, 9:57pm UTC](https://forum.inductiveautomation.com/t/template-canvas-issue-ok-button/32028/7 "2020-02-07T21:57:13Z")

</div>

Thank you both for the suggestions!

It seems that the Template Canvas Customizer has to be the last thing to touch the headers, even grabbing the current via system.dataset.getColumnHeaders and rewriting them would cause a discrepancy.

I got it working, but not sure if in the most elegant ways. Querying and deleting all rows, and running an array on the csv.reader and using system.dataset.addRow to repopulate the dataset. Not sure if you can not touch the headers with system.dataset.toDataSet, if anybody knows, please share.

---

<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 7, 2020, 10:01pm UTC](https://forum.inductiveautomation.com/t/template-canvas-issue-ok-button/32028/8 "2020-02-07T22:01:40Z")

</div>

It's probably an issue with column dataypes. You can force them by constructing datasets with the [DatasetBuilder](http://files.inductiveautomation.com/sdk/javadoc/ignition79/795/com/inductiveautomation/ignition/common/util/DatasetBuilder.html) class instead of system.dataset.toDataSet().

Example:

> [@Convert columntype in table to integer](http://forum.inductiveautomation.com/t/convert-columntype-in-table-to-integer/9103/6):
>
> Consider using the platform’s [DatasetBuilder](http://files.inductiveautomation.com/sdk/javadoc/ignition79/793/com/inductiveautomation/ignition/common/util/DatasetBuilder.html) class. Something like: from java.lang import Integer, String from com.inductiveautomation.ignition.common.util import DatasetBuilder def someFunction(): b = DatasetBuilder.newBuilder().colNames("col1", "col2").colTypes(Integer, String) for x in range(5): b.addRow(x, "V%d" % x) return b.build()
