1. 程式人生 > >VBA 格式化輸出XML(UTF-8無BOM編碼)

VBA 格式化輸出XML(UTF-8無BOM編碼)

VBA可以使用MSXML2.Document來建立XML Dom樹並輸出到檔案,先看個簡單的例子:

Function CreateXml(xmlFile As String)
    Dim xDoc As Object
    Dim rootNode As Object
    Dim header As Object
    Dim newNode As Object
    Dim tNode As Object

    Set xDoc = CreateObject("MSXML2.DOMDocument")
    Set rootNode = xDoc.createElement("BookList"
) Set xDoc.DocumentElement = rootNode 'xDoc.Load xmlFile Set header = xDoc.createProcessingInstruction("xml", "version='1.0' encoding='Unicode'") xDoc.InsertBefore header, xDoc.ChildNodes(0) Set newNode = xDoc.createElement("book") Set tNode = xDoc.DocumentElement.appendChild(newNode) tNode.setAttribute "type"
, "program" Set newNode = xDoc.createElement("name") Set tNode = xDoc.DocumentElement.ChildNodes.Item(0).appendChild(newNode) tNode.appendChild (xDoc.createTextNode("Thinking in Java")) Set newNode = xDoc.createElement("author") Set tNode = xDoc.DocumentElement.ChildNodes.Item(0).appendChild(newNode) tNode.appendChild (xDoc.createTextNode("Bruce Eckel"
)) Set newNode = xDoc.createElement("book") Set tNode = xDoc.DocumentElement.appendChild(newNode) tNode.setAttribute "type", "literature" Set newNode = xDoc.createElement("name") Set tNode = xDoc.DocumentElement.ChildNodes.Item(1).appendChild(newNode) tNode.appendChild (xDoc.createTextNode("邊城")) Set newNode = xDoc.createElement("author") Set tNode = xDoc.DocumentElement.ChildNodes.Item(1).appendChild(newNode) tNode.appendChild (xDoc.createTextNode("沈從文")) Set newNode = Nothing Set tNode = Nothing xDoc.save xmlFile End Function

在巨集工程中呼叫一下這個函式工程,就可以生成一個xml檔案,但是生成的xml檔案所有內容都顯示在一行上了,有沒有方法進行換行及縮排,讓xml檔案看起來更整齊美觀呢?方法是有的,藉助Msxml2.SAXXMLReader和Msxml2.MXXMLWriter就可以實現這個效果,看程式碼:

'格式化xml,帶換行縮排
Function PrettyPrintXml(xmldoc) As String
    Dim reader As Object
    Dim writer As Object
    Set reader = CreateObject("Msxml2.SAXXMLReader.6.0")
    Set writer = CreateObject("Msxml2.MXXMLWriter.6.0")
    writer.indent = True
    writer.omitXMLDeclaration = True
    reader.contentHandler = writer
    reader.Parse (xmldoc)
    PrettyPrintXml = writer.Output

End Function

然後將前面的xDoc.save xmlFile改一下:

'xDoc.save xmlFile
Dim xmlStr As String
xmlStr = PrettyPrintXml(xDoc)
WriteUtf8WithoutBom xmlFile, xmlStr
Open xmlFile For Output As #1
Print #1, xmlStr
Close #1

這樣就可以格式化輸出xml檔案了。還有一個問題,我們想要指定xml檔案的編碼格式,如UTF-8,GB2312等,我通常習慣儲存成UTF-8格式,那麼該如何設定呢?查詢資料,可以用ADODB.stream來搞。

Function WriteWithUtf8(filename As String, content As String)
    Dim stream As New ADODB.stream
    stream.Open
    stream.Type = adTypeText
    stream.Charset = "utf-8"
    stream.WriteText content
    stream.SaveToFile filename, adSaveCreateOverWrite

    stream.Flush
    stream.Close

End Function

