ExcelDataReader

C#源码 2025-08-11

ExcelDataReader

轻量级和快速库编写的C#读取Microsoft Excel文件(2.0-2021,365)。

请随时向叉子提交拉动请求,向开发分支提交。

如果您要报告一个问题,如果您可以提供示例Excel文件,那么这确实有用,因为这会使调试变得更加容易,并且没有它,我们可能无法解决任何问题。

连续整合

分支 建立状态
发展
掌握

支持的文件格式和版本

文件类型 容器格式 文件格式 Excel版本
.xlsx ZIP,CFB+ZIP OpenXML 2007年和更新
.xlsb Zip,CFB OpenXML 2007年和更新
.xls CFB Biff8 97,2000,XP,2003年
98,2001,VX,2004(MAC)
.xls CFB Biff5 5.0,95
.xls - Biff4 4.0
.xls - Biff3 3.0
.xls - Biff2 2.0,2.2
.csv - CSV (全部)

找到二进制文件

建议通过VS软件包管理台Install-Package <package>使用Nuget或使用VS“管理Nuget软件包...”扩展名。

从ExcelDataReader版本3.0开始,该项目被分为多个软件包:

安装ExcelDataReader基本软件包以使用“低级”读取器接口。与Net462,NetStandard2.0和NetStandard2.1兼容。

安装ExcelDataReader .DataSet扩展程序包以使用AsDataSet()方法填充System.Data.DataSet 。这也将拉入基本包。与Net462,NetStandard2.0和NetStandard2.1兼容。

如何使用

 using ( var stream = File . Open ( filePath , FileMode . Open , FileAccess . Read ) )
{
    // Auto-detect format, supports:
    //  - Binary Excel files (2.0-2003 format; *.xls)
    //  - OpenXml Excel files (2007 format; *.xlsx, *.xlsb)
    using ( var reader = ExcelReaderFactory . CreateReader ( stream ) )
    {
        // Choose one of either 1 or 2:

        // 1. Use the reader methods
        do
        {
            while ( reader . Read ( ) )
            {
                // reader.GetDouble(0);
            }
        } while ( reader . NextResult ( ) ) ;

        // 2. Use the AsDataSet extension method
        var result = reader . AsDataSet ( ) ;

        // The result of each spreadsheet is in result.Tables
    }
}

读取.csv文件

使用ExcelReaderFactory.CreateCsvReader而不是CreateReader来解析具有逗号分隔值的纯文本。

另请参阅配置选项FallbackEncodingAutodetectSeparators

输入CSV总是一次完全解析,以设置FieldCount,RowCount,编码,分离器(如果CSV缺乏BOM而不是UTF8,则两次),然后在迭代行记录时再次解析。 throws System.Text.DecoderFallbackException如果输入无法用指定的编码解析。

读者将所有CSV字段值作为字符串返回,并且没有尝试将数据转换为数字或日期。该呼叫者负责解释CSV数据。

使用阅读器方法

AsDataSet()扩展方法是快速获取数据的方便助手,但并非总是可用或可取的。我ExcelDataReader扩展了System.Data.IDataReaderIDataRecord Interfaces,以较低级别导航和检索数据。最重要的读取器方法和属性:

方法 财产
Read() 从当前表读取一行。
NextResult() 将光标推向下一张纸。
ResultsCount 返回当前工作簿中的床单。
Name 返回当前表的名称。
CodeName 返回当前表的VBA代码名称标识符。
FieldCount 返回当前表中的列数。
RowCount 返回当前表中的行数。这包括终端空行,否则这些行被Asdataset()排除在外。与AnalyzeInitialCsvRows一起使用时,在CSV文件上抛出InvalidOperationException
HeaderFooter 返回一个具有有关标头和页脚的信息的对象,或者如果没有的话,则null
MergeCells 返回当前表中合并的单元格范围。
RowHeight 返回当前行的视觉高度。如果隐藏行,则可能是0。
GetColumnWidth() 返回字符单元中的列的宽度。如果列隐藏,则可能是0。
GetFieldType() 返回当前行中值的类型。如果没有值,则始终是Excel支持的类型之一: doubleintboolDateTimeTimeSpanstringnull
IsDBNull() 检查当前行中的值是否为null。
GetValue() 从当前行返回一个值作为object ,如果没有值,则null
GetDouble()
GetInt32()
GetBoolean()
GetDateTime()
GetString()
从当前行铸造的值返回其各自类型。
GetNumberFormatString() 返回一个包含格式代码的字符串,用于当前行中的值,如果没有值,则返回null 。另请参见下面的格式部分。
GetNumberFormatIndex() 返回当前行中值的数字格式索引。索引值低于164,请参阅内置数字格式,否则表示自定义数字格式。
GetCellStyle() 返回当前行中包含单元格的样式信息的对象:凹痕,水平对齐,隐藏,锁定。
键入的Get*()方法 除非类型完全匹配,否则投掷InvalidCastException

