お仕事などでCSVをカラム(項目)ごとにファイルを分割したいとき、エクセルなど使って手作業でやっていませんか?
手作業でやらなくても、スクリプトを使えば一瞬にして実現できます。
言語はPowerShellなのでWindows10やWindows11のパソコンであれば特別な設定はせず、すぐに実行できます。
仕事柄CSVと戯れてばかりの私が、そんな実現方法を皆さんに共有します。
実現すること
こんなCSVがあったとします。
氏名,年齢,性別,部署
太郎,103,男,総務部
次郎,132,男,総務部
三郎,22,男,経理部
花子,13,女,総務部
花子2号,13,女,経理部
花子3号,142,女,いきものがかり
花子4号,17,女,経理部
例えば部署ごとに、このように一瞬で分割したい。
"氏名","年齢","性別","部署"
"太郎","103","男","総務部"
"次郎","132","男","総務部"
"花子","13","女","総務部"
"氏名","年齢","性別","部署"
"花子2号","13","女","経理部"
"三郎","22","男","経理部"
"花子4号","17","女","経理部"
"氏名","年齢","性別","部署"
"花子3号","142","女","いきものがかり"
実現するためのスクリプト
以下のソースが書かれたPowerShellを実行するだけで実現できます。
※2行、5行に記載のあるファイルは事前に作成する必要があります。
# csv読み込み場所を指定
$csv = "c:\sample.csv"
# 出力先フォルダ
$outFolder = "c:\tempfolder\"
# csvインポート(部署ごとに並び替えて抽出していることが重要)
$ImportCsv = Import-Csv $csv -Encoding Default | Sort-Object @{Expression="部署";asc=$true}
##### start #####
# 配列作成
$exCsv = @();
# 1行目を示すダミーを入力
$tempDep = "dummy"
# インポートしたCSVを1行ずつ読み込む
foreach($line1 in $ImportCsv){
# 最初のレコードでない かつ 前レコードと部署が異なる
if(($tempDep -ne "dummy") -and ($tempDep -ne $line1."部署")){
# 部署名の名前でファイル出力
$exCsv | Export-Csv -NoTypeInformation -Path ($outFolder + $tempDep + ".csv") -Encoding Default
# 配列をリセット
$exCsv = @();
}
$exCsv += $line1 # 配列にレコード追加
$tempDep = $line1."部署" # 前レコードの部署として次回ループ用に格納
}
# ループ処理最後の所属のエクスポート
$exCsv | Export-Csv -NoTypeInformation -Path ($outFolder + $tempDep + ".csv") -Encoding Default
以下からスクリプトをダウンロードすることができます。
※拡張子を「ps1」に変更してお使いください。
解説
アルゴリズムについて解説します。
CSVをインポートするときに下記の処理を入れることによって、インポートされたデータが部署の順番にソートされます。
8行 Sort-Object @{Expression=”部署”;asc=$true}
↓内部のデータはこんな状態
"氏名","年齢","性別","部署"
"花子3号","142","女","いきものがかり"
"花子2号","13","女","経理部"
"三郎","22","男","経理部"
"花子4号","17","女","経理部"
"太郎","103","男","総務部"
"次郎","132","男","総務部"
"花子","13","女","総務部"
18~31行目では、読み込んだCSVデータを1行ずつループで回します。
1行読み込んだらその行の部署情報を記憶しておきます。(28行)
次のループに入ったときに、もし異なる部署だったら配列をエクスポートし、配列を空の状態に戻します。(21~25行)
ループの中だけだと最後の部署がエクスポートされずに終わってしまうので、31行でエクスポート処理を入れています。
最後に
このアルゴリズムに関しては私がJavaという言語で習得したものをPowerShellに置き換えたものです。
1度覚えてしまえば、様々な場面で応用できます。
(もしかしたらPythonのpandasという技術を使えばこんなことせずとも一瞬でできるかもですが…)
今回の考え方を参考にしていただき、プログラミングを身に着けてもらえたら幸いです。
コメント