[.NET] Lire un fichier Excel avec le SDK Open XML 2.0
Pour les besoins d’un projet sur lequel je devais lier un fichier Excel à un DataGrid WPF 4.0, je me suis intéressé à la lecture de ce type de fichier à l’aide du SDK Open XML 2.0 que vous pouvez télécharger sur cette page.
Après plusieurs heures de recherches, j’ai enfin réussi à lire mon fichier :) Dans ce post, je vais vous expliquer la marche à suivre.
Partons d’un cas simple où le fichier Excel contient une liste de client de votre entreprise :
Chaque client sera représenté par une instance de la classe “Customer” ci-dessous :
public class Customer
{
public string ID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string City { get; set; }
}
Si vous aviez lu mon article traitant de la génération de document Word OpenXML, vous vous souvenez certainement que la particularité d’un document suivant cette norme OpenXML est de n’être rien d’autre qu’une archive zip contenant différents fichiers XML décrivant la structure et le contenu du document :
Sur l’image ci-contre, vous pouvez voir les différentes parties du fichier Excel qui nous intéressent ici :
- le dossier “worksheets” contient toutes les feuilles qui composent le document.
- le fichier “sharedStrings.xml” contient toutes les valeurs texte que nous avons entrées dans chacunes des cellules du document.
- le fichier “workbook.xml” représente le classeur Excel à proprement parlé.
Après avoir installé le SDK Open XML 2.0 (April 2009 CTP) dont le lien est indiqué ci-dessus, ajoutez une référence vers la librairie “DocumentFormat.OpenXML” :
C’est dans cette dernière que vous aller trouver les classes permettant de lire le fichier Excel, à savoir :
- SpreadsheetDocument : cette classe représente le document Excel à proprement parlé.
- WorkbookPart : c’est la classe qui correspond au fichier “workbook.xml” vu ci-dessus.
- WorksheetPart : cette classe permet de parser chaque fichier XML associé à une feuille de calcul Excel (dans le dossier “worksheets” de l’archive).
- SharedStringTablePart : cette classe représente le fichier “sharedStrings.xml”
- SheetData : cette classe va permettre la récupération des lignes (et donc des cellules d’une feuille de calcul).
- Row : représente une ligne dans un classeur
- Cell : représente une cellule dans une ligne. Chaque cellule est identifiée par un numéro unique, permettant ainsi de mapper la valeur dans le fichier “sharedStrings.xml”
Maintenant que les grands principes sont posés, nous pouvons rentrer plus en détails dans le code de l’application.
La classe SpreadsheetDocument possède une méthode statique “Open” permettant d’ouvrir un fichier Excel 2007/2010 (.xlsx) à partir de son chemin d’accès :
string customersFilePath = "Customers.xlsx";
//ouverture du fichier en lecture seule
using (SpreadsheetDocument customersDocument
= SpreadsheetDocument.Open(customersFilePath, false))
{
}
Nous pouvons alors récupérer le “WorkbookPart” ainsi que l’instance de “WorksheetPart” associée à la première feuille de calcul du fichier Excel :
WorkbookPart workbookPart = customersDocument.WorkbookPart;
WorksheetPart worksheetPart = workbookPart.GetPartsOfType<WorksheetPart>().First();
Le WorkbookPart permet également la récupération de la classe qui va permettre la lecture des valeurs des cellules dans le fichier “sharedStrings.xml” :
SharedStringTablePart sharedStringTablePart =
workbookPart.GetPartsOfType<SharedStringTablePart>().First();
Nous avons tout pour commencer à lire le fichier de clients. Pour cela, nous devons récupérer l’instance de “SheetData” associée à la feuille de calcul courante :
SheetData sheetData = worksheetPart.Worksheet.Descendants<SheetData>().First();
C’est sur celle-ci que nous allons récupérer lignes et colonnes :
//parcours des lignes sauf la première (titre de colonne)
foreach (var row in sheetData.Elements().Skip(1))
{
var cells = row.Elements| ().ToList();
} |
Il faut ensuite s’assurer que nous avons bien récupérer les 4 colonnes de notre document. Après cela, nous pouvons récupérer l’identifier unique de la colonne pour aller chercher sa valeur dans la “SharedStringTablePart” :
if (cells.Count == 4)
{
Customer cust = new Customer();
//ID
Cell IDCell = cells[0];
//si le type de donnée est bien un SharedString
if (IDCell.DataType == CellValues.SharedString)
{
//on récupère l'id de la cellule
int cellNumber = int.Parse(IDCell.CellValue.InnerText);
//on récupère la valeur dans la shared table
cust.ID = sharedStringTablePart.SharedStringTable.ChildElements[cellNumber].InnerText;
}
}
Note : pour ne pas surcharger la lecture, j’ai volontairement omis les autres propriétés de notre Client récupérable de manière identique dans les cellules d’index 1,2 et 3 :)
Vous avez donc récupéré votre liste de client en mémoire, il suffit de la lier à un DataGrid :
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding}" x:Name="dgCustomers">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding Path=ID}" />
<DataGridTextColumn Header="Nom" Binding="{Binding Path=LastName}" />
<DataGridTextColumn Header="Prénom" Binding="{Binding Path=FirstName}" />
<DataGridTextColumn Header="Ville" Binding="{Binding Path=City}" />
</DataGrid.Columns>
</DataGrid>
Et voilà le travail :
A vous de jouer !
A bientôt 
Sources : ExcelOpenXmlSDK.zip (68.05 kb)