Open XML SDK を利用してExcelファイルを読み込み、セルの内容を表示する - C#

Open XML SDK を利用してのExcelファイルを読み込んでセルの内容を読み込むコードを紹介します。

事前準備

Windows Form プロジェクトを作成し、Open XML SDK のインストールと参照を追加します。手順はこちらの記事を参照してください。

プログラム

UI

下図のUIを作成します。フォームにボタンとテキストボックスを一つ配置します。

コード

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Linq;
using System.Windows.Forms;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

namespace ExcelApp
{
  public partial class Form_GetCell : Form
  {
    public Form_GetCell()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      if (openFileDialog1.ShowDialog() == DialogResult.OK)
      {
        SpreadsheetDocument doc = SpreadsheetDocument.Open(openFileDialog1.FileName, false);

        WorkbookPart wbPart = doc.WorkbookPart;
        Sheets sheets = wbPart.Workbook.GetFirstChild<Sheets>();

        foreach (Sheet sheet in sheets)
        {
          textBox1.Text += "Excel Sheet Name : " + sheet.Name + "\r\n";

          Worksheet Worksheet = ((WorksheetPart)wbPart.GetPartById(sheet.Id)).Worksheet;
          SheetData sheetdata = Worksheet.GetFirstChild<SheetData>();

          foreach (Row crow in sheetdata)
          {
            foreach (Cell ccell in crow)
            {
              if (ccell.DataType != null)
              {
                int index = Convert.ToInt32(ccell.InnerText);
                SharedStringTablePart sstp = wbPart.GetPartsOfType<SharedStringTablePart>().ElementAt<SharedStringTablePart>(0);
                SharedStringItem item = sstp.SharedStringTable.Elements<SharedStringItem>().ElementAt<SharedStringItem>(index);
                Text t = item.Elements<Text>().ElementAt<Text>(0);

                textBox1.Text += string.Format("{0} : {1}\r\n", ccell.CellReference, t.Text);
              }
              else
              {
                textBox1.Text += string.Format("{0} : {1}\r\n", ccell.CellReference, ccell.InnerText);
              }
            }
          }
        }
      }
 
    }
  }
}

解説

ファイルを開くダイアログで選択したファイルパスをSpreadsheetDocument.Open() メソッドに与えて、SpreadsheetDocument オブジェクトを作成します。 SpreadsheetDocument オブジェクトから、WorkbookPartオブジェクト Sheetsオブジェクトを取得します

  SpreadsheetDocument doc = SpreadsheetDocument.Open(openFileDialog1.FileName, false);
  WorkbookPart wbPart = doc.WorkbookPart;
  Sheets sheets = wbPart.Workbook.GetFirstChild<Sheets>();

foreachループでシートを順番に取得します。
foreach (Sheet sheet in sheets)
{
}

シート名をテキストボックスに表示します。
  textBox1.Text += "Excel Sheet Name : " + sheet.Name + "\r\n";

シート内にあるSheetData オブジェクトを取得します。WorkbookPartオブジェクトのGetPartById()メソッドで、SheetオブジェクトのIDの要素を取得し、Worksheet プロパティに割り当てられている Worksheetオブジェクトを取得します。取得したWorksheetオブジェクトのGetFiestChild() メソッドを呼び出し、SheetDataオブジェクトを取得します。
  Worksheet Worksheet = ((WorksheetPart)wbPart.GetPartById(sheet.Id)).Worksheet;
  SheetData sheetdata = Worksheet.GetFirstChild<SheetData>();

SheetData内に行を表現しているRowオブジェクトがありますので、foreachループでアクセスします。
  foreach (Row crow in sheetdata)
  {
  }

Rowオブジェクト内にセルを表現しているCellオブジェクトがありますので、foreachループでアクセスします。
    foreach (Cell ccell in crow)
    {
    }

CellオブジェクトのDataTypeプロパティを判定します。DataTypeが設定されている場合には、セルの値は、SharedStringTable に格納されているため、 CellオブジェクトのInnerText プロパティの値をキーにして、SharedStringTable からセルの値を取得します。 取得した値をセルのアドレスを表現するCellオブジェクトの CellReference プロパティと合わせてテキストボックスに表示します。

DataTypeが設定されていない場合は、セルの値はInnerTextプロパティに設定されているため、セルのアドレスと合わせて、 InnerTextプロパティの値をテキストボックスに表示します。
  if (ccell.DataType != null)
  {
    int index = Convert.ToInt32(ccell.InnerText);
    SharedStringTablePart sstp = wbPart.GetPartsOfType<SharedStringTablePart>().ElementAt<SharedStringTablePart>(0);
    SharedStringItem item = sstp.SharedStringTable.Elements<SharedStringItem>().ElementAt<SharedStringItem>(index);
    Text t = item.Elements<Text>().ElementAt<Text>(0);

    textBox1.Text += string.Format("{0} : {1}\r\n", ccell.CellReference, t.Text);
  }
  else
  {
     textBox1.Text += string.Format("{0} : {1}\r\n", ccell.CellReference, ccell.InnerText);
   }

実行結果

テストデータ1

下図のExcelシートを用意します。Excelブック形式で保存します。


プロジェクトを実行します。下図のウィンドウが表示されます。


[button1]をクリックします。ファイルを開くダイアログが表示されます。用意したExcelファイルを選択して開きます。


シートのセルの内容がテキストボックスに表示されます。

テストデータ2

下図のExcelシートを用意します。複数のシートのあるExcelブックファイルを準備しました。



プロジェクトを実行し、Excelブックファイルを読み込みます。それぞれのシートのセルの値を読み込みテキストボックスに表示します。

補足:コードの記述

先に紹介したコードでは、foreach ループで Sheets SheetData Row のデフォルトプロパティを利用していますが、デフォルトプロパティを利用しない場合の記述として 以下のコードでも同じ動作になります。
 private void button2_Click(object sender, EventArgs e)
    {
      if (openFileDialog1.ShowDialog() == DialogResult.OK)
      {
        SpreadsheetDocument doc = SpreadsheetDocument.Open(openFileDialog1.FileName, false);

        WorkbookPart wbPart = doc.WorkbookPart;
        Sheets sheets = wbPart.Workbook.GetFirstChild<Sheets>();

        foreach (Sheet sheet in sheets.Elements<Sheet>())
        {
          textBox1.Text += "Excel Sheet Name : " + sheet.Name + "\r\n";

          Worksheet Worksheet = ((WorksheetPart)wbPart.GetPartById(sheet.Id)).Worksheet;
          SheetData sheetdata = Worksheet.GetFirstChild<SheetData>();
          foreach (Row crow in sheetdata.Elements<Row>())
          {
            foreach (Cell ccell in crow.Elements<Cell>())
            {
              if (ccell.DataType != null)
              {
                int index = Convert.ToInt32(ccell.InnerText);
                SharedStringTablePart sstp = wbPart.GetPartsOfType<SharedStringTablePart>().ElementAt<SharedStringTablePart>(0);
                SharedStringItem item = sstp.SharedStringTable.Elements<SharedStringItem>().ElementAt<SharedStringItem>(index);
                Text t = item.Elements<Text>().ElementAt<Text>(0);

                textBox1.Text += string.Format("{0} : {1}\r\n", ccell.CellReference, t.Text);
              }
              else
              {
                textBox1.Text += string.Format("{0} : {1}\r\n", ccell.CellReference, ccell.InnerText);
              }
            }
          }
        }
      }
    }
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2022-05-26
作成日: 2022-05-25
iPentec all rights reserverd.