# Best way to dynamically create a 'header' row for conversion to csv file using UDT tag name

**URL:** <https://forum.inductiveautomation.com/t/best-way-to-dynamically-create-a-header-row-for-conversion-to-csv-file-using-udt-tag-name/65549>\
**Category:** Ignition\
**Created:** [October 21, 2022, 7:01pm UTC](https://forum.inductiveautomation.com/t/best-way-to-dynamically-create-a-header-row-for-conversion-to-csv-file-using-udt-tag-name/65549 "2022-10-21T19:01:15Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![michael.black](https://avatars.discourse-cdn.com/v4/letter/m/ee7513/32.png) [@michael.black](https://forum.inductiveautomation.com/u/michael.black)\
**Post date:** [October 21, 2022, 7:01pm UTC](https://forum.inductiveautomation.com/t/best-way-to-dynamically-create-a-header-row-for-conversion-to-csv-file-using-udt-tag-name/65549/1 "2022-10-21T19:01:15Z")

</div>

I have created a csv file from a tag history query but want to change the header row. I was thinking I could not show the header when converting to csv file using system.dataset.toCSV and then insert a custom row in the dataset before I convert to a csv.

I want to dynamically read in 'DeviceName' from each UDT instance, then add an element for datetime by using system.dataset.addRow command,

I am able to create a list of tagpaths for the device names I want to read in. How would I go about reading in the values of each item in the list so its in a dataset vs with a pywrapper?

Here is what I have in the script console and its basically what I want but how would I go about adding an element in the beginning of the list that says Date?

Is there an easier way to do this by altering the column headers somehow without having to create/edit a header row?

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

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/5/6/5642c16ed2b607d2ab577033579805c1de574b45.png)

Here is my functioning code which gives me what I want except I want to replace/rename the header row values in the csv file

```auto
def create_analogin():
	#get tag paths
	
	
	#dynamically create list of analog input tag paths including filter to only look at UDT instance tags
	path = '[PLC]AnalogInputs'
	fltr = {'tagType': "UdtInstance"}
	tags = system.tag.browse(path,fltr)
	tagPaths = [str(tag['fullPath']) + "/InputValue" for tag in tags]
	
	endTime = system.date.now()
	startTime = system.date.addHours(endTime,-24)
	
	AIdataset = system.tag.queryTagHistory(paths=tagPaths, startDate=startTime,
		endDate=endTime, returnSize=-1, aggregationMode="LastValue", returnFormat='Wide')
	
	AInInfoTag = '[PLC]AnalogInputCSV'
	system.tag.writeBlocking(AInInfoTag, AIdataset)
	
	csv = system.dataset.toCSV(dataset = AIdataset, showHeaders = True)
	
	filePath = "C:\\DailyCSVFiles\\analogin.csv"
	system.file.writeFile(filePath, csv)

```

This is what I am getting for the csv file. I want to replace the top row with different data

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

---

<div class="post-metadata">

**Author:** ![djs](https://avatars.discourse-cdn.com/v4/letter/d/e47774/32.png) [@djs](https://forum.inductiveautomation.com/u/djs)\
**Post date:** [October 21, 2022, 7:47pm UTC](https://forum.inductiveautomation.com/t/best-way-to-dynamically-create-a-header-row-for-conversion-to-csv-file-using-udt-tag-name/65549/2 "2022-10-21T19:47:39Z")

</div>

Probably the simplest way is to use the _columnNames_ parameter of the [system.tag.queryTagHistory](https://docs.inductiveautomation.com/display/DOC81/system.tag.queryTagHistory) function. You can pass a list of strings that will replace the default headers in the returning dataset.

---

<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:** [October 24, 2022, 12:03pm UTC](https://forum.inductiveautomation.com/t/best-way-to-dynamically-create-a-header-row-for-conversion-to-csv-file-using-udt-tag-name/65549/3 "2022-10-24T12:03:53Z")

</div>

> [@michael.black](#):
>
> ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/2/c/2c043cc939e5d91de1a0b706fe8ca2f1fd510fbe.png)

There's something slightly wrong with this code.  
You're doing the same loop twice, once with a for loop, and once inside it with a list comprehension.  
You can just remove line 9 and have the exact same result.  
If you want to add an item to that list, it's easy, just use `+`:

```python
headers = ['date'] + [h.value for h in system.tag.readBlocking(hTagPaths)]

```

Note that I changed `system.tag.readAll` to `system.tag.readBlocking`, which is the newer version.

> [@djs](#):
>
> You can pass a list of strings that will replace the default headers in the returning dataset.

He'll still need to obtain the strings, which I believe is what he was asking.  
But your method is much simpler than adding the headers manually to the csv.

---

<div class="post-metadata">

**Author:** ![djs](https://avatars.discourse-cdn.com/v4/letter/d/e47774/32.png) [@djs](https://forum.inductiveautomation.com/u/djs)\
**Post date:** [October 24, 2022, 12:59pm UTC](https://forum.inductiveautomation.com/t/best-way-to-dynamically-create-a-header-row-for-conversion-to-csv-file-using-udt-tag-name/65549/4 "2022-10-24T12:59:37Z")

</div>

Unless I'm misunderstanding something, the list of strings is obtained with the piece of code that you fixed:

```auto
headers = ['date'] + [h.value for h in system.tag.readBlocking(hTagPaths)]

```

All that has to be done is pass `headers` to the _columnNames_ parameter.

---

<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:** [October 24, 2022, 1:03pm UTC](https://forum.inductiveautomation.com/t/best-way-to-dynamically-create-a-header-row-for-conversion-to-csv-file-using-udt-tag-name/65549/5 "2022-10-24T13:03:13Z")

</div>

No misunderstanding here, we were both answering two different things: I answered the title of the thread, and you answered the content of the post.

---

<div class="post-metadata">

**Author:** ![michael.black](https://avatars.discourse-cdn.com/v4/letter/m/ee7513/32.png) [@michael.black](https://forum.inductiveautomation.com/u/michael.black)\
**Post date:** [October 24, 2022, 2:55pm UTC](https://forum.inductiveautomation.com/t/best-way-to-dynamically-create-a-header-row-for-conversion-to-csv-file-using-udt-tag-name/65549/6 "2022-10-24T14:55:01Z")

</div>

Thanks! I did implement your suggestions and did get what I wanted as a result. Now when I try to convert this to a csv file I get the following error. It doesn't make sense to me though considering both rows 1 and 2 have three columns each?

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/c/f/cf9f107639a696d089f0cec36eda0b6f26cd01e4.png)

---

<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:** [October 24, 2022, 3:03pm UTC](https://forum.inductiveautomation.com/t/best-way-to-dynamically-create-a-header-row-for-conversion-to-csv-file-using-udt-tag-name/65549/7 "2022-10-24T15:03:19Z")

</div>

`system.dataset.toDataSet()` expects that the data is a List of Lists. You are only providing a list.

```auto
dataset = system.dataset.toDataSet(headers, [totalizers])

```

This will work for the script you have in the image, but in reality you will probably need to produce a list of lists, where each row is represented by a list of columns.

P.S. It is really dificult to help with scripts when they are posted as screen shots. Please use the pre-formatted text option `</>`.

---

<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:** [October 24, 2022, 3:04pm UTC](https://forum.inductiveautomation.com/t/best-way-to-dynamically-create-a-header-row-for-conversion-to-csv-file-using-udt-tag-name/65549/8 "2022-10-24T15:04:04Z")

</div>

They don't.  
Your header is a 3 items list. And so is `totalizer`.

But `totalizer`'s first row, on the other hand...

You need to make it a list of lists. Just surround it in brackets and you'll be fine.

---

<div class="post-metadata">

**Author:** ![michael.black](https://avatars.discourse-cdn.com/v4/letter/m/ee7513/32.png) [@michael.black](https://forum.inductiveautomation.com/u/michael.black)\
**Post date:** [October 24, 2022, 3:07pm UTC](https://forum.inductiveautomation.com/t/best-way-to-dynamically-create-a-header-row-for-conversion-to-csv-file-using-udt-tag-name/65549/9 "2022-10-24T15:07:35Z")

</div>

Ah, thanks! I see.

---

<div class="post-metadata">

**Author:** ![michael.black](https://avatars.discourse-cdn.com/v4/letter/m/ee7513/32.png) [@michael.black](https://forum.inductiveautomation.com/u/michael.black)\
**Post date:** [October 24, 2022, 3:07pm UTC](https://forum.inductiveautomation.com/t/best-way-to-dynamically-create-a-header-row-for-conversion-to-csv-file-using-udt-tag-name/65549/10 "2022-10-24T15:07:44Z")

</div>

Thanks!
