Поделиться через


Получение заголовка столбца из электронной таблицы

Дата последнего изменения: 14 октября 2010 г.

Применимо к: Excel 2010 | Office 2010 | PowerPoint 2010 | Word 2010

В этой статье
Создание объекта SpreadsheetDocument
Базовая структура документа SpreadsheetML
Механизм работы примера кода
Пример кода

В этом разделе показано, как можно использовать классы пакета SDK Open XML версии 2.0 для Microsoft Office для получения заголовка столбца из документа электронной таблицы программными средствами.

Для компиляции кода, представленного в этом разделе, требуются следующие директивы сборки.

using System.Collections.Generic;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System.Text.RegularExpressions;
Imports System.Collections.Generic
Imports System.Linq
Imports DocumentFormat.OpenXml.Packaging
Imports DocumentFormat.OpenXml.Spreadsheet
Imports System.Text.RegularExpressions

Создание объекта SpreadsheetDocument

В Open XML SDK пакет документа Excel представлен классом SpreadsheetDocument. Для создания документа Excel следует создать экземпляр класса SpreadsheetDocument и заполнить его соответствующими частями. Как минимум, документ должен содержать часть книги, которая служит контейнером для документа, и хотя бы одну часть листа. В этом пакете текст представляется в виде XML-кода с использованием разметки SpreadsheetML.

Чтобы создать экземпляр класса на основе документа, необходимо вызвать один из перегруженных методов Open(). В этом примере необходимо открыть файл только для чтения. Следовательно, можно воспользоваться методом Open(String, Boolean), присвоив логическому параметру (Boolean) значение false.

В следующем примере кода показано открытие файла только для чтения, указанного с помощью параметра filepath, с помощью метода Open.

// Open file as read-only.
using (SpreadsheetDocument document = SpreadsheetDocument.Open(docName, false))
' Open the document as read-only.
Dim document As SpreadsheetDocument = SpreadsheetDocument.Open(docName, False)

Инструкцию using рекомендуется использовать вместо традиционной последовательности .Open, .Save, .Close. Это позволяет обеспечить автоматический вызов метода Dispose (внутреннего метода, используемого пакетом SDK Open XML для очистки ресурсов) при достижении закрывающей скобки. Блок, следующий за инструкцией using, создает область для объекта, создаваемого или именуемого в инструкции using, в данном случае — mySpreadsheet.

Базовая структура документа SpreadsheetML

Базовая структура документа SpreadsheetML состоит из элементов Sheets и Sheet, которые ссылаются на листы в книге Workbook. Для каждого Worksheet создается отдельный XML-файл. В следующем примере показан код SpreadsheetML для книги с двумя листами MySheet1 и MySheet2, находящийся в файле Workbook.xml.

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<workbook xmlns=https://schemas.openxmlformats.org/spreadsheetml/2006/main xmlns:r="https://schemas.openxmlformats.org/officeDocument/2006/relationships">
    <sheets>
        <sheet name="MySheet1" sheetId="1" r:id="rId1" /> 
        <sheet name="MySheet2" sheetId="2" r:id="rId2" /> 
    </sheets>
</workbook>

XML-файлы листов содержат один или несколько элементов уровня блока, такие как SheetData. sheetData представляет таблицу ячеек и содержит один или несколько элементов Row. row содержит один или несколько элементов Cell. Каждая ячейка содержит элемент CellValue, который представляет значение ячейки. Например, разметка SpreadsheetML для первого листа книги, в котором только у ячейки A1 имеется значение 100, размещена в файле Sheet1.xml и показана в следующем примере кода.

<?xml version="1.0" encoding="UTF-8" ?> 
<worksheet xmlns="https://schemas.openxmlformats.org/spreadsheetml/2006/main">
    <sheetData>
        <row r="1">
<c r="A1">
    <v>100</v> 
</c>
        </row>
    </sheetData>
</worksheet>

