0

I have a range of cells that I am trying to save via macro as text file. The code below works, but I want it to save as UTF-8, since the some cells in the range contain the character enye (ñ):

Sub CreateTxtFiles()
Dim rng As Range
Dim ff As Long
Dim LastRow As Long
Dim i As Long
    LastRow = Range("AU" & Rows.Count).End(xlUp).Row
         
    Open "C:\Users\user1\Desktop\temp\output.txt" For Output As #ff
    
    For i = 2 To LastRow
        Set rng = Range("AU" & i)
        
        Print #ff, "" & rng.Value & ""
        
    Next i
    
    Close #ff
    
End Sub

I have seen this code in one of the solutions, but since I am a novice in VBA, I do not know how to integrate this code with my current code above:

Dim fsT As Object
Set fsT = CreateObject("ADODB.Stream")
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 And write binary data To the object
fsT.WriteText "special characters: äöüß"
fsT.SaveToFile sFileName, 2 'Save binary data To disk

How can I get the range to be exported as a UTF-8 text file?

JAT86
  • 997
  • 12
  • 24

1 Answers1

1

Please, try the next way:

Sub CreateUTFTxtFile() 'it looks to return UTF-16 LE-BOM
 Dim rng As Range, LastRow As Long, i As Long
 Dim fso As Object, MyFile As Object, boolUnicode As Boolean
 Dim myFileName As String
 
    myFileName = "C:\Users\user1\Desktop\temp\output.txt"
    LastRow = Range("AU" & rows.count).End(xlUp).row
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    boolUnicode = True
    Set MyFile = fso.CreateTextFile(myFileName, False, boolUnicode) 'open the file to write Unicode:
       For i = 2 To LastRow
         MyFile.WriteLine (Range("AU" & i).Value)
       Next i
    MyFile.Close
End Sub

Edited:

Please, test the next code. It will create a real UTF-8 text file. And the code should be fast:

Private Sub CreateUTFT8tFile() 'UTF-8 BOM for huge files...
 Dim rng As Range, LastRow As Long, i As Long
 Dim fso As Object, MyFile As Object, boolUnicode As Boolean
 Dim myFileName As String, myFileName2 As String, strText As String
 
    myFileName = "C:\Users\user1\Desktop\temp\outputUTF16.txt" 'temporary text container
    myFileName2 = "C:\Users\user1\Desktop\temp\output.txt"
    LastRow = Range("AU" & rows.count).End(xlUp).row
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    boolUnicode = True
    If dir(myFileName) <> "" Then Kill myFileName
    Set MyFile = fso.CreateTextFile(myFileName, False, boolUnicode) 'open the file to write UTF-16:
       For i = 2 To LastRow
         MyFile.WriteLine (Range("AU" & i).Value)
       Next i
    MyFile.Close
    strText = readTextUTF16$(myFileName)   'read UTF-16 file, used as container for the case of huge text content

    With CreateObject("ADODB.Stream")
       .Charset = "utf-8": .Open
        .WriteText strText
        .SaveToFile myFileName2, 2          'convert to UTF-8 BOM
    End With
End Sub
Function readTextUTF16$(f)
    With CreateObject("ADODB.Stream")
        .Charset = "utf-16": .Open
        .LoadFromFile f
        readTextUTF16$ = .ReadText
    End With
End Function

If you do not like UTF-8 BOM, please use the next version:

Sub CreateUTF8TxtFilesNoBOM() 'UTF-8 no BOM
 Dim LastRow As Long, oStream As Object
 Dim myFileName As String, arrTxt, strTxt As String
 
    myFileName = "C:\Users\user1\Desktop\temp\output.txt"
    LastRow = Range("AU" & rows.count).End(xlUp).row
    arrTxt = Application.Transpose(Range("AU2:AU" & LastRow).Value)
    strTxt = Join(arrTxt, vbCrLf)
    
    WriteUTF8WithoutBOM strTxt, myFileName
End Sub
Function WriteUTF8WithoutBOM(strText As String, fileName As String)
  Dim UTFStream As Object, BinaryStream As Object
  With CreateObject("adodb.stream")
     .Type = 2: .Mode = 3: .Charset = "UTF-8"
     .LineSeparator = -1
     .Open: .WriteText strText, 1
     .Position = 3 'skip BOM' !!!
     Set BinaryStream = CreateObject("adodb.stream")
         BinaryStream.Type = 1
         BinaryStream.Mode = 3
         BinaryStream.Open
        'Strips BOM (first 3 bytes)
        .CopyTo BinaryStream
        .Flush
    .Close
  End With
    BinaryStream.SaveToFile fileName, 2
    BinaryStream.Flush
    BinaryStream.Close
