Pythonで住信SBIネット銀行の入出金明細とデビットカードの利用明細からJDLIBEX出納帳への入力用CSVファイルを作成する

Pythonを使って、住信SBIネット銀行の入出金明細とデビットカードの利用明細からJDLIBEX出納帳への入力用csvファイルを作成します。

前提として、JDLIBEX出納帳の「電子明細」~「明細取込」は使っていません。

住信SBIネット銀行

Pythonのコードは以下の通り。

import pandas as pd

# 消費税の計算で四捨五入を行うため
from decimal import Decimal, ROUND_HALF_UP
def r_round(x):
    return int(Decimal(str(x)).quantize(Decimal('0'),rounding=ROUND_HALF_UP))

import os
import unicodedata
import shutil

os.chdir(r'C:\Users\XXXXX\XXXXX')

# JDLのデータ入力用CSVファイルの1行目から4行目(4行目はタイトル)をコピーする
shutil.copyfile('org.csv','py_yokin.csv')

# 住信SBIネット銀行の入出金明細を読み込み
df_temp = pd.read_csv('nyushukinmeisai_20241101.csv',encoding='cp932')

# '出金金額(円)'、'入金金額(円)'の記載内容にコンマ「,」が使用されているのでそれを削除する
df_temp.replace(',', '',inplace = True,regex=True)

# 列を追加する
df_temp['承認番号']=''
df_temp['内容2']=df_temp['内容']

# 後でstr.isdecimal()を使用したいので.astype('str')とする
# CSVファイルを読み込む際にdtype=strと指定すると、'出金金額(円)'、'入金金額(円)'の空欄にnanが入らないので、isdecimalを使用したときにエラーが出る
# いったんCSVファイルを読み込んだ後で.astypeを使用すると、'出金金額(円)'、'入金金額(円)'の空欄にnanが入る
# また、df_temp = df_temp.astype('str')という書き方ではだめで、新しいdataframeを指定する
df_temp2 = df_temp.astype('str')

df_temp2.loc[df_temp2['出金金額(円)'].str.isdecimal(),'出金'] = df_temp2['出金金額(円)']
df_temp2.loc[df_temp2['入金金額(円)'].str.isdecimal(),'入金'] = df_temp2['入金金額(円)']
df = df_temp2.astype({'出金': float,'入金': float})

# 半角に変換する関数 全角の空白も半角の空白に置き換わる
def hankaku(text):
    return unicodedata.normalize('NFKC', text)

# デビットカードを利用している場合(df['内容']に文字列'デビット'が含まれている場合)は、'承認番号'にデビットカードの承認番号(半角)を入れる
df.loc[df['内容'].str.contains('デビット'), '承認番号'] = df['内容'].map(hankaku).str[5:11]

# デビットカードの利用明細を読み込み
df_temp = pd.read_csv('meisai_20241101111932126.csv',encoding='cp932',dtype=str)

# Excelのvlookup関数に似た処理を行う
df_temp.set_index('承認番号',inplace=True)
dic_debit = df_temp['お取引内容'].to_dict()
# '承認番号'をキーにしてデビットカードのCSVファイルの'お取引内容'を検索し、'内容2'に入れる
df.loc[df['内容'].str.contains('デビット'), '内容2'] = df['承認番号'].map(dic_debit)

# '内容2'の文字列について
# 英数字は半角にする
df['内容2'] = df['内容2'].map(hankaku)
# 前後の空白を削除
df['内容2'] = df['内容2'].str.strip()
# 半角の空白は全角の空白にする
df['内容2'] = df['内容2'].str.replace(' ',' ')

# 出金のデータ作成
# JDLの入力用データと同じ列数のdataframeを作成して、内容をコピーする
# indexを指定しないと、['A']にデータが入らない

df_out = pd.DataFrame(index = df.index, columns=['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','AA','AB','AC','AD'])

#要素の転記

