web-dev-qa-db-fra.com

Méthode optimale pour lire un fichier Excel (.xls/.xlsx)

Je sais qu'il y a différentes façons de lire un fichier Excel:

  • Iterop
  • Oledb
  • Open Xml SDK

La compatibilité n'est pas une question, car le programme sera exécuté dans un environnement contrôlé.

Mon exigence:
Lire un fichier dans une DataTable/CUstom Entities (je ne sais pas comment créer des propriétés/champs dynamiques dans un objet [les noms de colonnes varieront dans un fichier Excel])

Utilisez DataTable/Custom Entities pour effectuer certaines opérations en utilisant ses données.

Mettre à jour DataTable avec les résultats des opérations

Réécris-le dans Excel file.

Ce qui serait plus simple.

Aussi, si possible, me conseiller sur les entités personnalisées (ajouter des propriétés/champs à un objet de manière dynamique)

54
Ankesh

Jetez un coup d'oeil à Linq-to-Excel . C'est plutôt chouette.

var book = new LinqToExcel.ExcelQueryFactory(@"File.xlsx");

var query =
    from row in book.Worksheet("Stock Entry")
    let item = new
    {
        Code = row["Code"].Cast<string>(),
        Supplier = row["Supplier"].Cast<string>(),
        Ref = row["Ref"].Cast<string>(),
    }
    where item.Supplier == "Walmart"
    select item;

Il permet également un accès fortement typé aux lignes.

61
Enigmativity

L'utilisation de OLE Query est très simple (par exemple, sheetName est Sheet1 $):

DataTable LoadWorksheetInDataTable(string fileName, string sheetName)
{           
    DataTable sheetData = new DataTable();
    using (OleDbConnection conn = this.returnConnection(fileName))
    {
       conn.Open();
       // retrieve the data using data adapter
       OleDbDataAdapter sheetAdapter = new OleDbDataAdapter("select * from [" + sheetName + "]", conn);
        sheetAdapter.Fill(sheetData);
    }                        
    return sheetData;
}

private OleDbConnection returnConnection(string fileName)
{
    return new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fileName + "; Jet OLEDB:Engine Type=5;Extended Properties=\"Excel 8.0;\"");
}

Pour les nouvelles versions d'Excel:

return new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filename + ";Extended Properties=Excel 12.0;");

Vous pouvez également utiliser Excel Data Reader un projet open source sur CodePlex. Cela fonctionne vraiment bien pour exporter des données à partir de feuilles Excel. 

L'exemple de code donné sur le lien spécifié:

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

//1. Reading from a binary Excel file ('97-2003 format; *.xls)
IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
//...
//2. Reading from a OpenXml Excel file (2007 format; *.xlsx)
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
//...
//3. DataSet - The result of each spreadsheet will be created in the result.Tables
DataSet result = excelReader.AsDataSet();
//...
//4. DataSet - Create column names from first row
excelReader.IsFirstRowAsColumnNames = true;
DataSet result = excelReader.AsDataSet();

//5. Data Reader methods
while (excelReader.Read())
{
//excelReader.GetInt32(0);
}

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

Référence: Comment importer d'Excel dans un DataSet à l'aide de Microsoft.Office.Interop.Excel?

20
Furqan Safdar

Essayez d’utiliser ce moyen gratuit pour cela, https://freenetexcel.codeplex.com

 Workbook workbook = new Workbook();

 workbook.LoadFromFile(@"..\..\parts.xls",ExcelVersion.Version97to2003);
 //Initialize worksheet
 Worksheet sheet = workbook.Worksheets[0];

 DataTable dataTable = sheet.ExportDataTable();
5
Hark.Tenl

Si vous pouvez le limiter aux seuls fichiers * .xlsx (format XML Open Office), alors la bibliothèque la plus populaire serait probablement EPPLus .

Le bonus est, il n'y a pas d'autres dépendances. Il suffit d'installer à l'aide de nuget:

Install-Package EPPlus
2
davewasthere

Personnellement, j'ai trouvé le open-source & free ExcelMapper plus facile à utiliser.

Il fournit un moyen beaucoup plus concis (c'est-à-dire plus lisible) de lire des fichiers Excel par rapport aux requêtes Microsoft.Interop & OLE habituelles.

1. Étant donné un fichier Excel :

enter image description here

2.Créez un objet Personne C #:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
}

3.Lisez-le avec ExcelMapper

  var fileName = @"C:\Temp\Names.xlsx"; // your Excel file
  List<Person> people = new ExcelMapper(fileName).Fetch<Person>();

