J'utilise ExcelDataReader
pour lire les données de mon classeur Excel en C #.
Mais la structure de ma feuille Excel est telle que les données à lire peuvent commencer à partir de n'importe quelle cellule et pas nécessairement A1
.
Quelqu'un peut-il, s'il vous plaît, suggérer un moyen sur la façon dont cela peut être réalisé en utilisant ExcelDataReader
?
Si vous utilisez ExcelDataReader 3+
, vous constaterez qu'il n'y a pas de méthode pour AsDataSet()
pour votre objet lecteur. Vous devez également installer un autre package pour ExcelDataReader.DataSet
, vous pouvez alors utiliser la méthode AsDataSet()
.
Il n’existe pas non plus de propriété pour IsFirstRowAsColumnNames
mais vous devez la définir à l’intérieur de ExcelDataSetConfiguration
.
Exemple:
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];
//...
}
Vous pouvez trouver le numéro de ligne et le numéro de colonne d'une référence de cellule comme ceci:
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());
Vous pouvez maintenant utiliser certaines boucles pour lire les données de cette cellule comme ceci:
for (var i = row; i < dataTable.Rows.Count; i++)
{
for (var j = col; j < dataTable.Columns.Count; j++)
{
var data = dataTable.Rows[i][j];
}
}
Mettre à jour:
Vous pouvez filtrer les lignes et les colonnes de votre feuille Excel en lecture avec cette configuration:
var i = 0;
var conf = new ExcelDataSetConfiguration
{
UseColumnDataType = true,
ConfigureDataTable = _ => new ExcelDataTableConfiguration
{
FilterRow = rowReader => fromRow <= ++i - 1,
FilterColumn = (rowReader, colIndex) => fromCol <= colIndex,
UseHeaderRow = true
}
};
Pour être plus clair, je vais commencer par le début.
Je vais m'appuyer sur l'exemple de code présent dans https://exceldatareader.codeplex.com/ , mais avec quelques modifications pour éviter les inconvénients.
Le code suivant détecte le format de fichier, xls ou 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;
Nous pouvons maintenant accéder au contenu du fichier de manière plus pratique. J'utilise DataTable pour cela. Voici un exemple pour accéder à une cellule spécifique et imprimer sa valeur dans la console:
DataTable dt = result.Tables[0];
Console.WriteLine(dt.Rows[rowPosition][columnPosition]);
Si vous ne souhaitez pas créer de DataTable, procédez comme suit:
Console.WriteLine(result.Tables[0].Rows[rowPosition][columnPosition]);
Il est important de ne pas essayer de lire au-delà des limites du tableau. Pour cela, vous pouvez voir le nombre de lignes et de colonnes comme suit:
Console.WriteLine(result.Tables[0].Rows.Count);
Console.WriteLine(result.Tables[0].Columns.Count);
Enfin, lorsque vous avez terminé, fermez le lecteur et libérez des ressources:
//5. Free resources (IExcelDataReader is IDisposable)
excelReader.Close();
J'espère que tu trouves cela utile.
(Je comprends que la question est ancienne, mais je fais cette contribution pour améliorer la base de connaissances, car il y a peu de matériel sur des implémentations particulières de cette bibliothèque).
J'ai trouvé cela utile de lire une colonne et une rangée spécifiques
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();
Une façon de le faire:
FileStream stream = File.Open(@"c:\working\test.xls", FileMode.Open, FileAccess.Read);
IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
excelReader.IsFirstRowAsColumnNames = true;
DataSet result = excelReader.AsDataSet();
Le result.Tables
contient les feuilles et le result.tables[0].Rows
contient les lignes de la cellule.
Très facile avec ExcelReaderFactory 3.1 et plus:
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
}
}
}