Использование SDK Open XML версии 2.0 позволяет создать структуру и содержимое документа с помощью строго типизированных классов, соответствующих элементам SpreadsheetML. Эти классы находятся в пространстве имен DocumentFormat.OpenXML.Spreadsheet. В следующей таблице представлены имена классов, соответствующие элементам workbook, sheets, sheet, worksheet и sheetData.

Элемент SpreadsheetML

Класс пакета SDK Open XML версии 2.0

Описание

workbook

Workbook

Корневой элемент основной части документа.

sheets

DocumentFormat.OpenXml.Spreadsheet.Sheets

Контейнер для структур уровня блока, таких как sheet, fileVersion и других, указанных в спецификации ISO/IEC 29500 (Возможно, на английском языке).

sheet

DocumentFormat.OpenXml.Spreadsheet.Sheet

Лист, указывающий на файл определения листа.

worksheet

DocumentFormat.OpenXml.Spreadsheet.Worksheet

Файл определения листа, который содержит данные листа.

sheetData

DocumentFormat.OpenXml.Spreadsheet.SheetData

Таблица ячеек, сгруппированная по строкам.

row

DocumentFormat.OpenXml.Spreadsheet.Row

Строка в таблице ячеек.

c

DocumentFormat.OpenXml.Spreadsheet.Cell

Ячейка в строке.

v

DocumentFormat.OpenXml.Spreadsheet.CellValue

Значение ячейки.

Механизм работы примера кода

Код, приведенный в этом руководстве, состоит из трех методов (функций в Visual Basic): GetColumnHeading, GetColumnName и GetRowIndex. Два последних метода вызываются из метода GetColumnHeading.

В качестве параметра метод GetColumnName принимает имя ячейки. Для получения имени столбца метод анализирует имя ячейки путем создания регулярного выражения и нахождения имени столбца из имени ячейки. Дополнительные сведения о регулярных выражениях см. в статье об элементах языка регулярных выражений.

// Create a regular expression to match the column name portion of the cell name.
Regex regex = new Regex("[A-Za-z]+");
Match match = regex.Match(cellName);

return match.Value;
' Create a regular expression to match the column name portion of the cell name.
Dim regex As Regex = New Regex("[A-Za-z]+")
Dim match As Match = regex.Match(cellName)
Return match.Value

В качестве параметра метод GetRowIndex принимает имя ячейки. Для получения индекса строки метод анализирует имя ячейки путем создания регулярного выражения и нахождения индекса строки из имени ячейки.

// Create a regular expression to match the row index portion the cell name.
Regex regex = new Regex(@"\d+");
Match match = regex.Match(cellName);

return uint.Parse(match.Value);
' Create a regular expression to match the row index portion the cell name.
Dim regex As Regex = New Regex("\d+")
Dim match As Match = regex.Match(cellName)
Return UInteger.Parse(match.Value)

Метод GetColumnHeading использует три параметра: полный путь к исходному файлу электронной таблицы, имя листа, содержащего указанный столбец, и имя ячейки в столбце, для которого нужно получить заголовок.

Для получения имени столбца указанной ячейки код вызывает метод GetColumnName. Кроме того, код получает ячейки в столбце и упорядочивает их по строкам с помощью метода GetRowIndex.

// Get the column name for the specified cell.
string columnName = GetColumnName(cellName);

// Get the cells in the specified column and order them by row.
IEnumerable<Cell> cells = worksheetPart.Worksheet.Descendants<Cell>().
    Where(c => string.Compare(GetColumnName(c.CellReference.Value), 
        columnName, true) == 0)
' Get the column name for the specified cell.
Dim columnName As String = GetColumnName(cellName)

' Get the cells in the specified column and order them by row.
Dim cells As IEnumerable(Of Cell) = worksheetPart.Worksheet.Descendants(Of Cell)().Where(Function(c) _
    String.Compare(GetColumnName(c.CellReference.Value), columnName, True) = 0).OrderBy(Function(r) GetRowIndex(r.CellReference))

