[WSH・Python]全銀フォーマットの入出金取引明細レコード・フォーマットをcsvに変換してみた

全銀フォーマットの入出金取引明細レコード・フォーマットをcsvに変換してみた。
和暦は2018を足して西暦にしてます。
言語はJscriptです。Windowsマシンなら動くでしょう。

cscript zengin2csv.js "全銀データのファイル"

zengin2csv.js


//入出金取引明細レコード・フォーマット
//① ヘッダー・レコード
type1=[['データ区分','N',1],
['種別コード','N',2],
['コード区分','N',1],
['作成日','N',6],
['勘定日(自)','N',6],
['勘定日(至)','N',6],
['銀行コード','N',4],
['銀行名','C',15],
['支店コード','N',3],
['支店名','C',15],
['ダミー','N',3],
['預金種目','N',1],
['口座番号(注)','N',10],
['口座名','C',40],
['※貸越区分','N',1],
['※通帳・証書区分','N',1],
['※取引前残高','N',14],
['ダミー','C',71]
]

//②-1 データ・レコード(普通預金・当座預金・貯蓄預金の場合)
type21=[['データ区分','N',1],
['※照会番号','N',8],
['勘定日','N',6],
['預入・払出日','N',6],
['入払区分(注)','N',1],
['※取引区分','N',2],
['取引金額','N',12],
['うち他店券金額','N',12],
['※交換呈示日','N',6],
['※不渡返還日','N',6],
['※手形・小切手区分','N',1],
['※手形・小切手番号','N',7],
['※僚店番号','N',3],
['※振込依頼人コード','N',10],
['※振込依頼人名または契約者番号','C',48],
['※仕向銀行名','C',15],
['※仕向店名','C',15],
['※摘要内容','C',20],
['※EDI 情報','C',20],
['ダミー','C',1]
]

//②-2 データ・レコード(通知預金・定期預金・積立定期預金の場合)
type22=[['データ区分','N',1],
['※識別番号','N',8],
['勘定日','N',6],
['預入・払出日','N',6],
['入払区分(注 1)','N',1],
['※取引区分','N',2],
['取引金額','N',12],
['うち他店券金額','N',12],
['※交換呈示日','N',6],
['※不渡返還日','N',6],
['※手形・小切手区分','N',1],
['※手形・小切手番号','N',7],
['※僚店番号','N',3],
['※当初預入日','N',6],
['利率(注 2)','N',6],
['※満期日','N',6],
['※期間(1)','N',7],
['※期間利息','N',11],
['※中間払利率','N',6],
['※中間払区分','N',1],
['※期後期間','N',4],
['※期後利率','N',6],
['※期後利息','N',9],
['※合計利息','N',11],
['※税区分','N',1],
['※税率','N',4],
['※税額','N',10],
['※税引後利息','N',11],
['※摘要内容','C',20],
['※期間(2)','N',5],
['※期間利息正負表示','N',1],
['ダミー','C',4]
]

//③ トレーラ・レコード
type8=[['項目名','桁',],
['データ区分','N',1],
['入金件数','N',6],
['入金額合計','N',13],
['出金件数','N',6],
['出金額合計','N',13],
['※貸越区分','N',1],
['※取引後残高','N',14],
['データ・レコード件数','N',7],
['ダミー','C',139]
]

//④ エンド・レコード
type9=[['項目名','桁',],
['データ区分','N',1],
['レコード総件数','N',10],
['口座数','N',5],
['ダミー','C',184]
]

data_len=200
f_debug = true


//ファイル名は引数で渡される
var args = WScript.Arguments

var outputfilename = args(0)+ ".csv"
var fs = new ActiveXObject( "Scripting.FileSystemObject" );
var ifile = fs.OpenTextFile(args(0), 1, true);
var ofile = fs.OpenTextFile(outputfilename, 2, true);

var str =ifile.ReadAll();

data_num = str.length / data_len

