Parsing Through XML File Excel VBA objDOM not Working - excel

Trying to parse thorugh an XML file with VBA and print the results to an Excel spreadsheet. But whenever I get to creating a list with the following code it doesn't create one and I can't figure out why.
Set Songs = objDOM.SelectNodes("/channel/item")
Full code and XML is below
Function fnReadXMLByTags()
'Code From: https://excel-macro.tutorialhorizon.com/vba-excel-read-xml-by-looping-through-nodes/
'And Here: https://desmondoshiwambo.wordpress.com/2012/07/03/how-to-load-xml-from-a-local-file-with-msxml2-domdocument-6-0-and-loadxml-using-vba/
Dim mainWorkBook As Workbook
Set mainWorkBook = ActiveWorkbook
mainWorkBook.Sheets("XML_Parser").Range("A:C").Clear
Dim intFile As Integer
Dim strTemp As String
Dim strXML As String
Dim strOrderText As String
Dim objDOM As Object
Dim Songs As Object
XMLFileName = ThisWorkbook.Path & "\PlaylistFeed.xml"
'Open file
intFile = FreeFile
Open XMLFileName For Input As intFile
strXML = ""
'Load XML into string strXML
While Not EOF(intFile)
Line Input #intFile, strTemp
strXML = strXML & strTemp
Wend
Close intFile
'Load the XML into DOMDocument object
Set objDOM = CreateObject("MSXML2.DOMDocument.6.0")
objDOM.LoadXML strXML
mainWorkBook.Sheets("XML_Parser").Range("A1,B1,C1,D1").Interior.ColorIndex = 40
mainWorkBook.Sheets("XML_Parser").Range("A1,B1,C1,D1").Borders.Value = 1
mainWorkBook.Sheets("XML_Parser").Range("A" & 1).Value = "Song Number"
mainWorkBook.Sheets("XML_Parser").Range("B" & 1).Value = "Tag Number"
mainWorkBook.Sheets("XML_Parser").Range("C" & 1).Value = "Item Node"
mainWorkBook.Sheets("XML_Parser").Range("D" & 1).Value = "Value"
Set Songs = objDOM.SelectNodes("/channel/item")
mainWorkBook.Sheets("XML_Parser").Range("A" & 2).Value = Songs.Length 'always says 0
intCounter = 2
For i = 0 To Songs.Length - 1
For j = 0 To Songs(i).ChildNodes.Length - 1
mainWorkBook.Sheets("XML_Parser").Range("A" & intCounter).Value = i + 1
mainWorkBook.Sheets("XML_Parser").Range("B" & intCounter).Value = j + 1
mainWorkBook.Sheets("XML_Parser").Range("C" & intCounter).Value = Songs(i).ChildNodes(j).tagname
mainWorkBook.Sheets("XML_Parser").Range("D" & intCounter).Value = Songs(i).ChildNodes(j).Text
mainWorkBook.Sheets("XML_Parser").Range("A" & intCounter).Borders.Value = 1
mainWorkBook.Sheets("XML_Parser").Range("B" & intCounter).Borders.Value = 1
mainWorkBook.Sheets("XML_Parser").Range("C" & intCounter).Borders.Value = 1
mainWorkBook.Sheets("XML_Parser").Range("D" & intCounter).Borders.Value = 1
intCounter = intCounter + 1
mainWorkBook.Sheets("XML_Parser").Range("A" & intCounter, "B" & intCounter, "C" & intCounter, "D" & intCounter).Interior.ColorIndex = 40
mainWorkBook.Sheets("XML_Parser").Range("A" & intCounter, "B" & intCounter, "C" & intCounter, "D" & intCounter).Borders.Value = 1
mainWorkBook.Sheets("XML_Parser").Range("A" & intCounter).Value = "Song Number"
mainWorkBook.Sheets("XML_Parser").Range("B" & intCounter).Value = "Tag Number"
mainWorkBook.Sheets("XML_Parser").Range("C" & intCounter).Value = "Item Node"
mainWorkBook.Sheets("XML_Parser").Range("D" & intCounter).Value = "Value"
Next
intCounter = intCounter + 1
Next
End Function
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
<channel>
<title>WTMD Playlist</title>
<link>http://www.wtmd.org</link>
<description>Recently Played Songs at WTMD</description>
<item>
<title>Son Volt - Drown</title>
<link>
http://www.amazon.com/exec/obidos/external-search?tag=wt897fmrafomu-20&index=digital-music-track&keyword=Son+Volt%2BDrown
</link>
<description>Album: Trace</description>
<pubDate>Mon, 03 Dec 2012 20:09:44 GMT</pubDate>
<guid>
http://www.amazon.com/exec/obidos/external-search?tag=wt897fmrafomu-20&index=digital-music-track&keyword=Son+Volt%2BDrown
</guid>
<dc:date>2012-12-03T20:09:44Z</dc:date>
</item>
<item>
<title>Allen Stone - Sleep</title>
<link>
http://www.amazon.com/exec/obidos/external-search?tag=wt897fmrafomu-20&index=digital-music-track&keyword=Allen+Stone%2BSleep
</link>
<description>Album: Allen Stone</description>
<pubDate>Mon, 03 Dec 2012 20:07:19 GMT</pubDate>
<guid>
http://www.amazon.com/exec/obidos/external-search?tag=wt897fmrafomu-20&index=digital-music-track&keyword=Allen+Stone%2BSleep
</guid>
<dc:date>2012-12-03T20:07:19Z</dc:date>
</item>
When testing the length the Songs list always comes at zero and I can't figure out why. Everything I've tried either has the same problem or gives an error.