End Function
FaneDuru
  • 38,298
  • 4
  • 19
  • 27
  • @JAT86 Didn't you find some time to test the above piece of code? If tested, didn't it do what you need? – FaneDuru Aug 18 '21 at 13:18
  • thank you for the code. Using your code, I opened the exported text file in Notepad++ and the range was exported correctly, but the character encoding shows it is UTF-16 LE-BOM instead of UTF-8. – JAT86 Aug 18 '21 at 14:09
  • @JAT86 Ups... I used such a piece of code to correctly save text in my language with diacritics. I will post a real UTF-8 variant in some minutes... – FaneDuru Aug 18 '21 at 18:17
  • I tried both the UTF-8 BOM and no BOM codes but both got an error `Run-time error 13 Type Mismatch` and Excel highlighted the line `arrTxt = Application.Transpose(Range("AU2:AU" & LastRow).Value)`. – JAT86 Aug 19 '21 at 18:28
  • @JAT86 Is there any data in column "AU:AU"? When stopped on error and move the cursor over `LastRow`, what does it show? Did you try the codes exactly as they are? – FaneDuru Aug 19 '21 at 18:31
  • @JAT86 If the column in discussion really contains data, how many rows are on it? More than 65000? – FaneDuru Aug 19 '21 at 18:37
  • Thank you for being patient with me. Yes, there is data in AU2 up to AU15000. AU2 contains a complex formula that generates a value, and I have filled it down up to AU15000. Each cell in column AU has about 12,000 characters. – JAT86 Aug 20 '21 at 18:15
  • Yes, I tried the exact codes except for the output directory. The same unknown error shows up: `Run-time error 13 Type Mismatch` with `arrTxt = Application.Transpose(Range("AU2:AU" & LastRow).Value)` highlighted. – JAT86 Aug 20 '21 at 18:18
  • @JAT86 OK. This part of the code only builds a string `vbCrLf ` separated in a compact way. It may exceed the `Transpose` function limits. I will adapt the first code to build the string by iteration, which should be fast enough and offer you the possibility of testing the UTF-8 issue. I think I can do it in 5 to 10 minutes, but I am afraid of your reaction time, which looks to be excessively slow... :) – FaneDuru Aug 20 '21 at 18:27
  • @JAT86 I adapted the code returning UTF-8 BOM, in order to build the string by iteration. Please, copy also the function `buildString`. I made a function, in order to be used for the second code, too. Please, confirm that it returns what you need. If you will do it today, I will be very happy... :) – FaneDuru Aug 20 '21 at 18:46
  • Very sorry for the late reply. I tried using both updated codes, but the `Sub CreateUTF8TxtFile()` code gave an error of `Run-time error '14': Out of string space` and Excel highlighted `: Next i` in line `For i = 1 To UBound(arr): strX = strX & arr(i, 1) & vbCrLf: Next i`. I also tried `Sub CreateUTF8TxtFilesNoBOM()` and got the error `Run-time error '13': Type mismatch` with line `strTxt = Join(arrTxt, vbCrLf)` highlighted in yellow. – JAT86 Aug 21 '21 at 08:15
  • @JAT86 I told you, I tried adapting only UTF-8 BOM variant... I could not imagine that the code should process such a huge file. If not something confidential, can you share the workbook you try processing? In this way I will prepare a solution for the respective one. In the meantime, I will adapt again the same version, creating UTF-16, then opening it using "ADODB.Stream" and convert to UTF 16. I do not need such a code, but it sound like a challenge... – FaneDuru Aug 21 '21 at 16:35
  • @JAT86 Adapted... Only UTF-8 BOM variant, as I said. Please, confirm that it works. Otherwise, no sense to try adapting the last version (UTF-8 no BOM). Anyhow, if you can share the workbook you try processing, it is much more probable to find a specific solution... – FaneDuru Aug 21 '21 at 16:54
  • Unortunately, I cannot share the workbook due to confidentiality. I tried the UTF-8 BOM code on a single row, and it worked, but on 15000 rows, it throws an error: `Run-time error '2147024882' (8007000e):` Not enough storage to complete this operation.` with `readTextUTF16$ = .ReadText` highlighted. I think I will be able to make do with the UTF-16 LE-BOM code you had earlier provided. Thank you very much for your help. – JAT86 Aug 21 '21 at 17:53