Glad you came up a with a solution that works for you, if I may I’ll offer some direction on the xml route. I too am happy with csv files, but for Ignition 8 I thought I would try my hands at xml. XML is really just a string of text like a csv. The separators are really the only difference and you can export a tag from Ignition as an example to get the schema.
Since the UDT does all the heavy lifting, if you just need to create an instance of the tag then the XML is pretty simple, 2 tag example:
<Tags MinVersion="8.0.0">
<Tag name="V10001" type="UdtInstance">
<Property name="typeId">PLC/Device Control/Valve</Property>
</Tag>
<Tag name="V10005" type="UdtInstance">
<Property name="typeId">PLC/Device Control/Valve</Property>
</Tag>
</Tags>
I assume you iterate through rows in Excel to create your csv rows, same concept. I added carriage returns to the xml in the example above to make it easier to read. If I remove those carriage returns then it starts to look more like your csv file output where each line is a new tag:
<Tags MinVersion="8.0.0">
<Tag name="V10001" type="UdtInstance"><Property name="typeId">PLC/Device Control/Valve</Property></Tag>
<Tag name="V10005" type="UdtInstance"><Property name="typeId">PLC/Device Control/Valve</Property></Tag>
</Tags>
At this point, you should be able to see how a comma in the csv row could be replaced with the associated xml tag.
If you’re like me, and you use parameters to indirectly point to an OPC tag, or provide additional context for the tag we’ll need to add some additional xml to define the parameter and it’s corresponding value.
Example of a tag with parameter content:
<Tags MinVersion="8.0.0">
<Tag name="V10001" type="UdtInstance">
<Property name="typeId">PLC/Device Control/Valve</Property>
<Parameters>
<Property name="IO Address Main" type="String">C01R01:12:O.0</Property>
<Property name="IO Address Main ZSC" type="String"></Property>
<Property name="IO Address Main ZSO" type="String"></Property>
<Property name="IO Address Upper Lift" type="String"></Property>
<Property name="IO Address Lower Lift" type="String"></Property>
<Property name="Description" type="String">Steam Supply Valve </Property>
<Property name="Device Number" type="String">1</Property>
<Property name="OPC Server" type="String">Ignition OPC UA Server</Property>
<Property name="OPC Topic" type="String">Logix PLC</Property>
<Property name="ASI Address" type="String"></Property>
</Parameters>
</Tag>
</Tags>
Again, carriage returns have been added to make easier to read. Instead of adding an additional column, you just add the additional xml tag as a new row.
What it looks like in VBA, note “Q” is used to insert a quotation into the output file rather than getting mixed in with the string concatenation needed for the VBA:
xmlString = "<Tags MinVersion=" & Q & "8.0.0" & Q & ">" & vbCrLf
For i = 0 to ###
xmlString = xmlString & " <Tag name=" & Q & Tag & Q & " type=" & Q & "UdtInstance" & Q & "> " & vbCrLf
xmlString = xmlString & " <Property name=" & Q & "typeId" & Q & ">PLC/Device Control/" & ValveObjName & "</Property>" & vbCrLf
xmlString = xmlString & " <Parameters>" & vbCrLf
xmlString = xmlString & " <Property name=" & Q & "IO Address Main" & Q & " type=" & Q & "String" & Q & ">" & ioMain & "</Property>" & vbCrLf
xmlString = xmlString & " <Property name=" & Q & "IO Address Main ZSC" & Q & " type=" & Q & "String" & Q & ">" & ioZSC & "</Property>" & vbCrLf
xmlString = xmlString & " <Property name=" & Q & "IO Address Main ZSO" & Q & " type=" & Q & "String" & Q & ">" & ioZSO & "</Property>" & vbCrLf
xmlString = xmlString & " <Property name=" & Q & "IO Address Upper Lift" & Q & " type=" & Q & "String" & Q & ">" & ioUL & "</Property>" & vbCrLf
xmlString = xmlString & " <Property name=" & Q & "IO Address Lower Lift" & Q & " type=" & Q & "String" & Q & ">" & ioLL & "</Property>" & vbCrLf
xmlString = xmlString & " <Property name=" & Q & "Description" & Q & " type=" & Q & "String" & Q & ">" & Desc & "</Property>" & vbCrLf
xmlString = xmlString & " <Property name=" & Q & "Device Number" & Q & " type=" & Q & "String" & Q & ">" & DeviceNum & "</Property>" & vbCrLf
xmlString = xmlString & " <Property name=" & Q & "OPC Server" & Q & " type=" & Q & "String" & Q & ">" & rlOPCServer & "</Property>" & vbCrLf
xmlString = xmlString & " <Property name=" & Q & "OPC Topic" & Q & " type=" & Q & "String" & Q & ">" & ignOPCTopic & "</Property>" & vbCrLf
xmlString = xmlString & " <Property name=" & Q & "ASI Address" & Q & " type=" & Q & "String" & Q & ">" & ASIAddy & "</Property>" & vbCrLf
xmlString = xmlString & " </Parameters>" & vbCrLf
xmlString = xmlString & " </Tag>" & vbCrLf
Next
xmlString = xmlString & "</Tags>"
Save to a file...
My VBA is just creating a long character string. Once the file has been created then I can use the native import right into the destination folder I choose.