Partager via


Récupérer les valeurs des cellules d’un document de feuille de calcul

Cette rubrique montre comment utiliser les classes du Kit de développement logiciel (SDK) Open XML pour Office afin de récupérer par programmation les valeurs des cellules d’un document de feuille de calcul. Elle contient un exemple de méthode GetCellValue pour illustrer cette tâche.

Méthode GetCellValue

Vous pouvez utiliser la méthode GetCellValue pour récupérer la valeur d'une cellule dans un classeur. La méthode requiert les trois paramètres suivants :

  • Chaîne contenant le nom du document à examiner.

  • Chaîne contenant le nom de la feuille à examiner.

  • Chaîne contenant l'adresse de la cellule (par exemple, A1, B12) à partir de laquelle récupérer une valeur.

La méthode renvoie la valeur de la cellule spécifiée, si elle a pu être trouvée. L'exemple de code suivant indique la signature de la méthode.

static string GetCellValue(string fileName, string sheetName, string addressName)

Fonctionnement du code

Le code commence par créer une variable pour contenir la valeur renvoyée et l'initialise sur la valeur NULL.

string? value = null;

Accès à la cellule

Le code ouvre le document à l’aide de la méthode Open, en indiquant que le document doit être ouvert en lecture seule (dernier paramètre false). Ensuite, le code récupère une référence au composant de classeur à l’aide de la propriété WorkbookPart du document.

