Using ExcelDataReader to read Excel data starting from a particular cell

ChhavishJ picture ChhavishJ · Dec 24, 2014 · Viewed 142k times · Source

I am using ExcelDataReader to read data from my Excel workbook in C#.
But structure of my Excel sheet is such that data to be read can start from any particular cell and not necessarily A1.

Can any one Please suggest a way on how this can be achieved using ExcelDataReader?

Answer

shA.t picture shA.t · Sep 3, 2017

If you are using ExcelDataReader 3+ you will find that there isn't any method for AsDataSet() for your reader object, You need to also install another package for ExcelDataReader.DataSet, then you can use the AsDataSet() method.
Also there is not a property for IsFirstRowAsColumnNames instead you need to set it inside of ExcelDataSetConfiguration.

Example:

using (var stream = File.Open(originalFileName, FileMode.Open, FileAccess.Read))
{
    IExcelDataReader reader;

    // Create Reader - old until 3.4+
    ////var file = new FileInfo(originalFileName);
    ////if (file.Extension.Equals(".xls"))
    ////    reader = ExcelDataReader.ExcelReaderFactory.CreateBinaryReader(stream);
    ////else if (file.Extension.Equals(".xlsx"))
    ////    reader = ExcelDataReader.ExcelReaderFactory.CreateOpenXmlReader(stream);
    ////else
    ////    throw new Exception("Invalid FileName");
    // Or in 3.4+ you can only call this:
    reader = ExcelDataReader.ExcelReaderFactory.CreateReader(stream)

    //// reader.IsFirstRowAsColumnNames
    var conf = new ExcelDataSetConfiguration
    {
        ConfigureDataTable = _ => new ExcelDataTableConfiguration
        {
            UseHeaderRow = true 
        }
    };

    var dataSet = reader.AsDataSet(conf);

    // Now you can get data from each sheet by its index or its "name"
    var dataTable = dataSet.Tables[0];

    //...
}

You can find row number and column number of a cell reference like this:

var cellStr = "AB2"; // var cellStr = "A1";
var match = Regex.Match(cellStr, @"(?<col>[A-Z]+)(?<row>\d+)");
var colStr = match.Groups["col"].ToString();
var col = colStr.Select((t, i) => (colStr[i] - 64) * Math.Pow(26, colStr.Length - i - 1)).Sum();
var row = int.Parse(match.Groups["row"].ToString());

Now you can use some loops to read data from that cell like this:

for (var i = row; i < dataTable.Rows.Count; i++)
{
    for (var j = col; j < dataTable.Columns.Count; j++)
    {
        var data = dataTable.Rows[i][j];
    }
}

Update:

You can filter rows and columns of your Excel sheet at read time with this config:

var i = 0;
var conf = new ExcelDataSetConfiguration
{
    UseColumnDataType = true,
    ConfigureDataTable = _ => new ExcelDataTableConfiguration
    {
        FilterRow = rowReader => fromRow <= ++i - 1,
        FilterColumn = (rowReader, colIndex) => fromCol <= colIndex,
        UseHeaderRow = true
    }
};