How can I use two patterns and show in the same file using VBScript? - vbscript

I have the code below:
Option Explicit
Dim myURL,oXMLHttp,objFSO,Description,write2File,ws
myURL = "https://www.cbsnews.com/latest/rss/main"
Set ws = CreateObject("wscript.shell")
Set oXMLHttp = CreateObject("MSXML2.XMLHTTP")
Set objFSO = CreateObject("Scripting.FileSystemObject")
oXMLHttp.Open "GET", myURL, False
oXMLHttp.Send
If oXMLHttp.Status = 200 Then
Description = Extract(oXMLHttp.responseText)
Set write2File = objFSO.CreateTextFile(".\Description.txt", True)
write2File.WriteLine(Description)
write2File.Close
End If
Function Extract(Data)
Dim re, Match, Matches
Set re = New RegExp
re.Global = True
re.IgnoreCase = True
re.MultiLine = True
re.Pattern = "<description>([\s\S]*?)<\/description>"
Set Matches = re.Execute(Data)
For Each Match in Matches
Description = Description & Match.SubMatches(0) & vbCrLf & vbCrLf
Next
Extract = Description
End Function
Now I need to save the title and description with two different patterns in the same text file. For exemple:
re.Pattern = "<title>([\s\S]*?)<\/title>" 'pattern 01
re.Pattern = "<description>([\s\S]*?)<\/description>" 'pattern 02
How it should be saved in the text file (exemple):
line 01: Text between tag "title"
line 02: Text between tag "description"
line 03: Text between tag "title"
line 04: Text between tag "description"
etc.
I tried a Forinside another For, but the result was not as expected, because I think I'm missing something.

Use an alternation:
re.Pattern = "<title>([\s\S]*?)</title>|<description>([\s\S]*?)</description>"
and append the respective submatch:
If Not IsEmpty(Match.SubMatches(0)) Then
Description = Description & Match.SubMatches(0)
ElseIf Not IsEmpty(Match.SubMatches(1)) Then
Description = Description & Match.SubMatches(1)
End If

Do you need read and parse xml ?
function Extract(Data)
Set doc = CreateObject("MSXML2.DOMDocument")
doc.loadXML(Data)
If doc.parseError <> 0 Then
response.write doc.parseError.reason
response.end
end if
Description = ""
For Each node In doc.selectNodes("/rss/channel/item")
if not node.selectSingleNode("title") is Nothing then
Description = Description & node.selectSingleNode("title").text & vbCrlf & vbCrlf
end if
if not node.selectSingleNode("description") is Nothing then
Description = Description & node.selectSingleNode("description").text & vbCrlf & vbCrlf
end if
Description = Description & vbCrlf & vbCrlf
Next
Extract = Description
end function

Related

How to extract data from tag or HTML class using vbscript? Only tags or classes I choose

