首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在VBA (Excel)中保存没有BOM编码的UTF-8文本文件(CSV)?

如何在VBA (Excel)中保存没有BOM编码的UTF-8文本文件(CSV)?
EN

Stack Overflow用户
提问于 2015-04-06 08:50:19
回答 2查看 19.6K关注 0票数 5

这是我的第一个问题。对我下面问题的答案似乎是,获得UTF-8 (和UTF-8没有BOM)编码的唯一解决方案是使用ADODB.Stream对象。

标题中我的新问题的答案是以代码形式发布的。

我坐在这里,试图将一个Save表作为一个带有VBA宏的.CSV_-文件。

但是,我想知道我是使用ADODB/ADODB.Stream还是只使用.SaveAs Fileformat:=xlCSV__。我尝试过搜索它,似乎我找不到哪种方法是“最好”的答案。我需要用逗号分隔,UTF-8和双引号("")作为文本标识符。

当您使用Fileformat:=__时,SaveAs UTF-8是不可能的,因为xlCSV没有使用该编码,这是正确的吗?是的,这是正确的。。

请看我对解决方案的回答。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-04-02 21:43:34

所以我再次遇到了需要这段代码的情况,我读了评论和Leonard的答案,这让我更新了我的代码,并提供了更好的描述。

此代码将转换您的Excel表,并将它保存为一个CSV文件与UTF-8没有BOM编码。我在一个网站上找到了这段代码,所以我不会因此而受到赞扬。无BOM链路的CSV

代码语言:javascript
运行
复制
Option Explicit

Sub CSVFileAsUTF8WithoutBOM()
Dim SrcRange As Range
Dim CurrRow As Range
Dim CurrCell As Range
Dim CurrTextStr As String
Dim ListSep As String
Dim FName As Variant
Dim UTFStream As Object
Dim BinaryStream As Object

' ADO Constants
Const adTypeBinary = 1 ' The stream contains binary data
Const adTypeText = 2 ' The stream contains text data (default)
Const adWriteLine = 1 ' write text string and a line separator (as defined by the LineSeparator property) to the stream.
Const adModeReadWrite = 3 ' Read/write
Const adLF = 10 ' Line feed only - default is carriage return line feed (adCRLF)
Const adSaveCreateOverWrite = 2 ' Overwrites the file with the data from the currently open Stream object, if the file already exists

' Open this workbook location
ChDrive Left(ThisWorkbook.Path, 1)
ChDir ThisWorkbook.Path

' ask for file name and path
  FName = Application.GetSaveAsFilename("", "CSV File (*.csv), *.csv")

' prepare UTF-8 stream
  Set UTFStream = CreateObject("adodb.stream")
  UTFStream.Type = adTypeText
  UTFStream.Mode = adModeReadWrite
  UTFStream.Charset = "UTF-8"
  UTFStream.LineSeparator = adLF
  UTFStream.Open

  'set field separator
  ListSep = ";"
  'set source range with data for csv file
  If Selection.Cells.Count > 1 Then
    Set SrcRange = Selection
  Else
    Set SrcRange = ActiveSheet.UsedRange
  End If

  For Each CurrRow In SrcRange.Rows
    'enclose each value with quotation marks and escape quotation marks in values
    CurrTextStr = ""
    For Each CurrCell In CurrRow.Cells
      CurrTextStr = CurrTextStr & """" & Replace(CurrCell.Value, """", """""") & """" & ListSep
    Next
    'remove ListSep after the last value in line
    While Right(CurrTextStr, 1) = ListSep
      CurrTextStr = Left(CurrTextStr, Len(CurrTextStr) - 1)
    Wend
    'add line to UTFStream
    UTFStream.WriteText CurrTextStr, adWriteLine ' Writes character data to a text Stream object
  Next

  'skip BOM
  UTFStream.Position = 3 ' sets or returns a long value that indicates the current position (in bytes) from the beginning of a Stream object

  'copy UTFStream to BinaryStream
  Set BinaryStream = CreateObject("adodb.stream")
  BinaryStream.Type = adTypeBinary
  BinaryStream.Mode = adModeReadWrite
  BinaryStream.Open ' Opens a Stream object

  'Strips BOM (first 3 bytes)
  UTFStream.CopyTo BinaryStream ' Copies a specified number of characters/bytes from one Stream object into another Stream object

  UTFStream.Flush ' Sends the contents of the Stream buffer to the associated underlying object
  UTFStream.Close ' Closes a Stream object

  'save to file
  BinaryStream.SaveToFile FName, adSaveCreateOverWrite
  BinaryStream.Flush ' Sends the contents of the Stream buffer to the associated underlying object
  BinaryStream.Close ' Closes a Stream object

End Sub
票数 2
EN

Stack Overflow用户

发布于 2018-03-21 01:24:52

谢谢你贴出这个问题和解决方案。这对我有很大帮助。是的,我还发现SaveAs没有在UTF8中保存CSV文件。在我的例子中,它使用shift-JIS。adodb.stream对我来说很好。

但是,我不知道为什么,但我必须声明您在代码中使用的一些常量(enum)。(我对VBA非常陌生,所以我可能忽略了为什么会发生这种情况)。我在函数的开头添加了这个,然后它完美地工作了:

代码语言:javascript
运行
复制
  Const adTypeText = 2
  Const adModeReadWrite = 3
  Const adTypeBinary = 1
  Const adLF = 10
  Const adSaveCreateOverWrite = 2
  Const adWriteLine = 1

我从微软文档中得到了价值。再一次,谢谢!

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29468070

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档