PowerShell を使って、ExcelDataReader で Excel ファイルを読み込む

[ブログからの転載](https://1bed.allright.life/?p=3003)

## 経緯

お客さまからいただく Excel ファイルを、あるフォーマットにするということを、手作業でちまちまやるのをやめたいので、ちょっとスクリプト書いてます

ググったら、「読み込むだけなら ExcelDataReader が速くていいぞー」「ExcelDataReader は xlsx だけではなくて、xls も読めるぞー」的なことを書いていて、ちょっと触ってみたくなったのです

## 環境

* Windows 10 Pro
* PowerShell 5.1
* ExcelDataReader 3.6.0
* ExcelDataReader.DataSet 3.6.0

## ライブラリのダウンロード

* ExcelDataReader  
  [https://www.nuget.org/packages/ExcelDataReader/](https://www.nuget.org/packages/ExcelDataReader/)

* ExcelDataReader.Dataset  
  [https://www.nuget.org/packages/ExcelDataReader.DataSet/](https://www.nuget.org/packages/ExcelDataReader.DataSet/)

それぞれ、右メニューにある Download package から nuget パッケージをダウンロードして、拡張子を zip に変えて解凍後、DLL を取り出した

## Excel ファイルの準備

サンプルで Excel ファイル (test.xlsx) を作りました

「商品」と「従業員」というシートを作って、それぞれ適当なデータを入れています

[![](https://1bed.allright.life/wp-content/uploads/2019/06/1.png)](https://1bed.allright.life/wp-content/uploads/2019/06/1.png)

[![](https://1bed.allright.life/wp-content/uploads/2019/06/2.png)](https://1bed.allright.life/wp-content/uploads/2019/06/2.png)

## Excel データの読み込み

DLL 2 つ、Excel ファイル 1 つ、 PowerShell ファイルをすべて同じディレクトリに置きました

ココまでの状態
[![](https://1bed.allright.life/wp-content/uploads/2019/06/3.png)](https://1bed.allright.life/wp-content/uploads/2019/06/3.png)

データを読み込むところまでコードを書いてみます

```powershell

$ErrorActionPreference = 'Stop'

# カレントのパス
$currentPath = Split-Path -Parent $MyInvocation.MyCommand.Path

# DDL の読み込み
[void][Reflection.Assembly]::LoadFile((Join-Path $currentPath '.\ExcelDataReader.dll'))
[void][Reflection.Assembly]::LoadFile((Join-Path $currentPath '.\ExcelDataReader.DataSet.dll'))

try {
    # FileStream を開く
    $stream = [System.IO.File]::Open('.\test.xlsx', [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)

    # ExcelReader の生成 
    $reader = [ExcelDataReader.ExcelReaderFactory]::CreateReader($stream)

    # ExcelDataSetConfiguration 生成
    $config = [ExcelDataReader.ExcelDataSetConfiguration]::new()
    $config.UseColumnDataType = $true
    $config.ConfigureDataTable = {
        $conf = [ExcelDataReader.ExcelDataTableConfiguration]::new()
        $conf.UseHeaderRow = $true
        return $conf
    }

    # データの読み込み
    $data = [ExcelDataReader.ExcelDataReaderExtensions]::AsDataSet($reader, $config)
} catch {
    throw
} finally {
    # オブジェクトの解放
    if ($reader -is [ExcelDataReader.IExcelDataReader]) {
        $reader.Close()
        $reader.Dispose()
        $reader = $null
    }
    if ($stream -is [System.IO.FileStream]) {
        $stream.Close()
        $stream.Dispose()
        $stream = $null
    }
}
```

`AsDataSet` メソッドを使うところがちょっと大変でした... (C# の例は腐るほどあったんですがｗ)

ここまでで、 `$data` にデータを取得できていますので、データタイプを見てみます  
[![](https://1bed.allright.life/wp-content/uploads/2019/06/4.png)](https://1bed.allright.life/wp-content/uploads/2019/06/4.png)  
DataSet で返ってきているのがわかります

中を雑にかくにんしてみます

```powershell
# 雑に中を確認
$data.Tables | %{
    Write-Output ('SheetName: {0}' -f $_.TableName)
    Format-Table -InputObject $_.Rows
}
```

[![](https://1bed.allright.life/wp-content/uploads/2019/06/5.png)](https://1bed.allright.life/wp-content/uploads/2019/06/5.png)

最後にオブジェクトを解放して終わります

```powershell
# ExcelDataReader.DataSet は .NET 3.5 でコンパイルされているようで、System.Type に比較演算子が実装されていないので FullName で判断
if ($data.GetType().FullName -eq "System.Data.DataSet") {
    $data.Clear()
    $data.Dispose()
    $data = $null
}
```