CreateAder()配置选项

ExcelReaderFactory.CreateReader()CreateBinaryReader()CreateOpenXmlReader()CreateCsvReader()方法接受可选的配置对象,以修改阅读器的行为:

ExcelDataReader object is disposed. Default: false LeaveOpen = false, // Gets or sets a value indicating the number of rows to analyze for // encoding, separator and field count in a CSV. When set, this option // causes the I ExcelDataReader .RowCount property to throw an exception. // Default: 0 - analyzes the entire file (CSV only, has no effect on other // formats) AnalyzeInitialCsvRows = 0, });">
 var reader = ExcelReaderFactory . CreateReader ( stream , new ExcelReaderConfiguration ( )
{
    // Gets or sets the encoding to use when the input XLS lacks a CodePage
    // record, or when the input CSV lacks a BOM and does not parse as UTF8. 
    // Default: cp1252 (XLS BIFF2-5 and CSV only)
    FallbackEncoding = Encoding . GetEncoding ( 1252 ) ,

    // Gets or sets the password used to open password protected workbooks.
    Password = "password" ,

    // Gets or sets an array of CSV separator candidates. The reader 
    // autodetects which best fits the input data. Default: , ; TAB | # 
    // (CSV only)
    AutodetectSeparators = new char [ ] { ',' , ';' , ' \t ' , '|' , '#' } ,

    // Gets or sets a value indicating whether to trim white space values for CSV (Default 'true').
    // (CSV only)
    TrimWhiteSpace = true ,

    // Gets or sets a value indicating whether to leave the stream open after
    // the I ExcelDataReader object is disposed. Default: false
    LeaveOpen = false ,

    // Gets or sets a value indicating the number of rows to analyze for
    // encoding, separator and field count in a CSV. When set, this option
    // causes the I ExcelDataReader .RowCount property to throw an exception.
    // Default: 0 - analyzes the entire file (CSV only, has no effect on other
    // formats)
    AnalyzeInitialCsvRows = 0 ,
} ) ;

Asdataset()配置选项

AsDataSet()方法接受可选的配置对象,以修改数据集转换的行为:

 var result = reader . AsDataSet ( new ExcelDataSetConfiguration ( )
{
    // Gets or sets a value indicating whether to set the DataColumn.DataType 
    // property in a second pass.
    UseColumnDataType = true ,

    // Gets or sets a callback to determine whether to include the current sheet
    // in the DataSet. Called once per sheet before ConfigureDataTable.
    FilterSheet = ( tableReader , sheetIndex ) => true ,

    // Gets or sets a callback to obtain configuration options for a DataTable. 
    ConfigureDataTable = ( tableReader ) => new ExcelDataTableConfiguration ( )
    {
        // Gets or sets a value indicating the prefix of generated column names.
        EmptyColumnNamePrefix = "Column" ,

        // Gets or sets a value indicating whether to use a row from the 
        // data as column names.
        UseHeaderRow = false ,

        // Gets or sets a callback to determine which row is the header row. 
        // Only called when UseHeaderRow = true.
        ReadHeaderRow = ( rowReader ) => {
            // F.ex skip the first row and use the 2nd row as column headers:
            rowReader . Read ( ) ;
        } ,

        // Gets or sets a callback to determine whether to include the 
        // current row in the DataTable.
        FilterRow = ( rowReader ) => {
            return true ;
        } ,

        // Gets or sets a callback to determine whether to include the specific
        // column in the DataTable. Called once per column after reading the 
        // headers.
        FilterColumn = ( rowReader , columnIndex ) => {
            return true ;
        }
    }
} ) ;

