C# 免裝Excel 就可以讀取 EXCEL 檔案 - ExcelDataReader (C# Read xls/xlsx/csv without excel using ExcelDataReader)


在幫公司開發程式的過程中,常常免不了要接收使用者或是客戶上傳的資料檔案, 通常我們程式設計師在解析檔案使用XML、CSV、TXT之類的檔案很好用,但對於使用者來說卻不是很友善的介面,通常會用統計資料的,也決不會是WORD,很多時候都是使用EXCEL或是CALC做出來的檔案。

在台灣大部分都是使用EXCEL做出來的統計檔案占絕大多數,因此處理這些EXCEL檔案便是家常便飯之事了。

而EXCEL產出的檔案,以附檔名類型上來說大致分為 .XLS 或是 .XLSX 這兩類。XLS檔案屬於BIFF格式檔案,它是一種二進位格式(Binary)檔案;XLSX則是比較新的檔案,屬於XML架構的檔案,一般又稱為 OpenXML,因此在處理與解讀上有所不同。

通常要處理 BIFF 檔案或是 OpenXML 檔案都需要有相當的格式研究能力,對於一般設計師來說都不是簡單的事,更不像TXT、CSV、XML這麼容易。

dotNet Framework 處理 EXCEL 當然自有一套方式,不管是LINQ、或是使用 Microsoft.Office.Interop.Excel 或是以 Microsoft.Jet.OLEDB.4.0 資料庫方式操作都避免不了一件事,就是執行讀取檔案的電腦必須安裝 EXCEL,但大家都知道 EXCEL本身不是免費的軟體,收費也很高,如果要在使用者端能夠執行,勢必在使用者端要裝上不少授權,光是費用都很驚人,也不是一般的小公司能夠負擔的。

ExcelDataReader - 這是一套在GitHub 上的 OpenSource 套件,它提供了強大的 Reader 功能,重點是免費,與強大的可攜性,它號稱是 Lightweight and fast library written in C# for reading Microsoft Excel files。

基本的讀取不是問題,處理檔案有它就很夠用了。

首先你可以到專案下的 NuGet 去取得套件:
總共有兩個套件要安裝:ExcelDataReader 和 ExcelDataReader.DataSet

要注意的是3.0.0以前的版本只有 ExcelDataReader,沒有 ExcelDataReader.DataSet,這個 DataSet 套件是從 3.0.0後分開的,屬於 System.Data 的擴展套件。

使用時一定要引用下面兩個 namespace

using System.Data;
using ExcelDataReader;


底下是基於Console 模式的程式碼,主要提供一個檔案給程式就可以讀取並顯示出到螢幕上

using System;
using System.IO;
using System.Data;
using System.Text;
using ExcelDataReader;

namespace XlsReader
{
    class Program
    {
        static public string AppPath;
        static int Main(string[] args)
        {
            DataSet ds;
            AppPath = AppDomain.CurrentDomain.BaseDirectory;
            if (args.Length > 0)
            {
                string file = Path.Combine(AppPath, args[0]);
                if (File.Exists(file))
                {
                    var extension = Path.GetExtension(file).ToLower();
                    Console.WriteLine("讀取檔案:" + file);
                    using (var stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                    {
                        //判斷格式套用讀取方法
                        IExcelDataReader reader = null;
                        if (extension == ".xls")
                        {
                            Console.WriteLine(" => XLS格式");
                            reader = ExcelReaderFactory.CreateBinaryReader(stream , new ExcelReaderConfiguration() {
                                FallbackEncoding =Encoding.GetEncoding("big5")
                            });
                        }
                        else if (extension == ".xlsx")
                        {
                            Console.WriteLine(" => XLSX格式");
                            reader = ExcelReaderFactory.CreateOpenXmlReader(stream);
                        }
                        else if (extension == ".csv")
                        {
                            Console.WriteLine(" => CSV格式");
                            reader = ExcelReaderFactory.CreateCsvReader(stream, new ExcelReaderConfiguration() {
                                FallbackEncoding = Encoding.GetEncoding("big5")
                            });
                        }
                        else if (extension == ".txt")
                        {
                            Console.WriteLine(" => Text(Tab Separated)格式");
                            reader = ExcelReaderFactory.CreateCsvReader(stream, new ExcelReaderConfiguration() {
                                FallbackEncoding = Encoding.GetEncoding("big5"),
                                AutodetectSeparators = new char[] { '\t' }
                            });
                        }

                        //沒有對應產生任何格式
                        if (reader == null)
                        {
                            Console.WriteLine("未知的處理檔案:" + extension);
                            Console.ReadKey();
                            return 20;
                        }
                        Console.WriteLine(" => 轉換中");
                        using (reader)
                        {
                         
                            ds = reader.AsDataSet(new ExcelDataSetConfiguration()
                            {
                                UseColumnDataType = false,
                                ConfigureDataTable = (tableReader) => new ExcelDataTableConfiguration()
                                {
                                    //設定讀取資料時是否忽略標題
                                    UseHeaderRow = false
                                }
                            });


                            //把 DataSet 顯示出來
                            var table = ds.Tables[0];
                            for(int row = 0; row < table.Rows.Count; row++)
                            {
                                for (var col = 0; col < table.Columns.Count; col++)
                                {
                                    string data = table.Rows[row][col].ToString();
                                    Console.Write(data + ",");
                                }
                                Console.WriteLine("");
                            }
                        }
                    }
                    Console.WriteLine("結束...按任意鍵離開...");
                    Console.ReadKey();
                    return 0;
                }
                else
                {
                    Console.WriteLine("檔案 " + file + " 不存在!");
                    Console.ReadKey();
                    return 18;
                }
             
            }
            else
            {
                Console.WriteLine("沒有提供參數!");
                Console.ReadKey();
                return 13;
            }
        }
    }
}



實際運行畫面:


程式碼中要注意的是,一般 XLS(BIFF) 、CSV 、TXT 檔案由於無法正常取得其編碼方式,必須給予指定編碼方式,目前我的檔案裡面的中文是BIG5,所以強制指定為 BIG5:

FallbackEncoding = Encoding.GetEncoding("big5")



其他參考:



留言

這個網誌中的熱門文章

【研究】列印的條碼為什麼很難刷(掃描)

C# 使用 Process.Start 執行外部程式

統一發票列印小程式