「毎日届く大量の売上CSVCSV [シーエスブイ]Comma-Separated Values。カンマ区切りのデータ形式ファイルを1つずつExcelで開いてコピペで結合しているが、数が多すぎて時間がかかる」「特定の条件に合致するデータだけを抽出して別ファイルにまとめる作業を自動化したい」といったお悩みを抱えていませんか?手作業で数多くのCSVファイルを処理するのはミスのもとであり、何より膨大な時間を奪われてしまいます。
この記事を読むことで、PowerShellを活用してフォルダ内の大量のCSVファイルを一括読み込みし、データの結合(マージ)や条件に応じた加工・出力を行うスクリプトの作り方が分かるようになります。情シスや社内SEの定型業務効率化を強力にサポートする実践的な方法をマスターしましょう。
確認した環境 本記事で紹介するスクリプトおよび手順は、以下の環境で動作を確認しています。
- OSOS [オーエス]Operating System。基本ソフトウェア: Windows 11 (64bit)
- スクリプト言語: PowerShell 5.1 (Windows PowerShell)
PowerShellによるCSV一括処理の概要とメリット
対象となる業務シーンと前提知識
企業のバックオフィスや情シス部門では、各支店やシステムから出力された複数のCSVファイルを統合する作業が頻繁に発生します。例えば、以下のようなシーンです。
- 毎日・毎月生成されるログや売上データのマージ
- 不要な列の削除や、特定のステータスを持つ行のフィルタリング
- 文字コードの違いによる文字化けの解消(※本記事ではファイルごとに適切な文字コードを指定して読み込む基本を解説します)
PowerShellを使用すれば、専用の有料ソフトを導入しなくても、Windows標準の機能だけで、CSVの読み込みから加工・出力までの一連の作業を自動化できます。
準備:テスト用のサンプルCSVファイル
本記事のスクリプトを実際に試すために、あらかじめ C:\Data\CsvFiles というフォルダを作成し、以下の3つのCSVファイルを保存しておきましょう。
ファイル保存時の注意点
- 文字コード: Shift-JIS(ANSI / CP932) ※以降のスクリプトで
-Encoding Defaultとして読み込むため - 改行コード: CRLF(Windows標準) ※メモ帳などのテキストエディタで直接作成する場合は、保存時の文字コード(エンコード)を「ANSI」等に設定してください。
sample1.csv
名前,ステータス,金額田中太郎,完了, 10000佐藤花子,処理中,20000sample2.csv
名前,ステータス,金額鈴木一郎,完了,30000山田次郎,完了, 5000sample3.csv
名前,ステータス,金額高橋美咲,未着手,15000伊藤健太,完了,25000※一部の「金額」データにわざと前後の空白(スペース)を含めています。後の解説にて、スクリプトでこれを取り除く加工(Trim処理)を行います。
フォルダ内の複数CSVファイルを一括取得する基本構文
Import-CsvとGet-ChildItemの組み合わせ
複数のCSVファイルを処理する第一歩として、フォルダ内にある対象ファイルを取得し、読み込む処理を構築します。
PowerShellでは、ファイルの列挙に Get-ChildItem コマンドレット、CSVファイルの読み込みに Import-Csv コマンドレットを使用します。
以下は、特定のフォルダ内にあるすべてのCSVファイルを読み込んで内容を確認する基本スクリプトです。 ※本記事では、一般的なカンマ区切りのCSVファイルを対象としています。
ファイル名: Read-CsvFiles.ps1
実行コマンド: .\Read-CsvFiles.ps1
# 対象フォルダのパスを指定$targetDir = "C:\Data\CsvFiles"
# フォルダ内のすべてのCSVファイルを取得してループ処理Get-ChildItem -Path $targetDir -Filter "*.csv" | ForEach-Object { $filePath = $_.FullName Write-Host "処理中のファイル: $filePath" -ForegroundColor Cyan
# CSVファイルを読み込む(日本語WindowsでShift-JIS系(CP932)の場合は -Encoding Default を指定) $csvData = Import-Csv -Path $filePath -Encoding Default
# 読み込んだデータの行数を表示 Write-Host "行数: $($csvData.Count)"}このコードでは、Get-ChildItem の -Filter "*.csv" によって対象フォルダからCSVのみを抽出し、パイプライン (|) を通して ForEach-Object に渡しています。各ファイルのフルパスを取得し、Import-Csv でオブジェクトとしてメモリ上に展開しています。
複数CSVデータを結合(マージ)して1ファイルに出力する方法
※本記事でいう「マージ」は、複数CSVのデータを行方向に連結して1つのCSVにまとめる処理を指します。
データ集約する際のパイプライン処理のコツ
次に、取得した複数のCSVファイルを1つに結合し、新たなCSVファイルとして出力する手順を解説します。すべてのCSVファイルの列名・列構成が統一されている前提であれば、単純にデータを蓄積して Export-Csv に渡すことでマージが可能です。
以下のスクリプトは、フォルダ内のすべてのCSVファイルを結合して C:\Data\Merged_Output.csv として出力する実用的なコードです。
ファイル名: Merge-CsvFiles.ps1
実行コマンド: .\Merge-CsvFiles.ps1
$targetDir = "C:\Data\CsvFiles"$outputPath = "C:\Data\Merged_Output.csv"
# フォルダ内の全CSVファイルを読み込んで結合$mergedData = Get-ChildItem -Path $targetDir -Filter "*.csv" | ForEach-Object { Import-Csv -Path $_.FullName -Encoding Default}
# 結合したデータを新しいCSVファイルとして出力# -NoTypeInformation を指定することで、余計な型情報ヘッダーの出力を防ぐ$mergedData | Export-Csv -Path $outputPath -NoTypeInformation -Encoding UTF8
Write-Host "すべてのCSVファイルの結合が完了しました: $outputPath" -ForegroundColor Greenポイントは Export-Csv コマンドレットの -NoTypeInformation オプションです。これを忘れると、出力されたCSVの1行目に #TYPE System.Management.Automation.PSCustomObject といった余分な行が挿入されてしまうため、必ず付与するようにしましょう。
また、大量のCSVを扱う場合、すべてのデータを一度変数($mergedData)に保持するとメモリ使用量が増加します。データ量が非常に大きい場合は、1ファイルずつ処理して追記(-Append オプション)する方式などを検討してください。
特定の条件でデータをフィルタリング・置換して保存する実用スクリプト
Where-ObjectやForEach-Objectを活用したデータ加工
単にマージするだけでなく、業務では「特定の値を持つ行だけを抽出したい」「特定の文字列を別の文字に置換したい」といった加工が必要になります。これらは Where-Object や ForEach-Object を組み合わせることで実現できます。
以下のスクリプトは、結合するデータの中から「ステータス」列が「完了」である行のみを抽出し、さらに「金額」の表記ゆれを修正して出力する例です。
ファイル名: Filter-CsvFiles.ps1
実行コマンド: .\Filter-CsvFiles.ps1
$targetDir = "C:\Data\CsvFiles"$outputPath = "C:\Data\Processed_Output.csv"
$processedData = Get-ChildItem -Path $targetDir -Filter "*.csv" | ForEach-Object { Import-Csv -Path $_.FullName -Encoding Default} | Where-Object { # 「ステータス」列が「完了」の行のみを抽出 $_.ステータス -eq "完了"} | ForEach-Object { # 必要に応じてデータを加工(例:金額の前後の空白を削除) # ※金額列が空欄($null)でないことを前提としています if ($null -ne $_.金額) { $_.金額 = $_.金額.Trim() } $_ # 加工したオブジェクトをパイプラインに返す}
# 加工済みのデータを、PowerShell 5.1で -Encoding UTF8 を指定してUTF-8(BOM付き)で出力$processedData | Export-Csv -Path $outputPath -NoTypeInformation -Encoding UTF8
Write-Host "データのフィルタリングと加工が完了しました。" -ForegroundColor Greenこのように、パイプラインで処理を繋げていくことで、読み込みからフィルタリング、加工、出力までを流れるようなコードで記述できます。
エラーハンドリングと文字コード(UTF-8/Shift-JIS)指定の注意点
PowerShellでCSVを扱う際、最も多く発生するトラブルが「文字化け」と「ファイルロックによるエラー」です。これらを回避するためのポイントを解説します。
1. 文字コードの指定
日本のビジネス環境では、Excelなどで作成・保存されたCSVがShift-JIS系(CP932)でエンコードされていることがあります。日本語WindowsでCP932のCSVを読み込む場合は、-Encoding Default を指定できます。一方、最新のシステムやWebからダウンロードしたCSVは UTF-8(BOM付き/BOMなし)が主流です。
文字化けを防ぐため、読み込み時と出力時の文字コードを意図的に指定することが重要です。
- 読み込み時:
Import-Csv -Path <ファイルパス> -Encoding Default(日本語WindowsのシステムANSIコードページを使用する場合。一般的にCP932/Shift-JIS系となります) ※文字コードが異なるCSVが混在している場合、現在のコードのように一律で読み込むと文字化けする可能性があります。ファイルごとに適切な-Encodingを指定する必要があります。 - 出力時:
Export-Csv -Path <ファイルパス> -Encoding UTF8(PowerShell 5.1ではUTF-8 BOM付きで出力されます)
2. ファイルロックへの対策
処理対象のCSVファイルがExcelなどの別のアプリケーションで使用されている場合、アプリケーション側のファイル共有設定などによっては、PowerShellから読み込めずエラーになることがあります。実運用では try-catch 構文を活用して、エラーハンドリングを組み込んでおくと安全です。
ファイル名: Test-CsvFileLock.ps1
実行コマンド: .\Test-CsvFileLock.ps1
$targetFile = "C:\Data\CsvFiles\sample.csv"
try { $data = Import-Csv -Path $targetFile -ErrorAction Stop Write-Host "読み込み成功: $targetFile"}catch { Write-Warning "ファイルの読み込みに失敗しました。他のアプリで開いている可能性があります: $_"}まとめ:PowerShellで日々のCSV処理を自動化しよう
今回は、PowerShellを使用して大量のCSVファイルを一括処理し、マージや加工を行う方法について解説しました。
Get-ChildItemとImport-Csvを組み合わせることで、フォルダ内の複数CSVファイルを効率的に読み込める。- パイプライン処理を利用して、データの結合(マージ)を数行のコードで実現できる。
Where-ObjectやForEach-Objectを活用すれば、条件に応じたデータのフィルタリングや加工も容易に行える。- 文字コード(Shift-JIS / UTF-8)やファイルロックに配慮することで、実業務で安定稼働するスクリプトを作成できる。
手作業で行っていたルーティンワークをPowerShellによる自動化に置き換えることで、ヒューマンエラーを防ぎ、業務効率を向上させることができます。ぜひ、ご自身の環境に合わせてサンプルスクリプトを調整し、活用してみてください。
以上で本記事の解説を終わります。
よいITライフを!
人気記事
- 1
- 2
- 3
- 4
- 5
思考の整理というテーマを、実務ですぐに使える具体的な「技術」として落とし込んだ一冊です。