As QHarr pointed out, in parts of the XML document, you have text containing the & symbol (ampersand), for example:
tag=wt897fmrafomu-20&index=digital-music-track
The & symbol on its own is not allowed as part of well formed XML and needs to be replaced by the entity reference &:
tag=wt897fmrafomu-20&index=digital-music-track
The XPath query in the call to selectNodes is also incorrect. You have:
Set Songs = objDOM.SelectNodes("/channel/item")
That would only be correct if "channel" was the root node of the XML document. In fact, "rss" is the root node so you would need to use this instead:
Set Songs = objDOM.SelectNodes("/rss/channel/item")
The calls to set the color index and borders are incorrect. You should have this instead:
mainWorkBook.Sheets("XML_Parser").Range("A" & intCounter & ":D" & intCounter).Interior.ColorIndex = 40
mainWorkBook.Sheets("XML_Parser").Range("A" & intCounter & ":D" & intCounter).Borders.Value = 1
The XML document as shown in the question is incomplete so I'm assuming that the remaining tags were added to close the "channel" and "rss" tags. I'm also assuming that an XML declaration was added at the start:
<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
<channel>
<title>WTMD Playlist</title>
<link>http://www.wtmd.org</link>
<description>Recently Played Songs at WTMD</description>
<item>
<title>Son Volt - Drown</title>
<link>
http://www.amazon.com/exec/obidos/external-search?tag=wt897fmrafomu-20&index=digital-music-track&keyword=Son+Volt%2BDrown
</link>
<description>Album: Trace</description>
<pubDate>Mon, 03 Dec 2012 20:09:44 GMT</pubDate>
<guid>
http://www.amazon.com/exec/obidos/external-search?tag=wt897fmrafomu-20&index=digital-music-track&keyword=Son+Volt%2BDrown
</guid>
<dc:date>2012-12-03T20:09:44Z</dc:date>
</item>
<item>
<title>Allen Stone - Sleep</title>
<link>
http://www.amazon.com/exec/obidos/external-search?tag=wt897fmrafomu-20&index=digital-music-track&keyword=Allen+Stone%2BSleep
</link>
<description>Album: Allen Stone</description>
<pubDate>Mon, 03 Dec 2012 20:07:19 GMT</pubDate>
<guid>
http://www.amazon.com/exec/obidos/external-search?tag=wt897fmrafomu-20&index=digital-music-track&keyword=Allen+Stone%2BSleep
</guid>
<dc:date>2012-12-03T20:07:19Z</dc:date>
</item>
</channel>
</rss>

Related

Having trouble with XML phase on VBA Excel

