PowerShellでCSVをブックに変換（Excel抜きで）

Excel抜きでCSVをブックに変換したくないか、少年？

タスクスケジューラから自動的にCSVをブック変換させようとすると、Excel起動のためにサインインしっぱなしにしなければなりません。
これが非常に煩わしいので、なんとかならないかいろいろググっていたところ、運良く
http://notshown.hatenablog.jp/entry/2017/07/07/162409
https://www.ka-net.org/blog/?p=11700
の記事に遭遇したので、寄せ集めてみました。

# 下準備

まず初めに EEPlus.dll を入手するのだ。

https://github.com/JanKallman/EPPlus

nugetするのが本筋ですが環境依存にしたくないという事情があったので、スクリプトを置くフォルダにlibというサブフォルダを作って、その下に eeplus.dll を入れて参照する方式です。

よって、下記スクリプトもこの前提です。

# 設定用JSON

必要に応じて指定してください。
記述は下記のような感じで。

```json
{
  "delimiter": "\t",
  "start_location": {
    "row": 2,
    "column": 1
  },
  "border": true,
  "templatePath": "template_yymmdd_hhmm.xlsx"
}
```

* 変換対象がTSV(タブ区切りCSV)の場合はdelimiterの指定必須。指定がなければCSVです。
* テンプレートが存在する場合はtemplatePathを設定。パスは**絶対パス**で。あとJSONなので指定するパスは**エスケープ**("\"→"\\\"など)してやる必要があります。
* 罫線を引く場合はborderを設定。細い罫線決め打ちなので必要に応じてスクリプトを書き換えてください。知らないだけかもしれませんが、EEPlusでは「上の行の書式設定を引きずる」というのができないみたいです。

# スクリプト

下記を ConvertTo-Book.ps1 という名前で保存。

```powershell:ConvertTo-Book.ps1
#引数
# CSVのパス
# 設定ファイルのパス(json)
param(
    [parameter(mandatory=$true)][string]$sourceDataPath,
    [string]$configPath
)

if(Test-Path $sourceDataPath){

    # 出力先パス
    $destinationPath = $sourceDataPath -replace ".\w+$",".xlsx"

    # EPPlusライブラリ参照
    [System.Reflection.Assembly]::LoadFrom((Join-Path (Split-Path $MyInvocation.MyCommand.Path) "\lib\EPPlus.dll")) | Out-Null

    # 設定ファイル読込
    if(("" -ne $configPath) -and (Test-Path $configPath)){
        $cfg = Get-Content -Path $configPath -Raw | ConvertFrom-Json
    }
    $row = $cfg.start_location.row
    if($null -eq $row){
        $row = 1
    }
    $col = $cfg.start_location.column
    if($null -eq $col){
        $col = 1
    }
    $delimiter = $cfg.delimiter
    $template = $cfg.templatePath

    # フォーマット設定
    $format = New-Object OfficeOpenXml.ExcelTextFormat
    # CSVファイルの文字コード指定
    $format.Encoding = [System.Text.Encoding]::GetEncoding("Shift_JIS")
    # 区切り文字
    if(-not ($null -eq $delimiter)){
    	$format.Delimiter = $delimiter
	}
    # 囲み文字
    $format.TextQualifier = '"'

    $locale = [System.Threading.Thread]::CurrentThread.CurrentCulture.ToString()
    $ci = New-Object -TypeName System.Globalization.CultureInfo -ArgumentList $locale
    # 桁区切り文字
    $ci.NumberFormat.NumberDecimalSeparator = ','
    $format.Culture = $ci

    # テンプレート読込
    if($null -ne $template){
        $pkg  = New-Object OfficeOpenXml.ExcelPackage -ArgumentList $template
        $sht  = $pkg.Workbook[0].Worksheets[1]
    }
    else {
        $pkg  = New-Object OfficeOpenXml.ExcelPackage
        $sht  = $pkg.Workbook.Worksheets.Add('Sheet1')
    }

    try {
        # CSV読込
        $in_fi = New-Object -TypeName System.IO.FileInfo -ArgumentList $sourceDataPath
        [void]$sht.Cells[$row, $col].LoadFromText($in_fi, $format)

        # 罫線
        if($cfg.border){
            $rmax = $sht.Dimension.End.Row
            $cmax = $sht.Dimension.End.Column
            $rmax-- # 余分に+1されているので減算

            # CSVを取り込んだ範囲に罫線を設定
            $thin = [OfficeOpenXml.Style.ExcelBorderStyle]::Thin
            $sht.Cells[$row, $col, $rmax, $cmax].Style.Border.Top.Style = $thin
            $sht.Cells[$row, $col, $rmax, $cmax].Style.Border.Bottom.Style = $thin
            $sht.Cells[$row, $col, $rmax, $cmax].Style.Border.Left.Style = $thin
            $sht.Cells[$row, $col, $rmax, $cmax].Style.Border.Right.Style = $thin
        }

        $pkg.SaveAs($destinationPath)
    }
    catch {
        #Write-Error("エラー: "+$_.Exception)
        exit 1
    }

    $pkg.Dispose()
    exit 0
}

```

# 使い方

```powershell
PS> ConvertTo-Book.ps1 元ファイル 設定JSON
```

で元ファイルと同じ場所に同じファイル名（拡張子は.xlsxになりますが）で変換後のブックを出力します。
設定JSONは必要に応じて指定してください。

なお、VBScript経由で起動する場合はWsh.Runの戻り値で成功(0)失敗(1)が判定できます。