細心點的話會發現用上面的方法實際上輸出的檔案格式是帶BOM的UTF-8,它跟UTF-8無BOM的區別在哪呢?用UltraEdit工具來看十六進位制碼,會發現前者在開頭多了三個位元組:0xEF,0xBB,0xBF,想儲存成UTF-8無BOM,把這三個位元組去掉不就行了,實現如下:

' utf8無BOM編碼格式
Function WriteUtf8WithoutBom(filename As String, content As String)
    Dim stream As New ADODB.stream
    stream.Open
    stream.Type = adTypeText
    stream.Charset = "utf-8"
    stream.WriteText "<?xml version=" & Chr(34) & "1.0" & Chr(34) & _
                     " encoding=" & Chr(34) & "UTF-8" & Chr(34) & "?>" & vbCrLf
    stream.WriteText content

    '移除前三個位元組(0xEF,0xBB,0xBF)
    stream.Position = 3

    Dim newStream As New ADODB.stream
    newStream.Type = adTypeBinary
    newStream.Mode = adModeReadWrite
    newStream.Open

    stream.CopyTo newStream
    stream.Flush
    stream.Close

    newStream.SaveToFile filename, adSaveCreateOverWrite
    newStream.Flush
    newStream.Close

End Function

注意需要引用兩個庫:Microsoft ADO Ext. 6.0 for DDL and Security,Microsoft ActiveX Data Objects 2.7 Library

最後附上完整程式碼:

Sub 按鈕2_Click()
    Dim xmlFile As String
    xmlFile = "D:\test\books.xml"
    CreateXml xmlFile
End Sub

Function CreateXml(xmlFile As String)
    Dim xDoc As Object
    Dim rootNode As Object
    Dim header As Object
    Dim newNode As Object
    Dim tNode As Object

    Set xDoc = CreateObject("MSXML2.DOMDocument")
    Set rootNode = xDoc.createElement("BookList")
    Set xDoc.DocumentElement = rootNode
    'xDoc.Load xmlFile
    Set header = xDoc.createProcessingInstruction("xml", "version='1.0' encoding='Unicode'")
    xDoc.InsertBefore header, xDoc.ChildNodes(0)

    Set newNode = xDoc.createElement("book")
    Set tNode = xDoc.DocumentElement.appendChild(newNode)
    tNode.setAttribute "type", "program"

    Set newNode = xDoc.createElement("name")
    Set tNode = xDoc.DocumentElement.ChildNodes.Item(0).appendChild(newNode)
    tNode.appendChild (xDoc.createTextNode("Thinking in Java"))

    Set newNode = xDoc.createElement("author")
    Set tNode = xDoc.DocumentElement.ChildNodes.Item(0).appendChild(newNode)
    tNode.appendChild (xDoc.createTextNode("Bruce Eckel"))

    Set newNode = xDoc.createElement("book")
    Set tNode = xDoc.DocumentElement.appendChild(newNode)
    tNode.setAttribute "type", "literature"

    Set newNode = xDoc.createElement("name")
    Set tNode = xDoc.DocumentElement.ChildNodes.Item(1).appendChild(newNode)
    tNode.appendChild (xDoc.createTextNode("邊城"))

    Set newNode = xDoc.createElement("author")
    Set tNode = xDoc.DocumentElement.ChildNodes.Item(1).appendChild(newNode)
    tNode.appendChild (xDoc.createTextNode("沈從文"))

    Set newNode = Nothing
    Set tNode = Nothing

    Dim xmlStr As String
    xmlStr = PrettyPrintXml(xDoc)
    WriteUtf8WithoutBom xmlFile, xmlStr

    Set rootNode = Nothing
    Set xDoc = Nothing

    MsgBox xmlFile & "輸出完成"

End Function

'格式化xml,帶換行縮排
Function PrettyPrintXml(xmldoc) As String
    Dim reader As Object
    Dim writer As Object
    Set reader = CreateObject("Msxml2.SAXXMLReader.6.0")
    Set writer = CreateObject("Msxml2.MXXMLWriter.6.0")
    writer.indent = True
    writer.omitXMLDeclaration = True
    reader.contentHandler = writer
    reader.Parse (xmldoc)
    PrettyPrintXml = writer.Output
