it-swarm.com.ru

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

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

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

14
ChhavishJ

Если вы используете 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
    }
};
26
shA.t

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

Я буду полагаться на пример кода, который можно найти в 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();

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

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

15
cesAR

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

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

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

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 содержит строки ячеек.

2
Sievajet

Очень легко с 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
        }
    }
}
0
VnDevil