スプレッドシート ドキュメント内の列見出しを取得する
適用対象: Excel 2010 | Office 2010 | PowerPoint 2010 | Word 2010
この記事の内容
SpreadsheetDocument オブジェクトを作成する
SpreadsheetML ドキュメントの基本構造
サンプル コードの動作のしくみ
サンプル コード
このトピックでは、Open XML SDK 2.0 for 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 では、SpreadsheetDocument クラスは Excel ドキュメント パッケージを表します。Excel ドキュメントを作成するには、SpreadsheetDocument クラスのインスタンスを作成して、パーツを設定します。少なくとも、ドキュメントのコンテナーとなるブック パーツと、ワークシート パーツが 1 つずつ必要です。テキストはパッケージ内で SpreadsheetML マークアップを使用して XML として表されます。
ドキュメントからクラス インスタンスを作成するには、Open() のいずれかのオーバーロード メソッドを呼び出します。この例では、ファイルを読み取りアクセス専用で開く必要があります。したがって、Open(String, Boolean) メソッドを使用でき、Boolean パラメーターを false に設定します。
次のコード例では、Open メソッドを呼び出し、filepath で指定されているファイルを読み取り専用アクセスで開いています。
// 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 メソッド (リソースをクリーンアップするために Open XML SDK で使用される内部メソッド) が自動的に呼び出されます。using ステートメントに続くブロックは、using ステートメントで作成または指定されたオブジェクト (この例では mySpreadsheet) のスコープを設定します。
SpreadsheetML ドキュメントの基本構造
SpreadsheetML ドキュメントの基本構造は、Sheets 要素と Sheet 要素で構成されます。これらの要素は、Workbook 内のワークシートを参照します。Worksheet ごとに個別の XML ファイルが作成されます。たとえば、MySheet1 と MySheet2 という名前の 2 つのワークシートがあるブックの SpreadsheetML は 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 などのブロック レベル要素が 1 つ以上含まれています。セルの表を表す sheetData には Row 要素が 1 つ以上含まれています。row には Cell が 1 つ以上含まれています。セルにはそれぞれ、セルの値を表す CellValue 要素が含まれています。たとえば、Sheet1.xml には、ブックにある 1 番目のワークシートの 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>
Open XML SDK 2.0 を使用すると、SpreadsheetML 要素に対応する厳密に型指定されたクラスを使用したドキュメント構造とコンテンツを作成できます。これらのクラスは DocumentFormat.OpenXML.Spreadsheet 名前空間にあります。次の表は、workbook、sheets、sheet、worksheet、sheetData の各要素に対応するクラスのクラス名の一覧です。
SpreadsheetML の要素 |
Open XML SDK 2.0 のクラス |
説明 |
---|---|---|
workbook |
Workbook |
メイン ドキュメント パーツのルート要素。 |
sheets |
DocumentFormat.OpenXml.Spreadsheet.Sheets |
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 |
セルの値。 |
サンプル コードの動作のしくみ
この例のコードは、3 つのメソッド (Visual Basic では関数) GetColumnHeading、GetColumnName、および GetRowIndex で構成されています。最後の 2 つのメソッドは、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 メソッドは 3 つのパラメーターを使用します。ソース スプレッドシートへの完全なパス、指定した列を含むワークシートの名前、および見出しを取得する列のセルの名前です。
コードは、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
サンプル コード
次のコード例では、列の名前を使用して列見出しを取得する方法を示します。"Sheet4.xlsx" ファイルを使用する次の例のような呼び出しを使用して、GetColumnHeading メソッドを呼び出すことができます。
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