Использование ExcelDataReader для чтения данных Excel, начиная с определенной ячейки

Я использую ExcelDataReader для чтения данных из моей книги Excel в С#.
Но структура моего листа Excel такова, что считываемые данные могут начинаться с любой конкретной ячейки и не обязательно A1.

Может ли кто-нибудь, пожалуйста, предложить способ, как это может быть достигнуто с помощью ExcelDataReader?

Ответ 1

Если вы используете ExcelDataReader 3+ вы обнаружите, что нет никакого метода для AsDataSet() для вашего объекта читателя. Вам также нужно установить другой пакет для ExcelDataReader.DataSet, тогда вы можете использовать метод AsDataSet().
Также нет свойства для IsFirstRowAsColumnNames вместо этого вам нужно установить его внутри ExcelDataSetConfiguration.

Пример:

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);
    var dataTable = dataSet.Tables[0];

    //...
}

Вы можете найти номер строки и номер столбца ссылки на ячейку следующим образом:

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());

Теперь вы можете использовать несколько циклов для чтения данных из этой ячейки, например:

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

Обновить:

Вы можете фильтровать строки и столбцы вашего листа Excel во время чтения с помощью этой конфигурации:

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

Ответ 2

Чтобы быть более ясным, я начну с самого начала.

Я опишу пример кода, найденный в https://exceldatareader.codeplex.com/, но с некоторыми изменениями, чтобы избежать неудобств.

Следующий код определяет формат файла: xls или xlsx.

FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read);
IExcelDataReader excelReader;

//1. Reading Excel file
if (Path.GetExtension(filePath).ToUpper() == ".XLS")
{
    //1.1 Reading from a binary Excel file ('97-2003 format; *.xls)
    excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
}
else
{
    //1.2 Reading from a OpenXml Excel file (2007 format; *.xlsx)
    excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
}

//2. DataSet - The result of each spreadsheet will be created in the result.Tables
DataSet result = excelReader.AsDataSet();

//3. DataSet - Create column names from first row
excelReader.IsFirstRowAsColumnNames = false;

Теперь мы можем получить доступ к содержимому файла более удобным способом. Для этого я использую DataTable. Ниже приведен пример доступа к определенной ячейке и печать его значения в консоли:

DataTable dt = result.Tables[0];
Console.WriteLine(dt.Rows[rowPosition][columnPosition]);

Если вы не хотите делать DataTable, вы можете сделать то же самое:

Console.WriteLine(result.Tables[0].Rows[rowPosition][columnPosition]);

Важно не пытаться читать за пределами таблицы, для этого вы можете увидеть количество строк и столбцов следующим образом:

Console.WriteLine(result.Tables[0].Rows.Count);
Console.WriteLine(result.Tables[0].Columns.Count);

Наконец, когда вы закончите, вы должны закрыть читателя и свободные ресурсы:

//5. Free resources (IExcelDataReader is IDisposable)
excelReader.Close();

Надеюсь, вы сочтете это полезным.

(Я понимаю, что вопрос старый, но я делаю этот вклад для улучшения базы знаний, потому что мало информации о конкретных реализациях этой библиотеки).

Ответ 3

Я нашел это полезным для чтения из определенного столбца и строки

        FileStream stream = File.Open(@"C:\Users\Desktop\ExcelDataReader.xlsx", FileMode.Open, FileAccess.Read);
        IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
        DataSet result = excelReader.AsDataSet();
        excelReader.IsFirstRowAsColumnNames = true;         
        DataTable dt = result.Tables[0];
        string text = dt.Rows[1][0].ToString();

Ответ 4

Один из способов сделать это:

FileStream stream = File.Open(@"c:\working\test.xls", FileMode.Open, FileAccess.Read);

IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);

excelReader.IsFirstRowAsColumnNames = true;

DataSet result = excelReader.AsDataSet();

result.Tables содержит листы, а result.tables[0].Rows содержит строки ячеек.

Ответ 5

Очень легко с ExcelReaderFactory 3.1 и выше:

using (var openFileDialog1 = new OpenFileDialog { Filter = "Excel Workbook|*.xls;*.xlsx;*.xlsm", ValidateNames = true })
{
    if (openFileDialog1.ShowDialog() == DialogResult.OK)
    {
        var fs = File.Open(openFileDialog1.FileName, FileMode.Open, FileAccess.Read);
        var reader = ExcelReaderFactory.CreateBinaryReader(fs);
        var dataSet = reader.AsDataSet(new ExcelDataSetConfiguration
        {
            ConfigureDataTable = _ => new ExcelDataTableConfiguration
            {
                UseHeaderRow = true // Use first row is ColumnName here :D
            }
        });
        if (dataSet.Tables.Count > 0)
        {
            var dtData = dataSet.Tables[0];
            // Do Something
        }
    }
}

Ответ 6

Вы можете использовать библиотеку .NET, чтобы сделать то же самое, что я считаю более простым.

string ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0; data source={path of your excel file}; Extended Properties=Excel 12.0;";

        OleDbConnection objConn = null;
        System.Data.DataTable dt = null;
        //Create connection object by using the preceding connection string.
        objConn = new OleDbConnection(connString);
        objConn.Open();
        //Get the data table containg the schema guid.
        dt = objConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
        string sql = string.Format("select * from [{0}$]", sheetName);
        var adapter = new System.Data.OleDb.OleDbDataAdapter(sql, ConnectionString);
        var ds = new System.Data.DataSet();
        string tableName = sheetName;
        adapter.Fill(ds, tableName);
        System.Data.DataTable data = ds.Tables[tableName];

После того, как у вас есть данные в datatable, вы можете получить к ним доступ, как обычно, с классом DataTable.