End Function

' utf8無BOM編碼格式
Function WriteUtf8WithoutBom(filename As String, content As String)
    Dim stream As New ADODB.stream
    stream.Open
    stream.Type = adTypeText
    stream.Charset = "utf-8"
    stream.WriteText "<?xml version=" & Chr(34) & "1.0" & Chr(34) & _
                     " encoding=" & Chr(34) & "UTF-8" & Chr(34) & "?>" & vbCrLf
    stream.WriteText content

    '移除前三個位元組(0xEF,0xBB,0xBF)
    stream.Position = 3

    Dim newStream As New ADODB.stream
    newStream.Type = adTypeBinary
    newStream.Mode = adModeReadWrite
    newStream.Open

    stream.CopyTo newStream
    stream.Flush
    stream.Close

    newStream.SaveToFile filename, adSaveCreateOverWrite
    newStream.Flush
    newStream.Close    
End Function

相關推薦

VBA 格式化輸出XML(UTF-8BOM編碼)

VBA可以使用MSXML2.Document來建立XML Dom樹並輸出到檔案,先看個簡單的例子: Function CreateXml(xmlFile As String) Dim xDoc As Object Dim rootNode As

讀取xml格式utf-8編碼utf-8 bom編碼格式,出現 前言中不允許有內容的問題

1,java 讀取 xml utf-8 編碼格式的檔案,出現  Caused by: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; 前言中不允許有內容。     出現這樣的原因, 是因為讀取檔案

utf-8BOM編碼格式什麼意思?

UTF-8不需要BOM來表明位元組順序,但可以用BOM來表明編碼方式。字元"ZERO WIDTH NO-BREAK SPACE"的UTF-8編碼是EF BB BF。所以如果接收者收到以EF BB BF開頭的位元組流,就知道這是UTF-8編碼了。 ---------------

C#使用StreamWriter生成UTF-8BOM編碼格式

