次の方法で共有


大きなスプレッドシート ドキュメントを解析して読み取る

このトピックでは、Open XML SDK for Office のクラスを使用して、大きな Excel ファイルをプログラムで読み取る方法について説明します。 SpreadsheetML ドキュメントの基本的な構造の詳細については、「SpreadsheetML ドキュメントの構造」を参照してください。

注:

複数のプラットフォーム間で Office エクスペリエンスを拡張するソリューションを開発することに関心がありますか? 新しい Office アドイン モデルを参照してください。 Office アドインは、VSTO アドインやソリューションに比べてフットプリントが小さく、HTML5、JavaScript、CSS3、XML などのほぼすべてのWeb プログラミング テクノロジーを使用して構築できます。


Open XML ファイルの解析方法

Open XML SDK には、Open XML ファイルの解析方法が 2 つ用意されています。 SDK ドキュメント オブジェクト モデル (DOM) を使用するか、Simple API for XML (SAX) の読み取りおよび書き込みの機能を使用できます。 SDK DOM は、厳密に型指定されたクラスを使用して Open XML ファイルのクエリや解析を簡単に実行できるように設計されています。 ただし、DOM アプローチでは Open XML パーツ全体をメモリに読み込む必要があるため、実際に大きなファイルを操作しているときに Out of Memory 例外が発生する可能性があります。 SAX を使用すると、OpenXMLReader を使用してファイル内の XML を 1 要素ずつ読み取ることができるため、ファイル全体をメモリに読み込む必要はありません。 非常に大きなファイルを扱うときは SAX の使用をお勧めします。

次のコードは、DOM を使用して非常に大きな Excel ファイルを読み取る方法を示します。

WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart ?? spreadsheetDocument.AddWorkbookPart();
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 + " ");
    }
}

次のコードは、前のサンプル (非常に大きな Excel ファイルを読み取るコード) と同じ処理を SAX を使用して実行します。 非常に大きなファイルを読み取る場合は、この方法の使用を推奨します。

WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart ?? spreadsheetDocument.AddWorkbookPart();
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 + " ");
    }
}


サンプル コード

たとえば、非常に大きな Excel スプレッドシートを扱う金融会社に勤務していると仮定します。 このようなスプレッドシートはアナリストによって毎日更新され、サイズが数百 MB を超えることもたびたびあります。 スプレッドシートから目的のデータを読み取り、抽出するソリューションが必要です。 次のコードには 2 つのメソッドがあり、それぞれは DOM 方式と SAX 方式に対応しています。 後者は、非常に大きなファイルを使用するときにメモリ例外を回避できる方式です。 このサンプル コードを試すときは、コードで 1 つのメソッドの呼び出しが完了してから次のメソッドを呼び出すか、実行しないメソッドをコメントにすることでメソッドを個別に呼び出すことができます。

// Comment one of the following lines to test the method separately.
ReadExcelFileDOM(args[0]);    // DOM
ReadExcelFileSAX(args[0]);    // 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 ?? spreadsheetDocument.AddWorkbookPart();
        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 ?? spreadsheetDocument.AddWorkbookPart();
        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();
    }
}

関連項目

SpreadsheetML ドキュメントの構造