Adding Attributes to XML node using VBA
-
Hi Friends, I am creating an xml file with excel vba. Now I wanted to add attributes to the xml child nodes..Please kindly help.. Thanks in advance Regards, Priya.
One option would be to use MS XML Core Services COM. Add a reference to the MS XML V6 library from the Tools Reference menu in the VBA editor. You can then refere to the MSDN documentation on how to use this with VB. http://msdn.microsoft.com/en-us/library/ms763742(v=VS.85).aspx[^] The example below will load an XML file from hdd.
Public Sub editXML()
'To use this add a com reference to MS XML, V6 from Tools References menu'Create a new XML DOM Document
Dim xmlfile As New DOMDocument'Load the xml data from file
xmlfile.Load ("c:\users\dave auld\desktop\test.xml")'Do what you want to do with the XML file
End Sub
Dave Don't forget to rate messages!
Find Me On: Web|Facebook|Twitter|LinkedIn
Waving? dave.m.auld[at]googlewave.com -
One option would be to use MS XML Core Services COM. Add a reference to the MS XML V6 library from the Tools Reference menu in the VBA editor. You can then refere to the MSDN documentation on how to use this with VB. http://msdn.microsoft.com/en-us/library/ms763742(v=VS.85).aspx[^] The example below will load an XML file from hdd.
Public Sub editXML()
'To use this add a com reference to MS XML, V6 from Tools References menu'Create a new XML DOM Document
Dim xmlfile As New DOMDocument'Load the xml data from file
xmlfile.Load ("c:\users\dave auld\desktop\test.xml")'Do what you want to do with the XML file
End Sub
Dave Don't forget to rate messages!
Find Me On: Web|Facebook|Twitter|LinkedIn
Waving? dave.m.auld[at]googlewave.comHi Thanks. WIthout using XNL COM, I tried the following by directly giving in the tag line itself. /Policy_Years Attribute=""1,1,0,1,16711680,2,0,0,1,16711680,0,0,0,0,0,0.5,10,Arial,1"" Attribute2=""""/Policy_Years-" The above line I am spliting with /, then the first tag will be 10 But when i give attribute like above I am getting error: A name contained an invalid character. Error processing resource 'file:///D:/PIMSlite/Output/PolicyLocation.xml'. Line 15,... </Policy_Years Attribute="1,1,0,1,16711680,2,0,0,1,16711680,0,0,0,0,0,0.5,10,Arial,1" Attribute2=""> ---------------^ Is any error in the line where I have specified Attribute.. Thanks again. Regards, Priya.
-
Hi Thanks. WIthout using XNL COM, I tried the following by directly giving in the tag line itself. /Policy_Years Attribute=""1,1,0,1,16711680,2,0,0,1,16711680,0,0,0,0,0,0.5,10,Arial,1"" Attribute2=""""/Policy_Years-" The above line I am spliting with /, then the first tag will be 10 But when i give attribute like above I am getting error: A name contained an invalid character. Error processing resource 'file:///D:/PIMSlite/Output/PolicyLocation.xml'. Line 15,... </Policy_Years Attribute="1,1,0,1,16711680,2,0,0,1,16711680,0,0,0,0,0,0.5,10,Arial,1" Attribute2=""> ---------------^ Is any error in the line where I have specified Attribute.. Thanks again. Regards, Priya.
You don't put attributes in the closing tags, you put them in the opening tag; <tag attribute="some value">tag value</tag> also, if you look at the first line you have 2 double quotes which is not valid. Dave <i>Don't forget to rate messages!</i><br><strong>Find Me On:</strong> <a href="http://www.dave-auld.net/" target="_blank">Web</a>|<a href="http://www.facebook.com/dave.m.auld/" target="_blank">Facebook</a>|<a href="http://www.twitter.com/daveauld/" target="_blank">Twitter</a>|<a href="http://www.linkedin.com/in/daveauld" target="_blank">LinkedIn</a><br>Waving? dave.m.auld[at]googlewave.com</br></br>
-
You don't put attributes in the closing tags, you put them in the opening tag; <tag attribute="some value">tag value</tag> also, if you look at the first line you have 2 double quotes which is not valid. Dave <i>Don't forget to rate messages!</i><br><strong>Find Me On:</strong> <a href="http://www.dave-auld.net/" target="_blank">Web</a>|<a href="http://www.facebook.com/dave.m.auld/" target="_blank">Facebook</a>|<a href="http://www.twitter.com/daveauld/" target="_blank">Twitter</a>|<a href="http://www.linkedin.com/in/daveauld" target="_blank">LinkedIn</a><br>Waving? dave.m.auld[at]googlewave.com</br></br>
-
Hi, Thanks for your reply. Actually I am keeping attribute only in opening tag and also i am keeping "" since in the code it is expecting. If i simply give value it is giving error.It is not accepting from code. Please help. Regards, Priya.
-
Hi Dave, Thanks again!.. Here is the code i am using for conversion. Function fGenerateXML(rngData As Range, rootNodeName As String, sn As Integer, ts As Integer) As String On Error Resume Next '=============================================================== ' XML Tags ' Table Const HEADER As String = "<?xml version=""1.0""?>" Dim TAG_BEGIN As String Dim TAG_END As String 'Dim strTAG_END As String Const NODE_DELIMITER As String = "/" '=============================================================== Dim intColCount As Integer Dim intRowCount As Integer Dim intColCounter As Integer Dim intRowCounter As Integer Dim rngCell As Range Dim strXML As String 'Dim str As String 'str = "" 'strTAG_END = "" ' Initial table tag... Dim rNode() As String rNode = Split(rootNodeName, NODE_DELIMITER) If sn = 0 Then TAG_BEGIN = vbCrLf & "<" & rNode(0) & ">" & vbCrLf & "<" & rNode(1) & ">" Else TAG_BEGIN = vbCrLf & "<" & rNode(1) & ">" & vbCrLf End If 'determining if it is final sheet for concatenation If sn = ts Then TAG_END = vbCrLf & "</" & rNode(1) & ">" & vbCrLf & "</" & rNode(0) & ">" Else TAG_END = vbCrLf & "</" & rNode(1) & ">" & vbCrLf End If 'TAG_BEGIN = vbCrLf & "<" & rootNodeName & ">" & vbCrLf 'TAG_END = vbCrLf & "</" & rootNodeName & ">" & vbCrLf If sn = 0 Then strXML = HEADER End If strXML = strXML & TAG_BEGIN With rngData ' Discover dimensions of the data we ' will be dealing with... intColCount = .Columns.Count intRowCount = .Rows.Count Dim strColNames() As String ReDim strColNames(intColCount) ' First Row is the Field/Tag names If intRowCount >= 1 Then ' Loop accross columns... For intColCounter = 1 To intColCount ' Mark the cell under current scrutiny by setting ' an object variable... Set rngCell = .Cells(1, intColCounter) '
-
Hi Dave, Thanks again!.. Here is the code i am using for conversion. Function fGenerateXML(rngData As Range, rootNodeName As String, sn As Integer, ts As Integer) As String On Error Resume Next '=============================================================== ' XML Tags ' Table Const HEADER As String = "<?xml version=""1.0""?>" Dim TAG_BEGIN As String Dim TAG_END As String 'Dim strTAG_END As String Const NODE_DELIMITER As String = "/" '=============================================================== Dim intColCount As Integer Dim intRowCount As Integer Dim intColCounter As Integer Dim intRowCounter As Integer Dim rngCell As Range Dim strXML As String 'Dim str As String 'str = "" 'strTAG_END = "" ' Initial table tag... Dim rNode() As String rNode = Split(rootNodeName, NODE_DELIMITER) If sn = 0 Then TAG_BEGIN = vbCrLf & "<" & rNode(0) & ">" & vbCrLf & "<" & rNode(1) & ">" Else TAG_BEGIN = vbCrLf & "<" & rNode(1) & ">" & vbCrLf End If 'determining if it is final sheet for concatenation If sn = ts Then TAG_END = vbCrLf & "</" & rNode(1) & ">" & vbCrLf & "</" & rNode(0) & ">" Else TAG_END = vbCrLf & "</" & rNode(1) & ">" & vbCrLf End If 'TAG_BEGIN = vbCrLf & "<" & rootNodeName & ">" & vbCrLf 'TAG_END = vbCrLf & "</" & rootNodeName & ">" & vbCrLf If sn = 0 Then strXML = HEADER End If strXML = strXML & TAG_BEGIN With rngData ' Discover dimensions of the data we ' will be dealing with... intColCount = .Columns.Count intRowCount = .Rows.Count Dim strColNames() As String ReDim strColNames(intColCount) ' First Row is the Field/Tag names If intRowCount >= 1 Then ' Loop accross columns... For intColCounter = 1 To intColCount ' Mark the cell under current scrutiny by setting ' an object variable... Set rngCell = .Cells(1, intColCounter) '
- can you edit your message and put the code in a code block with an attribute lang="vb", so it formats something more readable! 2) Do not user On Error Resume Next, how else will you trap problems Change to On Error Goto ERROR_HANDLER, then at the end of the function put;
' Return the HTML string...
fGenerateXML = strXML
Exit FunctionERROR_HANDLER:
MSGBOX "Error: " & Err.description
End Function
-
- can you edit your message and put the code in a code block with an attribute lang="vb", so it formats something more readable! 2) Do not user On Error Resume Next, how else will you trap problems Change to On Error Goto ERROR_HANDLER, then at the end of the function put;
' Return the HTML string...
fGenerateXML = strXML
Exit FunctionERROR_HANDLER:
MSGBOX "Error: " & Err.description
End Function
Hi Dave, Ya sure I will split this function. I wanted to add attribute which i have posted in my first post to the tags highlighted in bold. Appreaciate u lot..pls help..its urgent..
Function fGenerateXML(rngData As Range, rootNodeName As String, sn As Integer, ts As Integer) As String
On Error Resume Next
'===============================================================
' XML Tags
' TableConst HEADER As String = "<?xml version=""1.0""?>"
Dim TAG_BEGIN As String
Dim TAG_END As String
'Dim strTAG_END As String
Const NODE_DELIMITER As String = "/"'===============================================================
Dim intColCount As Integer
Dim intRowCount As Integer
Dim intColCounter As Integer
Dim intRowCounter As IntegerDim rngCell As Range
Dim strXML As String
'Dim str As String
'str = ""
'strTAG_END = ""' Initial table tag...
Dim rNode() As String
rNode = Split(rootNodeName, NODE_DELIMITER)If sn = 0 Then
TAG_BEGIN = vbCrLf & "<" & rNode(0) & ">" & vbCrLf & "<" & rNode(1) & ">"
Else
TAG_BEGIN = vbCrLf & "<" & rNode(1) & ">" & vbCrLf
End If'determining if it is final sheet for concatenation
If sn = ts Then
TAG_END = vbCrLf & "</" & rNode(1) & ">" & vbCrLf & "</" & rNode(0) & ">"
Else
TAG_END = vbCrLf & "</" & rNode(1) & ">" & vbCrLf
End If'TAG_BEGIN = vbCrLf & "<" & rootNodeName & ">" & vbCrLf
'TAG_END = vbCrLf & "</" & rootNodeName & ">" & vbCrLfIf sn = 0 Then
strXML = HEADER
End If
strXML = strXML & TAG_BEGINWith rngData
' Discover dimensions of the data we
' will be dealing with...
intColCount = .Columns.CountintRowCount = .Rows.Count
Dim strColNames() As String
ReDim strColNames(intColCount)
' First Row is the Field/Tag names
If intRowCount >= 1 Then' Loop accross columns...
For intColCounter = 1 To intColCount' Mark the cell under current scrutiny by setting
' an object variable...
Set rngCell = .Cells(1, intColCounter)' Is the cell merged?..
If Not rngCell.MergeArea.Address = _
rngCell.Address ThenMsgBox ("!! Cell Merged ... Invalid format")
Exit FunctionEnd If
'Sangeetha
strColNames(intColCounter) = rngCell.Text'loop thro the sheets for header
If rNode(1) = "Actual_Loss_History" Or rNode(1) = "As_If_Loss_History" ThenIf strColNames(intColCounter) = "Policy Years
-
Hi Dave, Ya sure I will split this function. I wanted to add attribute which i have posted in my first post to the tags highlighted in bold. Appreaciate u lot..pls help..its urgent..
Function fGenerateXML(rngData As Range, rootNodeName As String, sn As Integer, ts As Integer) As String
On Error Resume Next
'===============================================================
' XML Tags
' TableConst HEADER As String = "<?xml version=""1.0""?>"
Dim TAG_BEGIN As String
Dim TAG_END As String
'Dim strTAG_END As String
Const NODE_DELIMITER As String = "/"'===============================================================
Dim intColCount As Integer
Dim intRowCount As Integer
Dim intColCounter As Integer
Dim intRowCounter As IntegerDim rngCell As Range
Dim strXML As String
'Dim str As String
'str = ""
'strTAG_END = ""' Initial table tag...
Dim rNode() As String
rNode = Split(rootNodeName, NODE_DELIMITER)If sn = 0 Then
TAG_BEGIN = vbCrLf & "<" & rNode(0) & ">" & vbCrLf & "<" & rNode(1) & ">"
Else
TAG_BEGIN = vbCrLf & "<" & rNode(1) & ">" & vbCrLf
End If'determining if it is final sheet for concatenation
If sn = ts Then
TAG_END = vbCrLf & "</" & rNode(1) & ">" & vbCrLf & "</" & rNode(0) & ">"
Else
TAG_END = vbCrLf & "</" & rNode(1) & ">" & vbCrLf
End If'TAG_BEGIN = vbCrLf & "<" & rootNodeName & ">" & vbCrLf
'TAG_END = vbCrLf & "</" & rootNodeName & ">" & vbCrLfIf sn = 0 Then
strXML = HEADER
End If
strXML = strXML & TAG_BEGINWith rngData
' Discover dimensions of the data we
' will be dealing with...
intColCount = .Columns.CountintRowCount = .Rows.Count
Dim strColNames() As String
ReDim strColNames(intColCount)
' First Row is the Field/Tag names
If intRowCount >= 1 Then' Loop accross columns...
For intColCounter = 1 To intColCount' Mark the cell under current scrutiny by setting
' an object variable...
Set rngCell = .Cells(1, intColCounter)' Is the cell merged?..
If Not rngCell.MergeArea.Address = _
rngCell.Address ThenMsgBox ("!! Cell Merged ... Invalid format")
Exit FunctionEnd If
'Sangeetha
strColNames(intColCounter) = rngCell.Text'loop thro the sheets for header
If rNode(1) = "Actual_Loss_History" Or rNode(1) = "As_If_Loss_History" ThenIf strColNames(intColCounter) = "Policy Years
You have some wierdness going on around your arrays, either i am missing something or your code is wrong, here are all the
NodeStack
references; Line 141:Dim NodeStack() as String
Line 168:ReDim NodeStack(0)
Line 229:For i = 1 To UBound(Nodes)
If i <= UBound(NodeStack) Then
If Trim(Nodes(i)) <> Trim(NodeStack(i)) Then
'not match
'MsgBox (Nodes(i) & "," & NodeStack(i))
MatchAll = False
Exit For
End If
Else
MatchAll = False
Exit For
End If
NextUp until this point NodeStack does not contain any values, it is a completly empty array, but yet you are trying to compare values etc from it. It is not until later in your code that you give it any values by
NodeStack = Nodes
, and that is only if Nodes does actually contain values. I suspect your code is throwing exceptions, but because you currentOn Error Resume Next
you are not seeing them.Dave Don't forget to rate messages!
Find Me On: Web|Facebook|Twitter|LinkedIn
Waving? dave.m.auld[at]googlewave.com -
You have some wierdness going on around your arrays, either i am missing something or your code is wrong, here are all the
NodeStack
references; Line 141:Dim NodeStack() as String
Line 168:ReDim NodeStack(0)
Line 229:For i = 1 To UBound(Nodes)
If i <= UBound(NodeStack) Then
If Trim(Nodes(i)) <> Trim(NodeStack(i)) Then
'not match
'MsgBox (Nodes(i) & "," & NodeStack(i))
MatchAll = False
Exit For
End If
Else
MatchAll = False
Exit For
End If
NextUp until this point NodeStack does not contain any values, it is a completly empty array, but yet you are trying to compare values etc from it. It is not until later in your code that you give it any values by
NodeStack = Nodes
, and that is only if Nodes does actually contain values. I suspect your code is throwing exceptions, but because you currentOn Error Resume Next
you are not seeing them.Dave Don't forget to rate messages!
Find Me On: Web|Facebook|Twitter|LinkedIn
Waving? dave.m.auld[at]googlewave.comHi, Code is working fine. I tried by removing on error resume next. Problem is that if i add attribute to that tags which is like Attribute="1,1,1,..." then it is giving error. I am not sure the way to keep the attributes there. Or is there any way after generation of an xml, can we open that xml file and add attributes to that? Regards, Priya.
-
Hi, Code is working fine. I tried by removing on error resume next. Problem is that if i add attribute to that tags which is like Attribute="1,1,1,..." then it is giving error. I am not sure the way to keep the attributes there. Or is there any way after generation of an xml, can we open that xml file and add attributes to that? Regards, Priya.
I had a think about what i had written, and no it won't throw an excpetion, All that will happen is MatchAll will always be False so that code is effectively doing nothing (because 1 or higher is always greater than 0). All you are doing is generating a bunch of strings and bolting them altogether. After you generate the xml and the function exits, have you had a look at the XML file to see what it looks like?
Dave Don't forget to rate messages!
Find Me On: Web|Facebook|Twitter|LinkedIn
Waving? dave.m.auld[at]googlewave.com -
I had a think about what i had written, and no it won't throw an excpetion, All that will happen is MatchAll will always be False so that code is effectively doing nothing (because 1 or higher is always greater than 0). All you are doing is generating a bunch of strings and bolting them altogether. After you generate the xml and the function exits, have you had a look at the XML file to see what it looks like?
Dave Don't forget to rate messages!
Find Me On: Web|Facebook|Twitter|LinkedIn
Waving? dave.m.auld[at]googlewave.com -
In that case all you are doing now then is adding the attributes to the node. Create a helper function like;
getNodeAttributes(node as integer) as string
In it, test node to see which attributes you need to build, then return them in the function, if the node does not need any attributes, then return an empty string. Then modify;strXML = strXML & "<" & Nodes(t) & ">"
tostrXML = strXML & "<" & Nodes(t) & getNodeAttributes(t) & ">"
simples........Dave Don't forget to rate messages!
Find Me On: Web|Facebook|Twitter|LinkedIn
Waving? dave.m.auld[at]googlewave.com -
In that case all you are doing now then is adding the attributes to the node. Create a helper function like;
getNodeAttributes(node as integer) as string
In it, test node to see which attributes you need to build, then return them in the function, if the node does not need any attributes, then return an empty string. Then modify;strXML = strXML & "<" & Nodes(t) & ">"
tostrXML = strXML & "<" & Nodes(t) & getNodeAttributes(t) & ">"
simples........Dave Don't forget to rate messages!
Find Me On: Web|Facebook|Twitter|LinkedIn
Waving? dave.m.auld[at]googlewave.comHi Dave, Thanks lot. I tried adding the funtion like :
Function getNodeAttributes(node As String) As String
Dim str_att As String
If node = "Policy_Years" Then
str_att = "Attribute=" & "1,1,0,1,16711680,2,0,0,1,16711680,0,0,0,0,0,0.5,10,Arial,1"" Attribute2="""
End If
End Functionand also changed
strXML = strXML & "<" & Nodes(t) & getNodeAttributes(Nodes(t)) & ">"
Just tried assigning attribute to only one node. But I am not getting any in the output for the tag Policy_Years. Please Help.. Regards, Priya.
-
Hi Dave, Thanks lot. I tried adding the funtion like :
Function getNodeAttributes(node As String) As String
Dim str_att As String
If node = "Policy_Years" Then
str_att = "Attribute=" & "1,1,0,1,16711680,2,0,0,1,16711680,0,0,0,0,0,0.5,10,Arial,1"" Attribute2="""
End If
End Functionand also changed
strXML = strXML & "<" & Nodes(t) & getNodeAttributes(Nodes(t)) & ">"
Just tried assigning attribute to only one node. But I am not getting any in the output for the tag Policy_Years. Please Help.. Regards, Priya.
Of course you wont, your passing across the node index not the node name;
priyaahh wrote:
strXML = strXML & "<" & Nodes(t) & getNodeAttributes(Nodes(t)) & ">"
change to;
strXML = strXML & "<" & Nodes(t) & getNodeAttributes("Policy_Years") & ">"
Dave Don't forget to rate messages!
Find Me On: Web|Facebook|Twitter|LinkedIn
Waving? dave.m.auld[at]googlewave.com -
Of course you wont, your passing across the node index not the node name;
priyaahh wrote:
strXML = strXML & "<" & Nodes(t) & getNodeAttributes(Nodes(t)) & ">"
change to;
strXML = strXML & "<" & Nodes(t) & getNodeAttributes("Policy_Years") & ">"
Dave Don't forget to rate messages!
Find Me On: Web|Facebook|Twitter|LinkedIn
Waving? dave.m.auld[at]googlewave.com -
Hi Dave, Still no its not showing... :-( Is there any other way to implement this? Regards, Priya.
Well i fail to see what you are doing wrong. Don't give in! At the end of the day, all you are doing is simple string manipulation, it doesn't matter if it is in XML format or any other text based format. If your output XML file shows the attributes after your text generation then it is working. If your output does not show the attributes, then your code is wrong. You maybe need to start putting in extra breakpoints, debug.print(), or message boxes statements through your code until you can find out what is going on. everytime you generate a node or an attribute use these statements to see what the string is before and after. That way you will be able to see what you are getting versus what you are expecting at each stage. This is basic troubleshooting. As i have stated before your function is way to big, and you really need to restructure and break out lots of smaller helper functions which can then be called to piece the final text XML string. As i say, this is basic string manipulation, so something obvious is wrong somewhere!
Dave Don't forget to rate messages!
Find Me On: Web|Facebook|Twitter|LinkedIn
Waving? dave.m.auld[at]googlewave.com -
Well i fail to see what you are doing wrong. Don't give in! At the end of the day, all you are doing is simple string manipulation, it doesn't matter if it is in XML format or any other text based format. If your output XML file shows the attributes after your text generation then it is working. If your output does not show the attributes, then your code is wrong. You maybe need to start putting in extra breakpoints, debug.print(), or message boxes statements through your code until you can find out what is going on. everytime you generate a node or an attribute use these statements to see what the string is before and after. That way you will be able to see what you are getting versus what you are expecting at each stage. This is basic troubleshooting. As i have stated before your function is way to big, and you really need to restructure and break out lots of smaller helper functions which can then be called to piece the final text XML string. As i say, this is basic string manipulation, so something obvious is wrong somewhere!
Dave Don't forget to rate messages!
Find Me On: Web|Facebook|Twitter|LinkedIn
Waving? dave.m.auld[at]googlewave.comHi Dave, Thanks really!... I am planning another way. TO open the xml file generated and then adding attributes to elements. If you dont mind can you please give me example for this. Yes i remember, you have sent me the reference to DOM Methods for implementing this. But at this point of time with so much stress i cannt think of anything and this have to completed asap i do not have even hours of time...pls pls help.. Thanks in advance..reply if ur online Regards, Priya
-
Hi Dave, Thanks really!... I am planning another way. TO open the xml file generated and then adding attributes to elements. If you dont mind can you please give me example for this. Yes i remember, you have sent me the reference to DOM Methods for implementing this. But at this point of time with so much stress i cannt think of anything and this have to completed asap i do not have even hours of time...pls pls help.. Thanks in advance..reply if ur online Regards, Priya
No that is not the way to go, you are making things harder for your self, you will then have to read, parse, inject , save strings. You have already got a function that generates a valid XML file, so you are 99% of the way there. Have you done what i have suggested with regards to breakpoints and or debug statements? strategically place them in your code, and you will see where the attributes you have added are then disappearing (if they are disappearing at all that is). Also, in the previous message did you replace both instances of the code where you inject the attribute function? you have 2 lines that do it depending on the state of some value. Did you please a debug statement in your attribute function to prove it is being called? Did you add a debug.print statement to see what it was adding to the string?
Dave Don't forget to rate messages!
Find Me On: Web|Facebook|Twitter|LinkedIn
Waving? dave.m.auld[at]googlewave.com