使用UTF-8格式產生的檔案,用二進位制檢視會多出“\xef\xbb\xbf”幾個位元組 使用UTF-8無BOM格式: UTF8Encodingutf8 = new UTF8Encoding(fal

UTF-8UTF-8BOM,一個會導致文件中中文變量無法匹配的bug

阿裏旺旺 bsp bom logs 文件 匹配 文件的 程序 資料 昨晚用dom4j中的selectSingleNode解析xml,匹配節點。 發現匹配不到,但是確實存在該節點 將regex改為regex1後則可以匹配,也就是說文件中的“阿裏旺旺”和程序中的“阿裏旺旺

Visual Studio 2017 UTF-8 BOM 一站式解決辦法

exe end pre utf8 space spa code ets mic 問題背景:最近撿起C++,使用VS 2017平臺。因為以前的編程習慣,喜歡使用UTF-8 無 BOM 的編碼格式,好讓自己的代碼全球通用。但是VS 2017 對這個問題不是很友善。但最終找到了解

VS 修改預設編碼格式 為utf-8 BOMutf-8BOM

VS 在使用的時候預設的編碼格式為 GB2312 如何修改預設的編碼格式呢? 網上都說修改 VS 建立檔案時的模板 如C++ 則修改  C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcprojectitems

因字符集utf-8BOM格式編碼,導致用sql檔案匯入MySQL出現亂碼問題

在使用.sql檔案向MySQL資料庫插入時,部分中文字元出現亂碼,不能匯入,比如說“交通”、“釀”、“制”等。 sql語句: INSERT INTO `course` VALUES (1,'交通',901); 報錯:You have an error in your S

vs2015:/utf-8選項解決UTF-8 without BOM 原始碼中文輸出亂碼問題

本來我已經參考網上關於C++中文輸出亂碼的文章解決了,如下面的程式碼輸出前呼叫wcout.imbue設定locale,就可以正常輸出中文了。 std::wcout.imbue(std::locale(std::locale(), "", LC_CTYPE)

編碼格式簡介:ASCII碼、ANSI、GBK、GB2312、GB18030和Unicode、UTF-8BOM

family 用兩個 圖片 and 正是 全球化 asc 即使 little 編碼格式簡介:ASCII碼、ANSI、GBK、GB2312、GB18030和Unicode、UTF-8,BOM頭 二進制: 只有0和1。 十進制、十六進制、八進制: 計算機其實挺笨的,它只

去掉utf-8Bom頭:使用java以及jdbc不使用第三方庫執行sql文件腳本

語句 \n path expect continue 參數 oid while figure package com.xxx.xxx.dao; import java.io.BufferedReader; import java.io.File; import java

關於Encode in UTF-8 without BOM

什麽 nic 代碼 網頁代碼 使用 python 文件頭部 環境 解釋 定義BOM(Byte Order Mark),字節順序標記,出現在文本文件頭部,Unicode編碼標準中用於標識文件是采用哪種格式的編碼。它的編碼是FEFF。 說明 在 UTF-8 文件中放置 BOM

MySQL修改編碼UTF-8效果解決辦法

本來這是一件很簡單的事,有很多部落格裡都有教程,但卻足足花了我半天的時間才解決問題。 可能是因為我的MySQL安裝時沒有選擇預設路徑的原因,按照網上的教程修改了下圖中的my.ini配置檔案後編碼並沒有發生變化。 來回試了好幾次都不行,重啟了服務N次..... [mysqld] characte

UTF-8 without BOM

UTF-8編碼的檔案可以分為without BOM和BOM兩種格式。 何謂BOM? "EF BB BF" 這三個位元組就叫BOM,BOM的全稱叫做"Byte Order Mark". 在UTF-8檔案中常用BOM來表明這個檔案是UTF-8檔案, 而BOM的本意是在UTF-16中用來表示高低位元組序列

UTF-8UTF-8 without BOM

UTF-8編碼的檔案可以分為without BOM和BOM兩種格式。 何謂BOM? “EF BB BF” 這三個位元組就叫BOM,BOM的全稱叫做"Byte Order Mark". 在UTF-8檔案中常用BOM來表明這個檔案是UTF-8檔案, 而BOM的本意是

lua去掉字串中的UTF-8BOM三個位元組

今天被坑了,原因是在lua中解析csv時,由於csv使用的是UTF-8 BOM格式,所以在解析csv成lua表時,表頭ID欄位,明明你列印的時候在表中存在,但是你去訪問v[‘ID’]的時候,始終為nil。原因就是ID是csv表的開頭欄位字串,BOM格式會預設增加三個不可見的位元組 0xE

Python學習筆記:Convert UTF-8 with BOM to UTF-8 without BOM in Python

前言 windows對於utf-8編碼的檔案自帶BOM,但是其他系統utf-8編碼預設不帶BOM。 這就造成在某些情況下字元解碼會出現問題,比如python自帶的json在讀取在window下編碼得來的utf-8檔案時,會報如下錯誤: V

[經驗總結]利用MFC的CFile物件輸出utf-8和ansi編碼的文字

// 今天寫了一段輸出文字到檔案的程式碼,一開始用CFile輸出中文,總是出現亂碼,又是百度(Google被牆了)一番,網上的教程基本是隻知其一不知其二,大多隻講了輸出檔案位元組序標記和計算寬字元長度這兩個注意點,卻沒有提到字元轉換這個最關鍵的一步。下面的程式碼分別輸出UTF-8和ANSI(簡體中文Windo

使用dom4j 生成xml UTF-8 編碼錯誤之解決

//檔名稱 String fileName = "test.xml"; // 格式化XML文件 OutputFormat format = OutputFormat.createPrettyPrint(); format.setE

C# UTF-8BOM

在C#中,當使用帶有BOM頭的UTF-8編碼的字串時,一定要注意。 1)如果該字串用作路徑,用來定址。一定會出錯。2)轉換格式時,也很容易出錯。例如字串轉int就一定會出錯。 待續… ——————————————————————————————————————