// Open the spreadsheet document for read-only access.
using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, false))
{
    // Retrieve a reference to the workbook part.
    WorkbookPart? wbPart = document.WorkbookPart;

Pour rechercher la cellule demandée, le code doit d’abord récupérer une référence à la feuille à partir de son nom. Le code doit rechercher tous les descendants de type feuille de l’élément classeur du composant de classeur, puis examiner la propriété Name de chaque feuille trouvée. N’oubliez pas que cette recherche tient compte des relations du classeur et ne recherche pas vraiment un composant de feuille de calcul. Il recherche une référence à un objet Sheet contenant des informations, telles que le nom et l’Id de la feuille. Pour y parvenir, le plus simple est d’utiliser une requête LINQ, comme illustré dans l’exemple de code suivant.

// Find the sheet with the supplied name, and then use that 
// Sheet object to retrieve a reference to the first worksheet.
Sheet? theSheet = wbPart?.Workbook.Descendants<Sheet>().Where(s => s.Name == sheetName).FirstOrDefault();

// Throw an exception if there is no sheet.
if (theSheet is null || theSheet.Id is null)
{
    throw new ArgumentException("sheetName");
}

N’oubliez pas que la méthode FirstOrDefault renvoie la première référence correspondante (une feuille, dans ce cas) ou une référence Null si aucune correspondance n’est trouvée. Le code vérifie la référence Null et renvoie une exception si vous avez transmis un nom de feuille non valide. Quand vous avez des informations sur la feuille, le code doit récupérer une référence au composant de feuille de calcul correspondant. Parmi les informations de la feuille récupérées figure une propriété Id. À partir de la propriété Id, le code peut récupérer une référence au composant WorksheetPart correspondant en appelant la méthode GetPartById du composant de classeur.

// Retrieve a reference to the worksheet part.
WorksheetPart wsPart = (WorksheetPart)wbPart!.GetPartById(theSheet.Id!);

Comme pour la recherche de la feuille nommée, le code utilise la méthode Descendants pendant la recherche de la cellule nommée en recherchant la première correspondance où la propriété CellReference est égale au paramètre addressName spécifié. Après l’appel de cette méthode, la variable nommée theCell contient soit une référence à la cellule, soit une référence Null.

// Use its Worksheet property to get a reference to the cell 
// whose address matches the address you supplied.
Cell? theCell = wsPart.Worksheet?.Descendants<Cell>()?.Where(c => c.CellReference == addressName).FirstOrDefault();

Récupération de la valeur

À ce stade, la variable nommée theCell contient une référence Null ou une référence à la cellule demandée. Si vous examinez le contenu Open XML (autrement dit, theCell.OuterXml) de la cellule, le code XML est semblable au code suivant.

    <x:c r="A1">
        <x:v>12.345000000000001</x:v>
    </x:c>

La propriété InnerText contient le contenu de la cellule. Ainsi, le bloc de code suivant récupère cette valeur.

// If the cell does not exist, return an empty string.
if (theCell is null || theCell.InnerText.Length < 0)
{
    return string.Empty;
}
value = theCell.InnerText;

À présent, l'exemple de méthode doit interpréter la valeur. Dans ce cas, le code gère des valeurs numériques et de date, des chaînes et des valeurs booléennes. Vous pouvez étendre l’exemple si nécessaire. Le type Cell fournit une propriété DataType qui indique le type de données dans la cellule. La valeur de la propriété DataType est Null pour les valeurs numériques et de date. Elle contient la valeur CellValues.SharedString pour les chaînes et CellValues.Boolean pour les valeurs booléennes. Si la propriété DataType est null, le code renvoie la valeur de la cellule (qui est une valeur numérique). Dans le cas contraire, le code poursuit par la création de branche en fonction du type de données.

// If the cell represents an integer number, you are done. 
// For dates, this code returns the serialized value that 
// represents the date. The code handles strings and 
// Booleans individually. For shared strings, the code 
// looks up the corresponding value in the shared string 
// table. For Booleans, the code converts the value into 
// the words TRUE or FALSE.
if (theCell.DataType is not null)
{
    if (theCell.DataType.Value == CellValues.SharedString)
    {

Si la propriété DataType contient CellValues.SharedString, le code doit récupérer une référence au seul objet SharedStringTablePart.

// For shared strings, look up the value in the
// shared strings table.
var stringTable = wbPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault();

Ensuite, si la table de chaînes existe (dans le cas contraire, le classeur est endommagé et l'exemple de code renvoie l'index dans la table de chaînes plutôt que dans la chaîne elle-même), le code renvoie la propriété InnerText de l'élément qu'il trouve au niveau de l'index spécifié (en convertissant d'abord la valeur de la propriété en un nombre entier).

// If the shared string table is missing, something 
// is wrong. Return the index that is in
// the cell. Otherwise, look up the correct text in 
// the table.
if (stringTable is not null)
{
    value = stringTable.SharedStringTable.ElementAt(int.Parse(value)).InnerText;
}

Si la propriété DataType contient CellValues.Boolean, le code convertit le chiffre 0 ou 1 qu'il trouve dans la valeur de la cellule en la chaîne de texte appropriée.

switch (value)
{
    case "0":
        value = "FALSE";
        break;
    default:
        value = "TRUE";

Enfin, la procédure renvoie la variable value, qui contient les informations demandées.

Exemple de code

Voici l'exemple de code GetCellValue complet en C# et Visual Basic

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System;
using System.Linq;

Console.WriteLine(GetCellValue(args[0], args[1], args[2]));
// Retrieve the value of a cell, given a file name, sheet name, 
// and address name.
static string GetCellValue(string fileName, string sheetName, string addressName)
{
    string? value = null;
    // Open the spreadsheet document for read-only access.
    using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, false))
    {
        // Retrieve a reference to the workbook part.
        WorkbookPart? wbPart = document.WorkbookPart;
        // Find the sheet with the supplied name, and then use that 
        // Sheet object to retrieve a reference to the first worksheet.
        Sheet? theSheet = wbPart?.Workbook.Descendants<Sheet>().Where(s => s.Name == sheetName).FirstOrDefault();

        // Throw an exception if there is no sheet.
        if (theSheet is null || theSheet.Id is null)
        {
            throw new ArgumentException("sheetName");
        }
        // Retrieve a reference to the worksheet part.
        WorksheetPart wsPart = (WorksheetPart)wbPart!.GetPartById(theSheet.Id!);
        // Use its Worksheet property to get a reference to the cell 
        // whose address matches the address you supplied.
        Cell? theCell = wsPart.Worksheet?.Descendants<Cell>()?.Where(c => c.CellReference == addressName).FirstOrDefault();
        // If the cell does not exist, return an empty string.
        if (theCell is null || theCell.InnerText.Length < 0)
        {
            return string.Empty;
        }
        value = theCell.InnerText;
        // If the cell represents an integer number, you are done. 
        // For dates, this code returns the serialized value that 
        // represents the date. The code handles strings and 
        // Booleans individually. For shared strings, the code 
        // looks up the corresponding value in the shared string 
        // table. For Booleans, the code converts the value into 
        // the words TRUE or FALSE.
        if (theCell.DataType is not null)
        {
            if (theCell.DataType.Value == CellValues.SharedString)
            {
                // For shared strings, look up the value in the
                // shared strings table.
                var stringTable = wbPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault();
                // If the shared string table is missing, something 
                // is wrong. Return the index that is in
                // the cell. Otherwise, look up the correct text in 
                // the table.
                if (stringTable is not null)
                {
                    value = stringTable.SharedStringTable.ElementAt(int.Parse(value)).InnerText;
                }
            }
            else if (theCell.DataType.Value == CellValues.Boolean)
            {
                switch (value)
                {
                    case "0":
                        value = "FALSE";
                        break;
                    default:
                        value = "TRUE";
                        break;
                }
            }
        }
    }

    return value;
}