Excel開啟CSV時的中文編碼問題補遺

很久很久以前,我介紹過CSV與Excel的整合應用,當時同事Daniel補充了一點"Excel只接受ANSI/BIG5編碼的CSV,若存成Unicode,Excel就無法正確顯示"。恰巧最近在河道上也看到有人在討論匯出Excel檔時的中文編碼問題,就決定把我後來研究的心得再整理一下。

經驗裡要透過ASPX轉出非BIG5的CSV的確會有問題,如以下的程式:

<%@ Page Language="C#" %>
<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.AddHeader("content-disposition", 
            "attachment;filename=UnicodeChar.csv");
        Response.ContentType = "application/octet-stream";
        Response.ContentEncoding = Encoding.UTF8;
        Response.Write("犇,很多牛");
        Response.End();
 
    }
</script>

在上例中,Encoding設為UTF8或Unicode都會得到亂碼,設成BIG5卻又無法顯示"犇"字! 難道本題無解? Excel註定不能開啟Unicode Encoding的CSV?

"身經百戰的Excel無法開啟Unicode CSV?" 直覺上是個不合邏輯的推論。於是我做了一個有趣的實驗:

 
namespace Lab
{
    class ExcelEncTest
    {
        public static void Test()
        {
            writeCSV("Unicode.CSV", 
                Encoding.Unicode);
            writeCSV("UTF8.CSV",
                Encoding.UTF8);
            writeCSV("UTF8woBOM.CSV",
                new UTF8Encoding(false));
        }
 
        static void writeCSV(string file, Encoding enc)
        {
            string s = "犇,很多牛";
            using (StreamWriter sw = 
                new StreamWriter(Path.Combine("C:\\TEMP", file), 
                    false, enc)) 
            {
                sw.WriteLine(s);
                sw.Close();
            }
        }
    }
}

三個檔案中,Unicode.csv能正確顯示中文,卻沒有分成兩個欄位。UTF8.csv則中文顯示正常,也明確分成兩欄,看來就是我們期望的結果。至於UTF8woBOM.csv,我用了點技巧,故意不寫入BOM符號,用Excel開啟UTF8woBOM.csv的話有點意思...

有沒有很眼熟? 不就跟我們在第一張圖看到UTF8版的亂碼相同? 換句話說,ASPX傳回UTF8編碼CSV之所以變亂碼是因為少了BOM?

知道了問題所在,要解決就不過是蛋糕一塊!  改用SteamWriter,輸出帶有BOM的CSV內容,Excel就可以正確地顯示萬犇奔騰的CSV囉!

<%@ Page Language="C#" %>
<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.AddHeader("content-disposition", 
            "attachment;filename=UnicodeChar.csv");
        Response.ContentType = "application/octet-stream";
        Response.ContentEncoding = Encoding.UTF8;
        System.IO.StreamWriter sw =
            new System.IO.StreamWriter(
            Response.OutputStream,
            Encoding.UTF8);
        sw.Write("犇,很多牛");
        sw.Close();
        Response.End();
 
    }
</script>
歡迎推文分享:
Published 06 September 2009 03:22 AM 由 Jeffrey
Filed under: , ,


意見

# Ark said on 05 September, 2009 11:27 AM

以前爬文~記得如果是xls 像是 Response.ContentEncoding = Encoding.UTF7;可以搞定

# James said on 04 October, 2009 08:47 PM

請問你寫入BOM的語法是以下這段嗎?

       System.IO.StreamWriter sw =

           new System.IO.StreamWriter(

           Response.OutputStream,

           Encoding.UTF8);

我的做法是在輸出主資料前:

HttpContext.Current.Response.BinaryWrite(New Byte() {&HEF, &HBB, &HBF})

# Sally said on 20 November, 2009 01:47 AM

您好

由於excel2000不支援utf-8,當我改寫成unicode的時候,excle開啟CSV檔時無法將欄位自動分割,所有欄位都在同一個欄位,不過可以確定unicode可正常顯示文字,不知道您是否有研究出來unicode如何讓欄位自動分割??

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 

請輸入以上的數字:

搜尋

Go

<September 2009>
SunMonTueWedThuFriSat
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910
 
RSS
【工商服務】
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


BlogLook Score and Rank

Syndication