大きなサイズのスプレッドシート ドキュメントを解析して読み取る
適用対象: Excel 2010 | Office 2010 | PowerPoint 2010 | Word 2010
この記事の内容
SpreadsheetDocument オブジェクトの取得
Open XML ファイルの解析方法
サンプル コード
ここでは、Open XML SDK 2.0 for Microsoft Office のクラスを使用して、大きな Excel ファイルをプログラムによって読み取る方法を説明します。SpreadsheetML ドキュメントの基本構造の詳細については、「SpreadsheetML ドキュメントの構造」を参照してください。
このトピックのコードをコンパイルするには、次の using ディレクティブまたは Imports ステートメントを使用する必要があります。
using System;
using System.Linq;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
Imports System
Imports System.Linq
Imports DocumentFormat.OpenXml
Imports DocumentFormat.OpenXml.Packaging
Imports DocumentFormat.OpenXml.Spreadsheet
SpreadsheetDocument オブジェクトの取得
Open XML SDK では、SpreadsheetDocument クラスが ドキュメント パッケージを表します。 ドキュメントを開いて操作するには、ドキュメントから SpreadsheetDocument クラスのインスタンスを作成します。ドキュメントからインスタンスを作成した後、ワークシートが含まれているメインのブック パーツにアクセスできます。ドキュメント内のテキストは、パッケージ内で SpreadsheetML マークアップを使用して XML として表されます。
クラス インスタンスを作成するには、Open() メソッドのオーバーロードの 1 つを呼び出します。次のコード サンプルでは、Open(String, Boolean) オーバーロードの使用方法を示します。最初のパラメーターは、開くドキュメントへの完全なパスを表す文字列を受け取ります。2 番目のパラメーターは、true 値または false 値を受け取ります。これらの値は、編集のためにファイルを開くかどうかを表します。この例ではドキュメントを読み取り専用で開くため、このパラメーターは false です。
// Open the document for editing.
using (SpreadsheetDocument spreadsheetDocument =
SpreadsheetDocument.Open(fileName, false))
{
// Code removed here.
}
' Open the document for editing.
Using spreadsheetDocument As SpreadsheetDocument = _
SpreadsheetDocument.Open(filename, False)
' Code removed here.
End Using
Open XML ファイルの解析方法
Open XML SDK は、Open XML ファイルを解析する手段を 2 つ提供します。SDK ドキュメント オブジェクト モデル (DOM) を使用するか、Simple API for XML (SAX) の読み取りおよび書き込みの機能を使用できます。SDK DOM は、厳密に型指定されたクラスを使用して Open XML ファイルのクエリや解析を簡単に実行できるように設計されています。ただし、DOM を使用するには Open XML パーツ全体をメモリに読み込む必要があり、非常に大きなファイルを操作している場合に "メモリ不足" 例外が発生する可能性があります。SAX を使用すると、OpenXMLReader を使用してファイル内の XML を 1 要素ずつ読み取ることができるため、ファイル全体をメモリに読み込む必要はありません。非常に大きなファイルを扱うときは SAX の使用をお勧めします。
次のコードは、DOM を使用して非常に大きな Excel ファイルを読み取る方法を示します。
WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();
string text;
foreach (Row r in sheetData.Elements<Row>())
{
foreach (Cell c in r.Elements<Cell>())
{
text = c.CellValue.Text;
Console.Write(text + " ");
}
}
Dim workbookPart As WorkbookPart = spreadsheetDocument.WorkbookPart
Dim worksheetPart As WorksheetPart = workbookPart.WorksheetParts.First()
Dim sheetData As SheetData = worksheetPart.Worksheet.Elements(Of SheetData)().First()
Dim text As String
For Each r As Row In sheetData.Elements(Of Row)()
For Each c As Cell In r.Elements(Of Cell)()
text = c.CellValue.Text
Console.Write(text & " ")
Next
Next
次のコードは、前のサンプル (非常に大きな Excel ファイルを読み取るコード) と同じ処理を SAX を使用して実行します。非常に大きなファイルを読み取る場合は、この方法の使用を推奨します。
WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
OpenXmlReader reader = OpenXmlReader.Create(worksheetPart);
string text;
while (reader.Read())
{
if (reader.ElementType == typeof(CellValue))
{
text = reader.GetText();
Console.Write(text + " ");
}
}
Dim workbookPart As WorkbookPart = spreadsheetDocument.WorkbookPart
Dim worksheetPart As WorksheetPart = workbookPart.WorksheetParts.First()
Dim reader As OpenXmlReader = OpenXmlReader.Create(worksheetPart)
Dim text As String
While reader.Read()
If reader.ElementType = GetType(CellValue) Then
text = reader.GetText()
Console.Write(text & " ")
End If
End While
サンプル コード
たとえば、非常に大きな Excel スプレッドシートを扱う金融会社に勤務していると仮定します。このようなスプレッドシートはアナリストによって毎日更新され、サイズが数百 MB を超えることもたびたびあります。スプレッドシートから目的のデータを読み取り、抽出するソリューションが必要です。次のコードには 2 つのメソッドがあり、それぞれは DOM 方式と SAX 方式に対応しています。後者は、非常に大きなファイルを使用するときにメモリ例外を回避できる方式です。このサンプル コードを試すときは、コードで 1 つのメソッドの呼び出しが完了してから次のメソッドを呼び出すか、実行しないメソッドをコメントにすることでメソッドを個別に呼び出すことができます。
String fileName = @"C:\Users\Public\Documents\BigFile.xlsx";
// Comment one of the following lines to test the method separately.
ReadExcelFileDOM(fileName); // DOM
ReadExcelFileSAX(fileName); // SAX
Dim fileName As String = "C:\Users\Public\Documents\BigFile.xlsx"
' Comment one of the following lines to test each method separately.
ReadExcelFileDOM(fileName) ' DOM
ReadExcelFileSAX(fileName) ' SAX
以下に、C# と Visual Basic の両方の完全なサンプル コードを示します。
// The DOM approach.
// Note that the code below works only for cells that contain numeric values.
//
static void ReadExcelFileDOM(string fileName)
{
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(fileName, false))
{
WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();
string text;
foreach (Row r in sheetData.Elements<Row>())
{
foreach (Cell c in r.Elements<Cell>())
{
text = c.CellValue.Text;
Console.Write(text + " ");
}
}
Console.WriteLine();
Console.ReadKey();
}
}
// The SAX approach.
static void ReadExcelFileSAX(string fileName)
{
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(fileName, false))
{
WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
OpenXmlReader reader = OpenXmlReader.Create(worksheetPart);
string text;
while (reader.Read())
{
if (reader.ElementType == typeof(CellValue))
{
text = reader.GetText();
Console.Write(text + " ");
}
}
Console.WriteLine();
Console.ReadKey();
}
}
' The DOM approach.
' Note that the this code works only for cells that contain numeric values.
Private Sub ReadExcelFileDOM(ByVal fileName As String)
Using spreadsheetDocument As SpreadsheetDocument = SpreadsheetDocument.Open(fileName, False)
Dim workbookPart As WorkbookPart = spreadsheetDocument.WorkbookPart
Dim worksheetPart As WorksheetPart = workbookPart.WorksheetParts.First()
Dim sheetData As SheetData = worksheetPart.Worksheet.Elements(Of SheetData)().First()
Dim text As String
For Each r As Row In sheetData.Elements(Of Row)()
For Each c As Cell In r.Elements(Of Cell)()
text = c.CellValue.Text
Console.Write(text & " ")
Next
Next
Console.WriteLine()
Console.ReadKey()
End Using
End Sub
' The SAX approach.
Private Sub ReadExcelFileSAX(ByVal fileName As String)
Using spreadsheetDocument As SpreadsheetDocument = SpreadsheetDocument.Open(fileName, False)
Dim workbookPart As WorkbookPart = spreadsheetDocument.WorkbookPart
Dim worksheetPart As WorksheetPart = workbookPart.WorksheetParts.First()
Dim reader As OpenXmlReader = OpenXmlReader.Create(worksheetPart)
Dim text As String
While reader.Read()
If reader.ElementType = GetType(CellValue) Then
text = reader.GetText()
Console.Write(text & " ")
End If
End While
Console.WriteLine()
Console.ReadKey()
End Using
End Sub