LoginSignup
7
4

More than 1 year has passed since last update.

PowerShellでExcelファイルをCSV形式に変換する

Last updated at Posted at 2022-05-03

はじめに

先日、複数のExcelファイルをCSVファイルへ変換する必要がでてきました。
1ファイルずつ手でExcelを操作すると少々手間がかかりそうです。でも、PowerShellを利用すれば、一括で変換できそうです。
そこで、PowerShellを利用して、ExcelファイルのデータをCSVファイルに変換するスクリプトを書いてみました。

前提/環境

次の環境で、動作確認しました。

  • Windows 10
  • PowerShell 5.1

プログラムでは、Excelの機能を呼び出しているので、Excelがインストールされている必要があります。

基本的なコード

下記の関数では、Excelの機能を使って、1つのExcelファイルを読み込み、各シートをそれぞれCSVファイルとして保存します。
Excelファイルを開く際、相対パスだとうまく動かなかったので、絶対パスに変換する処理を入れています。
正常終了時、またはエラー終了時に、Excelプロセスを終了させるため、Quitメソッドを呼び出しています。ただし、呼び出してもすぐには終了しないこともあるようです。

function ConvExcelToCsv($InPath) {
  $fullInPath = Resolve-Path $InPath
  $basePath = $fullInPath -replace '\.xls(.)?', ''
  $excel = New-Object -ComObject Excel.Application

  try {
    # 既に同名CSVファイルがあっても確認ダイアログを表示しない(上書きする)。
    $excel.DisplayAlerts = $false

    $excel.Workbooks.Open($fullInPath) | ForEach-Object {
      $_.Worksheets | ForEach-Object {
        $outPath = "$($basePath)_$($_.Name).csv"
        $_.SaveAs($outPath, [Microsoft.Office.Interop.Excel.XlFileFormat]::xlCSV)
      }
    }
  }
  finally {
    $excel.Quit()
  }
}

上記では、1つのExcelファイルを対象としていました。複数のExcelファイルを処理するには、次のコードを書きました。
引数\$InPathに、フォルダーが指定されている場合、そのフォルダー配下のファイルを再帰的に検索し、拡張子がxlsやxlsxなどのExcelファイルを対象に、上述したConvExcelToCsv関数を呼び出しています。
引数\$InPathにワイルドカードが指定されている場合、ワイルドカードに該当するファイルを処理します。1つのExcelファイルのパスを指定しても動作します。

function ConvExcelToCsv2($InPath) {
  if (Test-Path -PathType leaf $InPath) {
    Get-ChildItem -File $InPath | ForEach-Object {
      ConvExcelToCsv $_.FullName
    }
  } else {
    Get-ChildItem -File $InPath -Recurse -Include ('*.xls', '*.xls?') | ForEach-Object {
      ConvExcelToCsv $_.FullName
    }
  }
}

もう少し複雑なことをしたい場合

特定のシートや、特定のセル範囲だけをCSVファイルに出力したい場合、以下のように記述しました。
引数\$InSheetにシート名を指定すると、指定したシートのみを処理対象にします。未指定なら全シートを処理。
引数\$InRangeに"A1C3"のようなセル範囲を指定すると、指定したセル範囲のみを処理対象にします。未指定なら全セル。
引数\$OutPathには、出力先のCSVファイルパスを指定します。未指定なら、入力Excelファイルの拡張子をcsvに変更したパスとしています。
また、Excel処理をすこし慎重に記述してみました。Excelファイルを読み込む時に読み取り専用モードにしたり、Excelファイルクローズ時に変更を保存しないオプションを指定したり、Excelプロセスの開放処理を追加したりしました。

function ConvExcelToCsv($InPath, $InSheet, $InRange, $OutPath) {
  $fullInPath = Resolve-Path $InPath
  if (!$OutPath) {
    $dir = [System.IO.Path]::GetDirectoryName($fullInPath)
    $name = [System.IO.Path]::GetFileNameWithoutExtension($fullInPath)
    $OutPath = Join-Path $dir ($name + '.csv')
  }
  if (Test-Path $OutPath) {
    Remove-Item $OutPath
  }
  $excel = New-Object -ComObject Excel.Application

  try {
    $excel.Visible = $false
    $excel.DisplayAlerts = $false

    # Excelファイルを開く。
    # UpdateLinks=0 外部参照(リンク)を更新しない
    # ReadOnly=$true 読み取り専用モード
    $excel.Workbooks.Open($fullInPath, 0, $true) | ForEach-Object {
      # シートを処理する。
      $sheets = $_.Worksheets
      if ($InSheet) {
        $sheets = $_.Worksheets($InSheet)
      }
      $sheets | ForEach-Object {
        # セルを処理する。
        $range = $_.UsedRange
        if ($InRange) {
          $range = $_.Range($InRange)
        }
        $range.Rows | ForEach-Object {
          $line = ''
          $_.Columns | ForEach-Object {
            if ($_.Column -gt 1) {
              $line += ','
            }
            $line += $_.Text
          }
          $line | Out-File -Append -Encoding Default $OutPath
        }
      }

      # Excelファイルを閉じる。
      # SaveChanges=$false 変更を保存しない
      $_.Close($false)
      # 次の書き方も可能。
      # $excel.Workbooks.Close()

      Write-Verbose "$OutPath を保存しました。"
    }
  }
  finally {
    # Excelプロセスを終了する。
    $excel.Quit()
    # 念のため、Excelプロセスが残らないように、COMオブジェクトを開放する。
    [System.Runtime.InteropServices.Marshal]::ReleaseComObject($excel) | Out-Null
    # 即時にExcelプロセスを終了させるため、GCを実行する。
    [System.GC]::Collect()
    [System.GC]::WaitForPendingFinalizers()
  }
}

おわりに

PowerShellで、ExcelファイルをCSVファイルに変換するコードを説明いたしました。

上述のコードをスクリプトファイルにしたものは、次の場所に置いてあります。

参考サイト

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4