Vous pouvez également lire d'autres feuilles de calcul, en passant simplement un argument de feuille supplémentaire:

  var fileName = @"C:\Temp\Names.xlsx"; // your Excel file
  List<Person> people = new ExcelMapper(fileName).Fetch<Person>("Sheet2");

Vous pouvez l'installer en utilisant NuGet

Install-Package ExcelMapper

Avertissement: Je ne suis pas associé à ExcelMapper, mais après avoir essayé différentes bibliothèques, j'ai trouvé que cette bibliothèque était la plus facile à utiliser.

instructional video - how to read Excel files in c# Voici un court vidéo présentant ce qui précède.

1
Mark H

Essayez d’utiliser la bibliothèque Aspose.cells, c’est plutôt bien.

Install-package Aspose.cells

Il y a un exemple de code:

_using Aspose.Cells;
using System;

namespace ExcelReader
{
    class Program
    {
        static void Main(string[] args)
        {
            // Replace path for your file
            readXLS(@"C:\MyExcelFile.xls"); // or "*.xlsx"
            Console.ReadKey();
        }

        public static void readXLS(string PathToMyExcel)
        {
            //Open your template file.
            Workbook wb = new Workbook(PathToMyExcel);

            //Get the first worksheet.
            Worksheet worksheet = wb.Worksheets[0];

            //Get cells
            Cells cells = worksheet.Cells;

            // Get row and column count
            int rowCount = cells.MaxDataRow;
            int columnCount = cells.MaxDataColumn;

            // Current cell value
            string strCell = "";

            Console.WriteLine(String.Format("rowCount={0}, columnCount={1}", rowCount, columnCount));

            for (int row = 0; row <= rowCount; row++) // Numeration starts from 0 to MaxDataRow
            {
                for (int column = 0; column <= columnCount; column++)  // Numeration starts from 0 to MaxDataColumn
                {
                    strCell = "";
                    strCell = Convert.ToString(cells[row, column].Value);
                    if (String.IsNullOrEmpty(strCell))
                    {
                        continue;
                    }
                    else
                    {
                        // Do your staff here
                        Console.WriteLine(strCell);
                    }
                }
            }
        }
    }
}
_
0
fr0ga

Je sais que cette question a été posée il y a près de 7 ans, mais certains résultats de recherche Google restent importants dans l'importation de données Excel avec C #. Je souhaitais donc proposer une alternative basée sur certains développements technologiques récents.

L'importation de données Excel est devenue une tâche si courante dans mes tâches quotidiennes que j'ai rationalisé le processus et documenté la méthode sur mon blog: le meilleur moyen de lire un fichier Excel en c # .

J'utilise NPOI car il peut lire/écrire des fichiers Excel sans Microsoft Office et ne pas utiliser COM + ni interops. Cela signifie que cela peut fonctionner dans le cloud!

Mais la vraie magie vient de l'association avec NPOI Mapper de Donny Tian car cela me permet de mapper les colonnes Excel aux propriétés de mes classes C # sans écrire de code. C'est beau.

Voici l'idée de base:

Je crée une classe .net qui correspond/mappe les colonnes Excel qui m'intéressent:

        class CustomExcelFormat
        {
            [Column("District")]
            public int District { get; set; }

            [Column("DM")]
            public string FullName { get; set; }

            [Column("Email Address")]
            public string EmailAddress { get; set; }

            [Column("Username")]
            public string Username { get; set; }

            public string FirstName
            {
                get
                {
                    return Username.Split('.')[0];
                }
            }

            public string LastName
            {
                get
                {
                    return Username.Split('.')[1];
                }
            }
        }

Remarquez, cela me permet de mapper en fonction du nom de la colonne si je le souhaite! 

Ensuite, lorsque je traite le fichier Excel, tout ce dont j'ai besoin est la suivante:

        public void Execute(string localPath, int sheetIndex)
        {
            IWorkbook workbook;
            using (FileStream file = new FileStream(localPath, FileMode.Open, FileAccess.Read))
            {
                workbook = WorkbookFactory.Create(file);
            }

            var importer = new Mapper(workbook);
            var items = importer.Take<CustomExcelFormat>(sheetIndex);
            foreach(var item in items)
            {
                var row = item.Value;
                if (string.IsNullOrEmpty(row.EmailAddress))
                    continue;

                UpdateUser(row);
            }

            DataContext.SaveChanges();
        }

Maintenant, certes, mon code ne modifie pas le fichier Excel lui-même. Au lieu de cela, je sauvegarde les données dans une base de données à l'aide d'Entity Framework (c'est pourquoi vous voyez "UpdateUser" et "SaveChanges" dans mon exemple). Mais il y a déjà une bonne discussion sur SO sur la façon de sauvegarder/modifier un fichier en utilisant NPOI .

0
Dan