Если указанный столбец существует, код получает первую ячейку в столбце с помощью метода IEnumerable(T).First. Первая ячейка содержит заголовок.

// Get the first cell in the column.
Cell headCell = cells.First();
' Get the first cell in the column.
Dim headCell As Cell = cells.First()

Если содержимое ячейки размещено в объекте SharedStringTablePart, код возвращает элементы общей строки и содержимое заголовка столбца с помощью метода M:System.Int32.Parse(System.String). Если содержимое ячейки не размещено в объекте SharedStringTable, код возвращает содержимое ячейки.

// If the content of the first cell is stored as a shared string, get the text of the first cell
// from the SharedStringTablePart and return it. Otherwise, return the string value of the cell.
if (headCell.DataType != null && headCell.DataType.Value == 
    CellValues.SharedString)
{
    SharedStringTablePart shareStringPart = document.WorkbookPart.
GetPartsOfType<SharedStringTablePart>().First();
    SharedStringItem[] items = shareStringPart.
SharedStringTable.Elements<SharedStringItem>().ToArray();
    return items[int.Parse(headCell.CellValue.Text)].InnerText;
}
else
{
    return headCell.CellValue.Text;
}
' If the content of the first cell is stored as a shared string, get the text of the first cell
' from the SharedStringTablePart and return it. Otherwise, return the string value of the cell.
If ((Not (headCell.DataType) Is Nothing) AndAlso (headCell.DataType.Value = CellValues.SharedString)) Then
    Dim shareStringPart As SharedStringTablePart = document.WorkbookPart.GetPartsOfType(Of SharedStringTablePart)().First()
    Dim items() As SharedStringItem = shareStringPart.SharedStringTable.Elements(Of SharedStringItem)().ToArray()
    Return items(Integer.Parse(headCell.CellValue.Text)).InnerText
Else
    Return headCell.CellValue.Text
End If

Пример кода

В следующем примере кода показано извлечение заголовка столбца по заданному имени столбца. Для вызова метода GetColumnHeading можно использовать вызов, показанный в следующем примере, в котором используется файл "Sheet4.xlsx".

string docName = @"C:\Users\Public\Documents\Sheet4.xlsx";
string worksheetName = "Sheet1";
string cellName = "B2";
string s1 = GetColumnHeading(docName, worksheetName, cellName);
Dim docName As String = "C:\Users\Public\Documents\Sheet4.xlsx"
Dim worksheetName As String = "Sheet1"
Dim cellName As String = "B2"
Dim s1 As String = GetColumnHeading(docName, worksheetName, cellName)

Ниже полностью приведен пример кода для языков C# и Visual Basic.

// Given a document name, a worksheet name, and a cell name, gets the column of the cell and returns
// the content of the first cell in that column.
public static string GetColumnHeading(string docName, string worksheetName, string cellName)
{
    // Open the document as read-only.
    using (SpreadsheetDocument document = SpreadsheetDocument.Open(docName, false))
    {
IEnumerable<Sheet> sheets = document.WorkbookPart.Workbook.Descendants<Sheet>().Where(s => s.Name == worksheetName);
if (sheets.Count() == 0)
{
    // The specified worksheet does not exist.
    return null;
}

WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(sheets.First().Id);

// Get the column name for the specified cell.
string columnName = GetColumnName(cellName);

// Get the cells in the specified column and order them by row.
IEnumerable<Cell> cells = worksheetPart.Worksheet.Descendants<Cell>().Where(c => string.Compare(GetColumnName(c.CellReference.Value), columnName, true) == 0)
    .OrderBy(r => GetRowIndex(r.CellReference));

if (cells.Count() == 0)
{
    // The specified column does not exist.
    return null;
}

// Get the first cell in the column.
Cell headCell = cells.First();

// If the content of the first cell is stored as a shared string, get the text of the first cell
// from the SharedStringTablePart and return it. Otherwise, return the string value of the cell.
if (headCell.DataType != null && headCell.DataType.Value == CellValues.SharedString)
{
    SharedStringTablePart shareStringPart = document.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First();
    SharedStringItem[] items = shareStringPart.SharedStringTable.Elements<SharedStringItem>().ToArray();
    return items[int.Parse(headCell.CellValue.Text)].InnerText;
}
else
{
    return headCell.CellValue.Text;
}
    }
}
// Given a cell name, parses the specified cell to get the column name.
private static string GetColumnName(string cellName)
{
    // Create a regular expression to match the column name portion of the cell name.
    Regex regex = new Regex("[A-Za-z]+");
    Match match = regex.Match(cellName);

    return match.Value;
}