df_out['A'] = '1000'
df_out['B'] = '0'
df_out['C'] = df['日付'].str[0:4] + df['日付'].str[5:7] + df['日付'].str[8:10]
df_out['D'] = '183'
df_out['E'] = '' 
df_out['F'] = ''
df_out['G'] = '1'
df_out['H'] = ''
df_out['I'] = ''
df_out['J'] = ''
df_out['K'] = ''
df_out['L'] = df['出金']
df_out['M'] = 0
df_out['N'] = '131'
df_out['O'] = ''
df_out['P'] = ''
df_out['Q'] = '3'
df_out['R'] = ''
df_out['S'] = ''
df_out['T'] = ''
df_out['U'] = ''
df_out['V'] = df['出金']
df_out['W'] = 0
df_out['X'] = df['内容2']
df_out['Y'] = ''
df_out['Z'] = ''
df_out['AA'] = '0'
df_out['AB'] = ''
df_out['AC'] = '0'
df_out['AD'] = 'no'

# df['出金金額(円)']に金額が入っているデータとindexが一致するデータを抽出する
df_out_dec = df_out[df['出金金額(円)'].str.isdecimal()]

# 入金のデータ作成
# JDLの入力用データと同じ列数のdataframeを作成して、内容をコピーする
# indexを指定しないと、['A']にデータが入らない

df_in = pd.DataFrame(index = df.index, columns=['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','AA','AB','AC','AD'])

# 要素の転記

df_in['A'] = '1000'
df_in['B'] = '0'
df_in['C'] = df['日付'].str[0:4] + df['日付'].str[5:7] + df['日付'].str[8:10]
df_in['D'] = '131'
df_in['E'] = '' 
df_in['F'] = ''
df_in['G'] = '3'
df_in['H'] = ''
df_in['I'] = ''
df_in['J'] = ''
df_in['K'] = ''
df_in['L'] = df['入金']
df_in['M'] = 0
df_in['N'] = '319'
df_in['O'] = ''
df_in['P'] = ''
df_in['Q'] = '3'
df_in['R'] = ''
df_in['S'] = ''
df_in['T'] = ''
df_in['U'] = ''
df_in['V'] = df['入金']
df_in['W'] = 0
df_in['X'] = df['内容2']
df_in['Y'] = ''
df_in['Z'] = ''
df_in['AA'] = '0'
df_in['AB'] = ''
df_in['AC'] = '0'
df_in['AD'] = 'no'

# df['入金金額(円)']に金額が入っているデータとindexが一致するデータを抽出する
df_in_dec = df_in[df['入金金額(円)'].str.isdecimal()]

# 出金データと入金データを連結する
# sort_indexを行うことにより、データの並び順が元の入出金明細と同じになる
df_concat = pd.concat([df_out_dec, df_in_dec]).sort_index()

# '内容2'の文字列から、勘定科目等を判定する

df_concat.loc[df_concat['X'] == 'AAAAA, ['N','Q']] =['319','1']

df_concat.loc[df_concat['X'] == 'BBBBB', ['D','G']] = ['314','11']

df_concat.loc[df_concat['X'].str.contains('CCCCC'), ['D','G','I','J','K']] = ['843','11','仕 入','10%','内税']

df_concat.loc[df_concat['X'] == 'DDDDD', ['D','G','I','J','K']] = ['846','11','仕 入','10%','内税']

# 必要に応じて消費税額を計算
df_concat.loc[df_concat['J'] == '10%', 'M'] = df_concat['L'] - (df_concat['L']/1.1).map(r_round)

# 金額の入っている列をint型に変換する
df_concat_int = df_concat.astype({'L': int,'V': int})

#csvファイルに書き込み
df_concat_int.to_csv('py_yokin.csv',mode = 'a',encoding = 'cp932',header = False,index = False)

デビットカードを使用している場合への対応

デビットカードを使用している場合、預金の入出金明細の「内容」欄には

デビット 696377

のようにしか記載されませんので(数字は承認番号で、全角)、その詳細については別途デビットカードの利用明細を見ないとわかりません。

それで、デビットカードの利用明細についてもdataframeにして、入出金明細のdataframeから承認番号をキーにしてデビットカードの利用明細の「お取引内容」を参照できるようにしました。

 

タイトルとURLをコピーしました