I need to parse a XML file having the structure as follows: (I can't show the data as it is confidential)
<?xml version="1.0" encoding="UTF-8"?>
<GACDWBulkLoadInterface xsi:schemaLocation="http://www.example.org/GACDWSchema GACDWSchema.xsd" xmlns="http://www.example.org/GACDWSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<BLConfiguration>
<BLProperties>
<BLProperty>
<key>isEmpty</key>
<value xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:boolean">true</value>
</BLProperty>
</BLProperties>
<version>api-ag-1.1.68-20210315-43</version>
</BLConfiguration>
<Customer>
<CustomerID></CustomerID>
<Customer_Name></Customer_Name>
<ISOCountryCode></ISOCountryCode>
<customerType></customerType>
<dataSourceProvider></dataSourceProvider>
<function></function>
<TopLevelCI>
<Contact Action="Create">
<Id>4</Id>
<artifactType></artifactType>
<contactType></contactType>
<email></email>
<firstName></firstName>
<lastName></lastName>
<userID></userID>
<ChildCI/>
</Contact>
<PhysicalComputerSystem Action="Create">
<Id>2</Id>
<artifactType></artifactType>
<assetLifeCycleState></assetLifeCycleState>
<category></category>
<ciLifeCycleState></ciLifeCycleState>
<custname></custname>
<description></description>
<discontinuedDate></discontinuedDate>
<machineType></machineType>
<managed></managed>
<manufacturer></manufacturer>
<model></model>
<serialNumber></serialNumber>
<virtualFlag></virtualFlag>
<ChildCI>
<PhysicalComputerSystemContact Action="Create">
<contactUID></contactUID>
</PhysicalComputerSystemContact>
<PhysicalComputerSystemLocation Action="Create">
<buildingID></buildingID>
<buildingName></buildingName>
<city></city>
<countryName></countryName>
<isoCountryCode></isoCountryCode>
<postalCode></postalCode>
<siteName></siteName>
<stateProvince></stateProvince>
<streetAddress></streetAddress>
</PhysicalComputerSystemLocation>
</ChildCI>
</PhysicalComputerSystem>
<OperatingSystem Action="Create">
<Id>1</Id>
<aliasHostname></aliasHostname>
<artifactType></artifactType>
<assetLifeCycleState></assetLifeCycleState>
<backupContr></backupContr>
<barSaId></barSaId>
<cacfCustomGroup></cacfCustomGroup>
<category></category>
<ciLifeCycleState></ciLifeCycleState>
<classification></classification>
<cpuCount></cpuCount>
<description></description>
<discontinuedDate></discontinuedDate>
<fqhn></fqhn>
<hostsystemID></hostsystemID>
<hostsystemType></hostsystemType>
<installationDate></installationDate>
<ipAddress></ipAddress>
<majorBusProc></majorBusProc>
<managed></managed>
<memory></memory>
<memoryUnit></memoryUnit>
<osModLevel></osModLevel>
<osName></osName>
<osBuildNumber></osBuildNumber>
<osProvider></osProvider>
<osRelease></osRelease>
<osVersion></osVersion>
<prodDate></prodDate>
<purgeDate></purgeDate>
<purpose></purpose>
<securityClass></securityClass>
<serverType></serverType>
<supportEnddate></supportEnddate>
<useAliasHostname></useAliasHostname>
<virtualFlag></virtualFlag>
<ChildCI>
<OperatingSystemContact Action="Create">
<contactUID></contactUID>
</OperatingSystemContact>
<OperatingSystemEnvironmentProfile Action="Create">
<authFlag></authFlag>
<authExceptDate></authExceptDate>
<authExceptReasonCode></authExceptReasonCode>
<authExceptText></authExceptText>
<disasterRecSys></disasterRecSys>
<domain></domain>
<extUsersMax></extUsersMax>
<hcAutoInterv></hcAutoInterv>
<hcExceptDate></hcExceptDate>
<hcExceptReasonCode></hcExceptReasonCode>
<hcExceptText></hcExceptText>
<hcUnit></hcUnit>
<healthchAutoFlag></healthchAutoFlag>
<highestClientDataClassification></highestClientDataClassification>
<highestDataClassification></highestDataClassification>
<highestIbmDataClassification></highestIbmDataClassification>
<ibmCbnInterval></ibmCbnInterval>
<ibmCbnRequired></ibmCbnRequired>
<ibmCbnType></ibmCbnType>
<ibmCbnUnit></ibmCbnUnit>
<ibmPrivIDUnit></ibmPrivIDUnit>
<ibmPrivType></ibmPrivType>
<ibmQevFlag></ibmQevFlag>
<ibmQevInterval></ibmQevInterval>
<ibmQevUnit></ibmQevUnit>
<ibmUsersMax></ibmUsersMax>
<internetAccFlag></internetAccFlag>
<personalData></personalData>
<privIDFlag></privIDFlag>
<privIDInterv></privIDInterv>
<regulatoryRequirements></regulatoryRequirements>
<remediationtimeHi></remediationtimeHi>
<remediationtimeLo></remediationtimeLo>
<remediationtimeMd></remediationtimeMd>
<rerFlag></rerFlag>
<rerInterv></rerInterv>
<rerType></rerType>
<rerUnit></rerUnit>
<scExceptDate></scExceptDate>
<scExceptReasonCode></scExceptReasonCode>
<scExceptText></scExceptText>
<secExemptionDesc></secExemptionDesc>
<secExemptionFlag></secExemptionFlag>
<securityPackage></securityPackage>
<securityPolicyCategory></securityPolicyCategory>
<securityPolicyOther></securityPolicyOther>
<securityPolicyType></securityPolicyType>
<serverPurpose></serverPurpose>
<sharedIDFlag></sharedIDFlag>
<shrdExceptDate></shrdExceptDate>
<shrdExceptReasonCode></shrdExceptReasonCode>
<shrdExceptText></shrdExceptText>
<vitalBusProcessYN></vitalBusProcessYN>
</OperatingSystemEnvironmentProfile>
<OperatingSystemIpAddress Action="Create">
<dotnotation></dotnotation>
<hostName></hostName>
<isPrimaryIpHost></isPrimaryIpHost>
<name></name>
<netMask></netMask>
<vsExceptDate></vsExceptDate>
<vsExceptReasonCode></vsExceptReasonCode>
<vsExceptText></vsExceptText>
<vulScanUnit></vulScanUnit>
<vulscanAutoFlag></vulscanAutoFlag>
<vulscanAutoInterval></vulscanAutoInterval>
</OperatingSystemIpAddress>
</ChildCI>
</OperatingSystem>
<Subsystem Action="Create">
<Id>3</Id>
<applSIDataType></applSIDataType>
<artifactType></artifactType>
<assetLifeCycleState></assetLifeCycleState>
<ciLifeCycleState></ciLifeCycleState>
<controlProductName></controlProductName>
<controlProductRelease></controlProductRelease>
<controlProductType></controlProductType>
<controlProductVendor></controlProductVendor>
<controlProductVersion></controlProductVersion>
<description></description>
<discontinuedDate></discontinuedDate>
<fqhn></fqhn>
<managed></managed>
<name></name>
<parentUID></parentUID>
<piFlag></piFlag>
<productModLevel></productModLevel>
<productName></productName>
<productPatchLevel></productPatchLevel>
<productRelease></productRelease>
<productVersion></productVersion>
<purgeDate></purgeDate>
<scanTime></scanTime>
<vendorName></vendorName>
<ChildCI>
<SubsystemContact Action="Create">
<contactUID></contactUID>
</SubsystemContact>
<SubsystemEnvironmentProfile Action="Create">
<authFlag></authFlag>
<authExceptDate></authExceptDate>
<authExceptReasonCode></authExceptReasonCode>
<authExceptText></authExceptText>
<disasterRecSys></disasterRecSys>
<hcAutoInterv></hcAutoInterv>
<hcExceptDate></hcExceptDate>
<hcExceptReasonCode></hcExceptReasonCode>
<hcExceptText></hcExceptText>
<hcUnit></hcUnit>
<healthchAutoFlag></healthchAutoFlag>
<ibmCbnInterval></ibmCbnInterval>
<ibmCbnRequired></ibmCbnRequired>
<ibmCbnType></ibmCbnType>
<ibmCbnUnit></ibmCbnUnit>
<ibmPrivIDUnit></ibmPrivIDUnit>
<ibmPrivType></ibmPrivType>
<ibmQevFlag></ibmQevFlag>
<ibmQevInterval></ibmQevInterval>
<ibmQevUnit></ibmQevUnit>
<privIDFlag></privIDFlag>
<privIDInterv></privIDInterv>
<rerFlag></rerFlag>
<rerInterv></rerInterv>
<rerType></rerType>
<rerUnit></rerUnit>
<scExceptDate></scExceptDate>
<scExceptReasonCode></scExceptReasonCode>
<scExceptText></scExceptText>
<sharedIDFlag></sharedIDFlag>
<shrdExceptDate></shrdExceptDate>
<shrdExceptReasonCode></shrdExceptReasonCode>
<shrdExceptText></shrdExceptText>
<vitalBusProcessYN></vitalBusProcessYN>
</SubsystemEnvironmentProfile>
</ChildCI>
</Subsystem>
</TopLevelCI>
<Relationship>
<RelationshipName>Hosted_by</RelationshipName>
<sourceCIType>OperatingSystem</sourceCIType>
<targetCIType>OperatingSystem</targetCIType>
</Relationship>
<Relationship>
<RelationshipName>Runs_on</RelationshipName>
<sourceCIType>Subsystem</sourceCIType>
<targetCIType>OperatingSystem</targetCIType>
</Relationship>
<Relationship>
<RelationshipName>Runs_on_hw</RelationshipName>
<sourceCIType>OperatingSystem</sourceCIType>
<targetCIType>PhysicalComputerSystem</targetCIType>
</Relationship>
</Customer>
</GACDWBulkLoadInterface>
I have researched and come up with my VBA code here
Sub ReadXML()
Dim oXML As MSXML2.DOMDocument60
Dim vaFile As Variant
Set oXML = New MSXML2.DOMDocument60
'Open Browse file dialog
vaFile = Application.GetOpenFilename("XML Files (*.xml), *.xml", _
Title:="Select XML files", MultiSelect:=False)
oXML.validateOnParse = True
oXML.setProperty "SelectionLanguage", "XPath" ' necessary in version 3.0, possibly redundant here
oXML.async = False
If Not oXML.Load(vaFile) Then 'Load XML has gone bad
Dim xPE As Object ' Set xPE = CreateObject("MSXML2.IXMLDOMParseError")
Dim strErrText As String
Set xPE = oXML.parseError
With xPE
strErrText = "Load error " & .ErrorCode & " xml file " & vbCrLf & _
Replace(.URL, "file:///", "") & vbCrLf & vbCrLf & _
xPE.reason & _
"Source Text: " & .srcText & vbCrLf & vbCrLf & _
"Line No.: " & .Line & vbCrLf & _
"Line Pos.: " & .linepos & vbCrLf & _
"File Pos.: " & .filepos & vbCrLf & vbCrLf
End With
MsgBox strErrText, vbExclamation
Set xPE = Nothing
Exit Sub
End If
Debug.Print "|" & oXML.XML & "|"
Dim nodeList As MSXML2.IXMLDOMNodeList, iNode As MSXML2.IXMLDOMNode
Dim Searched As String
Searched = "/*/*"
Set nodeList = oXML.SelectNodes(Searched)
'Set Queries = oXML.DocumentElement.SelectNodes(Searched)
For Each iNode In nodeList
'Debug.Print "<" & iNode.BaseName & ">"
Debug.Print "<" & iNode.nodeName & ">"
Next
However, My problem is no matter what I come up with Xpath queries. None of them work except \* or \.
I can't specific any path. Both .SelectSingleNode or .SelectNodes alway return length =0. Is there any problem with my code or my XML file or Xpath syntax?
As mentioned in comments your xml document has namespace definitions in its DocumentElement <GACDWBulkLoadInterface> (xmlns stands for xml name space). Furthermore "it contains a default namespace so any attempted parsing on named nodes must map to this namespace URI otherwise returns nothing."
To allow eventual analysis it's necessary to include a user defined prefix (e.g. :s) into explicit namespace settings, which can be used in later XPath expressions:
Dim oXML As MSXML2.DOMDocument60
Set oXML = New MSXML2.DOMDocument60
oXML.validateOnParse = True
Dim XMLNamespaces As String
XMLNamespaces = "xmlns:s='http://www.example.org/GACDWSchema'"
oXML.SetProperty "SelectionNamespaces", XMLNamespaces
Eventually you can define any XPath expression, e.g. the childnodes of Customer[1]:
Dim nodeList As MSXML2.IXMLDOMNodeList, iNode As MSXML2.IXMLDOMNode
Dim Searched As String
Searched = "//s:Customer/s:*"
Set nodeList = oXML.SelectNodes(Searched)
Related links
Displaying XML structures including attributes via recursive function calls
Display XML with hierarchy in cells
Apparently OP's source code: Parse DomDocument

Loop that extracts XML nodes into table under the corresponding headers

I read an XML document to collect user logon times.
<UserName="Jenny" Monday="7:00" Tuesday="7:30" Wednesday="0" Thursday="7:10" Friday="7:25" Saturday="6:00" Sunday="0"/><UserName="Simon" Monday="8:20" Tuesday="7:45" Wednesday="7:45" Thursday="7:10" Friday="7:25" Saturday="7:00" Sunday="0"/><UserName="Jenny" Monday="8:00" Tuesday="8:30" Wednesday="8:00" Thursday="7:10" Friday="7:25" Saturday="0" Sunday="0"/>Chris
I can get and paste info into a table on an Excel spreadsheet one by one.
Dim pTeamTimes As New XMLdoc
Dim objPlan As IXMLDOMElement
'build file path
strTeamXMLPath = "C:\Users\Public\Libraries\Times" & ".xml"
'load document
objPlan .LoadDocument strTeamXMLPath , "TeamTimes"
For Each objPlan In pTeamTimes.Root.ChildNodes
.Cells(intRow, 13) = User
.Cells(intRow, 14) = objPlan .getAttribute("Monday")
.Cells(intRow, 15) = objPlan .Attributes.getNamedItem("Tuesday").Text
.Cells(intRow, 16) = objPlan .Attributes.getNamedItem("Wednesday").Text
.Cells(intRow, 17) = objPlan .Attributes.getNamedItem("Thursday").Text
.Cells(intRow, 18) = objPlan .Attributes.getNamedItem("Friday").Text
.Cells(intRow, 19) = objPlan .Attributes.getNamedItem("Saturday").Text
.Cells(intRow, 20) = objPlan .Attributes.getNamedItem("Sunday").Text
intRow = intRow + 1
Next objPlan
This pastes the data into a table with the user name on the left and the times to the right row by row (see below).
User|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday
Is there a way to loop through the file and extract the appropriate data for the appropriate header?
I also played with .getAttribute("Monday") and .Attributes.getNamedItem("Tuesday").Text
Is there a major difference in using each of these methods?
Streamlining display of xml node attributes (array approach)
Your XML file snippet's syntax isn't correct. Each node has to show its node name after the opening bracket <SomeNode ...>, but this nodename cannot be followed immediately by an equals character = indicating always a following attribute assignment.
Therefore I built a wellformed xml structure to be able to illustrate a working MCV Example choosing to ("re")name the individual nodes <User ...> followed by UserName and weekday attributes (Monday="7:00" Tuesday="" ...).
<?xml version="1.0" encoding="UTF-8"?>
<AllUsers>
<Team>
<User UserName="Jenny" Monday="7:00" Tuesday="7:30" Wednesday="0" Thursday="7:10" Friday="7:25" Saturday="6:00" Sunday="0"/>
<User UserName="Simon" Monday="8:20" Tuesday="7:45" Wednesday="7:45" Thursday="7:10" Friday="7:25" Saturday="7:00" Sunday="0"/>
<User UserName="Jenny2" Monday="8:00" Tuesday="8:30" Wednesday="8:00" Thursday="7:10" Friday="7:25" Saturday="0" Sunday="0"/>
</Team>
</AllUsers>
Example code
Based on this assumed example structure (loaded here via .LoadXML), I demonstrate how to streamline code getting attributes via a NodeList loop based on the following xml content.
In order to allow a quickly reproducible example, I didn't refer to an external file via .Load, but to a pure string content (received by help function getContent()) loaded via .LoadXML. Of course loading an external file needs the following syntax: xDoc.Load strTeamXMLPath. - Btw several parts of the original code aren't clear, e.g. I don't know what's behind .LoadDocument
Sub GetAttributes()
Dim xdoc As MSXML2.DOMDocument60 ' early binding needs reference to Microsoft 'XML, v6.0'
Set xdoc = New MSXML2.DOMDocument60
If xdoc.LoadXML(getContent()) Then
Dim users As MSXML2.IXMLDOMNodeList
Set users = xdoc.SelectNodes("//Team/User") ' nodelist is zero-based
ReDim tmp(1 To users.Length, 1 To 8)
Dim i As Long
For i = 1 To users.Length
Dim j As Long
For j = 1 To users(i - 1).Attributes.Length
'assign to 1-based 2-dim tmp array
'(whereas users nodelist incl. node attributes list are zero-based!)
tmp(i, j) = users(i - 1).Attributes(j - 1).Text
'Debug.Print i & "." & j, tmp(i, j) ' optional display in VB Editor's immediate window
Next
Debug.Print i, Join(Application.Index(tmp, i, 0), "|")
Next i
Else ' XML Parse Error
Debug.Print getParseError(xdoc)
End If
' write tmp to any target
With Sheet1 ' << change to your project's sheet Code(Name)
' 'a) write captions starting from cell M1 (optional)
' For i = 1 To UBound(tmp, 2)
' .Range("M1").Offset(0, i - 1) = users(0).Attributes(i - 1).BaseName
' Next i
'write tmp results
.Range("M2").Resize(UBound(tmp, 1), UBound(tmp, 2)) = tmp
End With
End Sub
Additionaly you could test other syntax, e.g. for the 1st user (Jenny) to get the Monday attribute:
Debug.Print users(0).Attributes.getNamedItem("Monday").BaseName ' "Monday"
Debug.Print users(0).Attributes.getNamedItem("Monday").Text ' 7:00
Debug.Print xdoc.DocumentElement.SelectSingleNode("Team/User[1]/#Monday").Text ' 7:00
Help functions
Function getContent() gets an assumed minimal, but wellformed xml string content as described above replacing the unknown structure of OP's external file content.
Function getContent() As String
Dim tmp As String
tmp = "<?xml version=""1.0"" encoding=""UTF-8""?>" & vbNewLine
tmp = tmp & "<AllUsers>" & vbNewLine & " <Team>" & vbNewLine & _
vbTab & "<User UserName=""Jenny"" Monday=""7:00"" Tuesday=""7:30"" Wednesday=""0"" Thursday=""7:10"" Friday=""7:25"" Saturday=""6:00"" Sunday=""0""/>" & vbNewLine & _
vbTab & "<User UserName=""Simon"" Monday=""8:20"" Tuesday=""7:45"" Wednesday=""7:45"" Thursday=""7:10"" Friday=""7:25"" Saturday=""7:00"" Sunday=""0""/>" & vbNewLine & _
vbTab & "<User UserName=""Jenny2"" Monday=""8:00"" Tuesday=""8:30"" Wednesday=""8:00"" Thursday=""7:10"" Friday=""7:25"" Saturday=""0"" Sunday=""0""/>" & vbNewLine & _
" </Team>" & vbNewLine & "</AllUsers>"
getContent = tmp
Debug.Print getContent
End Function
Function getParseError(xdoc As MSXML2.DOMDocument60) As String
Dim xPE As MSXML2.IXMLDOMParseError
Set xPE = xdoc.parseError
With xPE
getParseError = "Load Error " & .ErrorCode & " XML File " & vbCrLf & _
Replace(.Url, "file:///", "") & vbCrLf & vbCrLf & _
xPE.reason & _
"Source Text: " & .srcText & vbCrLf & vbCrLf & _
"Line No: " & .Line & vbCrLf & _
"Line Pos: " & .linepos & vbCrLf & _
"File Pos: " & .filepos & vbCrLf & vbCrLf
End With
End Function

