特別徴収住民税の納付データCSVに変換する

職場に持ち込む都合上、ついでに記事にします。
実務で使う場合は、ご自分で検証して、自己責任でお願いします。:expressionless:

##やりたいこと
住民税の特別徴収のデータから、eLTAX指定のCSV様式（変換後）に変換します。

###変換前

|市区町村コード|市区町村名|指定番号|給与件数|給与税額|
|---|---|---|---|---|
|500001|甲子町|999999|1|1000|
|500002|乙丑町|999999|2|2000|
|500003|丙寅町|999999|3|3000|
|500004|丁卯町|999999|4|4000|
|500005|戊辰町|999999|5|5000|
|500006|己巳町|999999|6|6000|

※後述の模擬データからデータに起こせます。

###変換後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370992/ec5ddc5f-db74-4e7a-553a-343feadc5554.png)

※空欄に見える箇所は、下記の通り、nullと半角スペースと両方あります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370992/6b697e1f-617a-301e-5c89-be329d448e1b.png)



##CSVとして保存するネタを作るコード
模擬データを変換し、パラメータを使って、生成するクエリを作ります。
Power Queryの技術的には難しくないですけど、可読性が上がるよう、努めました。

###パラメータ（年月）
システムなどから出るデータに年月が入っていない、入っていても表の枠外となる例が多いと思うので、パラメータを採用しました。こんな感じで登録します。
このうち年と月を使って、後述のクエリ内で「平成ベース」で年月4桁を生成することになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370992/abf36fbc-10e6-7d02-c390-fb6eeee96863.png)