设置AsDataSet()配置,使用FilterRow回调在加载时实现“进度指示器”,例如:

 var result = reader . AsDataSet ( new ExcelDataSetConfiguration ( )
{
    ConfigureDataTable = ( tableReader ) => new ExcelDataTableConfiguration ( )
    {
        FilterRow = ( rowReader ) => {
            int progress = ( int ) Math . Ceiling ( ( decimal ) rowReader . Depth / ( decimal ) rowReader . RowCount * ( decimal ) 100 ) ;
            // progress is in the range 0..100
            return true ;
        }
    }
} ) ; 

格式化

ExcelDataReader不直接支持格式化。用户可以通过I ExcelDataReader .GetNumberFormatString(i)重新删除单元格的数字格式字符串,并使用第三方excelnumberformat库进行格式化。

使用ExcelDataReader和excelnumberformat的示例辅助方法,以格式化一个值:

ExcelDataReader reader, int columnIndex, CultureInfo culture) { var value = reader.GetValue(columnIndex); var formatString = reader.GetNumberFormatString(columnIndex); if (formatString != null) { var format = new NumberFormat(formatString); return format.Format(value, culture); } return Convert.ToString(value, culture); }">
 string GetFormattedValue ( I ExcelDataReader reader , int columnIndex , CultureInfo culture )
{
    var value = reader . GetValue ( columnIndex ) ;
    var formatString = reader . GetNumberFormatString ( columnIndex ) ;
    if ( formatString != null )
    {
        var format = new NumberFormat ( formatString ) ;
        return format . Format ( value , culture ) ;
    }
    return Convert . ToString ( value , culture ) ;
}

参见:

  • https://gi*th*ub*.com/andersnm/excelnumberformat
  • https://www.*nug**et.org/packages/excelnumberformat

从ExcelDataReader 2.x升级时要注意

ExcelDataReader 3发生了一些破裂的变化,较旧的代码可能会产生类似的错误消息:

ExcelDataReader' does not contain a definition for 'AsDataSet'... 'I ExcelDataReader ' does not contain a definition for 'IsFirstRowAsColumnNames'...">
 'I ExcelDataReader ' does not contain a definition for 'AsDataSet'...
'I ExcelDataReader ' does not contain a definition for 'IsFirstRowAsColumnNames'...

修复:

  1. 确保将代码中的任何Excel名称空间引用重命名为新名称空间ExcelDataReader

  2. 确保该项目对ExcelDataReader .DataSet软件包的参考来使用AsDataSet()

  3. 使用IsFirstRowAsColumnNames删除代码行,然后将呼叫更改为Asdataset()以下内容:

 var result = reader . AsDataSet ( new ExcelDataSetConfiguration ( )
{
    ConfigureDataTable = ( _ ) => new ExcelDataTableConfiguration ( )
    {
        UseHeaderRow = true
    }
} ) ; 

在.NET核心上的重要说明

默认情况下, ExcelDataReader抛出了一个notsupportedException“没有用于编码1252的数据。”在.NET Core和.NET 5.0或更高版本上。

要修复,请将依赖项添加到package System.Text.Encoding.CodePages ,然后在应用程序初始化期间添加代码以注册代码页提供商(instup.cs中的F.EX):

 System . Text . Encoding . RegisterProvider ( System . Text . CodePagesEncodingProvider . Instance ) ;

这是在二进制BIFF2-5 excel文档中解析字符串所必需的,该文档编码了DOS-era代码页面。这些编码默认情况下在完整的.NET框架中注册,但在.NET Core和.NET 5.0或更高版本上不注册。

下载源码

通过命令行克隆项目:

git clone https://github.com/ExcelDataReader/ExcelDataReader.git