Compartilhar via


Obter os valores das células num documento de folha de cálculo

Este tópico mostra como utilizar as classes no SDK Open XML para o Office para obter programaticamente os valores das células num documento de folha de cálculo. Contém um método de exemplo GetCellValue para ilustrar esta tarefa.

Método GetCellValue

Pode utilizar o GetCellValue método para obter o valor de uma célula num livro. O método requer os três parâmetros seguintes:

  • Uma cadeia que contém o nome do documento a examinar.

  • Uma cadeia que contém o nome da folha a examinar.

  • Uma cadeia que contém o endereço da célula (como A1, B12) a partir do qual obter um valor.

O método devolve o valor da célula especificada, caso possa ser encontrado. O seguinte exemplo de código mostra a assinatura do método.

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

Como Funciona o Código

O código começa por criar uma variável para manter o valor devolvido e inicializa-o como nulo.

string? value = null;

Aceder à Célula

Em seguida, o código abre o documento com o Open método , indicando que o documento deve estar aberto para acesso só de leitura (o parâmetro final false ). Em seguida, o código obtém uma referência à parte do livro com a WorkbookPart propriedade do documento.

// 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;

Para localizar a célula pedida, o código tem primeiro de obter uma referência para a folha, dado o respetivo nome. O código tem de procurar todos os descendentes do tipo de folha do elemento de livro da parte do livro e examinar a Name propriedade de cada folha que encontrar. Tenha em atenção que esta pesquisa analisa as relações do livro e não encontra realmente uma peça de folha de cálculo. Localiza uma referência a um Sheet, que contém informações como o nome e Id a folha. A forma mais simples de o fazer é utilizar uma consulta LINQ, conforme mostrado no exemplo de código seguinte.

// 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");
}

Tenha em atenção que o FirstOrDefault método devolve a primeira referência correspondente (uma folha, neste caso) ou uma referência nula se não for encontrada nenhuma correspondência. O código verifica a referência nula e gera uma exceção se tiver transmitido um nome de folha inválido. Agora que tem informações sobre a folha, o código tem de obter uma referência à parte da folha de cálculo correspondente. As informações da folha que já obteve fornecem uma Id propriedade e, tendo em conta essa propriedade de ID , o código pode obter uma referência ao correspondente WorksheetPart ao chamar o método de peça GetPartById do livro.

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

Tal como ao localizar a folha com nome, ao localizar a célula com nome, o código utiliza o Descendants método , procurando a primeira correspondência em que a CellReference propriedade é igual à especificada addressName parâmetro. Após esta chamada de método, a variável com o nome theCell conterá uma referência à célula ou conterá uma referência nula.

// 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();

A obter o Valor

Neste momento, a variável com o nome theCell contém uma referência nula ou uma referência à célula que pediu. Se examinar o conteúdo Open XML (ou seja, theCell.OuterXml) da célula, encontrará XML, como o seguinte.

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

A InnerText propriedade contém o conteúdo da célula e, por isso, o bloco de código seguinte obtém este valor.

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

Agora, o método de exemplo tem de interpretar o valor. Tal como está, o código processa valores numéricos e de data, cadeia e booleanos. Pode expandir o exemplo conforme necessário. O Cell tipo fornece uma DataType propriedade que indica o tipo de dados na célula. O valor da DataType propriedade é nulo para tipos numéricos e de data. Contém o valor CellValues.SharedString para cadeias e CellValues.Boolean para valores booleanos. Se a DataType propriedade for nula, o código devolve o valor da célula (é um valor numérico). Caso contrário, o código continua a ramificar com base no tipo de dados.

// 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)
    {

Se a DataType propriedade contiver CellValues.SharedString, o código tem de obter uma referência para o único SharedStringTablePart.

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

Em seguida, se a tabela de cadeias existir (e se não existir, o livro está danificado e o código de exemplo devolve o índice na tabela de cadeias em vez da própria cadeia), o código devolve a InnerText propriedade do elemento que encontra no índice especificado (primeiro convertendo a propriedade do valor num número inteiro).

// 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;
}

Se a DataType propriedade contiver CellValues.Boolean, o código converte o 0 ou 1 que encontra no valor da célula na cadeia de texto adequada.

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

Por fim, o procedimento devolve a variável value, que contém as informações pedidas.

Código de exemplo

Segue-se o exemplo de código completo GetCellValue em C# e Visual Basic.

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;
}

Confira também