// Given a cell name, parses the specified cell to get the row index.
private static uint GetRowIndex(string cellName)
{
    // Create a regular expression to match the row index portion the cell name.
    Regex regex = new Regex(@"\d+");
    Match match = regex.Match(cellName);

    return uint.Parse(match.Value);
}
' Given a document name, a worksheet name, and a cell name, gets the column of the cell and returns
' the content of the first cell in that column.
Public Function GetColumnHeading(ByVal docName As String, ByVal worksheetName As String, ByVal cellName As String) As String
    ' Open the document as read-only.
    Dim document As SpreadsheetDocument = SpreadsheetDocument.Open(docName, False)

    Using (document)
Dim sheets As IEnumerable(Of Sheet) = document.WorkbookPart.Workbook.Descendants(Of Sheet)().Where(Function(s) s.Name = worksheetName)
If (sheets.Count() = 0) Then
    ' The specified worksheet does not exist.
    Return Nothing
End If

Dim worksheetPart As WorksheetPart = CType(document.WorkbookPart.GetPartById(sheets.First.Id), WorksheetPart)

' Get the column name for the specified cell.
Dim columnName As String = GetColumnName(cellName)

' Get the cells in the specified column and order them by row.
Dim cells As IEnumerable(Of Cell) = worksheetPart.Worksheet.Descendants(Of Cell)().Where(Function(c) _
    String.Compare(GetColumnName(c.CellReference.Value), columnName, True) = 0).OrderBy(Function(r) GetRowIndex(r.CellReference))

If (cells.Count() = 0) Then
    ' The specified column does not exist.
    Return Nothing
End If

' Get the first cell in the column.
Dim headCell As Cell = cells.First()

' If the content of the first cell is stored as a shared string, get the text of the first cell
' from the SharedStringTablePart and return it. Otherwise, return the string value of the cell.
If ((Not (headCell.DataType) Is Nothing) AndAlso (headCell.DataType.Value = CellValues.SharedString)) Then
    Dim shareStringPart As SharedStringTablePart = document.WorkbookPart.GetPartsOfType(Of SharedStringTablePart)().First()
    Dim items() As SharedStringItem = shareStringPart.SharedStringTable.Elements(Of SharedStringItem)().ToArray()
    Return items(Integer.Parse(headCell.CellValue.Text)).InnerText
Else
    Return headCell.CellValue.Text
End If

    End Using
End Function

' Given a cell name, parses the specified cell to get the column name.
Private Function GetColumnName(ByVal cellName As String) As String
    ' Create a regular expression to match the column name portion of the cell name.
    Dim regex As Regex = New Regex("[A-Za-z]+")
    Dim match As Match = regex.Match(cellName)
    Return match.Value
End Function

' Given a cell name, parses the specified cell to get the row index.
Private Function GetRowIndex(ByVal cellName As String) As UInteger
    ' Create a regular expression to match the row index portion the cell name.
    Dim regex As Regex = New Regex("\d+")
    Dim match As Match = regex.Match(cellName)
    Return UInteger.Parse(match.Value)
End Function

См. также

Ссылка

Class Library Reference

Другие ресурсы

LINQ

Лямбда-выражения

Лямбда-выражения (руководство по программированию в C#)