vaguely

和歌山に戻りました。ふらふらと色々なものに手を出す毎日。

【C#】ClosedXMLでExcelのデータ読み込み

はじめに

みなさん Excel 使ってますか Excel

今日も(多分)外道な使い方をしている増井です。どうもこんにちは。

今回は ClosedXML を使って、 Excel(Spreadsheet) のデータを読み込んでみることにします。

https://github.com/ClosedXML/ClosedXML

基本的な使い方は Wiki に書かれていますが、いくつかやりたかったことが見つけられなかったため、備忘録的に書き残しておきます。

https://github.com/ClosedXML/ClosedXML/wiki

コード

今回は WPF を使って、ボタンを押したら指定のファイルを読み込む、ということにします。

MainWindow.xaml

< Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    < Grid>
        < Button Name="LoadFile1" Content="File1" HorizontalAlignment="Left" Margin="155,86,0,0" VerticalAlignment="Top" Width="75" Click="LoadFile1_Click"/>
    < /Grid>
< /Window>

デフォルトでできる XAML にボタンを追加しただけです。

MainWindow.xaml.cs

using System.Windows;
using WpfApp1.FileAccessor;

namespace WpfApp1 {
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
        }
        private void LoadFile1_Click(object sender, RoutedEventArgs e) {
            FirstExcelAccessor accessor = new FirstExcelAccessor();
            accessor.Load();
        }
    }
}

ボタンイベントを追加しました。

FirstExcelAccessor.cs

using System;
using System.Linq;
using ClosedXML.Excel;

namespace WpfApp1.FileAccessor {
    class FirstExcelAccessor {
        public void Load() {
            string path = @"ファイルのパス";
            // Excel(Book を開く)
            using (XLWorkbook workbook = new XLWorkbook(path)) {
              // シート、セルにアクセスして必要な処理を行う.
            }
        }
    }
}

今回はファイルのパスを固定で持たせています。
必要に応じて Explorer から取得するなどしてください。

特定のセルの列・行番号を取得する

workbook.Worksheet("シート名") でシートを、 worksheet.Cell("セル名") で取得できます。

また、取得したシートの列数、行数を取得するには下記のようにします。

using (XLWorkbook workbook = new XLWorkbook(path)) {
    using (IXLWorksheet worksheet = workbook.Worksheet("Sheet1")) {
        IXLCell cell = worksheet.Cell("calc");
        int rowNum = cell.Address.RowNumber;
        int columnNum = cell.Address.ColumnNumber;

        // セルの値を string として取得.
        var value = cell.GetString();
    }
}

セルに計算式が入っている場合、 cell.GetString() で取得できるのは計算後の値です。

セルの名前からシートを探す

セルの名前だけがわかっていて、どのシートにそのセルがあるかはわからない場合。

workbook.Cell や workbook.Range でいけそうな気がしたのですが、うまく見つけられず null になってしまうので下記のようにしました。

https://github.com/ClosedXML/ClosedXML/wiki/Accessing-Named-Ranges

var foundSheet = workbook.Worksheets
    .FirstOrDefault(sheet => sheet.Cell("world") != null);

if (foundSheet != null) {
    Console.WriteLine(foundSheet.Name);
}

コードとしてはシンプル(な気がする)ですが、全シートを見ることになるので特にシート数が多かったり、頻繁に検索する必要がある場合などは他の方法を考えたほうが良いかもしれません。