for (var j = 0; j < data_num; j++) {
	//レコードの切り出し
	data_rec=str.substr( 200*j, data_len );
	//WScript.Echo( data_rec);
	
	//1文字目でデータ種別を判断
	column_data=""
	switch (data_rec.substr(0,1)) {
		case "1":
			//実行する処理; //式が値1に当てはまる場合に実行される

			
			//カラム行出力
			for (var i = 0; i < type1.length; i++) {
				column_data += type1[i][0]+","
			}
			if (f_debug) WScript.Echo(column_data)
			ofile.WriteLine(column_data)
			
			if (f_debug) WScript.Echo(text2csv(data_rec,type1))
			ofile.WriteLine(text2csv(data_rec,type1))

			column_data=""
			
			
			//62文字(0始まり)で預金種目を区別
			if (data_rec.substr(62,1) == "1") {
				type2=type21
			} else {
				type2=type22
			}
			//上の場合分けは不要みたい
             type2=type21


			
			//カラム行出力
			for (var i = 0; i < type2.length; i++) {
				column_data += type2[i][0]+","
			}
			if (f_debug) WScript.Echo(column_data)
			ofile.WriteLine(column_data)
			
			
			break;
		case "2":
		
			if (f_debug) WScript.Echo(text2csv(data_rec,type2))
			ofile.WriteLine(text2csv(data_rec,type2))
			//WScript.quit(0);
			break;
		case "8":
			//実行する処理;
			break;
		case "9":
			//実行する処理;
			break;
		default:
			//実行する処理;
	} 
	
	
}


ifile.Close();
ofile.Close();


//  オブジェクトを解放
fs = null;

function text2csv(data_rec,type) {
	data_pos=0
	column_data=""
	for (var i = 0; i < type.length; i++) {
	
		if (type[i][1]=="N") {
			//末尾が日で終わる項目
			if (data_pos,type[i][0].match(/日$/) && (data_rec.substr(data_pos,type[i][2]) != '000000')) {
				//日付形式に直す.
				date_data1 = data_rec.substr(data_pos,type[i][2])
				//和暦を西暦に
				date_data2 =  Number(date_data1.substr(0,2))+2018 + '/' + date_data1.substr(2,2) + '/' + date_data1.substr(4,2) 
			
				column_data += '"' + date_data2 + '",'
				
			} else {
		
				column_data += data_rec.substr(data_pos,type[i][2])+','
			}
		} else {
			//末尾の空白を削除して"で囲む
			column_data += '"'+data_rec.substr(data_pos,type[i][2]).replace(/\s+$/g, '')+'",'
		}

	
		//column_data += data_rec.substr(data_pos,type[i][2])+","
		data_pos=data_pos+type[i][2]
	}
	return column_data
}

Pythonでも同じようなものを作ってみた。

import sys
import os
import re
import csv
import shutil
import glob
from datetime import datetime
#from dateutil.parser import parse
import time


#入出金取引明細レコード・フォーマット
#① ヘッダー・レコード
type1=[['データ区分','N',1],
['種別コード','N',2],
['コード区分','N',1],
['作成日','N',6],
['勘定日(自)','N',6],
['勘定日(至)','N',6],
['銀行コード','N',4],
['銀行名','C',15],
['支店コード','N',3],
['支店名','C',15],
['ダミー','N',3],
['預金種目','N',1],
['口座番号(注)','N',10],
['口座名','C',40],
['※貸越区分','N',1],
['※通帳・証書区分','N',1],
['※取引前残高','N',14],
['ダミー','C',71]
]

#②-1 データ・レコード(普通預金・当座預金・貯蓄預金の場合)
type21=[['データ区分','N',1],
['※照会番号','N',8],
['勘定日','N',6],
['預入・払出日','N',6],
['入払区分(注)','N',1],
['※取引区分','N',2],
['取引金額','N',12],
['うち他店券金額','N',12],
['※交換呈示日','N',6],
['※不渡返還日','N',6],
['※手形・小切手区分','N',1],
['※手形・小切手番号','N',7],
['※僚店番号','N',3],
['※振込依頼人コード','N',10],
['※振込依頼人名または契約者番号','C',48],
['※仕向銀行名','C',15],
['※仕向店名','C',15],
['※摘要内容','C',20],
['※EDI 情報','C',20],
['ダミー','C',1]
]

