我可以用UTF-8输出excel数据吗?
我通过Excelmacros(VBScript)导出Microsoft Excel数据。 由于文件是lua脚本,我将其导出为UTF-8。 我可以在Excel中制作UTF-8的唯一方法就是使用adodb.stream
set fileLua = CreateObject("adodb.stream") fileLua.Type = 2 fileLua.Mode = 3 fileLua.Charset = "UTF-8" fileLua.Open fileLua.WriteText("test") fileLua.SaveToFile("Test.lua") fileLua.flush fileLua.Close
我想从Test.lua中删除BOM,但我不知道如何。 (因为Test.lua有一些unicode文本,我必须使用UTF-8格式。)
你知道如何在excel文件中制作没有BOM的UTF-8文件吗? 提前致谢。
我也有同样的问题:必须将数据从Excel(Office 2003,VBA6.5)导出到UTF-8编码的文件。 从你的问题find答案! 在我的例子下面,我也使用技巧#2从boost的(谢谢!)答案剥离BOM。 我没有得到#1的工作,从来没有尝试#3。
Sub WriteUTF8WithoutBOM() Dim UTFStream As Object Set UTFStream = CreateObject("adodb.stream") UTFStream.Type = adTypeText UTFStream.Mode = adModeReadWrite UTFStream.Charset = "UTF-8" UTFStream.LineSeparator = adLF UTFStream.Open UTFStream.WriteText "This is an unicode/UTF-8 test.", adWriteLine UTFStream.WriteText "First set of special characters: öäåñüûú€", adWriteLine UTFStream.WriteText "Second set of special characters: qwertzuiopõúasdfghjkléáûyxcvbnm\|Ä€Í÷×äðÐ[]í³£;?¤>#&@{}<;>*~¡^¢°²`ÿ´½¨¸0", adWriteLine UTFStream.Position = 3 'skip BOM Dim BinaryStream As Object Set BinaryStream = CreateObject("adodb.stream") BinaryStream.Type = adTypeBinary BinaryStream.Mode = adModeReadWrite BinaryStream.Open 'Strips BOM (first 3 bytes) UTFStream.CopyTo BinaryStream 'UTFStream.SaveToFile "d:\adodb-stream1.txt", adSaveCreateOverWrite UTFStream.Flush UTFStream.Close BinaryStream.SaveToFile "d:\adodb-stream2.txt", adSaveCreateOverWrite BinaryStream.Flush BinaryStream.Close End Sub
我使用的ADOstream对象引用 。
一些可能性:
-
将文本以UTF-8,Type = 2的forms放入缓冲区,然后设置Type = 1(以二进制forms)并写出。 这可能会说服ADODB.Stream跳过添加BOM。
-
创build另一个缓冲区,types为二进制,并使用CopyTo将数据从BOM之后的一个点复制到该缓冲区。
-
再次使用Scripting.FileSystemObject读取文件,修剪BOM,再次写出
如果有其他人正在与adTypeText常量挣扎,则需要在“工具” – >“引用”下包含“Microsoft ActiveX Data Objects 2.5 Object Library”。
如果你喜欢本地的T-SQL,而不是外部代码
DECLARE @FILE_NAME VARCHAR(255) = 'd:\utils\test.xml' --drive:\path\filename\ DECLARE @FILE_DATA VARCHAR(MAX) = '<?xml version="1.0" encoding="UTF-8"?>test</xml>' --binary as varchar(max) DECLARE @FILE_NAME_TO VARCHAR(255) --Temp name for text stream DECLARE @FSO_ID_TXTSTRM INT --Text Stream DECLARE @FSO_ID_BINSTRM INT --Binary Stream DECLARE @RC INT EXEC @RC = sp_OACreate 'ADODB.Stream', @FSO_ID_TXTSTRM OUTPUT EXEC @RC = sp_OASetProperty @FSO_ID_TXTSTRM, 'Type', 2 --1 = binary, 2 = text EXEC @RC = sp_OASetProperty @FSO_ID_TXTSTRM, 'Mode', 3 --0 = not set, 1 read, 2 write, 3 read/write EXEC @RC = sp_OASetProperty @FSO_ID_TXTSTRM, 'Charset', 'UTF-8' --'ISO-8859-1' EXEC @RC = sp_OASetProperty @FSO_ID_TXTSTRM, 'LineSeparator', 'adLF' EXEC @RC = sp_OAMethod @FSO_ID_TXTSTRM, 'Open' EXEC @RC = sp_OAMethod @FSO_ID_TXTSTRM, 'WriteText', NULL, @FILE_DATA --text method --Create binary stream EXEC @RC = sp_OACreate 'ADODB.Stream', @FSO_ID_BINSTRM OUTPUT EXEC @RC = sp_OASetProperty @FSO_ID_BINSTRM, 'Type', 1 --1 = binary, 2 = text EXEC @RC = sp_OAMethod @FSO_ID_BINSTRM, 'Open' EXEC @RC = sp_OASetProperty @FSO_ID_BINSTRM, 'Mode', 3 --0 = not set, 1 read, 2 write, 3 read/write --Move 3 positions forward in text stream (BOM is first 3 positions) EXEC @RC = sp_OASetProperty @FSO_ID_TXTSTRM, 'Position', 3 --Copy text stream to binary stream EXEC @RC = sp_OAMethod @FSO_ID_TXTSTRM, 'CopyTo', NULL, @FSO_ID_BINSTRM --Commit data and close text stream EXEC @RC = sp_OAMethod @FSO_ID_TXTSTRM, 'Flush' EXEC @RC = sp_OAMethod @FSO_ID_TXTSTRM, 'Close' EXEC @RC = sp_OADestroy @FSO_ID_TXTSTRM --Save binary stream to file and close EXEC @RC = sp_OAMethod @FSO_ID_BINSTRM, 'SaveToFile', NULL, @FILE_NAME, 2 --1 = notexist 2 = overwrite EXEC @RC = sp_OAMethod @FSO_ID_BINSTRM, 'Close' EXEC @RC = sp_OADestroy @FSO_ID_BINSTRM
这是另一个BOM处理黑客,从一个答案重叠您的问题。
对于迟到的答案抱歉 – 对于遇到字节顺序标记的其他人来说更是如此 – 而且这个问题的页面浏览告诉我,你的问题与几个相关的问题有关:在VBA中写一个无BOM文件是非常困难的 – 即使是一些常用的stream库,也会将BOM存储在输出中,无论您是否要求input。
我说我的答案是“重叠”,因为下面的代码解决了一个稍微不同的问题 – 主要目的是为具有异构文件集合的文件夹编写一个Schema文件 – 但这是一个BOM清除和无BOM文件的工作示例书面使用 ,相关部分清晰标注。
关键的function是我们遍历一个文件夹中的所有'.csv'文件,我们用前四个字节的快速半字节来testing每个文件:我们只承担剥离标记的繁重任务,如果我们看到一个。
我们正在使用原始C的底层文件处理代码。我们必须一直使用字节数组,因为您在VBA中执行的所有操作都会将字节顺序标记embedded到stringvariables 。
所以,没有进一步的adodb,这里是代码:
BOM-处理schema.ini文件中的文本文件的代码:
Public Sub SetSchema(strFolder As String) 在错误恢复下一步
将Schema.ini文件写入数据文件夹。
'这是必要的,如果我们没有registry权限设置 '正确'ImportMixedTypes =文本'registry值,这将覆盖IMEX = 1
'代码还检查ANSI或UTF-8和UTF-16文件,并应用一个 'CharacterSet(UNICODE | ANSI)的一个可怕的黑客可用的设置。
'OEM代码页定义文本不支持:需要进一步编码
'...如果我们看到它们,我们会删除字节顺序标记(ORB SQL) '文本文件提供程序不能处理UTF-16或UTF-8文件中的BOM
'未实现:处理制表符分隔的文件或其他分隔符。 该 '代码假设一个包含列的标题行,指定'扫描所有行',和 如果数据types是混合的,则'强制'将列读为文本''。
Dim strSchema As String Dim strFile As String Dim hndFile As Long Dim arrFile()As Byte Dim arrBytes(0 To 4)As Byte
如果右(strFolder,1)<>“\”那么strFolder = strFolder&“\”
当你用通配符调用它时,Dir()是一个迭代器函数:
strFile = VBA.FileSystem.Dir(strFolder&“* .csv”)
当Len(strFile)> 0时执行
hndFile = FreeFile 打开strFolder&strFile作为二进制文件#hndFile 获取#hndFile,,arrBytes closures#hndFile
strSchema = strSchema&“[”&strFile&“]”&vbCrLf strSchema = strSchema&“Format = CSVDelimited”&vbCrLf strSchema = strSchema&“ImportMixedTypes = Text”&vbCrLf strSchema = strSchema&“MaxScanRows = 0”&vbCrLf
如果arrBytes(2)= 0或arrBytes(3)= 0那么这是一个破解 strSchema = strSchema&“CharacterSet = UNICODE”&vbCrLf 其他 strSchema = strSchema&“CharacterSet = ANSI”&vbCrLf 万一
strSchema = strSchema&“ColNameHeader = True”&vbCrLf strSchema = strSchema&vbCrLf
'************************************************* **********
'BOM处理 - 字节顺序标记破坏Access OLEDB文本提供程序:
如果arrBytes(0)=&HFE和arrBytes(1)=&HFF _ 或者arrBytes(0)=&HFF和arrBytes(1)=&HFE那么
hndFile = FreeFile 打开strFolder&strFile作为二进制文件#hndFile ReDim arrFile(0到LOF(hndFile) - 1) 获取#hndFile,arrFile closures#hndFile
BigReplace arrFile,arrBytes(0)&arrBytes(1),“”
hndFile = FreeFile 打开strFolder&strFile作为二进制文件#hndFile 把#hndFile,,arrFile closures#hndFile 擦除arrFile
ElseIf arrBytes(0)=&HEF And arrBytes(1)=&HBB and arrBytes(2)=&HBF Then
hndFile = FreeFile 打开strFolder&strFile作为二进制文件#hndFile ReDim arrFile(0到LOF(hndFile) - 1) 获取#hndFile,arrFile closures#hndFile BigReplace arrFile,arrBytes(0)&arrBytes(1)&arrBytes(2),“”
hndFile = FreeFile 打开strFolder&strFile作为二进制文件#hndFile 把#hndFile,,arrFile closures#hndFile 擦除arrFile
万一
'************************************************* **********
strFile =“” strFile = Dir
循环
如果Len(strSchema)> 0那么
strFile = strFolder&“Schema.ini”
hndFile = FreeFile 打开strFile对于二进制为#hndFile 把#hndFile,strSchema closures#hndFile
万一
结束小组
Public Sub BigReplace(ByRef arrBytes()As Byte,_ ByRef SearchFor As String,_ ByRef ReplaceWith As String) 在错误恢复下一步
Dim varSplit As Variant
varSplit = Split(arrBytes,SearchFor) arrBytes =join$(varSplit,ReplaceWith)
擦除varSplit
结束小组
如果您知道可以将Byte数组分配给VBA.String,则代码更容易理解,反之亦然。 BigReplace()函数是一种避免VBA的低效率string处理,特别是分配的黑客攻击:如果以其他方式执行,会发现大文件会导致严重的内存和性能问题。
我一直在使用user272735的方法一年,当我发现它在文件的末尾添加了一个LF。 我没有注意到这个额外的LF,直到我做了一些非常详细的testing,所以这不是一个重要的错误。 但是,我的最新版本丢弃了LF,以防万一它变得重要。
Public Sub PutTextFileUtf8(ByVal PathFileName As String, ByVal FileBody As String) ' Outputs FileBody as a text file (UTF-8 encoding without leading BOM) ' named PathFileName ' Needs reference to "Microsoft ActiveX Data Objects nn Library" ' Addition to original code says version 2.5. Tested with version 6.1. ' 1Nov16 Copied from http://stackoverflow.com/a/4461250/973283 ' but replaced literals with parameters. ' 15Aug17 Discovered routine was adding an LF to the end of the file. ' Added code to discard that LF. ' References: http://stackoverflow.com/a/4461250/973283 ' https://www.w3schools.com/asp/ado_ref_stream.asp Dim BinaryStream As Object Dim UTFStream As Object Set UTFStream = CreateObject("adodb.stream") UTFStream.Type = adTypeText UTFStream.Mode = adModeReadWrite UTFStream.Charset = "UTF-8" ' The LineSeparator will be added to the end of FileBody. It is possible ' to select a different value for LineSeparator but I can find nothing to ' suggest it is possible to not add anything to the end of FileBody UTFStream.LineSeparator = adLF UTFStream.Open UTFStream.WriteText FileBody, adWriteLine UTFStream.Position = 3 'skip BOM Set BinaryStream = CreateObject("adodb.stream") BinaryStream.Type = adTypeBinary BinaryStream.Mode = adModeReadWrite BinaryStream.Open UTFStream.CopyTo BinaryStream ' Oriinally I planned to use "CopyTo Dest, NumChars" to not copy the last ' byte. However, NumChars is described as an integer whereas Position is ' described as Long. I was concerned by "integer" they mean 16 bits. 'Debug.Print BinaryStream.Position BinaryStream.Position = BinaryStream.Position - 1 BinaryStream.SetEOS 'Debug.Print BinaryStream.Position UTFStream.Flush UTFStream.Close Set UTFStream = Nothing BinaryStream.SaveToFile PathFileName, adSaveCreateOverWrite BinaryStream.Flush BinaryStream.Close Set BinaryStream = Nothing End Sub