Need dictionary/loop assistance

I have some work to complete where I have 9 tabs of data (some of which contain thousands of lines of data). Each tab contains (amongst others) a policy number, a credit and/or a debit number.
Every policy number will have a match somewhere in the tabs containing an equal credit or debit, e.g.
tab 1 will have Policy number 123 and a credit of £100 and
tab 5 will also have policy number 123 with a debit of £100.
What I'm looking to do is, look through each policy number on every tab and find where the opposite amount is located adding the location address to each policy number.
I'm certainly not looking for anyone to create the coding for me, but what I am looking for is advice. I've looked at using loops but feel this may take a very long time to process. I've also looked at Dictionaries but am relatively new to these so am not very confident.
Is what I'm looking for even possible? And if so any ideas where to start or pointers? Any advice is greatly appreciated. Thanks!
Usage Example
#Matt555, You can test the created XML file with the following code to get the sheet names of policy "123" and debit of 100. I tested the code assuming your titles in row A:A contain "policy" and "debit"
#Peh, You are right, xml dom methods aren't used too often within vba. The advantage of using XML in this connex is a great flexibility in searching via XPath as well as performance over huge files. I prefer it even to arrays or dictionaries when filtering unique values. It is possible to return the found item number in node lists without looping through the whole data set ...
Option Explicit
Sub testPolicy()
Dim policy
Dim debit As Double
policy = "123"
debit = "100"
MsgBox "Policy " & policy & " found in " & vbNewLine & _
findSheetName(policy, debit), vbInformation, "Policy " & policy & " in Tabs"
' You can easily split this to an array and analyze the results
End Sub
Function findSheetName(ByVal policy, Optional ByVal debit) As String
' Purpose: Finds Sheet Names where policy AND/OR debit is found
' Note: Assuming your titles in row A:A contain "policy" and "debit"
' You can declare xDoc also after Option Explicit to make it public
Dim xDoc As Object
Dim xNd As Object ' MSXML.IXMDOMNode
Dim xNdList As Object ' MSXML.IXMLDOMNodeList
Dim s As String
' XPath expression
Dim xPth As String
If IsMissing(debit) Then
xPth = "//row[policy=""" & policy & """]"
Else
xPth = "//row[policy=""" & policy & """][debit=""" & debit & """]"
End If
' XML to memory
Set xDoc = CreateObject("MSXML2.Domdocument.6.0")
' allow XPath
xDoc.setProperty "SelectionLanguage", "XPath"
xDoc.validateOnParse = False
' ========
' LOAD XML
' ========
xDoc.Load ThisWorkbook.Path & "\" & "output.xml"
' Loop thru NodeList
Set xNdList = xDoc.DocumentElement.SelectNodes(xPth)
Debug.Print xPth, xNdList.Length
For Each xNd In xNdList
s = s & xNd.ParentNode.NodeName & "|"
Next xNd
Set xDoc = Nothing
findSheetName = s
End Function
You could
a) create an XML file looping through all sheets,
b) open it via load method and
c) perform a simple XPath search (I can give some examples later)
I modified a recent answer (cf. excel-vba-xml-parsing-performance)
to do step "a)" using late binding thus
a) avoiding a reference to the latest MS XML Version Version 6 (msxml6.dll) and
b) getting data over all xheets. XML allows you structured search via XPath over nodes in a logical structure comparable to HTML. The root node in this example is called data, the following nodes are named with the sheets' names and the subsequent nodes get the names in row A:A of each sheet.
A XML file is a simple text file, which you can open by a text editor. Above all you can use VBA XMLDOM methods to analyze or search through the items (nodes). I will give you examples to relating to your question, but give me some time. => see answer "Usage Example", where I explain some Advantages of XML, too (#Peh).
Please pay Attention to the added notes, too.
Option Explicit
Sub xmlExportSheets()
' Zweck: XML Export over all sheets in workbook
' cf. Site: [excel-vba-xml-parsing-performance][1][https://stackoverflow.com/questions/40986395/excel-vba-xml-parsing-performance/40987237#40987237][1]
' Note: pretty printed raw output with line breaks and indentation using an embedded XSLT stylesheet
On Error GoTo ErrHandle
' A. Declarations
' 1 DECLARE XML DOC OBJECT '
' a) Early Binding: VBA REFERENCE MSXML, v6.0 necessary'
' Dim doc As New MSXML2.DOMDocument60, xslDoc As New MSXML2.DOMDocument60, newDoc As New MSXML2.DOMDocument60
' Dim root As IXMLDOMElement, dataNode As IXMLDOMElement, datesNode As IXMLDOMElement, namesNode As IXMLDOMElement
' b) Late Binding XML Files:
Dim doc As Object
Dim xslDoc As Object
Dim newDoc As Object
' c) Late Binding XML Nodes:
Dim root As Object
Dim sh As Object ' xml node containing Sheet Name
Dim dataNode As Object
Dim datesNode As Object
Dim namesnode As Object
' 2 DECLARE other variables
Dim i As Long
Dim j As Long
Dim tmpValue As Variant
Dim tit As String
Dim ws As Worksheet
' B. XML Docs to Memory
Set doc = CreateObject("MSXML2.Domdocument.6.0")
Set xslDoc = CreateObject("MSXML2.Domdocument.6.0")
Set newDoc = CreateObject("MSXML2.Domdocument.6.0")
' C. Set DocumentElement (= root node)'
Set root = doc.createElement("data")
' D. Create Root Node
doc.appendChild root
' ===========================
' ITERATE THROUGH Sheets
' ===========================
For Each ws In ThisWorkbook.Sheets
Set sh = doc.createElement(ws.Name) '
root.appendChild sh
' ===========================
' ITERATE THROUGH ROWS ' A2:NNn
' ===========================
For i = 2 To ws.UsedRange.Rows.Count ' Sheets(1)
' DATA ROW NODE '
Set dataNode = doc.createElement("row") '
sh.appendChild dataNode
' TABLES NODE (orig.: DATES NODE) '
Set datesNode = doc.createElement(ws.Cells(1, 1)) ' Dates
datesNode.Text = ws.Range("A" & i)
dataNode.appendChild datesNode
' NAMES NODE '
For j = 1 To ws.UsedRange.Columns.Count - 1 ' = 12
tit = ws.Cells(1, j + 1)
tmpValue = ws.Cells(i, j + 1)
Set namesnode = doc.createElement(tit)
namesnode.Text = tmpValue
dataNode.appendChild namesnode
Next j
Next i
Next ws
' =============================
' PRETTY PRINT RAW OUTPUT (XSL)
' =============================
xslDoc.LoadXML "<?xml version=" & Chr(34) & "1.0" & Chr(34) & "?>" _
& "<xsl:stylesheet version=" & Chr(34) & "1.0" & Chr(34) _
& " xmlns:xsl=" & Chr(34) & "http://www.w3.org/1999/XSL/Transform" & Chr(34) & ">" _
& "<xsl:strip-space elements=" & Chr(34) & "*" & Chr(34) & " />" _
& "<xsl:output method=" & Chr(34) & "xml" & Chr(34) & " indent=" & Chr(34) & "yes" & Chr(34) & "" _
& " encoding=" & Chr(34) & "UTF-8" & Chr(34) & "/>" _
& " <xsl:template match=" & Chr(34) & "node() | #*" & Chr(34) & ">" _
& " <xsl:copy>" _
& " <xsl:apply-templates select=" & Chr(34) & "node() | #*" & Chr(34) & " />" _
& " </xsl:copy>" _
& " </xsl:template>" _
& "</xsl:stylesheet>"
' XSLT (Transformation)
xslDoc.async = False
doc.transformNodeToObject xslDoc, newDoc
' =================
' Save the XML File
' =================
newDoc.Save ThisWorkbook.Path & "\Output.xml"
MsgBox "Successfully exported Excel data to " & ThisWorkbook.Path & "\Output.XML!", vbInformation
' Regular End of procedure
Exit Sub
ErrHandle:
MsgBox Err.Number & " - " & Err.Description, vbCritical
Exit Sub
End Sub
Note
Sheet names have to be without spaces
Added Note (important hint):
XML Nodes use titles in first row of every sheet. As the modified procedure gets title names via UsedRange it's important not to have any empty cells in row A:A for this example.
Additional remark
I don't know the reason why my prompt answer (marked as "a") was downgraded by someone. I would find it helpful to argue this :-)

Find specific string in a text file with VBS script

I need to find the string "Test Case " & index in a txt file.
I give you an example of the lines you can find in this file:
<tr><td>Log_ in_U1A1</td></tr>
<tr><td>Form1</td></tr>
As you can see in the second line I have an occurrence of the string "Test Case".
What I want to do is to add another particular string in the line which preceeds the one where "Test Case 5" appears. For example:
<tr><td>Log_ in_U1A1</td></tr>
<tr><td>Beginning_of_DD_TC5</td></tr>
<tr><td>Form1</td></tr>
It's also important that the line I add has an index i which depends on the Test Case number, and i need to add it before the first occurrence of "Test Case" & i, i dont care about the following occurrences.
I tested if InStr function worked with an example:
Dim objFSO, filepath, objInputFile, tmpStr, substrToFind
Set objFSO = CreateObject("Scripting.FileSystemObject")
filepath = "C:\VBS\filediprova.txt"
substrToFind = "<tr><td><a href=" & chr(34) & "../Test case 5"
Set objInputFile = objFSO.OpenTextFile(filepath)
tmpStr = objInputFile.ReadLine
If InStr(tmpStr, substrToFind) <= 0 Then
WScript.Echo "No matches"
Else
WScript.Echo "Found match"
End If
And it works, it recognizes my substring. In this small example the txt file only contans the followingline:
<tr><td>Form1</td></tr>
Now, when I try to loop over a file with much more lines I have some problem, I use the same InStr function.
I wrote the following loop:
Do until objInputFile.AtEndOfStream
strToAdd = "<tr><td>Beginning_of_DD_TC" & CStr(index) & "</td></tr>"
substrToFind = "<tr><td><a href=" & chr(34) & "../Test case " & index
firstStr = "<?xml version" 'my file always starts like this
tmpStr = objInputFile.ReadLine
If InStr(tmpStr, substrToFind) <= 0 Then
If Instr(tmpStr, firstStr) > 0 Then
text = tmpStr 'to avoid the first empty line
Else
text = text & vbCrLf & tmpStr
End If
Else
text = text & vbCrLf & strToAdd & vbCrLf & tmpStr
index = index + 1
End If
Loop
What's wrong?
I'd recommend using a regular expressions instead of string operations for this:
Set fso = CreateObject("Scripting.FileSystemObject")
filename = "C:\VBS\filediprova.txt"
newtext = vbLf & "<tr><td>Beginning_of_DD_TC5</td></tr>"
Set re = New RegExp
re.Pattern = "(\n.*?Test Case \d)"
re.Global = False
re.IgnoreCase = True
text = f.OpenTextFile(filename).ReadAll
f.OpenTextFile(filename, 2).Write re.Replace(text, newText & "$1")
The regular expression will match a line feed (\n) followed by a line containing the string Test Case followed by a number (\d), and the replacement will prepend that with the text you want to insert (variable newtext). Setting re.Global = False makes the replacement stop after the first match.
If the line breaks in your text file are encoded as CR-LF (carriage return + line feed) you'll have to change \n into \r\n and vbLf into vbCrLf.
If you have to modify several text files, you could do it in a loop like this:
For Each f In fso.GetFolder("C:\VBS").Files
If LCase(fso.GetExtensionName(f.Name)) = "txt" Then
text = f.OpenAsTextStream.ReadAll
f.OpenAsTextStream(2).Write re.Replace(text, newText & "$1")
End If
Next
Wow, after few attempts I finally figured out how to deal with my text edits in vbs. The code works perfectly, it gives me the result I was expecting. Maybe it's not the best way to do this, but it does its job.
Here's the code:
Option Explicit
Dim StdIn: Set StdIn = WScript.StdIn
Dim StdOut: Set StdOut = WScript
Main()
Sub Main()
Dim objFSO, filepath, objInputFile, tmpStr, ForWriting, ForReading, count, text, objOutputFile, index, TSGlobalPath, foundFirstMatch
Set objFSO = CreateObject("Scripting.FileSystemObject")
TSGlobalPath = "C:\VBS\TestSuiteGlobal\Test suite Dispatch Decimal - Global.txt"
ForReading = 1
ForWriting = 2
Set objInputFile = objFSO.OpenTextFile(TSGlobalPath, ForReading, False)
count = 7
text=""
foundFirstMatch = false
Do until objInputFile.AtEndOfStream
tmpStr = objInputFile.ReadLine
If foundStrMatch(tmpStr)=true Then
If foundFirstMatch = false Then
index = getIndex(tmpStr)
foundFirstMatch = true
text = text & vbCrLf & textSubstitution(tmpStr,index,"true")
End If
If index = getIndex(tmpStr) Then
text = text & vbCrLf & textSubstitution(tmpStr,index,"false")
ElseIf index < getIndex(tmpStr) Then
index = getIndex(tmpStr)
text = text & vbCrLf & textSubstitution(tmpStr,index,"true")
End If
Else
text = text & vbCrLf & textSubstitution(tmpStr,index,"false")
End If
Loop
Set objOutputFile = objFSO.CreateTextFile("C:\VBS\NuovaProva.txt", ForWriting, true)
objOutputFile.Write(text)
End Sub
Function textSubstitution(tmpStr,index,foundMatch)
Dim strToAdd
strToAdd = "<tr><td>Beginning_of_CF5.0_Features_TC" & CStr(index) & "</td></tr>"
If foundMatch = "false" Then
textSubstitution = tmpStr
ElseIf foundMatch = "true" Then
textSubstitution = strToAdd & vbCrLf & tmpStr
End If
End Function
Function getIndex(tmpStr)
Dim substrToFind, charAtPos, char1, char2
substrToFind = "<tr><td><a href=" & chr(34) & "../Test case "
charAtPos = len(substrToFind) + 1
char1 = Mid(tmpStr, charAtPos, 1)
char2 = Mid(tmpStr, charAtPos+1, 1)
If IsNumeric(char2) Then
getIndex = CInt(char1 & char2)
Else
getIndex = CInt(char1)
End If
End Function
Function foundStrMatch(tmpStr)
Dim substrToFind
substrToFind = "<tr><td><a href=" & chr(34) & "../Test case "
If InStr(tmpStr, substrToFind) > 0 Then
foundStrMatch = true
Else
foundStrMatch = false
End If
End Function
This is the original txt file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type" />
<title>Test Suite</title>
</head>
<body>
<table id="suiteTable" cellpadding="1" cellspacing="1" border="1" class="selenium"><tbody>
<tr><td><b>Test Suite</b></td></tr>
<tr><td>TC_Environment_setting</td></tr>
<tr><td>TC_Set_variables</td></tr>
<tr><td>TC_Set_ID</td></tr>
<tr><td>Log_in_Admin</td></tr>
<tr><td>Set_Roles_Dispatch_Decimal</td></tr>
<tr><td>Log_ in_U1A1</td></tr>
<tr><td>Form1</td></tr>
<tr><td>contrD1</td></tr>
<tr><td>Logout</td></tr>
<tr><td>Log_ in_U1B1</td></tr>
<tr><td>Search&OpenApp</td></tr>
<tr><td>FormEND</td></tr>
<tr><td>Controllo END</td></tr>
<tr><td>Logout</td></tr>
<tr><td>Log_ in_U1A1</td></tr>
<tr><td>Form1</td></tr>
<tr><td>contrD1</td></tr>
<tr><td>Logout</td></tr>
<tr><td>Log_ in_U1B1</td></tr>
<tr><td>Search&OpenApp</td></tr>
<tr><td>FormEND</td></tr>
<tr><td>Controllo END</td></tr>
<tr><td>Logout</td></tr>
<tr><td>Log_ in_U1A1</td></tr>
<tr><td>Form1</td></tr>
<tr><td>Controllo DeadLetter</td></tr>
<tr><td>Logout</td></tr>
<tr><td>Set_Roles_Dispatch_Decimal</td></tr>
<tr><td>Logout_BAC</td></tr>
</tbody></table>
</body>
</html>
And this is the result I'm expecting
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type" />
<title>Test Suite</title>
</head>
<body>
<table id="suiteTable" cellpadding="1" cellspacing="1" border="1" class="selenium"><tbody>
<tr><td><b>Test Suite</b></td></tr>
<tr><td>TC_Environment_setting</td></tr>
<tr><td>TC_Set_variables</td></tr>
<tr><td>TC_Set_ID</td></tr>
<tr><td>Log_in_Admin</td></tr>
<tr><td>Set_Roles_Dispatch_Decimal</td></tr>
<tr><td>Log_ in_U1A1</td></tr>
<tr><td>Beginning_of_CF5.0_Features_TC5</td></tr>
<tr><td>Form1</td></tr>
<tr><td>Form1</td></tr>
<tr><td>contrD1</td></tr>
<tr><td>Logout</td></tr>
<tr><td>Log_ in_U1B1</td></tr>
<tr><td>Search&OpenApp</td></tr>
<tr><td>FormEND</td></tr>
<tr><td>Controllo END</td></tr>
<tr><td>Logout</td></tr>
<tr><td>Log_ in_U1A1</td></tr>
<tr><td>Beginning_of_CF5.0_Features_TC6</td></tr>
<tr><td>Form1</td></tr>
<tr><td>contrD1</td></tr>
<tr><td>Logout</td></tr>
<tr><td>Log_ in_U1B1</td></tr>
<tr><td>Search&OpenApp</td></tr>
<tr><td>Controllo END</td></tr>
<tr><td>Logout</td></tr>
<tr><td>Log_ in_U1A1</td></tr>
<tr><td>Beginning_of_CF5.0_Features_TC7</td></tr>
<tr><td>Form1</td></tr>
<tr><td>Controllo DeadLetter</td></tr>
<tr><td>Logout</td></tr>
<tr><td>Set_Roles_Dispatch_Decimal</td></tr>
<tr><td>Logout_BAC</td></tr>
</tbody></table>
</body>
</html>
Try to change like this ..
firstStr = "<?xml version" 'my file always starts like this
Do until objInputFile.AtEndOfStream
strToAdd = "<tr><td>Beginning_of_DD_TC" & CStr(index) & "</td></tr>"
substrToFind = "<tr><td><a href=" & chr(34) & "../Test case " & trim(cstr((index)))
tmpStr = objInputFile.ReadLine
If InStr(tmpStr, substrToFind) <= 0 Then
If Instr(tmpStr, firstStr) > 0 Then
text = tmpStr 'to avoid the first empty line
Else
text = text & vbCrLf & tmpStr
End If
Else
text = text & vbCrLf & strToAdd & vbCrLf & tmpStr
End If
index = index + 1
Loop

Creating Excel Macro for Exporting XML to a certain folder

I need to create a macro (which I have never done before) and if you guys can guide me to a right path, it would be really appreciated.
What I'm doing currently:
I have created a mapping XML which I have imported into Excel. Once it is imported into Excel, users will then go ahead and paste some data in it and export it to receive an XML data file, which then user can drop it to a FTP where the job picks it up and imports it into database.
Here's the problem:
The export has following node, which I do not want:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
Instead I want to replace it with following:
<?xml version="1.0" ?>
<Root xmlns="http://tempuri.org/CourseImport.xsd">
How do I automate this? Is there some kind of setting in Excel that could make it happen?
Basically, I want the export to have my root instead of the default root and I want to automatically be able to drop the file to specified path: example: \development\school\course import
Thanks!
My co-worker actually helped me out with this. I thought I should share what I did
Sub ExportXML()
'
' Export XML Macro exports the data that is in Excel to XML.
'
Const ForReading = 1
Const ForWriting = 2
Set objFSO = CreateObject("Scripting.FileSystemObject")
'
newFileName = Application.GetSaveAsFilename("out.xml", "XML Files (*.xml), *.xmls")
If newFileName = False Then
Exit Sub
End If
If objFSO.FileExists(newFileName) Then
objFSO.DeleteFile (newFileName)
End If
ActiveWorkbook.XmlMaps("Root_Map").Export URL:=newFileName
Set objFile = objFSO.OpenTextFile(newFileName, ForReading)
Dim count
count = 0
Do Until objFile.AtEndOfStream
strLine = objFile.ReadLine
If count = 0 Then
strNewContents = strNewContents & "<?xml version=""1.0"" ?>" & vbCrLf
ElseIf count = 1 Then
strNewContents = strNewContents & "<Root xmlns=""http://tempuri.org/import.xsd"">" & vbCrLf
Else
strNewContents = strNewContents & strLine & vbCrLf
End If
count = count + 1
Loop
objFile.Close
Set objFile = objFSO.OpenTextFile(newFileName, ForWriting)
objFile.Write strNewContents
objFile.Close
End Sub

Resources