スプレッドシート ドキュメント内のセルの値を取得する
このトピックでは、Open XML SDK for Office のクラスを使用して、スプレッドシート ドキュメント内のセルの値をプログラムで取得する方法について説明します。 このタスクを示すメソッド GetCellValue
例が含まれています。
GetCellValue メソッド
GetCellValue
メソッドを使用して、ブック内のセルの値を取得できます。 このメソッドには次の 3 つのパラメーターが必要です。
調べるドキュメントの名前を含む文字列。
調べるシートの名前を含む文字列。
値を取得するセル番地 (A1、B12 など) を含む文字列。
このメソッドは、指定されたセルの値が見つかると、その値を返します。 次のコード例は、メソッド シグネチャを示しています。
static string GetCellValue(string fileName, string sheetName, string addressName)
コードの動作のしくみ
コードでは、まず、戻り値を格納する変数を作成し、その変数を null に初期化します。
string? value = null;
セルへのアクセス
次に、 Open メソッドを使用してドキュメントを開き、ドキュメントを読み取り専用アクセス (最後の false
パラメーター) で開く必要があることを示します。 次に、コードはドキュメントの WorkbookPart プロパティを使用してブック パーツへの参照を取得します。
// 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;
要求されたセルを検出するため、まず指定した名前のシートへの参照を取得する必要があります。 コードでは、ブック パーツブック要素のすべてのシートタイプの子孫を検索し、見つけた各シートの Name プロパティを調べる必要があります。 この検索は、ブックのさまざまな関係を見ているだけであり、実際にブック パートを検索しているわけではないことに注意してください。 シートの名前やIdなどの情報を含むSheetへの参照を検索します。 そのための最も簡単な方法は、次のサンプル コードに示されているように LINQ クエリを使用することです。
// 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");
}
FirstOrDefault メソッドは、最初に一致する参照 (この場合はシート) または null 参照 (一致するものが見つからない場合) のいずれかを返します。 null 参照かどうかをチェックした後、無効なシート名が渡された場合には例外をスローします。これでシートについての情報が得られたので、対応する worksheet パーツへの参照を取得する必要があります。 既に取得したシート情報は、Id プロパティを提供し、Id プロパティを指定すると、コードはブック パーツGetPartByIdメソッドを呼び出すことによって、対応するWorksheetPartへの参照を取得できます。
// Retrieve a reference to the worksheet part.
WorksheetPart wsPart = (WorksheetPart)wbPart!.GetPartById(theSheet.Id!);
名前付きシートを見つけるのと同じように、名前付きセルを見つけるとき、コードは Descendants メソッドを使用して、 CellReference プロパティが指定したと等しい最初の一致を検索します
addressName
パラメーター。 このメソッドを呼び出した後、 theCell
という名前の変数には、セルへの参照または 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();
値の取得
この時点で、 theCell
という名前の変数には、null 参照または要求したセルへの参照が含まれます。 セルの Open XML コンテンツ (つまり、 theCell.OuterXml
) を調べると、次のような XML が表示されます。
<x:c r="A1">
<x:v>12.345000000000001</x:v>
</x:c>
InnerText プロパティにはセルのコンテンツが含まれているため、次のコード ブロックはこの値を取得します。
// If the cell does not exist, return an empty string.
if (theCell is null || theCell.InnerText.Length < 0)
{
return string.Empty;
}
value = theCell.InnerText;
ここで、サンプル メソッドでは、値を解釈する必要があります。 そのため、数値、日付、文字列、およびブールの値を処理します。 必要に応じて、サンプルを拡張することができます。
Cell型は、セル内のデータの種類を示す DataType プロパティを提供します。 数値型と日付型の場合、 DataType
プロパティの値は null です。 これには、文字列の値 CellValues.SharedString
とブール値の CellValues.Boolean
が含まれます。
DataType
プロパティが null の場合、コードはセルの値 (数値) を返します。 それ以外の場合、このコードはデータ型に基づく分岐を続行します。
// 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)
{
DataType
プロパティにCellValues.SharedString
が含まれている場合、コードは単一のSharedStringTablePartへの参照を取得する必要があります。
// For shared strings, look up the value in the
// shared strings table.
var stringTable = wbPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault();
次に、文字列テーブルが存在する場合 (存在しない場合はブックが破損し、サンプル コードは文字列自体ではなく文字列テーブルにインデックスを返します)、指定したインデックスで検出された要素の InnerText
プロパティを返します (最初に value プロパティを整数に変換します)。
// 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;
}
DataType
プロパティにCellValues.Boolean
が含まれている場合、コードはセル値で見つけた 0 または 1 を適切なテキスト文字列に変換します。
switch (value)
{
case "0":
value = "FALSE";
break;
default:
value = "TRUE";
break;
}
最後に、プロシージャは、要求された情報を含む変数 value
を返します。
サンプル コード
C# と Visual Basic の完全な GetCellValue
コード サンプルを次に示します。
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;
}