Can someone help me? I need to extract the texts that are between tags or HTML classes using VBScript and save to a single text file. I need to save the tags or classes I define on different lines.
I've found a lot of code on the internet, but none worked as expected.
For example, I have the code below, but I can't extract classes through it, and it's not possible for more than one tag either. In many cases the code doesn't even work.
myURL = "http://rss.cnn.com/rss/edition.rss"
Set oXMLHttp = CreateObject("MSXML2.XMLHTTP")
Set ohtmlFile = CreateObject("htmlfile")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Const ForReading = 1, ForWriting = 2, ForAppending = 8
oXMLHttp.Open "GET", myURL, False
oXMLHttp.send
If oXMLHttp.Status = 200 Then
ohtmlFile.Write oXMLHttp.responseText
ohtmlFile.Close
Set oTable = ohtmlFile.getElementsByTagName("description")
sFileName = "c:\users\user\desktop\News.txt"
Set objFile = objFSO.OpenTextFile(sFileName, ForAppending, True)
For Each oTab In oTable
objFile.Write oTab.Innertext & vbCrLf
Next
objFile.Close
End If
WScript.Quit
thanks!
You could use a regular expression instead, though:
Option Explicit
Dim myURL,oXMLHttp,objFSO,Description,write2File,ws
myURL = "http://rss.cnn.com/rss/edition.rss"
set ws = CreateObject("wscript.shell")
Set oXMLHttp = CreateObject("MSXML2.XMLHTTP")
Set objFSO = CreateObject("Scripting.FileSystemObject")
oXMLHttp.Open "GET", myURL, False
oXMLHttp.send
If oXMLHttp.Status = 200 Then
Description = Extract(oXMLHttp.responseText)
Set write2File = objFSO.CreateTextFile(".\News.txt",True)
write2File.WriteLine(Description)
write2File.Close
ws.run ".\News.txt"
End If
'-------------------------------------------------------------------------
Function Extract(Data)
Dim re,Match,Matches
Set re = New RegExp
re.Global = True
re.IgnoreCase = True
re.Pattern = "<description><!\[CDATA\[([\s\S]*?)\]\]><\/description>"
Set Matches = re.Execute(Data)
For Each Match in Matches
Description = Description & Match.SubMatches(0) & vbCrlf & vbCrlf
Next
Extract = Description
End Function
'-------------------------------------------------------------------------
EDIT :
For your second request about how to get news from google :
Option Explicit
Dim myURL,oXMLHttp,objFSO,GoogleNews,write2File,ws
myURL = "https://news.google.com/?hl=en-US&gl=US&ceid=US:en"
set ws = CreateObject("wscript.shell")
Set oXMLHttp = CreateObject("MSXML2.XMLHTTP")
Set objFSO = CreateObject("Scripting.FileSystemObject")
oXMLHttp.Open "GET", myURL, False
oXMLHttp.send
If oXMLHttp.Status = 200 Then
GoogleNews = Extract(oXMLHttp.responseText)
Set write2File = objFSO.CreateTextFile(".\GoogleNews.txt",True,-1)
write2File.WriteLine(GoogleNews)
write2File.Close
ws.run ".\GoogleNews.txt"
End If
'-------------------------------------------------------------------------
Function Extract(Data)
Dim re,Match,Matches
Set re = New RegExp
re.Global = True
re.IgnoreCase = True
re.MultiLine = True
re.Pattern = "(\bclass=""DY5T1d"" >)(.+?)<\/a>"
Set Matches = re.Execute(Data)
For Each Match in Matches
GoogleNews = GoogleNews & Match.SubMatches(1) & vbCrlf & vbCrlf
Next
GoogleNews = Replace(GoogleNews,"'","'")
GoogleNews = Replace(GoogleNews,""",chr(34))
Extract = GoogleNews
End Function
'-------------------------------------------------------------------------
You are on the right track with using the getElementsByTagName Method with your ohtmlFile object. You can specify the tag types you want. For example:
Set objAnchors = ohtmlFile.getElementsByTagName("a")
This returns all <a> tags in the HTML document.

VBScript RegEx : Replace Content

I want to update the Unbound_DNS configuration file from a raw source but I can not get the desired result.
I would like to format each entry (each line):
address=/abc.com/0.0.0.0
To
local-zone: "abc.com" redirect
local-data: "abc.com 86400 IN A 0.0.0.0"
Here is what I did (thanks to hackoofr):
Option Explicit
Dim URL,Save2File,ws
If Not WScript.Arguments.Named.Exists("elevate") Then
CreateObject("Shell.Application").ShellExecute WScript.FullName _
, """" & WScript.ScriptFullName & """ /elevate", "", "runas", 1
WScript.Quit
End If
URL = "https://raw.githubusercontent.com/notracking/hosts-blocklists/master/domains.txt"
Set ws = CreateObject("wscript.Shell")
Save2File = ws.ExpandEnvironmentStrings("%Windir%\Temp\test")
Call Download(URL,Save2File)
'**********************************************************************************************
Sub Download(URL,Save2File)
Dim File,Line,BS,ws,RegExp
On Error Resume Next
Set File = CreateObject("MSXML2.XMLHTTP")
File.Open "GET",URL, False
File.Send
If err.number <> 0 then
Line = Line & vbcrlf & "Error Getting File"
Line = Line & vbcrlf & "Error " & err.number & "(0x" & hex(err.number) & ") " & vbcrlf &_
err.description
Line = Line & vbcrlf & "Source " & err.source
MsgBox Line,vbCritical,"Error getting file"
Err.clear
wscript.quit
End If
If File.Status = 200 Then
'**********************************************************************************************
' Replace content for use with the file service.conf of soft Unbound_DNS
'
' address=/abc.com/0.0.0.0 to local-zone: "abc.com" redirect
' local-data: "abc.com 3600 IN A 0.0.0.0"
'**********************************************************************************************
Set RegExp = CreateObject("VBScript.RegExp")
RegExp.IgnoreCase = True
RegExp.Global = True
RegExp.Pattern = "address=/(.*)/([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})"
File.ResponseBody = RegExp.Replace(File.ResponseBody, "local-zone: \""$1\"" redirect $1" & ret & ">local-data: \""$1 3600 IN A $2\""")
Set RegExp = Nothing
'**********************************************************************************************
' Write content
'**********************************************************************************************
Set BS = CreateObject("ADODB.Stream")
Set ws = CreateObject("wscript.Shell")
BS.type = 1
BS.open
BS.Write File.ResponseBody
BS.SaveToFile Save2File, 2
'**********************************************************************************************
' Clean cache DNS
'**********************************************************************************************
wshShell.run("cmd /c psexec \\ -s ipconfig /flushdns >> & hostName,TRUE")
ElseIf File.Status = 404 Then
MsgBox "UpdateHostname.vbs : File Not Found : " & File.Status,vbCritical,"UpdateHostname.vbs : Error File Not Found"
Else
MsgBox "UpdateHostname.vbs : Unknown Error : " & File.Status,vbCritical,"UpdateHostname.vbs : Error getting file"
End If
End Sub
'**********************************************************************************************
Thank you in advance for your help.
Edit 1:
The content does not change. File.ResponseBody returns the content correctly, but no modification by the regexp!
Replace the following code:
Set RegExp = CreateObject("VBScript.RegExp")
RegExp.IgnoreCase = True
RegExp.Global = True
RegExp.Pattern = "address=/(.*)/([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})"
File.ResponseBody = RegExp.Replace(File.ResponseBody, "local-zone: \""$1\"" redirect $1" & ret & ">local-data: \""$1 3600 IN A $2\""")
Set RegExp = Nothing
with this:
Dim objReg, strTest, objMatches, objMatch
Set objReg = New RegExp
strTest = File.ResponseBody 'address=/abc.com/0.0.0.0
objReg.Global = True
objReg.Pattern = "address=/(.*?)/(\d{1,3}(?:\.\d{1,3}){3})" 'abc.com gets stored in Group 1 and the IP address gets stored in Group 2
Set objMatches = objReg.Execute(strTest)
For Each objMatch In objMatches
strTest = "local zone: """ & objMatch.Submatches.Item(0) & """ redirect" & vbCrLf &_
"local data: """ & objMatch.Submatches.Item(0) & " 86400 in A " & objMatch.Submatches.Item(1)&""""
Next
File.ResponseBody = strTest
set objReg = Nothing
Click for Regex Demo(in the demo, / is escaped by \)
Regex Explanation:
address=/(.*?)/(\d{1,3}(?:\.\d{1,3}){3})
address=/ - matches address=/ literally
(.*?) - matches 0+ occurrences of any character(except a newline), as few as possible. The parenthesis are used to capture this match as group 1
/ - matches / literally
(\d{1,3}(?:\.\d{1,3}){3}) - matches a string of the pattern 12.222.212.33 and captures it in Group 2
Update:
Here is my final solution. From what I could understand from your code, you first get the response body from the server, modify and store the updated response in a file called test in the temp folder. Below is the code I have written to do the same thing. I have tested it on my system and the final output which gets stored in the C:\Windows\Temp\test.txt file looks correct as shown in the attached screenshot. Now, this may not be exactly what you want but you can get an idea from this. Store this code in a new vbs file and run it directly as it is.
Note: Since the response text from the server is very long, It takes a bit long to get executed. If you just want to see if it is working or not, uncomment the code inside the for loop. You will be able to see that you are getting the desired result for the first few URLs
Regex Demo
Option Explicit
Dim File, objReg, strTest, objMatches, objMatch, saveToFile, fso, outFile, strReplace, objShell, i
Set objShell = CreateObject("wscript.shell")
saveToFile = objShell.ExpandEnvironmentStrings("%windir%\Temp\test.txt")
Set File = CreateObject("MSXML2.XMLHTTP")
File.Open "GET","https://raw.githubusercontent.com/notracking/hosts-blocklists/master/domains.txt", False
File.send
If File.Status = 200 Then
Set objReg = New RegExp
strTest = File.responseText 'address=/abc.com/0.0.0.0
objReg.Global = True
objReg.Pattern = "address=/(.*?)/(\d{1,3}(?:\.\d{1,3}){3})" 'abc.com gets stored in Group 1 and the IP address gets stored in Group 2
Set objMatches = objReg.Execute(strTest)
For Each objMatch In objMatches
strReplace = "local zone: """ & objMatch.Submatches.Item(0) & """ redirect" & vbCrLf &_
"local data: """ & objMatch.Submatches.Item(0) & " 86400 in A " & objMatch.Submatches.Item(1)&"""" & vbCrLf
strTest = Replace(strTest,objMatch.Value,strReplace)
'Uncomment the following code to see the result for the 1st 5 URLs, if the whole thing is taking too long to get executed
'i=i+1
'If(i>5) Then
' Exit for
'End If
Next
set objReg = Nothing
'**********************************************************************************************
' Write content
'**********************************************************************************************
Set fso = CreateObject("scripting.filesystemobject")
Set outFile = fso.OpenTextFile(saveToFile,2,True)
outFile.Write strTest
outFile.Close
End If
Output:
Here is the update of the code that works very well based on the response of #Gurman and the comment of #Ansgar Wiechers. Thank you for your help
Option Explicit
Dim File, objReg, strTest, RegExp, objMatches, objMatch, saveToFile, fso, outFile, strReplace, objShell, i
Set objShell = CreateObject("wscript.shell")
saveToFile = objShell.ExpandEnvironmentStrings("%windir%\Temp\test.txt")
Set File = CreateObject("MSXML2.XMLHTTP")
File.Open "GET","https://raw.githubusercontent.com/notracking/hosts-blocklists/master/domains.txt", False
File.send
If File.Status = 200 Then
'**********************************************************************************************
' Replace content for use with the file service.conf of soft Unbound_DNS
'
' address=/abc.com/0.0.0.0 to local-zone: "abc.com" redirect
' local-data: "abc.com 86400 IN A 0.0.0.0"
'**********************************************************************************************
strTest = File.responseText
Set RegExp = CreateObject("VBScript.RegExp")
RegExp.IgnoreCase = True
RegExp.Global = True
RegExp.Pattern = "address=/(.*?)/(\d{1,3}(?:\.\d{1,3}){3})"
strReplace = "local-zone: ""$1"" redirect" & vbCrLf & "local-data: ""$1 86400 IN A $2"""
strTest = RegExp.Replace(strTest, strReplace)
Set RegExp = Nothing
'**********************************************************************************************
' Write content
'**********************************************************************************************
Set fso = CreateObject("scripting.filesystemobject")
Set outFile = fso.OpenTextFile(saveToFile,2,True)
outFile.Write strTest
outFile.Close
End If

vbscript adding qoutes to base64 converted string

I got some script to convert string to base64 and write encoded data to text file that's all goes fine and result stored in encoded.txt but I need each line to be double quoted at the start and '& _' with double quotes at the end so how to make this script do that automatically for each line? here is my script
Option Explicit
Const fsDoOverwrite = true
Const fsAsASCII = false
Const adTypeBinary = 1
Dim objFSO
Dim objFileOut
Dim objXML
Dim objDocElem
Dim objStream
Set objStream = CreateObject("ADODB.Stream")
objStream.Type = adTypeBinary
objStream.Open()
objStream.LoadFromFile(Wscript.scriptfullname)
Set objXML = CreateObject("MSXml2.DOMDocument")
Set objDocElem = objXML.createElement("Base64Data")
objDocElem.dataType = "bin.base64"
objDocElem.nodeTypedValue = objStream.Read()
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFileOut = objFSO.CreateTextFile("encoded.txt", fsDoOverwrite, fsAsASCII)
objFileOut.Write objDocElem.text
objFileOut.Close()
Set objFSO = Nothing
Set objFileOut = Nothing
Set objXML = Nothing
Set objDocElem = Nothing
Set objStream = Nothing
Sub encodeFileBase64( inputFile, outputFile )
Const fsDoOverwrite = True
Const fsAsASCII = False
Const adTypeBinary = 1
Dim stream, strBuffer
Set stream = WScript.CreateObject("ADODB.Stream")
With stream
.Type = adTypeBinary
.Open
.LoadFromFile inputFile
End With
With WScript.CreateObject("MSXML2.DOMDocument").CreateElement("Base64Data")
.dataType = "bin.base64"
.nodeTypedValue = stream.Read()
strBuffer = .Text
End With
stream.Close
With New RegExp
.Multiline = True
.Global = True
.IgnoreCase = False
.Pattern = "[\r\n]+(?=[0-9A-Za-z])"
strBuffer = Chr(34) & .Replace(strBuffer, Chr(34) & " & _" & vbCrLf & Chr(34) ) & Chr(34)
End With
WScript.CreateObject("Scripting.FileSystemObject").CreateTextFile( outputFile, fsDoOverwrite, fsAsASCII ).Write strBuffer
End Sub
encodeFileBase64 WScript.ScriptFullName, WScript.ScriptFullName & ".b64"
This will use a regular expression object to replace all intermediate line endings with the adecuated line termination/start and two aditional quotes, one at the start and one at the end.
Split the text by a line break, then loop through and put it all back together while you add the quotes. (not tested, but probably close, code follows; there is a strong chance you'll need to find the right type of line feed for your situation - I picked vbCr as an example):
allTextArray = SPLIT(originalText, vbCr)
For i=0 to UBound(allTextArray)
allTextWithQuotes = allTextWithQuotes & """" & allTextArray(i) & """"
Next

subscript out of range error in vbscript

Can someone look at the below script and tell me why it's throwing this error subscript out of range error in vbscript ..In the text file there are two entries it writes to the file correctly but then it throws an error while exiting the loop so it never calls the other function..I think it's trying to run 3 times but there are just 2 entries in the text file
The text file is in this format
Format.css Shared
Design.css Shared
Dim strInputPath1
Dim txsInput1,txsOutput
Dim FSO
Dim Filename
Set FSO = CreateObject("Scripting.FileSystemObject")
strOutputPath = "C:\txt3.txt"
Set txsOutput = FSO.CreateTextFile(strOutputPath)
Set re = New RegExp
re.Pattern = "\s+"
re.Global = True
Set f = FSO.OpenTextFile("C:\Users\spadmin\Desktop\Main\combination.txt")
Do Until f.AtEndOfStream
tokens = Split(Trim(re.Replace(f.ReadLine, " ")))
extension = Split(tokens(0),".")
strInputPath1 = "C:\inetpub\wwwroot\Test\files\" & tokens(1) & "\" & extension(1) & "\" & tokens(0)
Set txsInput1 = FSO.OpenTextFile(strInputPath1, 1)
WScript.Echo strInputPath1
txsOutput.Writeline txsInput1.ReadAll
Loop
WScript.Echo "Calling"
txsInput1.Close
txsOutput.Close
f.Close
Call CreateCSSFile()
''''''''''''''''''''''''''''''''''''
' Merge Css Files
''''''''''''''''''''''''''''''''''''
Sub CreateCSSFile()
WScript.Echo "Called"
Dim FilenameCSS
Dim strInputPathCSS
Dim txsInputCSS,txsOutputCSS
Dim FSOCSS
Set FSOCSS = CreateObject("Scripting.FileSystemObject")
strOutputPathCSS = "C:\txt4.txt"
Set txsOutputCSS = FSOCSS.CreateTextFile(strOutputPath)
Set re = New RegExp
re.Pattern = "\s+"
re.Global = True
Set fCSS = FSOCSS.OpenTextFile("C:\Users\spadmin\Desktop\TestingTheWebService\combination.txt")
Do Until fCSS.AtEndOfStream
tokensCSS = Split(Trim(re.Replace(fCSS.ReadLine, " ")))
extensionCSS = Split(tokensCSS(0),".")
strInputPathCSS = "C:\inetpub\wwwroot\EpsShared\c\" & tokensCSS(1) & "\" & extensionCSS(1) & "\" & tokensCSS(0)
Set txsInputCSS = FSOCSS.OpenTextFile(strInputPathCSS, 1)
txsOutputCSS.Writeline txsInputCSS.ReadAll
Loop
fCSS.Close
txsInputCSS.Close
txsOutputCSS.Close
Set FSOCSS = Nothing
End Sub
If your file contains trailing blank lines, applying Split() may return arrays with less than 2 elements. In that case token(1) should throw a 'subscript out of range' error.
You should always check, if Split() workes as expected:
tokens = Split(Trim(re.Replace(f.ReadLine, " ")))
If 1 = UBound(tokens) Then
extension = Split(tokens(0),".")
If 1 = UBound(extension) Then
strInputPath1 = "..." & tokens(1) & "..."
Else
... parse error ...
End If
Else
... parse error or just trailing blank lines? ...
End If

Export sheet as UTF-8 CSV file (using Excel-VBA)

I would like to export a file I have created in UTF-8 CSV using VBA. From searching message boards, I have found the following code that converts a file to UTF-8 (from this thread):
Sub SaveAsUTF8()
Dim fsT, tFileToOpen, tFileToSave As String
tFileToOpen = InputBox("Enter the name and location of the file to convert" & vbCrLf & "With full path and filename ie. C:\MyFolder\ConvertMe.Txt")
tFileToSave = InputBox("Enter the name and location of the file to save" & vbCrLf & "With full path and filename ie. C:\MyFolder\SavedAsUTF8.Txt")
tFileToOpenPath = tFileToOpen
tFileToSavePath = tFileToSave
Set fsT = CreateObject("ADODB.Stream"): 'Create Stream object
fsT.Type = 2: 'Specify stream type – we want To save text/string data.
fsT.Charset = "utf-8": 'Specify charset For the source text data.
fsT.Open: 'Open the stream
fsT.LoadFromFile tFileToOpenPath: 'And write the file to the object stream
fsT.SaveToFile tFileToSavePath, 2: 'Save the data to the named path
End Sub
However, this code only converts a non-UTF-8 file to UTF-8. If I were to save my file in non-UTF-8 and then convert it to UTF-8, it would have already lost all the special characters it contained, thus rendering the process pointless!
What I'm looking to do is save an open file in UTF-8 (CSV). Is there any way of doing this with VBA?
n.b. I have also asked this question on the 'ozgrid' forum. Will close both threads together if I find a solution.
Finally in Office 2016, you can simply savs as CSV in UTF8.
Sub SaveWorkSheetAsCSV()
Dim wbNew As Excel.Workbook
Dim wsSource As Excel.Worksheet, wsTemp As Excel.Worksheet
Dim name As String
Set wsSource = ThisWorkbook.Worksheets(1)
name = "test"
Application.DisplayAlerts = False 'will overwrite existing files without asking
Set wsTemp = ThisWorkbook.Worksheets(1)
Set wbNew = ActiveWorkbook
Set wsTemp = wbNew.Worksheets(1)
wbNew.SaveAs name & ".csv", xlCSVUTF8 'new way
wbNew.Close
Application.DisplayAlerts = True
End Sub
This will save the worksheet 1 into csv named test.
Update of this code. I used this one to change all .csv files in a specified folder (labeled "Bron") and save them as csv utf-8 in another folder (labeled "doel")
Sub SaveAsUTF8()
Dim fsT As Variant, tFileToOpen As String, tFileToSave As String
Dim Message As String
Dim wb As Workbook
Dim fileName As String
Set wb = ActiveWorkbook
With Application
.ScreenUpdating = False
.DisplayAlerts = False
End With
Message = "Source folder incorrect"
SourceFolder = wb.Worksheets("Menu").Range("Bron") & "\"
If Dir(SourceFolder, vbDirectory) = "" Or IsEmpty(SourceFolder) Then GoTo errorhandler
Message = "Target folder incorrect"
TargetFolder = wb.Worksheets("Menu").Range("Doel") & "\"
If Dir(TargetFolder, vbDirectory) = "" Or IsEmpty(TargetFolder) Then GoTo errorhandler
fileName = Dir(SourceFolder & "\*.csv", vbNormal)
Message = "No files available."
If Len(fileName) = 0 Then GoTo errorhandler
Do Until fileName = ""
tFileToOpen = SourceFolder & fileName
tFileToSave = TargetFolder & fileName
tFileToOpenPath = tFileToOpen
tFileToSavePath = tFileToSave
Set fsT = CreateObject("ADODB.Stream"): 'Create Stream object
fsT.Type = 2: 'Specify stream type – we want To save text/string data.
fsT.Charset = "utf-8": 'Specify charset For the source text data.
fsT.Open: 'Open the stream
fsT.LoadFromFile tFileToOpenPath: 'And write the file to the object stream
fsT.SaveToFile tFileToSavePath, 2: 'Save the data to the named path
fileName = Dir()
Loop
Message = "Okay to remove all old files?"
If QuestionMessage(Message) = False Then
GoTo the_end
Else
On Error Resume Next
Kill SourceFolder & "*.csv"
On Error GoTo errorhandler
End If
the_end:
With Application
.ScreenUpdating = True
.DisplayAlerts = True
End With
Exit Sub
errorhandler:
With Application
.ScreenUpdating = True
.DisplayAlerts = True
End With
CriticalMessage (Message)
Exit Sub
End Sub
'----------
Function CriticalMessage(Message As String)
MsgBox Message
End Function
'----------
Function QuestionMessage(Message As String)
If MsgBox(Message, vbQuestion + vbYesNo) = vbNo Then
QuestionMessage = False
Else
QuestionMessage = True
End If
End Function
Here's my solution based on Excel VBA - export to UTF-8, which user3357963 linked to earlier. It includes macros for exporting a range and a selection.
Option Explicit
Const strDelimiter = """"
Const strDelimiterEscaped = strDelimiter & strDelimiter
Const strSeparator = ","
Const strRowEnd = vbCrLf
Const strCharset = "utf-8"
Function CsvFormatString(strRaw As String) As String
Dim boolNeedsDelimiting As Boolean
boolNeedsDelimiting = InStr(1, strRaw, strDelimiter) > 0 _
Or InStr(1, strRaw, Chr(10)) > 0 _
Or InStr(1, strRaw, strSeparator) > 0
CsvFormatString = strRaw
If boolNeedsDelimiting Then
CsvFormatString = strDelimiter & _
Replace(strRaw, strDelimiter, strDelimiterEscaped) & _
strDelimiter
End If
End Function
Function CsvFormatRow(rngRow As Range) As String
Dim arrCsvRow() As String
ReDim arrCsvRow(rngRow.Cells.Count - 1)
Dim rngCell As Range
Dim lngIndex As Long
lngIndex = 0
For Each rngCell In rngRow.Cells
arrCsvRow(lngIndex) = CsvFormatString(rngCell.Text)
lngIndex = lngIndex + 1
Next rngCell
CsvFormatRow = Join(arrCsvRow, ",") & strRowEnd
End Function
Sub CsvExportRange( _
rngRange As Range, _
Optional strFileName As Variant _
)
Dim rngRow As Range
Dim objStream As Object
If IsMissing(strFileName) Or IsEmpty(strFileName) Then
strFileName = Application.GetSaveAsFilename( _
InitialFileName:=ActiveWorkbook.Path & "\" & rngRange.Worksheet.Name & ".csv", _
FileFilter:="CSV (*.csv), *.csv", _
Title:="Export CSV")
End If
Set objStream = CreateObject("ADODB.Stream")
objStream.Type = 2
objStream.Charset = strCharset
objStream.Open
For Each rngRow In rngRange.Rows
objStream.WriteText CsvFormatRow(rngRow)
Next rngRow
objStream.SaveToFile strFileName, 2
objStream.Close
End Sub
Sub CsvExportSelection()
CsvExportRange ActiveWindow.Selection
End Sub
Sub CsvExportSheet(varSheetIndex As Variant)
Dim wksSheet As Worksheet
Set wksSheet = Sheets(varSheetIndex)
CsvExportRange wksSheet.UsedRange
End Sub

Resources