Excelシート内でパラメータを指定する方法については、下記記事を参考にしてください。
[パラメータテーブルと、その値を取るカスタム関数｜Power Query](https://qiita.com/tanuki_phoenix/items/d82a34e5c6b411bbae5f)

###模擬データ(t_sample)
こんな感じのデータが得られる（成形する）ものとします。たいていはPower Queryでたぶん乗りきれるはずです。
自治体コードも架空なので、このデータのまま読み込みをかけると、その旨、エラーが出ると思います。

※空のクエリを作り、詳細エディタで、下記コードを貼ると、模擬データができます。

```
let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMjUAAkMlHaXnUzY9XTvh+ZRdQLYlGAAZIAlDoAKlWB2oUiOgyJOdM5/smIimFCRhhKLUGKR0x8yn61vRlIIkjFGUmoCVNj7tXY+mFCRhgqLUFCjyrKPrxb4NaEpBEqYoSs2AIk+3b3y6fTOaUpCEGVhpLAA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [市区町村コード = _t, 市区町村名 = _t, 指定番号 = _t, 給与件数 = _t, 給与税額 = _t]),
    変更された型 = Table.TransformColumnTypes(Source,{{"給与件数", type number}, {"給与税額", type number}})
in
    変更された型
```


###クエリのコード

```
let
    ヘッダーレコード      = Table.FromRows({{1,99}}),
    エンドレコード        = Table.FromRows({{9," "}}),

    //以下、データレコードの作成
    納付年月の指定       = Table.AddColumn(t_sample, "納付年月", 
                                each Text.Format("#{0}#{1}",{Date.Year(年月)-2000+12,Number.ToText(Date.Month(年月),"00")})
                          ),
    おまけ列の生成       = Table.AddColumn(納付年月の指定, "その他セット",
                                each [データ区分=3,督促=0,延滞=0,合計件数=[給与件数],合計税額=[給与税額],備考=null,ダミー=" "]
                          ),
    レコードの展開       = Table.ExpandRecordColumn(おまけ列の生成, "その他セット", Record.FieldNames(おまけ列の生成[その他セット]{0})),
    仕様通りに並び替え   = Table.SelectColumns(レコードの展開,{"データ区分", "市区町村コード", "納付年月", "指定番号", "給与件数", "給与税額", "督促", "延滞", "合計件数", "合計税額", "備考", "ダミー"}),
    //列名をColumn1～にする。
    データレコード       = Table.RemoveFirstN( Table.DemoteHeaders(仕様通りに並び替え),1 ),

    //以下、トレーラーコードの作成
    トレーラーの中身    = Table.FromRecords({
                                [区分= 8,給与件数合計=List.Sum(t_sample[給与件数]),給与税額合計=List.Sum(t_sample[給与税額]),
                                 退職件数=null,退職税額合計=null,総件数=給与件数合計,総税額=給与税額合計,ダミー=" "]
                         }),
    トレーラーレコード   = Table.RemoveFirstN( Table.DemoteHeaders(トレーラーの中身),1 ),

    //合成して仕上げ
    合成               = Table.Combine({ヘッダーレコード,データレコード,トレーラーレコード,エンドレコード}),
    変更された型        = Table.TransformColumnTypes(合成,
                            //{{Column1,type text},・・・,{Column12,type text}}ということ。
                            List.Transform( {1..12},each {Text.Format("Column#{0}",{_}),type text} )
                         )

in
    変更された型
```
##おまけ：CSVファイルに保存するVBAコード
一応、作ってみました。「ブックとじない版」は僕の技術力では面倒だったので、今日は諦めました。

```vb:ExportCSV_and_Close
Sub ExportCSV_and_Close()
    If MsgBox("保存後、CSV出力します。よろしいですか？", vbYesNo) = vbNo Then
        MsgBox "処理を取り消しました。"
        Exit Sub
    End If
    ActiveWorkbook.Save
    
    Dim path As String
    Dim TargetSheetName As String
    
    path = "C:\Users\Public\Documents\特徴住民税.csv" 
    TargetSheetName = "特徴住民税"

    Application.DisplayAlerts = False
    On Error Resume Next

    ActiveWorkbook.Sheets(TargetSheetName).Select
    ActiveWorkbook.SaveAs Filename:=path, FileFormat:=xlCSV
    MsgBox "出力完了しました。"

    Application.DisplayAlerts = True
    ActiveWorkbook.Close
End Sub
```




##解説
###CSV仕様について
全銀CSVと似ています。以下、簡単に構造を説明します。

####ヘッダーレコード
ただの始まりの印。データによらず一定。
####データレコード
肝心のデータ部分。1納付先1行で、必要な分だけ行を増やせばいいです。
ちなみに、同じ自治体を複数行に分けて入れると、eLTAX側で合算集計をしてくれる雰囲気でした。
####トレーラーレコード
データレコードの集計値を入れるところ。
####エンドレコード
ただの終わりの印。データによらず一定。

※作成する際は必ず、公式ドキュメントを読みましょう。Excel手作業でも十分作れますよ。
[個人住民税（特別徴収）CSVレイアウト仕様書（CSVフォーマット）｜eLTAX](https://www.eltax.lta.go.jp/documents/00103)


##参考
###eLTAXからの納税について
eLTAXには昨年、ダイレクト方式の納税制度ができました。これを導入してしまえば、eLtaxのwebサイトにログイン後、CSVをデータアップロードするだけで、納付できてしまいます。
納付担当あるいは住民税納税チェックをする人がeLTAXにアクセスできる、という組織であれば、おすすめです。
eLTAX自体や共通納税の始め方は、公式のホームページを見てください。
[共通納税とは ｜ eLTAX 地方税ポータルシステム](https://www.eltax.lta.go.jp/kyoutsuunouzei/gaiyou/)

###納付にはPCdeskはweb版を使おう。
PCdeskはeLTAXサービスを使うためのソフトウェアで、実務的には、そのデスクトップ版かweb版を使うことになります。
僕が試した限り、デスクトップ版はエラーメッセージが貧弱で、取り付く島もありません。:pensive:
他方、web版ではエラーメッセージが細かく出て、どこが仕様に合っていないか分かります。なので、仕様とずれたファイルを作った場合でも、エラーメッセージを読めば、修正して読み込みに成功までたどり着ける可能性が高いです。
[PCdesk(WEB版)｜eLTAX 地方税ポータルシステム](https://www.portal.eltax.lta.go.jp/apa/web/webindexb#eLTAX)

##記事の改訂履歴
うまくいかない箇所など出てくれば、随時修正します。
初版：2020/1/11　14:45
二訂：2020/1/14　23:45：おまけ列の生成にて、督促、加算をそれぞれnullから0に修正。nullだとエラーになりますね。すみません。