質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.53%

  • PowerShell

    466questions

    Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。

【PowerShell】CSVファイルを1行ずつ読み込み、値を編集加工し、別のCSVファイルを作成する。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 16K+

watan

score 7

前提・実現したいこと

PowerShell初心者です。

CSVファイルを読み込み、入力レコードを元に値を作成したもので、別CSVファイルを作成するスクリプトを作っています。

1行づつ処理をした結果をカスタムオブジェクトへ格納し、それをCSV 出力・・としようとしていますが、配列をうまく進めることができません。

該当のソースコード

言語:PowerShell

<入力ファイル:input.csv>
"Col1","Col2","Col3","Col4","Col5","Col6","Col7"
"November 1, 2016","","AAA","BBB","2016/12/02",1,1
"November 2, 2016","","AAA","CCC","2016/11/18",1,1
"November 3, 2016","","DDD","EEE","2016/11/25",1,1

<出力ファイル>
"Date1","Date2","Date3","Date4","Str1","Str2","Num_当年","Num_前年"

<プログラム:MakeCSVTest.ps1>
$Infile  = 'C:\Users\n0000437\CHK\input.csv'
$Outfile = 'C:\Users\n0000437\CHK\OutFile.csv'

$opBSDT = ([datetime]$args[0]).tostring("yyyy/MM/dd")
$dpBSDT = ([datetime]$args[1]).tostring("yyyy/MM/dd")

"基準日1:$opBSDT"
"基準日2:$dpBSDT"

function ReadYoyaku{

$OutLines = New-Object System.Collections.ArrayList
$OutLine = New-Object PSObject | Select-Object "Date1","Date2","Str1","Str2","Num_当年","Num_前年"
$OutLines | ft -AutoSize

Import-Csv $Infile |  ForEach-Object {
$SDate1=([datetime]$_.Col1).tostring("yyyy/MM/dd")

$OutLine.Date1    = $SDate1
if( $SDate1 -lt $opBSDT ) { 
$OutLine.Date2 = ([datetime]$_.Col1).AddDays(+364).tostring("yyyy/MM/dd") }
else {
$OutLine.Date2        = $SDate1 
}

$OutLine.Str1    = $_.Col3
$OutLine.Str2   = $_.Col4

if( $SDate -lt $dpBSDT ) { 
$OutLine.Num_当年    = 0
$OutLine.Num_前年    = $_.Col7
} else {
$OutLine.Num_当年    = $_.Col7
$OutLine.CV_前年    = 0
}
[void]$OutLines.Add($OutLine)
$OutLines | ft -AutoSize
}
$OutLines | ft -AutoSize
}    
ReadYoyaku

<起動>
起動時に日付をパラメータ渡しします。
> .\MakeCSVTest.ps1 2017/1/1 2016/1/1

問題・困っていること

出力結果が、入力ファイルの最後のレコードですべて置き換わってしまいま

上記実行結果が↓のようになってしまいます。

Date1      Date2      Str1 Str2 Num_当年 Num_前年
-----      -----      ---- ---- -------- --------
2016/11/03 2017/11/02 DDD  EEE         0 6
2016/11/03 2017/11/02 DDD  EEE         0 6
2016/11/03 2017/11/02 DDD  EEE         0 6

こうなってほしい↓
Date1      Date2      Str1 Str2 Num_当年 Num_前年
-----      -----      ---- ---- -------- --------
2016/11/01 2017/10/31 AAA  BBB         0 2
2016/11/02 2017/11/01 AAA  CCC         0 4
2016/11/03 2017/11/02 DDD  EEE         0 6

補足情報(言語/FW/ツール等のバージョンなど)

$PSVersionTable

Name                           Value
----                           -----
CLRVersion                     2.0.50727.5485
BuildVersion                   6.1.7601.17514
PSVersion                      2.0
WSManStackVersion              2.0
PSCompatibleVersions           {1.0, 2.0}
SerializationVersion           1.1.0.1
PSRemotingProtocolVersion      2.1

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

$OutLineのインスタンスがループ(ForEach-Object)の前に作成されていてループの中では同じインスタンスに上書きしてます。
で$OutLinesにaddしてますが同じインスタンスの参照をaddしてるので最後のデータになってしまいます。

function ReadYoyaku{

$OutLines = New-Object System.Collections.ArrayList 
# ここではなく
# $OutLine = New-Object PSObject | Select-Object "Date1","Date2","Str1","Str2","Num_当年","Num_前年" 

$OutLines | ft -AutoSize

Import-Csv $Infile |  ForEach-Object { 
    # ここでOutLineのインスタンスを作成してください。
    $OutLine = New-Object PSObject | Select-Object 
    $SDate1=([datetime]$_.Col1).tostring("yyyy/MM/dd")

# ・・・・略・・・・

補足すると、以下のようなことです。[void]$OutLines.Add($OutLine)の後で$OutLine.Date1='BBB'とすると、$OutLinesに追加したものも'BBB'になります。

PS C:\> $OutLine = New-Object PSObject | Select-Object "Date1","Date2","Str1","Str2","Num_当年","Num_前年"
PS C:\> $OutLines = New-Object System.Collections.ArrayList
PS C:\> $OutLines
PS C:\> $OutLine.Date1='AAA'
PS C:\> [void]$OutLines.Add($OutLine)
PS C:\> $OutLines

Date1    : AAA
Date2    :
Str1     :
Str2     :
Num_当年 :
Num_前年 :

PS C:\> $OutLine.Date1='BBB'
PS C:\> $OutLine.Date2='BBB'
PS C:\> $OutLines

Date1    : BBB
Date2    : BBB
Str1     :
Str2     :
Num_当年 :
Num_前年 :

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/08 17:26

    ありがとうございました。解決いたしました!
    補足もありがとうございます。理解できました。

    キャンセル

同じタグがついた質問を見る

  • PowerShell

    466questions

    Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。