Microsoft ExcelデータをExcelマクロ(VBScript)でエクスポートしています。ファイルは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でエンコードされたファイルにデータをエクスポートする必要があります。あなたの質問から答えを見つけました!ブーストの(ありがとう!)回答からトリック#2を使用して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
ADOストリームオブジェクト参照 私が使用しました。
他の誰かがadTypeText定数で苦労している場合は、「ツール」->「参照」の下に「Microsoft ActiveXデータオブジェクト2.5オブジェクトライブラリ」を含める必要があります。
いくつかの可能性:
テキストをUTF-8、Type = 2としてバッファーに入れますが、Type = 1(バイナリーとして)を設定し、それを書き出します。これは、BOMの追加をスキップするようにADODB.Streamを説得する可能性があります。
タイプバイナリとして別のバッファを作成し、CopyToを使用して、BOMの後のポイントからそのバッファにデータをコピーします。
Scripting.FileSystemObjectを使用してファイルを再度読み取り、BOMを切り取り、再度書き込みます
編集
Rellampecからのコメントにより、LFを削除するより良い方法がuser272735のメソッドによってファイルの最後に追加されたことがわかりました。新しいバージョンのルーチンを最後に追加しました。
元の投稿
User272735のメソッドを1年間首尾よく使用していて、ファイルの最後にLFが追加されていることを発見しました。このLFまで、私はいくつかの非常に詳細なテストを行ったので、これは重要なエラーではありませんが、最新のバージョンでは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 n.n 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
ルーチンの新しいバージョン
このバージョンでは、最初にLFを追加するのを回避するため、最後に追加された不要なLFを破棄するコードを省略しています。元のバージョンを末尾の文字を削除する手法に誰もが興味がある場合。
Public Sub PutTextFileUtf8NoBOM(ByVal PathFileName As String, ByVal FileBody As String)
' Outputs FileBody as a text file named PathFileName using
' UTF-8 encoding without leading BOM
' Needs reference to "Microsoft ActiveX Data Objects n.n 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.
' 11Oct17 Posted to StackOverflow
' 9Aug18 Comment from rellampec suggested removal of adWriteLine from
' WriteTest statement would avoid adding LF.
' 30Sep18 Amended routine to remove adWriteLine from WriteTest statement
' and code to remove LF from file. Successfully tested new version.
' 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"
UTFStream.Open
UTFStream.WriteText FileBody
UTFStream.Position = 3 'skip BOM
Set BinaryStream = CreateObject("adodb.stream")
BinaryStream.Type = adTypeBinary
BinaryStream.Mode = adModeReadWrite
BinaryStream.Open
UTFStream.CopyTo BinaryStream
UTFStream.Flush
UTFStream.Close
Set UTFStream = Nothing
BinaryStream.SaveToFile PathFileName, adSaveCreateOverWrite
BinaryStream.Flush
BinaryStream.Close
Set BinaryStream = Nothing
End Sub
これは、質問と重複する回答からの別のBOM廃棄ハックです。
遅い回答への謝罪-これはバイトオーダーマーカーに遭遇している他の人のための詳細です-この質問のページビューは、あなたの質問がいくつかの関連する問題に関連していることを教えてくれます:VBAでBOMフリーのファイルを書くのは驚くほど難しい-一般的なストリームライブラリの一部でも、要求したかどうかにかかわらず、出力にBOMを配置します。
以下のコードは少し異なる問題を解決しているため、私の答えは「オーバーラップ」と言います-主な目的は、異種のファイルコレクションを含むフォルダーのスキーマファイルを書き込むことですが、BOM削除およびBOMフリーファイルの実用的な例です書き込み 使用中で、関連するセグメントが明確にマークされています。
重要な機能は、フォルダー内のすべての「.csv」ファイルを反復処理し、最初の4バイトの短いニブルで各ファイルをテストすることです。マーカーを取り除くという面倒なタスクは、 1つ参照してください。
原始的なCの低レベルのファイル処理コードを使用しています。バイト配列を使用するまでは、 vBAで行う他のすべては、文字列変数の構造に埋め込まれたバイトオーダーマーカーを配置します。
したがって、さらにadodbを使わずに、コードを次に示します。
Public Sub SetSchema(strFolder As String) On Error Resume Next
'Schema.iniファイルをデータフォルダに書き込みます。
'これは、IMEX = 1を上書きする '正しい 'ImportMixedTypes = Text'レジストリ値を設定するレジストリ権限がない場合に必要です。
'このコードは、ANSIまたはUTF-8およびUTF-16ファイルもチェックし、恐ろしいハックでCharacterSet(UNICODE | ANSI)に '使用可能な設定を適用します。
'OEMコードページ定義のテキストはサポートされていません。さらにコーディングが必要です
'...そして、バイトオーダーマーカーが表示された場合、それらを取り除きます。テキストファイル用のOLEDB SQL 'プロバイダーは、UTF-16またはUTF-8のBOMを処理できませんファイル
'実装されていません:タブ区切りファイルまたはその他の区切り文字を処理しています。 'コードは列のあるヘッダー行を想定し、「すべての行をスキャンする」を指定し、 」はデータ型が混在している場合は「列をテキストとして読み取る」ことを強制します。
Dim strSchema As String Dim strFile As String Dim hndFile As Long Dim arrFile()As Byte Dim arrBytes(0 To 4)バイトとして
If Right(strFolder、1)<> "\" Then strFolder = strFolder& "\"
'Dir()は、ワイルドカードを使用して呼び出す場合の反復関数です。
strFile = VBA.FileSystem.Dir(strFolder& "* .csv")
Do While Len(strFile)> 0
hndFile = FreeFile バイナリのstrFolder&strFileを#hndFile として開く#hndFile、、arrBytes を閉じる#hndFile
strSchema = strSchema& "["&strFile& "]"&vbCrLf strSchema&strSchema& "Format = CSVDelimited"&vbCrLf strSchema = strSchema& "ImportMixedTypes = Text" &vbCrLf strSchema = strSchema& "MaxScanRows = 0"&vbCrLf
If arrBytes(2)= 0 Or arrBytes(3)= 0 Then 'これはハックです strSchema = strSchema& "CharacterSet = UNICODE"&vbCrLf Else strSchema = strSchema& "CharacterSet = ANSI"&vbCrLf End If
strSchema = strSchema& "ColNameHeader = True"&vbCrLf strSchema = strSchema&vbCrLf
'******************************************** ***************
'BOMの破棄-バイトオーダーマークにより、Access OLEDBテキストプロバイダーが壊れます。
if arrBytes(0)=&HFE And arrBytes(1)=&HFF _ またはarrBytes(0)=&HFF And arrBytes(1)=&HFE Then
hndFile = FreeFile バイナリ用にstrFolderとstrFileを#hndFile として開くReDim arrFile(0 To LOF(hndFile)-1) Get #hndFile、、arrFile #hndFileを閉じる
BigReplace arrFile、arrBytes(0)&arrBytes(1)、 ""
hndFile = FreeFile バイナリのstrFolderとstrFileを#hndFile として開きます#hndFile、、arrFile を閉じます#hndFile を削除しますarrFileを消去します
ElseIf arrBytes(0)=&HEF And arrBytes(1)=&HBB And arrBytes(2)=&HBF Then
hndFile = FreeFile バイナリ用にstrFolderとstrFileを#hndFile として開くReDim arrFile(0 To LOF(hndFile)-1) Get #hndFile、、arrFile 閉じる#hndFile BigReplace arrFile、arrBytes(0)&arrBytes(1)&arrBytes(2)、 ""
hndFile = FreeFile バイナリ用にstrFolderとstrFileを#hndFile として開きます#hndFile、、arrFile を閉じます#hndFile を削除しますarrFileを消去します
終了する場合
'******************************************** ***************
strFile = "" strFile = Dir
ループ
If Len(strSchema)> 0 Then
strFile = strFolder& "Schema.ini"
hndFile = FreeFile #hndFile としてバイナリのstrFileを開く#hndFile、、strSchema Put #hndFile
終了する場合
End Sub
Public Sub BigReplace(ByRef arrBytes()As Byte、_ ByRef SearchFor As String、_ ByRef ReplaceWith As String) On Error Resume Next
Dim varSplit As Variant
varSplit = Split(arrBytes、SearchFor) arrBytes = Join $(varSplit、ReplaceWith)
varSplitを消去する
サブを終了
バイト配列をVBA.Stringに割り当てることができ、その逆も可能であることがわかっている場合は、コードを理解しやすくなります。 BigReplace()関数は、VBAの非効率的な文字列処理、特に割り当ての一部を回避するハックです。他の方法で実行すると、大きなファイルはメモリとパフォーマンスの問題を引き起こすことがわかります。
外部コードではなくネイティブ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