#②-2 データ・レコード(通知預金・定期預金・積立定期預金の場合)
type22=[['データ区分','N',1],
['※識別番号','N',8],
['勘定日','N',6],
['預入・払出日','N',6],
['入払区分(注 1)','N',1],
['※取引区分','N',2],
['取引金額','N',12],
['うち他店券金額','N',12],
['※交換呈示日','N',6],
['※不渡返還日','N',6],
['※手形・小切手区分','N',1],
['※手形・小切手番号','N',7],
['※僚店番号','N',3],
['※当初預入日','N',6],
['利率(注 2)','N',6],
['※満期日','N',6],
['※期間(1)','N',7],
['※期間利息','N',11],
['※中間払利率','N',6],
['※中間払区分','N',1],
['※期後期間','N',4],
['※期後利率','N',6],
['※期後利息','N',9],
['※合計利息','N',11],
['※税区分','N',1],
['※税率','N',4],
['※税額','N',10],
['※税引後利息','N',11],
['※摘要内容','C',20],
['※期間(2)','N',5],
['※期間利息正負表示','N',1],
['ダミー','C',4]
]

#③ トレーラ・レコード
type8=[['項目名','桁',],
['データ区分','N',1],
['入金件数','N',6],
['入金額合計','N',13],
['出金件数','N',6],
['出金額合計','N',13],
['※貸越区分','N',1],
['※取引後残高','N',14],
['データ・レコード件数','N',7],
['ダミー','C',139]
]

#④ エンド・レコード
type9=[['項目名','桁',],
['データ区分','N',1],
['レコード総件数','N',10],
['口座数','N',5],
['ダミー','C',184]
]

data_len=200
f_debug = 1

def text2csv(data_rec,type):
    data_pos = 0
    column_data = ""
    for i in range(len(type)):
        if type[i][1]=="N":
            #//末尾が日で終わる項目
            if re.search('日', type[i][0]) and data_rec[data_pos:data_pos+type[i][2]] != '000000':
                #print("hit",type[i][0])
                date_data1 = data_rec[data_pos: data_pos+type[i][2]]

                date_dat0 = date_data1[0:2]
                date_dat1 = date_data1[2:4]
                date_dat2 = date_data1[4:6]
                date_dat4 = str(int(date_data1[0:2])+2018)
                date_data2 = str(int(date_data1[0:2])+2018) + '/' + date_data1[2:4] + '/' + date_data1[4:6]
                column_data += '"' + date_data2 + '",'
            else:
                column_data += data_rec[data_pos:data_pos+type[i][2]]+','
        else:
            column_data += '"' + re.sub('\s+$', '', data_rec[data_pos:data_pos + type[i][2]]) + '",'

        data_pos += type[i][2]
    return column_data





def transZengin(inputfilename):
    x_cnt=0
    outputfilename = inputfilename+ ".csv"
    ifile = open(inputfilename, 'r')
    ofile = open(outputfilename, 'w')

    text = ifile.read()
    data_num = int(len(text) / data_len)

    for j in range(data_num):
        #レコードの切り出し
        data_rec = text[data_len * j:data_len * j+data_len]
        column_data=""
        if data_rec[0:1]=="1":
            #//見出し出力
            for i in range(len(type1)):
                column_data += type1[i][0] + ","
            if f_debug==1:
                print(column_data)
            ofile.write(column_data+'\n')

            column_data=text2csv(data_rec,type1)
            if f_debug==1:
                print(column_data)
            ofile.write(column_data+'\n')

            #データレコードの見出し行出力
            column_data = ""
            if data_rec[62:63]=="1":
                type2 = type21
            else:
                type2 = type22
            #//上の場合分けは不要みたい
            type2 = type21
            #//見出し出力
            for i in range(len(type2)):
                column_data += type2[i][0] + ","
            if f_debug==1:
                print(column_data)
            ofile.write(column_data+'\n')

        elif data_rec[0:1]=="2":
            column_data=text2csv(data_rec,type2)
            if f_debug==1:
                print(column_data)
            ofile.write(column_data+'\n')
            x_cnt = +1

    ifile.close()
    ofile.close()
    if x_cnt>0:
        return outputfilename
    else:
        return ''

inputfilename = 'Zengin0000554'
transZengin(inputfilename)