2017/01/21

CSVにダブルクォーテーションをつけるには?

ExcelからCSV形式にするとダブルクォーテーションがつかない感じ。
PowerShellで まとめて付けてみようと思ったのでメモ。

今日のコンテンツ
  • 試した環境
  • つくるもの
  • 作成手順
  • ちょっとだけ説明

試した環境


  • Windows 8.1
  • PowerShellのバージョンは 4

C:\Users\vagrant\Documents\work>powershell
Windows PowerShell
Copyright (C) 2013 Microsoft Corporation. All rights reserved.
 
PS C:\Users\vagrant\Documents\work> $PSVersionTable
 
Name                           Value
----                           -----
PSVersion                      4.0
WSManStackVersion              3.0
SerializationVersion           1.1.0.1
CLRVersion                     4.0.30319.34014
BuildVersion                   6.3.9600.16394
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion      2.2


  • batファイル
  • ダブルクリックしたらbatファイルと同じ階層に「temp」フォルダを作成
  • batファイルと同じ階層にあるCSVファイルが変換対象
  • batファイルと同じ階層にあるCSVファイルはそのまま残す
  •  「temp」フォルダ内にダブルクォーテーション付きに変換したCSVファイルを入れていく

こんな感じ
「add-double-quotes.bat」とかテキトーな名前で作ってみた。

ファイルの配置例


ダブルクォーテーションの付いていないファイル(変換前のファイル)の例。

ダブルクォーテーションの付いていないCSVファイル

実行後は「temp」フォルダができる。

実行後にできるtempフォルダ

「temp」フォルダの中身はダブルクォーテーション付きのCSVファイルが入ってる。

tempフォルダの中身

こんな感じでダブルクォーテーションがつく。

処理後のCSVファイル


  • 「add-double-quotes.bat」というファイルを作る
  • 右クリックで「編集」を選択
  • 以下のコードをコピペ

powershell -NoProfile -ExecutionPolicy RemoteSigned "& { $d='.\temp';ni $d -t d -f > $null;ls|?{$_.Name -like '*.csv'}|foreach{$f=Join-Path $d $_.Name;gc $_.Name|ConvertFrom-CSV|ConvertTo-CSV -nti|sc $f} }"
pause

PowerShellのバージョンが 3 以降なら`Import-CSV -Encoding Default`が使えるので少しだけ短くできる。

powershell -NoProfile -ExecutionPolicy RemoteSigned "& { $d='.\temp';ni $d -t d -f > $null;ls|?{$_.Name -like '*.csv'}|foreach{$f=Join-Path $d $_.Name;Import-CSV $_.Name -Encoding Default|Export-CSV $f -Encoding Default -NTI} }"
pause



  • $d='.\temp';

$dという変数にこれから作るフォルダのパス(相対パス)を退避している。

;をつけるとコマンドレットを連続して実行することができる。

この場合は変数に代入するステートメントを完了させたいので;をつけてる。


  • ni $d -t d -f > $null;

niNew-Itemのエイリアス(別名)。$dは先ほどフォルダパスを退避した変数。

-t dは省略せずに書くと-ItemType Directory、つまり「フォルダを作る」の意。-ItemType Fileなら「ファイルを作る」を意味する。

-fは省略せずに書くと-Force。これをつけない場合、すでにあるフォルダを作成しようとするとエラーとなる。-fをつけておくとすでに存在する場合は何もしない。

> $nullは出力結果を破棄している。なぜこんなことをするのか。それはniでフォルダを作成すると、そのフォルダの情報を表示しようとするから。以降の処理の邪魔になるので出力結果を破棄する(何も表示させない)ようにしている。

;は先ほどと同様、フォルダ作成の処理を終了させるため・次の処理を実行させるためにつけている。


  • ls

lsGet-ChildItemのエイリアス。Linuxのlsコマンドとよく似ている。カレントディレクトリ内のものを列挙してくれる。


  • |

|はパイプライン。左側のコマンドの出力を右側のコマンドの入力にすることができる。


  • ?{$_.Name -like '*.csv'}

?Where-Objectのエイリアス。入力に対して条件に該当するものだけにフィルタリングすることができる。SQLのWhereと似てる。 $_.Name -like '*.csv'はSQLと同じで項目(この場合lsコマンドの出力結果にあるNameの項目)に対して抽出したい条件を書いている。


  • |foreach{$f=Join-Path $d $_.Name;gc $_.Name|ConvertFrom-CSV|ConvertTo-CSV -n|sc $f}

foreach{}はプログラム言語でよくみるループのやつ。入力されたもの(今回の場合は見つかったCSVのファイル名)ごとに繰り返し処理を行う。


$f=Join-Path $d $_.Name;はファイルの出力先パスを組み立てている。先ほどの変数$d(「temp」フォルダのパス)で$_.Nameは見つけたCSVファイルの名前。


gcGet-Contentのエイリアス。ファイルの中身を読み取ることができる。Linuxのcatみたいなやつ。


ConvertFrom-CSVはCSVデータを一旦PSCustomObjectとかいうやつに変換している。


ConvertTo-CSVでは一旦PSCustomObjectに変換したものを再度CSVデータに変換している。 この時にダブルクォーテーションが付加される。 ただ-nti(省略せずに書くと-NoTypeInformation)をつけておかないと入力元の型名のコメント行が1行ついてしまう。


scSet-Contentのエイリアス。ファイルなどに書き込むことができる。


今日はここまで。疲れた〜。



[広告]

Microsoft Public Affiliate Program (JP)

JP_Office2016Launch_468x60



関連記事

スポンサーリンク

スポンサーリンク

スポンサーリンク

コメント

非公開コメント