Abrufen einer Spaltenüberschrift in einem Tabellenkalkulationsdokument
In diesem Thema wird gezeigt, wie Sie die Klassen im Open XML SDK für Office verwenden, um eine Spaltenüberschrift in einem Tabellenkalkulationsdokument programmgesteuert abzurufen.
Grundlegende Struktur eines SpreadsheetML-Dokuments
Die grundlegende Struktur eines SpreadsheetML-Dokuments besteht aus den Sheets and Sheet-Elementen, die auf Arbeitsblätter in der Arbeitsmappe verweisen. Es wird eine separate XML-Datei für jedes Arbeitsblatt erstellt. Beispiel: SpreadsheetML für eine Arbeitsmappe, die zwei Arbeitsblätter „MySheet1“ und „MySheet2“ enthält, befindet sich in der Datei „Workbook.xml“ und wird im nachstehenden Codebeispiel angezeigt.
<?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>
Die XML-Dateien des Arbeitsblatts enthalten ein oder mehrere Elemente auf Blockebene, z. B. sheetData stellt die Zelltabelle dar und enthält ein oder mehrere Row-Elemente . Eine Zeile enthält ein oder mehrere Cell-Elemente. Jede Zelle enthält ein CellValue-Element, das den Wert der Zelle darstellt. Beispiel: SpreadsheetML für das erste Arbeitsblatt in einer Arbeitsmappe, das nur den Wert „100“ in Zelle A1 aufweist, befindet sich in der Datei „Sheet1.xml“ und wird im nachstehenden Codebeispiel angezeigt.
<?xml version="1.0" encoding="UTF-8" ?>
<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<sheetData>
<row r="1">
<c r="A1">
<v>100</v>
</c>
</row>
</sheetData>
</worksheet>
Mit dem Open XML SDK können Sie Dokumentstrukturen und Inhalte erstellen, die stark typisierte Klassen verwenden, die SpreadsheetML-Elementen entsprechen. Diese Klassen sind im DocumentFormat.OpenXML.Spreadsheet-Namespace enthalten. Die folgende Tabelle enthält die Namen der Klassen, die den Elementen workbook, sheets, sheet, worksheet und sheetData entsprechen.
SpreadsheetML-Element | Open XML SDK-Klasse | Beschreibung |
---|---|---|
workbook | DocumentFormat.OpenXML.Spreadsheet.Workbook | Das Stammelement des Hauptdokumentteils. |
sheets | DocumentFormat.OpenXML.Spreadsheet.Sheets | Der Container für die Strukturen auf Blockebene, wie z. B. "sheet", "fileVersion" und andere Elemente, die in der Spezifikation ISO/IEC 29500 angegeben sind. |
sheet | DocumentFormat.OpenXml.Spreadsheet.Sheet | Ein Blatt, das auf eine Blattdefinitionsdatei zeigt. |
worksheet | DocumentFormat.OpenXML.Spreadsheet. Worksheet | Eine Blattdefinitionsdatei, welche die Blattdaten enthält. |
sheetData | DocumentFormat.OpenXML.Spreadsheet.SheetData | Die Zellentabelle, die mithilfe von Zeilen gruppiert wird. |
row | DocumentFormat.OpenXml.Spreadsheet.Row | Eine Zeile in der Zellentabelle. |
c | DocumentFormat.OpenXml.Spreadsheet.Cell | Eine Zelle in einer Zeile. |
v | DocumentFormat.OpenXml.Spreadsheet.CellValue | Der Wert einer Zelle. |
Funktionsweise des Beispielcodes
Der Code in dieser Anleitung besteht aus drei Methoden (Funktionen in Visual Basic): GetColumnHeading, GetColumnName und GetRowIndex. Die letzten beiden Methoden werden in der GetColumnHeading-Methode aufgerufen.
Die GetColumnName-Methode akzeptiert den Zellennamen als Parameter. Sie analysiert den Zellennamen zum Abrufen des Spaltennamens, indem ein regulärer Ausdruck für den Abgleich des Spaltennamensteils des Zellennamens erstellt wird. Weitere Informationen über reguläre Ausdrücke finden Sie unter Sprachelemente für reguläre Ausdrücke.
// 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;
Die GetRowIndex-Methode akzeptiert den Zellennamen als Parameter. Sie analysiert den Zellennamen, um den Zeilenindex durch Erstellen eines regulären Ausdrucks zu ermitteln, der den Zeilenindexteil des Zellennamens abgleicht.
// 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);
Die GetColumnHeading-Methode verwendet drei Parameter: den vollständigen Pfad zur Quelldatei der Tabellenkalkulation, den Namen des Arbeitsblatts mit der angegebenen Spalte und den Namen einer Zelle in der Spalte, für die die Überschrift abgerufen werden soll.
Der Code ruft den Namen der Spalte der angegebenen Zelle durch Aufrufen der GetColumnName-Methode ab. Zudem ruft er die Zellen in der Spalte ab und sortiert sie mithilfe der GetRowIndex-Methode nach Spalten.
// 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) ?? 0);
Wenn die angegebene Spalte vorhanden ist, wird die erste Zelle in der Spalte mithilfe der IEnumerable(T).First-Methode abgerufen. Die erste Zelle enthält die Überschrift. Andernfalls ist die angegebene Spalte nicht vorhanden, und die Methode gibt zurück. null
/ Nothing
if (cells.Count() == 0)
{
// The specified column does not exist.
return null;
}
// Get the first cell in the column.
Cell headCell = cells.First();
Wenn der Inhalt der Zelle im SharedStringTablePart-Objekt gespeichert ist, werden die SharedString-Elemente abgerufen, und der Inhalt der Spaltenüberschrift wird mithilfe derM:System.Int32.Parse(System.String)-Methode zurückgegeben. Wenn sich der Zelleninhalt nicht im SharedStringTable-Objekt befindet, wird der Inhalt der Zelle zurückgegeben.
// 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 is not null && headCell.DataType.Value == CellValues.SharedString && int.TryParse(headCell.CellValue?.Text, out int index))
{
SharedStringTablePart shareStringPart = document.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First();
SharedStringItem[] items = shareStringPart.SharedStringTable.Elements<SharedStringItem>().ToArray();
return items[index].InnerText;
}
else
{
return headCell.CellValue?.Text;
}
Beispielcode
Nachstehend ist der vollständige Beispielcode in C# und Visual Basic aufgeführt.
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
// 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.
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 is null || sheets.Count() == 0)
{
// The specified worksheet does not exist.
return null;
}
string? id = sheets.First().Id;
if (id is null)
{
// The worksheet does not have an ID.
return null;
}
WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart!.GetPartById(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) ?? 0);
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 is not null && headCell.DataType.Value == CellValues.SharedString && int.TryParse(headCell.CellValue?.Text, out int index))
{
SharedStringTablePart shareStringPart = document.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First();
SharedStringItem[] items = shareStringPart.SharedStringTable.Elements<SharedStringItem>().ToArray();
return items[index].InnerText;
}
else
{
return headCell.CellValue?.Text;
}
}
}
// Given a cell name, parses the specified cell to get the column name.
static string GetColumnName(string? cellName)
{
if (cellName is null)
{
return string.Empty;
}
// 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.
static uint? GetRowIndex(string? cellName)
{
if (cellName is null)
{
return null;
}
// 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);
}